diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
new file mode 100644
index 0000000000..d632634540
--- /dev/null
+++ b/.github/FUNDING.yml
@@ -0,0 +1 @@
+open_collective: svelte
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
deleted file mode 100644
index 2aa885cfcb..0000000000
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ /dev/null
@@ -1,56 +0,0 @@
----
-name: Bug report
-about: Create a report to help us improve
-title: ''
-labels: 'Bug'
-assignees: ''
-
----
-
-## Is this about svelte@next? This project is currently in a pre-release stage and breaking changes may occur at any time. Please do not post any kind of bug reports or questions on GitHub about it.
-
-**Describe the bug**
-A clear and concise description of what the bug is.
-
-**Logs**
-Please include browser console and server logs around the time this bug occurred.
-
-**To Reproduce**
-To help us help you, if you've found a bug please consider the following:
-
-* If you can demonstrate the bug using https://svelte.dev/repl, please do.
-* If that's not possible, we recommend creating a small repo that illustrates the problem.
-* Reproductions should be small, self-contained, correct examples – http://sscce.org.
-
-Occasionally, this won't be possible, and that's fine – we still appreciate you raising the issue. But please understand that Svelte is run by unpaid volunteers in their free time, and issues that follow these instructions will get fixed faster.
-
-**Expected behavior**
-A clear and concise description of what you expected to happen.
-
-**Stacktraces**
-If you have a stack trace to include, we recommend putting inside a `` block for the sake of the thread's readability:
-
-
- Stack trace
-
- Stack trace goes here...
-
-
-**Information about your Svelte project:**
-To make your life easier, just run `npx envinfo --system --npmPackages svelte,rollup,webpack --binaries --browsers` and paste the output here.
-
-- Your browser and the version: (e.x. Chrome 52.1, Firefox 48.0, IE 10)
-
-- Your operating system: (e.x. OS X 10, Ubuntu Linux 19.10, Windows XP, etc)
-
-- Svelte version (Please check you can reproduce the issue with the latest release!)
-
-- Whether your project uses Webpack or Rollup
-
-**Severity**
-How severe an issue is this bug to you? Is this annoying, blocking some users, blocking an upgrade or blocking your usage of Svelte entirely?
-
-Note: the more honest and specific you are here the more we will take you seriously.
-
-**Additional context**
-Add any other context about the problem here.
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
new file mode 100644
index 0000000000..38a971864b
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -0,0 +1,50 @@
+name: "\U0001F41E Bug report"
+description: Report an issue with Svelte
+labels: ["triage: bug"]
+body:
+ - type: markdown
+ attributes:
+ value: |
+ Thanks for taking the time to fill out this bug report!
+ - type: textarea
+ id: bug-description
+ attributes:
+ label: Describe the bug
+ description: A clear and concise description of what the bug is. If you intend to submit a PR for this issue, tell us in the description. Thanks!
+ placeholder: Bug description
+ validations:
+ required: true
+ - type: textarea
+ id: reproduction
+ attributes:
+ label: Reproduction
+ description: Please provide a link to a repo or REPL that can reproduce the problem you ran into. If a report is vague (e.g. just a generic error message) and has no reproduction, it will receive a "need reproduction" label. If no reproduction is provided within a reasonable time-frame, the issue will be closed.
+ placeholder: Reproduction
+ validations:
+ required: true
+ - type: textarea
+ id: logs
+ attributes:
+ label: Logs
+ description: "Please include browser console and server logs around the time this bug occurred. Optional if provided reproduction. Please try not to insert an image but copy paste the log text."
+ render: shell
+ - type: textarea
+ id: system-info
+ attributes:
+ label: System Info
+ description: Output of `npx envinfo --system --npmPackages svelte,rollup,webpack --binaries --browsers`
+ render: shell
+ placeholder: System, Binaries, Browsers
+ validations:
+ required: true
+ - type: dropdown
+ id: severity
+ attributes:
+ label: Severity
+ description: Select the severity of this issue
+ options:
+ - annoyance
+ - blocking an upgrade
+ - blocking all usage of svelte
+ validations:
+ required: true
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
new file mode 100644
index 0000000000..ee3e5a41b9
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -0,0 +1,5 @@
+blank_issues_enabled: false
+contact_links:
+ - name: Discord Chat
+ url: https://svelte.dev/chat
+ about: Ask questions and discuss with other Svelte users in real time.
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
deleted file mode 100644
index 923bfdb50c..0000000000
--- a/.github/ISSUE_TEMPLATE/feature_request.md
+++ /dev/null
@@ -1,28 +0,0 @@
----
-name: Feature request
-about: Suggest an idea for this project
-title: ''
-labels: 'New Feature'
-assignees: ''
-
----
-
-
-
-**Is your feature request related to a problem? Please describe.**
-A clear and concise description of what the problem is. For example: I'm always frustrated when [...]
-
-**Describe the solution you'd like**
-A clear and concise description of what you want to happen.
-
-**Describe alternatives you've considered**
-A clear and concise description of any alternative solutions or features you've considered.
-
-**How important is this feature to you?**
-Note: the more honest and specific you are here the more we will take you seriously.
-
-**Additional context**
-Add any other context or screenshots about the feature request here.
diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml
new file mode 100644
index 0000000000..2174f851a0
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature_request.yml
@@ -0,0 +1,42 @@
+name: "Feature Request"
+description: Request a new Svelte feature
+labels: [enhancement]
+body:
+ - type: markdown
+ attributes:
+ value: |
+ Thanks for taking the time to request this feature! If your feature request is complex or substantial enough to warrant in-depth discussion, maintainers may close the issue and ask you to open an [RFC](https://github.com/sveltejs/rfcs).
+ - type: textarea
+ id: problem
+ attributes:
+ label: Describe the problem
+ description: Please provide a clear and concise description the problem this feature would solve. The more information you can provide here, the better.
+ placeholder: I'm always frustrated when...
+ validations:
+ required: true
+ - type: textarea
+ id: solution
+ attributes:
+ label: Describe the proposed solution
+ description: Please provide a clear and concise description of what you would like to happen.
+ placeholder: I would like to see...
+ validations:
+ required: true
+ - type: textarea
+ id: alternatives
+ attributes:
+ label: Alternatives considered
+ description: "Please provide a clear and concise description of any alternative solutions or features you've considered."
+ validations:
+ required: true
+ - type: dropdown
+ id: importance
+ attributes:
+ label: Importance
+ description: How important is this feature to you?
+ options:
+ - nice to have
+ - would make my life easier
+ - i cannot use svelte without it
+ validations:
+ required: true
diff --git a/.github/ISSUE_TEMPLATE/questions-and-help.md b/.github/ISSUE_TEMPLATE/questions-and-help.md
deleted file mode 100644
index a6e0dc6e19..0000000000
--- a/.github/ISSUE_TEMPLATE/questions-and-help.md
+++ /dev/null
@@ -1,12 +0,0 @@
----
-name: Questions and help
-about: If you think you need help with something related to Svelte
-title: ''
-labels: 'Question'
-assignees: ''
-
----
-
-This issue tracker is intended to collect bug reports and feature requests.
-
-For help with installation, information on how features work, or questions about specific features of Svelte, please come and join us in the [Svelte Discord](https://svelte.dev/chat), or ask your question on [Stack Overflow](https://stackoverflow.com/questions/tagged/svelte). Any issues open for help requests will be closed to keep from clogging up the issue tracker.
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index d14a0f9fe4..7de5a35e13 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -1,5 +1,6 @@
### Before submitting the PR, please make sure you do the following
- [ ] It's really useful if your PR references an issue where it is discussed ahead of time. In many cases, features are absent for a reason. For large changes, please create an RFC: https://github.com/sveltejs/rfcs
+- [ ] Prefix your PR title with `[feat]`, `[fix]`, `[chore]`, or `[docs]`.
- [ ] This message body should clearly illustrate what problems it solves.
- [ ] Ideally, include a test that fails without this PR but passes with it.
diff --git a/.github/stale.yml b/.github/stale.yml
new file mode 100644
index 0000000000..3bc3fa6b99
--- /dev/null
+++ b/.github/stale.yml
@@ -0,0 +1,52 @@
+# Configuration for probot-stale - https://github.com/probot/stale
+
+# Only issues or pull requests with all of these labels are check if stale. Defaults to `[]` (disabled)
+onlyLabels: []
+
+# Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable
+exemptLabels:
+ - popular
+ - pinned
+ - security
+ - bug
+ - "[Status] Maybe Later"
+
+# Set to true to ignore issues in a project (defaults to false)
+exemptProjects: false
+
+# Set to true to ignore issues in a milestone (defaults to false)
+exemptMilestones: false
+
+# Set to true to ignore issues with an assignee (defaults to false)
+exemptAssignees: false
+
+# Label to use when marking as stale
+staleLabel: stale-bot
+
+# Comment to post when removing the stale label.
+# unmarkComment: >
+# Your comment here.
+
+# Limit the number of actions per hour, from 1-30. Default is 30
+limitPerRun: 30
+
+# Optionally, specify configuration settings that are specific to just 'issues' or 'pulls':
+pulls:
+ daysUntilStale: 210
+ daysUntilClose: 25
+ markComment: >
+ This pull request has been automatically marked as stale because it has not had
+ recent activity. It will be closed if no further activity occurs. Thank you
+ for your contributions.
+ closeComment: >
+ This pull request has been closed as it was previously marked as stale and saw no subsequent activity.
+
+issues:
+ daysUntilStale: 180
+ daysUntilClose: 14
+ markComment: >
+ This issue has been automatically marked as stale because it has not had
+ recent activity. It will be closed if no further activity occurs. Thank you
+ for your contributions.
+ closeComment: >
+ This issue has been closed as it was previously marked as stale and saw no subsequent activity.
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 12819d3e2a..f6a9fdf42f 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -3,58 +3,39 @@ on: [push, pull_request]
jobs:
Tests:
runs-on: ${{ matrix.os }}
- timeout-minutes: 10
+ timeout-minutes: 15
strategy:
matrix:
node-version: [8, 10, 12, 14]
os: [ubuntu-latest, windows-latest, macOS-latest]
steps:
- - uses: actions/checkout@v1
- - uses: actions/setup-node@v1
- with:
- node-version: ${{ matrix.node-version }}
- - id: npm-cache-dir
- run: echo "::set-output name=dir::$(npm config get cache)"
- - uses: actions/cache@v2
- id: npm-cache
- with:
- path: ${{ steps.npm-cache-dir.outputs.dir }}
- key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
- restore-keys: ${{ runner.os }}-node-
- - run: npm install
- - run: npm test
- env:
- CI: true
+ - uses: actions/checkout@v1
+ - uses: actions/setup-node@v2
+ with:
+ node-version: ${{ matrix.node-version }}
+ cache: npm
+ - run: npm install
+ - run: npm test
+ env:
+ CI: true
Lint:
runs-on: ubuntu-latest
- timeout-minutes: 2
+ timeout-minutes: 5
steps:
- - uses: actions/checkout@v1
- - uses: actions/setup-node@v1
- - id: npm-cache-dir
- run: echo "::set-output name=dir::$(npm config get cache)"
- - uses: actions/cache@v2
- id: npm-cache
- with:
- path: ${{ steps.npm-cache-dir.outputs.dir }}
- key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
- restore-keys: ${{ runner.os }}-node-
- - run: 'npm i && npm run lint'
+ - uses: actions/checkout@v1
+ - uses: actions/setup-node@v2
+ with:
+ cache: npm
+ - run: 'npm i && npm run lint'
Unit:
runs-on: ${{ matrix.os }}
- timeout-minutes: 5
+ timeout-minutes: 10
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macOS-latest]
steps:
- - uses: actions/checkout@v1
- - uses: actions/setup-node@v1
- - id: npm-cache-dir
- run: echo "::set-output name=dir::$(npm config get cache)"
- - uses: actions/cache@v2
- id: npm-cache
- with:
- path: ${{ steps.npm-cache-dir.outputs.dir }}
- key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
- restore-keys: ${{ runner.os }}-node-
- - run: 'npm i && npm run test:unit'
+ - uses: actions/checkout@v1
+ - uses: actions/setup-node@v2
+ with:
+ cache: npm
+ - run: 'npm i && npm run test:unit'
diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
new file mode 100644
index 0000000000..ea6e0f5a60
--- /dev/null
+++ b/.github/workflows/docs.yml
@@ -0,0 +1,28 @@
+name: Docs
+
+on:
+ push:
+ branches:
+ - master
+ paths:
+ - site/content/**
+
+jobs:
+ release:
+ name: Deploy docs
+ runs-on: ubuntu-latest
+ steps:
+ - name: my-app-install token
+ id: github-app
+ uses: getsentry/action-github-app-token@v1
+ with:
+ app_id: ${{ secrets.GH_APP_ID }}
+ private_key: ${{ secrets.GH_APP_PRIVATE_KEY }}
+
+ - name: run deploy docs workflow
+ uses: 'sveltejs/action-deploy-docs/dispatch@main'
+ with:
+ repo: 'svelte'
+ branch: 'master'
+ docs_path: 'site/content'
+ token: ${{ steps.github-app.outputs.token }}
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index bddabf688b..911ff19cab 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,6 +8,7 @@ node_modules
/compiler.d.ts
/compiler.*js
/index.*js
+/ssr.*js
/internal
/store
/easing
@@ -30,8 +31,6 @@ _output
/site/static/svelte-app.json
/site/static/contributors.jpg
/site/static/workers
-/site/static/organisations
/site/scripts/svelte-app
/site/scripts/community
/site/src/routes/_contributors.js
-/site/src/routes/_components/WhosUsingSvelte.*
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e1d2fe716b..54a678accb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,149 @@
# Svelte changelog
+## 3.43.0
+
+* Use export map to expose no-op versions of lifecycle functions for SSR ([#6743](https://github.com/sveltejs/svelte/pull/6743))
+* Prefer `context` passed to component constructor, even when running synchronously in another component ([#6753](https://github.com/sveltejs/svelte/issues/6753))
+* Handle preprocessors that return empty sourcemaps ([#6757](https://github.com/sveltejs/svelte/pull/6757))
+
+## 3.42.6
+
+* Hide private preprocess typings ([#6622](https://github.com/sveltejs/svelte/issues/6622))
+* Fix reactive function in `{:else if}` expression not being properly re-run ([#6727](https://github.com/sveltejs/svelte/pull/6727))
+
+## 3.42.5
+
+* In `draw` transition, account for `stroke-linecap` in determining length ([#4540](https://github.com/sveltejs/svelte/issues/4540))
+* Fix regression with destructuring assignments with default values ([#6699](https://github.com/sveltejs/svelte/issues/6699))
+
+## 3.42.4
+
+* Only apply optimized `src` attribute handling when in an `html` namespace ([#6575](https://github.com/sveltejs/svelte/issues/6575))
+* Fix styles for transitions and animations being attached to the wrong `document` in `
-{/if}
+{/if}
\ No newline at end of file
diff --git a/site/content/tutorial/06-bindings/04-group-inputs/app-b/App.svelte b/site/content/tutorial/06-bindings/04-group-inputs/app-b/App.svelte
index a46c61c7e7..d97db41f0b 100644
--- a/site/content/tutorial/06-bindings/04-group-inputs/app-b/App.svelte
+++ b/site/content/tutorial/06-bindings/04-group-inputs/app-b/App.svelte
@@ -17,17 +17,17 @@
Size
-
+
One scoop
-
+
Two scoops
-
+
Three scoops
@@ -35,7 +35,7 @@
{#each menu as flavour}
-
+
{flavour}
{/each}
@@ -49,4 +49,4 @@
You ordered {scoops} {scoops === 1 ? 'scoop' : 'scoops'}
of {join(flavours)}
-{/if}
+{/if}
\ No newline at end of file
diff --git a/site/content/tutorial/06-bindings/04-group-inputs/text.md b/site/content/tutorial/06-bindings/04-group-inputs/text.md
index 97edb8db76..b48b23921f 100644
--- a/site/content/tutorial/06-bindings/04-group-inputs/text.md
+++ b/site/content/tutorial/06-bindings/04-group-inputs/text.md
@@ -7,7 +7,7 @@ If you have multiple inputs relating to the same value, you can use `bind:group`
Add `bind:group` to each input:
```html
-
+
```
In this case, we could make the code simpler by moving the checkbox inputs into an `each` block. First, add a `menu` variable to the `
-
+{@html marked(value)}
-{@html marked(value)}
\ No newline at end of file
+
diff --git a/site/content/tutorial/06-bindings/05-textarea-inputs/app-b/App.svelte b/site/content/tutorial/06-bindings/05-textarea-inputs/app-b/App.svelte
index be338bf47f..f9521d6db6 100644
--- a/site/content/tutorial/06-bindings/05-textarea-inputs/app-b/App.svelte
+++ b/site/content/tutorial/06-bindings/05-textarea-inputs/app-b/App.svelte
@@ -3,10 +3,10 @@
let value = `Some words are *italic*, some are **bold**`;
-
+{@html marked(value)}
-{@html marked(value)}
\ No newline at end of file
+
diff --git a/site/content/tutorial/06-bindings/06-select-bindings/app-a/App.svelte b/site/content/tutorial/06-bindings/06-select-bindings/app-a/App.svelte
index b6f50b935e..a70b928809 100644
--- a/site/content/tutorial/06-bindings/06-select-bindings/app-a/App.svelte
+++ b/site/content/tutorial/06-bindings/06-select-bindings/app-a/App.svelte
@@ -14,10 +14,6 @@
}
-
-
Insecurity questions
-selected question {selected ? selected.id : '[waiting...]'}
\ No newline at end of file
+selected question {selected ? selected.id : '[waiting...]'}
+
+
\ No newline at end of file
diff --git a/site/content/tutorial/06-bindings/06-select-bindings/app-b/App.svelte b/site/content/tutorial/06-bindings/06-select-bindings/app-b/App.svelte
index 3f1e7fa7e1..c584c95b0e 100644
--- a/site/content/tutorial/06-bindings/06-select-bindings/app-b/App.svelte
+++ b/site/content/tutorial/06-bindings/06-select-bindings/app-b/App.svelte
@@ -14,10 +14,6 @@
}
-
-
Insecurity questions
-selected question {selected ? selected.id : '[waiting...]'}
\ No newline at end of file
+selected question {selected ? selected.id : '[waiting...]'}
+
+
\ No newline at end of file
diff --git a/site/content/tutorial/06-bindings/06-select-bindings/text.md b/site/content/tutorial/06-bindings/06-select-bindings/text.md
index f4972557ab..b9cf2de6ec 100644
--- a/site/content/tutorial/06-bindings/06-select-bindings/text.md
+++ b/site/content/tutorial/06-bindings/06-select-bindings/text.md
@@ -2,7 +2,7 @@
title: Select bindings
---
-We can also use `bind:value` with `` elements. Update line 24:
+We can also use `bind:value` with `` elements. Update line 20:
```html
@@ -10,4 +10,4 @@ We can also use `bind:value` with `` elements. Update line 24:
Note that the `` values are objects rather than strings. Svelte doesn't mind.
-> Because we haven't set an initial value of `selected`, the binding will set it to the default value (the first in the list) automatically. Be careful though — until the binding is initialised, `selected` remains undefined, so we can't blindly reference e.g. `selected.id` in the template.
\ No newline at end of file
+> Because we haven't set an initial value of `selected`, the binding will set it to the default value (the first in the list) automatically. Be careful though — until the binding is initialised, `selected` remains undefined, so we can't blindly reference e.g. `selected.id` in the template.
diff --git a/site/content/tutorial/06-bindings/07-multiple-select-bindings/text.md b/site/content/tutorial/06-bindings/07-multiple-select-bindings/text.md
index f6137d3f1d..42263e5ec1 100644
--- a/site/content/tutorial/06-bindings/07-multiple-select-bindings/text.md
+++ b/site/content/tutorial/06-bindings/07-multiple-select-bindings/text.md
@@ -16,4 +16,6 @@ Returning to our [earlier ice cream example](tutorial/group-inputs), we can repl
{/each}
-```
\ No newline at end of file
+```
+
+> Press and hold the `control` key (or the `command` key on MacOS) for selecting multiple options.
diff --git a/site/content/tutorial/06-bindings/09-each-block-bindings/app-a/App.svelte b/site/content/tutorial/06-bindings/09-each-block-bindings/app-a/App.svelte
index 4a2eae9147..b0323eb00a 100644
--- a/site/content/tutorial/06-bindings/09-each-block-bindings/app-a/App.svelte
+++ b/site/content/tutorial/06-bindings/09-each-block-bindings/app-a/App.svelte
@@ -16,12 +16,6 @@
$: remaining = todos.filter(t => !t.done).length;
-
-
Todos
{#each todos as todo}
@@ -47,3 +41,9 @@
Clear completed
+
+
\ No newline at end of file
diff --git a/site/content/tutorial/06-bindings/09-each-block-bindings/app-b/App.svelte b/site/content/tutorial/06-bindings/09-each-block-bindings/app-b/App.svelte
index ff91612ec5..b42cbe3b0a 100644
--- a/site/content/tutorial/06-bindings/09-each-block-bindings/app-b/App.svelte
+++ b/site/content/tutorial/06-bindings/09-each-block-bindings/app-b/App.svelte
@@ -16,12 +16,6 @@
$: remaining = todos.filter(t => !t.done).length;
-
-
Todos
{#each todos as todo}
@@ -47,3 +41,9 @@
Clear completed
+
+
\ No newline at end of file
diff --git a/site/content/tutorial/06-bindings/09-each-block-bindings/text.md b/site/content/tutorial/06-bindings/09-each-block-bindings/text.md
index 7e50966c32..9c352703f1 100644
--- a/site/content/tutorial/06-bindings/09-each-block-bindings/text.md
+++ b/site/content/tutorial/06-bindings/09-each-block-bindings/text.md
@@ -5,15 +5,17 @@ title: Each block bindings
You can even bind to properties inside an `each` block.
```html
-
+{#each todos as todo}
+
-
+
+{/each}
```
-> Note that interacting with these ` ` elements will mutate the array. If you prefer to work with immutable data, you should avoid these bindings and use event handlers instead.
\ No newline at end of file
+> Note that interacting with these ` ` elements will mutate the array. If you prefer to work with immutable data, you should avoid these bindings and use event handlers instead.
diff --git a/site/content/tutorial/06-bindings/10-media-elements/app-a/App.svelte b/site/content/tutorial/06-bindings/10-media-elements/app-a/App.svelte
index 122b2cf9e9..0b3b4f0881 100644
--- a/site/content/tutorial/06-bindings/10-media-elements/app-a/App.svelte
+++ b/site/content/tutorial/06-bindings/10-media-elements/app-a/App.svelte
@@ -7,37 +7,35 @@
let showControls = true;
let showControlsTimeout;
- function handleMousemove(e) {
+ // Used to track time of last mouse down event
+ let lastMouseDown;
+
+ function handleMove(e) {
// Make the controls visible, but fade out after
// 2.5 seconds of inactivity
clearTimeout(showControlsTimeout);
showControlsTimeout = setTimeout(() => showControls = false, 2500);
showControls = true;
- if (!(e.buttons & 1)) return; // mouse not down
if (!duration) return; // video not loaded yet
+ if (e.type !== 'touchmove' && !(e.buttons & 1)) return; // mouse not down
+ const clientX = e.type === 'touchmove' ? e.touches[0].clientX : e.clientX;
const { left, right } = this.getBoundingClientRect();
- time = duration * (e.clientX - left) / (right - left);
+ time = duration * (clientX - left) / (right - left);
}
+ // we can't rely on the built-in click event, because it fires
+ // after a drag — we have to listen for clicks ourselves
function handleMousedown(e) {
- // we can't rely on the built-in click event, because it fires
- // after a drag — we have to listen for clicks ourselves
+ lastMouseDown = new Date();
+ }
- function handleMouseup() {
+ function handleMouseup(e) {
+ if (new Date() - lastMouseDown < 300) {
if (paused) e.target.play();
else e.target.pause();
- cancel();
- }
-
- function cancel() {
- e.target.removeEventListener('mouseup', handleMouseup);
}
-
- e.target.addEventListener('mouseup', handleMouseup);
-
- setTimeout(cancel, 200);
}
function format(seconds) {
@@ -51,6 +49,31 @@
}
+Caminandes: Llamigos
+From Blender Open Projects . CC-BY
+
+
+
+
+
+
+
+
+
+
+ {format(time)}
+ click anywhere to {paused ? 'play' : 'pause'} / drag to seek
+ {format(duration)}
+
+
+
+
-
-Caminandes: Llamigos
-From Blender Open Projects . CC-BY
-
-
-
-
-
-
-
-
-
-
- {format(time)}
- click anywhere to {paused ? 'play' : 'pause'} / drag to seek
- {format(duration)}
-
-
-
diff --git a/site/content/tutorial/06-bindings/10-media-elements/app-b/App.svelte b/site/content/tutorial/06-bindings/10-media-elements/app-b/App.svelte
index 6135105d6a..e6a0635a12 100644
--- a/site/content/tutorial/06-bindings/10-media-elements/app-b/App.svelte
+++ b/site/content/tutorial/06-bindings/10-media-elements/app-b/App.svelte
@@ -7,37 +7,35 @@
let showControls = true;
let showControlsTimeout;
- function handleMousemove(e) {
+ // Used to track time of last mouse down event
+ let lastMouseDown;
+
+ function handleMove(e) {
// Make the controls visible, but fade out after
// 2.5 seconds of inactivity
clearTimeout(showControlsTimeout);
showControlsTimeout = setTimeout(() => showControls = false, 2500);
showControls = true;
- if (!(e.buttons & 1)) return; // mouse not down
if (!duration) return; // video not loaded yet
+ if (e.type !== 'touchmove' && !(e.buttons & 1)) return; // mouse not down
+ const clientX = e.type === 'touchmove' ? e.touches[0].clientX : e.clientX;
const { left, right } = this.getBoundingClientRect();
- time = duration * (e.clientX - left) / (right - left);
+ time = duration * (clientX - left) / (right - left);
}
+ // we can't rely on the built-in click event, because it fires
+ // after a drag — we have to listen for clicks ourselves
function handleMousedown(e) {
- // we can't rely on the built-in click event, because it fires
- // after a drag — we have to listen for clicks ourselves
+ lastMouseDown = new Date();
+ }
- function handleMouseup() {
+ function handleMouseup(e) {
+ if (new Date() - lastMouseDown < 300) {
if (paused) e.target.play();
else e.target.pause();
- cancel();
- }
-
- function cancel() {
- e.target.removeEventListener('mouseup', handleMouseup);
}
-
- e.target.addEventListener('mouseup', handleMouseup);
-
- setTimeout(cancel, 200);
}
function format(seconds) {
@@ -51,6 +49,34 @@
}
+Caminandes: Llamigos
+From Blender Open Projects . CC-BY
+
+
+
+
+
+
+
+
+
+
+ {format(time)}
+ click anywhere to {paused ? 'play' : 'pause'} / drag to seek
+ {format(duration)}
+
+
+
+
-
-Caminandes: Llamigos
-From Blender Open Projects . CC-BY
-
-
-
-
-
-
-
-
-
-
- {format(time)}
- click anywhere to {paused ? 'play' : 'pause'} / drag to seek
- {format(duration)}
-
-
-
\ No newline at end of file
diff --git a/site/content/tutorial/06-bindings/10-media-elements/text.md b/site/content/tutorial/06-bindings/10-media-elements/text.md
index 0a854f19e9..b63c5368ff 100644
--- a/site/content/tutorial/06-bindings/10-media-elements/text.md
+++ b/site/content/tutorial/06-bindings/10-media-elements/text.md
@@ -4,18 +4,21 @@ title: Media elements
The `` and `` elements have several properties that you can bind to. This example demonstrates a few of them.
-On line 116, add `currentTime={time}`, `duration` and `paused` bindings:
+On line 62, add `currentTime={time}`, `duration` and `paused` bindings:
```html
+ bind:paused>
+
+
```
> `bind:duration` is equivalent to `bind:duration={duration}`
@@ -41,4 +44,4 @@ The complete set of bindings for `` and `` is as follows — six *
* `volume` — a value between 0 and 1
* `muted` — a boolean value where true is muted
-Videos additionally have readonly `videoWidth` and `videoHeight` bindings.
\ No newline at end of file
+Videos additionally have readonly `videoWidth` and `videoHeight` bindings.
diff --git a/site/content/tutorial/06-bindings/11-dimensions/app-a/App.svelte b/site/content/tutorial/06-bindings/11-dimensions/app-a/App.svelte
index 62e92cd536..67bb5db8af 100644
--- a/site/content/tutorial/06-bindings/11-dimensions/app-a/App.svelte
+++ b/site/content/tutorial/06-bindings/11-dimensions/app-a/App.svelte
@@ -5,12 +5,6 @@
let text = 'edit me';
-
-
@@ -18,4 +12,10 @@
{text}
-
\ No newline at end of file
+
+
+
\ No newline at end of file
diff --git a/site/content/tutorial/06-bindings/11-dimensions/app-b/App.svelte b/site/content/tutorial/06-bindings/11-dimensions/app-b/App.svelte
index 920c74d276..fbed44dadc 100644
--- a/site/content/tutorial/06-bindings/11-dimensions/app-b/App.svelte
+++ b/site/content/tutorial/06-bindings/11-dimensions/app-b/App.svelte
@@ -5,12 +5,6 @@
let text = 'edit me';
-
-
@@ -18,4 +12,10 @@
{text}
-
\ No newline at end of file
+
+
+
\ No newline at end of file
diff --git a/site/content/tutorial/06-bindings/12-bind-this/app-a/App.svelte b/site/content/tutorial/06-bindings/12-bind-this/app-a/App.svelte
index f8f93edc2b..cf08455942 100644
--- a/site/content/tutorial/06-bindings/12-bind-this/app-a/App.svelte
+++ b/site/content/tutorial/06-bindings/12-bind-this/app-a/App.svelte
@@ -15,7 +15,7 @@
for (let p = 0; p < imageData.data.length; p += 4) {
const i = p / 4;
const x = i % canvas.width;
- const y = i / canvas.height >>> 0;
+ const y = i / canvas.width >>> 0;
const r = 64 + (128 * x / canvas.width) + (64 * Math.sin(t / 1000));
const g = 64 + (128 * y / canvas.height) + (64 * Math.cos(t / 1000));
@@ -36,6 +36,11 @@
});
+
+
-
-
diff --git a/site/content/tutorial/06-bindings/12-bind-this/app-b/App.svelte b/site/content/tutorial/06-bindings/12-bind-this/app-b/App.svelte
index 17005e273a..0e53c533ac 100644
--- a/site/content/tutorial/06-bindings/12-bind-this/app-b/App.svelte
+++ b/site/content/tutorial/06-bindings/12-bind-this/app-b/App.svelte
@@ -15,7 +15,7 @@
for (let p = 0; p < imageData.data.length; p += 4) {
const i = p / 4;
const x = i % canvas.width;
- const y = i / canvas.height >>> 0;
+ const y = i / canvas.width >>> 0;
const r = 64 + (128 * x / canvas.width) + (64 * Math.sin(t / 1000));
const g = 64 + (128 * y / canvas.height) + (64 * Math.cos(t / 1000));
@@ -36,6 +36,12 @@
});
+
+
-
-
diff --git a/site/content/tutorial/06-bindings/13-component-bindings/app-a/Keypad.svelte b/site/content/tutorial/06-bindings/13-component-bindings/app-a/Keypad.svelte
index c457a15cb5..631f7964e2 100644
--- a/site/content/tutorial/06-bindings/13-component-bindings/app-a/Keypad.svelte
+++ b/site/content/tutorial/06-bindings/13-component-bindings/app-a/Keypad.svelte
@@ -10,19 +10,6 @@
const submit = () => dispatch('submit');
-
-
1
2
@@ -37,4 +24,17 @@
clear
0
submit
-
\ No newline at end of file
+
+
+
\ No newline at end of file
diff --git a/site/content/tutorial/06-bindings/13-component-bindings/app-b/Keypad.svelte b/site/content/tutorial/06-bindings/13-component-bindings/app-b/Keypad.svelte
index c457a15cb5..631f7964e2 100644
--- a/site/content/tutorial/06-bindings/13-component-bindings/app-b/Keypad.svelte
+++ b/site/content/tutorial/06-bindings/13-component-bindings/app-b/Keypad.svelte
@@ -10,19 +10,6 @@
const submit = () => dispatch('submit');
-
-
1
2
@@ -37,4 +24,17 @@
clear
0
submit
-
\ No newline at end of file
+
+
+
\ No newline at end of file
diff --git a/site/content/tutorial/06-bindings/14-component-this/app-a/App.svelte b/site/content/tutorial/06-bindings/14-component-this/app-a/App.svelte
new file mode 100644
index 0000000000..41a6a10d3d
--- /dev/null
+++ b/site/content/tutorial/06-bindings/14-component-this/app-a/App.svelte
@@ -0,0 +1,5 @@
+
+
+
diff --git a/site/content/tutorial/06-bindings/14-component-this/app-a/InputField.svelte b/site/content/tutorial/06-bindings/14-component-this/app-a/InputField.svelte
new file mode 100644
index 0000000000..e2b04b93ed
--- /dev/null
+++ b/site/content/tutorial/06-bindings/14-component-this/app-a/InputField.svelte
@@ -0,0 +1,9 @@
+
+
+
\ No newline at end of file
diff --git a/site/content/tutorial/06-bindings/14-component-this/app-b/App.svelte b/site/content/tutorial/06-bindings/14-component-this/app-b/App.svelte
new file mode 100644
index 0000000000..f14332b398
--- /dev/null
+++ b/site/content/tutorial/06-bindings/14-component-this/app-b/App.svelte
@@ -0,0 +1,9 @@
+
+
+
+
+ field.focus()}>Focus field
diff --git a/site/content/tutorial/06-bindings/14-component-this/app-b/InputField.svelte b/site/content/tutorial/06-bindings/14-component-this/app-b/InputField.svelte
new file mode 100644
index 0000000000..e2b04b93ed
--- /dev/null
+++ b/site/content/tutorial/06-bindings/14-component-this/app-b/InputField.svelte
@@ -0,0 +1,9 @@
+
+
+
\ No newline at end of file
diff --git a/site/content/tutorial/06-bindings/14-component-this/text.md b/site/content/tutorial/06-bindings/14-component-this/text.md
new file mode 100644
index 0000000000..00af193604
--- /dev/null
+++ b/site/content/tutorial/06-bindings/14-component-this/text.md
@@ -0,0 +1,19 @@
+---
+title: Binding to component instances
+---
+
+Just as you can bind to DOM elements, you can bind to component instances themselves. For example, we can bind the instance of `` to a prop named `field` in the same way we did when binding DOM Elements
+
+```html
+
+```
+
+Now we can programmatically interact with this component using `field`.
+
+```html
+
+ Focus field
+
+```
+
+> Note that we can't do `{field.focus}` since field is undefined when the button is first rendered and throws an error.
\ No newline at end of file
diff --git a/site/content/tutorial/07-lifecycle/01-onmount/app-a/App.svelte b/site/content/tutorial/07-lifecycle/01-onmount/app-a/App.svelte
index e8306d1957..f76c377ad3 100644
--- a/site/content/tutorial/07-lifecycle/01-onmount/app-a/App.svelte
+++ b/site/content/tutorial/07-lifecycle/01-onmount/app-a/App.svelte
@@ -2,20 +2,6 @@
let photos = [];
-
-
Photo album
@@ -28,4 +14,18 @@
loading...
{/each}
-
\ No newline at end of file
+
+
+
\ No newline at end of file
diff --git a/site/content/tutorial/07-lifecycle/01-onmount/app-b/App.svelte b/site/content/tutorial/07-lifecycle/01-onmount/app-b/App.svelte
index 1b83727627..831914fa6a 100644
--- a/site/content/tutorial/07-lifecycle/01-onmount/app-b/App.svelte
+++ b/site/content/tutorial/07-lifecycle/01-onmount/app-b/App.svelte
@@ -9,20 +9,6 @@
});
-
-
Photo album
@@ -35,4 +21,18 @@
loading...
{/each}
-
\ No newline at end of file
+
+
+
\ No newline at end of file
diff --git a/site/content/tutorial/07-lifecycle/02-ondestroy/app-a/App.svelte b/site/content/tutorial/07-lifecycle/02-ondestroy/app-a/App.svelte
index 28cdb73d0d..8fdca8d81d 100644
--- a/site/content/tutorial/07-lifecycle/02-ondestroy/app-a/App.svelte
+++ b/site/content/tutorial/07-lifecycle/02-ondestroy/app-a/App.svelte
@@ -1,10 +1,20 @@
-
- The page has been open for
- {seconds} {seconds === 1 ? 'second' : 'seconds'}
-
\ No newline at end of file
+
+
{open ? 'Close' : 'Open'} Timer
+
+ The Timer component has been open for
+ {seconds} {seconds === 1 ? 'second' : 'seconds'}
+
+ {#if open}
+
+ {/if}
+
diff --git a/site/content/tutorial/07-lifecycle/02-ondestroy/app-a/Timer.svelte b/site/content/tutorial/07-lifecycle/02-ondestroy/app-a/Timer.svelte
new file mode 100644
index 0000000000..0eb5a7461d
--- /dev/null
+++ b/site/content/tutorial/07-lifecycle/02-ondestroy/app-a/Timer.svelte
@@ -0,0 +1,20 @@
+
+
+
+ This component executes a callback every
+ {interval} millisecond{interval === 1 ? '' : 's'}
+
+
+
diff --git a/site/content/tutorial/07-lifecycle/02-ondestroy/app-a/utils.js b/site/content/tutorial/07-lifecycle/02-ondestroy/app-a/utils.js
index 7b65e75c8c..64ab7e50c7 100644
--- a/site/content/tutorial/07-lifecycle/02-ondestroy/app-a/utils.js
+++ b/site/content/tutorial/07-lifecycle/02-ondestroy/app-a/utils.js
@@ -1,5 +1,9 @@
import { onDestroy } from 'svelte';
export function onInterval(callback, milliseconds) {
- // implementation goes here
+ const interval = setInterval(callback, milliseconds);
+
+ onDestroy(() => {
+ // Fix the memory leak here
+ });
}
\ No newline at end of file
diff --git a/site/content/tutorial/07-lifecycle/02-ondestroy/app-b/App.svelte b/site/content/tutorial/07-lifecycle/02-ondestroy/app-b/App.svelte
index 93a721ef44..49936b6617 100644
--- a/site/content/tutorial/07-lifecycle/02-ondestroy/app-b/App.svelte
+++ b/site/content/tutorial/07-lifecycle/02-ondestroy/app-b/App.svelte
@@ -1,11 +1,20 @@
-
- The page has been open for
- {seconds} {seconds === 1 ? 'second' : 'seconds'}
-
\ No newline at end of file
+
+
{open ? 'Close' : 'Open'} Timer
+
+ The Timer component has been open for
+ {seconds} {seconds === 1 ? 'second' : 'seconds'}
+
+ {#if open}
+
+ {/if}
+
diff --git a/site/content/tutorial/07-lifecycle/02-ondestroy/app-b/Timer.svelte b/site/content/tutorial/07-lifecycle/02-ondestroy/app-b/Timer.svelte
new file mode 100644
index 0000000000..0eb5a7461d
--- /dev/null
+++ b/site/content/tutorial/07-lifecycle/02-ondestroy/app-b/Timer.svelte
@@ -0,0 +1,20 @@
+
+
+
+ This component executes a callback every
+ {interval} millisecond{interval === 1 ? '' : 's'}
+
+
+
diff --git a/site/content/tutorial/07-lifecycle/02-ondestroy/text.md b/site/content/tutorial/07-lifecycle/02-ondestroy/text.md
index 647fbaa160..34bbf83cbf 100644
--- a/site/content/tutorial/07-lifecycle/02-ondestroy/text.md
+++ b/site/content/tutorial/07-lifecycle/02-ondestroy/text.md
@@ -10,8 +10,8 @@ For example, we can add a `setInterval` function when our component initialises,
@@ -37,7 +37,9 @@ export function onInterval(callback, milliseconds) {
-```
\ No newline at end of file
+```
+
+Open and close the timer a few times and make sure the counter keeps ticking and the CPU load increases. This is due to a memory leak as the previous timers are not deleted. Don't forget to refresh the page before solving the example.
\ No newline at end of file
diff --git a/site/content/tutorial/08-stores/01-writable-stores/app-a/App.svelte b/site/content/tutorial/08-stores/01-writable-stores/app-a/App.svelte
index ee542f789d..f2a4023f25 100644
--- a/site/content/tutorial/08-stores/01-writable-stores/app-a/App.svelte
+++ b/site/content/tutorial/08-stores/01-writable-stores/app-a/App.svelte
@@ -6,7 +6,7 @@
let count_value;
- const unsubscribe = count.subscribe(value => {
+ count.subscribe(value => {
count_value = value;
});
@@ -15,4 +15,4 @@
-
\ No newline at end of file
+
diff --git a/site/content/tutorial/08-stores/01-writable-stores/text.md b/site/content/tutorial/08-stores/01-writable-stores/text.md
index 57c27411ea..247ef86e8d 100644
--- a/site/content/tutorial/08-stores/01-writable-stores/text.md
+++ b/site/content/tutorial/08-stores/01-writable-stores/text.md
@@ -24,4 +24,4 @@ Finally, in `Resetter.svelte`, implement `reset`:
function reset() {
count.set(0);
}
-```
\ No newline at end of file
+```
diff --git a/site/content/tutorial/08-stores/02-auto-subscriptions/app-a/App.svelte b/site/content/tutorial/08-stores/02-auto-subscriptions/app-a/App.svelte
index ee542f789d..f2a4023f25 100644
--- a/site/content/tutorial/08-stores/02-auto-subscriptions/app-a/App.svelte
+++ b/site/content/tutorial/08-stores/02-auto-subscriptions/app-a/App.svelte
@@ -6,7 +6,7 @@
let count_value;
- const unsubscribe = count.subscribe(value => {
+ count.subscribe(value => {
count_value = value;
});
@@ -15,4 +15,4 @@
-
\ No newline at end of file
+
diff --git a/site/content/tutorial/08-stores/02-auto-subscriptions/text.md b/site/content/tutorial/08-stores/02-auto-subscriptions/text.md
index af584261f4..27d3251c6e 100644
--- a/site/content/tutorial/08-stores/02-auto-subscriptions/text.md
+++ b/site/content/tutorial/08-stores/02-auto-subscriptions/text.md
@@ -2,9 +2,18 @@
title: Auto-subscriptions
---
-The app in the previous example works, but there's a subtle bug — the `unsubscribe` function never gets called. If the component was instantiated and destroyed many times, this would result in a *memory leak*.
+The app in the previous example works, but there's a subtle bug — the store is subscribed to, but never unsubscribed. If the component was instantiated and destroyed many times, this would result in a *memory leak*.
-One way to fix it would be to use the `onDestroy` [lifecycle hook](tutorial/ondestroy):
+Start by declaring `unsubscribe` in `App.svelte`:
+
+```js
+const unsubscribe = count.subscribe(value => {
+ count_value = value;
+});
+```
+> Calling a `subscribe` method returns an `unsubscribe` function.
+
+You now declared `unsubscribe`, but it still needs to be called, for example through the `onDestroy` [lifecycle hook](tutorial/ondestroy):
```html
-
-
@@ -31,4 +24,11 @@
100%
-
\ No newline at end of file
+
+
+
\ No newline at end of file
diff --git a/site/content/tutorial/09-motion/01-tweened/app-b/App.svelte b/site/content/tutorial/09-motion/01-tweened/app-b/App.svelte
index 83f3b50a04..ee3c7a1b5d 100644
--- a/site/content/tutorial/09-motion/01-tweened/app-b/App.svelte
+++ b/site/content/tutorial/09-motion/01-tweened/app-b/App.svelte
@@ -8,13 +8,6 @@
});
-
-
@@ -35,4 +28,11 @@
100%
-
\ No newline at end of file
+
+
+
\ No newline at end of file
diff --git a/site/content/tutorial/09-motion/02-spring/app-a/App.svelte b/site/content/tutorial/09-motion/02-spring/app-a/App.svelte
index 813c6366b1..aa8a406c2b 100644
--- a/site/content/tutorial/09-motion/02-spring/app-a/App.svelte
+++ b/site/content/tutorial/09-motion/02-spring/app-a/App.svelte
@@ -5,11 +5,6 @@
let size = writable(10);
-
-
stiffness ({coords.stiffness})
@@ -28,4 +23,15 @@
on:mouseup="{() => size.set(10)}"
>
-
\ No newline at end of file
+
+
+
\ No newline at end of file
diff --git a/site/content/tutorial/09-motion/02-spring/app-b/App.svelte b/site/content/tutorial/09-motion/02-spring/app-b/App.svelte
index 2cb0fd1eb7..d8a0287c2c 100644
--- a/site/content/tutorial/09-motion/02-spring/app-b/App.svelte
+++ b/site/content/tutorial/09-motion/02-spring/app-b/App.svelte
@@ -9,11 +9,6 @@
let size = spring(10);
-
-
stiffness ({coords.stiffness})
@@ -32,4 +27,14 @@
on:mouseup="{() => size.set(10)}"
>
-
\ No newline at end of file
+
+
+
\ No newline at end of file
diff --git a/site/content/tutorial/10-transitions/04-custom-css-transitions/app-a/App.svelte b/site/content/tutorial/10-transitions/04-custom-css-transitions/app-a/App.svelte
index d1f044360d..872c2e4aa3 100644
--- a/site/content/tutorial/10-transitions/04-custom-css-transitions/app-a/App.svelte
+++ b/site/content/tutorial/10-transitions/04-custom-css-transitions/app-a/App.svelte
@@ -11,6 +11,17 @@
}
+
+
+ visible
+
+
+{#if visible}
+
+ transitions!
+
+{/if}
+
-
-
-
- visible
-
-
-{#if visible}
-
- transitions!
-
-{/if}
\ No newline at end of file
+
\ No newline at end of file
diff --git a/site/content/tutorial/10-transitions/04-custom-css-transitions/app-b/App.svelte b/site/content/tutorial/10-transitions/04-custom-css-transitions/app-b/App.svelte
index 6e8dfcaf08..a98f38272a 100644
--- a/site/content/tutorial/10-transitions/04-custom-css-transitions/app-b/App.svelte
+++ b/site/content/tutorial/10-transitions/04-custom-css-transitions/app-b/App.svelte
@@ -22,6 +22,17 @@
}
+
+
+ visible
+
+
+{#if visible}
+
+ transitions!
+
+{/if}
+
-
-
-
- visible
-
-
-{#if visible}
-
- transitions!
-
-{/if}
\ No newline at end of file
+
\ No newline at end of file
diff --git a/site/content/tutorial/10-transitions/05-custom-js-transitions/app-b/App.svelte b/site/content/tutorial/10-transitions/05-custom-js-transitions/app-b/App.svelte
index 396c793639..5e1ad9863c 100644
--- a/site/content/tutorial/10-transitions/05-custom-js-transitions/app-b/App.svelte
+++ b/site/content/tutorial/10-transitions/05-custom-js-transitions/app-b/App.svelte
@@ -1,7 +1,7 @@
-
-
show list
@@ -29,4 +22,11 @@
{item}
{/each}
-{/if}
\ No newline at end of file
+{/if}
+
+
\ No newline at end of file
diff --git a/site/content/tutorial/10-transitions/07-local-transitions/app-b/App.svelte b/site/content/tutorial/10-transitions/07-local-transitions/app-b/App.svelte
index 3d569cfcbb..46603a8b53 100644
--- a/site/content/tutorial/10-transitions/07-local-transitions/app-b/App.svelte
+++ b/site/content/tutorial/10-transitions/07-local-transitions/app-b/App.svelte
@@ -6,13 +6,6 @@
let items = ['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten'];
-
-
show list
@@ -29,4 +22,11 @@
{item}
{/each}
-{/if}
\ No newline at end of file
+{/if}
+
+
\ No newline at end of file
diff --git a/site/content/tutorial/10-transitions/08-deferred-transitions/app-a/App.svelte b/site/content/tutorial/10-transitions/08-deferred-transitions/app-a/App.svelte
index f05c581390..3b6c6776a6 100644
--- a/site/content/tutorial/10-transitions/08-deferred-transitions/app-a/App.svelte
+++ b/site/content/tutorial/10-transitions/08-deferred-transitions/app-a/App.svelte
@@ -145,4 +145,4 @@
label:hover button {
opacity: 1;
}
-
+
\ No newline at end of file
diff --git a/site/content/tutorial/10-transitions/08-deferred-transitions/app-b/App.svelte b/site/content/tutorial/10-transitions/08-deferred-transitions/app-b/App.svelte
index b7447ca7de..f3a26915a3 100644
--- a/site/content/tutorial/10-transitions/08-deferred-transitions/app-b/App.svelte
+++ b/site/content/tutorial/10-transitions/08-deferred-transitions/app-b/App.svelte
@@ -152,4 +152,4 @@
label:hover button {
opacity: 1;
}
-
+
\ No newline at end of file
diff --git a/site/content/tutorial/10-transitions/09-key-blocks/app-a/App.svelte b/site/content/tutorial/10-transitions/09-key-blocks/app-a/App.svelte
new file mode 100644
index 0000000000..3385a02339
--- /dev/null
+++ b/site/content/tutorial/10-transitions/09-key-blocks/app-a/App.svelte
@@ -0,0 +1,19 @@
+
+
+
+ The number is:
+
+ {number}
+
+
+
+ {
+ number += 1;
+ }}>
+ Increment
+
diff --git a/site/content/tutorial/10-transitions/09-key-blocks/app-b/App.svelte b/site/content/tutorial/10-transitions/09-key-blocks/app-b/App.svelte
new file mode 100644
index 0000000000..0e40dc57d1
--- /dev/null
+++ b/site/content/tutorial/10-transitions/09-key-blocks/app-b/App.svelte
@@ -0,0 +1,21 @@
+
+
+
+ The number is:
+ {#key number}
+
+ {number}
+
+ {/key}
+
+
+ {
+ number += 1;
+ }}>
+ Increment
+
diff --git a/site/content/tutorial/10-transitions/09-key-blocks/text.md b/site/content/tutorial/10-transitions/09-key-blocks/text.md
new file mode 100644
index 0000000000..05a54d592a
--- /dev/null
+++ b/site/content/tutorial/10-transitions/09-key-blocks/text.md
@@ -0,0 +1,16 @@
+---
+title: Key blocks
+---
+
+Key blocks destroy and recreate their contents when the value of an expression changes.
+
+```html
+{#key value}
+ {value}
+{/key}
+```
+
+This is useful if you want an element to play its transition whenever a value changes instead of only when the element enters or leaves the DOM.
+
+Wrap the `` element in a key block depending on `number`. This will make the
+animation play whenever you press the increment button.
diff --git a/site/content/tutorial/11-animations/01-animate/app-a/App.svelte b/site/content/tutorial/11-animations/01-animate/app-a/App.svelte
index b7447ca7de..f3a26915a3 100644
--- a/site/content/tutorial/11-animations/01-animate/app-a/App.svelte
+++ b/site/content/tutorial/11-animations/01-animate/app-a/App.svelte
@@ -152,4 +152,4 @@
label:hover button {
opacity: 1;
}
-
+
\ No newline at end of file
diff --git a/site/content/tutorial/11-animations/01-animate/app-b/App.svelte b/site/content/tutorial/11-animations/01-animate/app-b/App.svelte
index 0d232bf02b..5c5e76331d 100644
--- a/site/content/tutorial/11-animations/01-animate/app-b/App.svelte
+++ b/site/content/tutorial/11-animations/01-animate/app-b/App.svelte
@@ -155,4 +155,4 @@
label:hover button {
opacity: 1;
}
-
+
\ No newline at end of file
diff --git a/site/content/tutorial/13-classes/01-classes/app-a/App.svelte b/site/content/tutorial/13-classes/01-classes/app-a/App.svelte
index baa2543562..f0db8b3214 100644
--- a/site/content/tutorial/13-classes/01-classes/app-a/App.svelte
+++ b/site/content/tutorial/13-classes/01-classes/app-a/App.svelte
@@ -2,17 +2,6 @@
let current = 'foo';
-
-
baz
\ No newline at end of file
+>baz
+
+
\ No newline at end of file
diff --git a/site/content/tutorial/13-classes/01-classes/app-b/App.svelte b/site/content/tutorial/13-classes/01-classes/app-b/App.svelte
index a8861ad537..00851567ef 100644
--- a/site/content/tutorial/13-classes/01-classes/app-b/App.svelte
+++ b/site/content/tutorial/13-classes/01-classes/app-b/App.svelte
@@ -2,17 +2,6 @@
let current = 'foo';
-
-
baz
\ No newline at end of file
+>baz
+
+
\ No newline at end of file
diff --git a/site/content/tutorial/13-classes/02-class-shorthand/app-a/App.svelte b/site/content/tutorial/13-classes/02-class-shorthand/app-a/App.svelte
index 5ff6497230..d944a63313 100644
--- a/site/content/tutorial/13-classes/02-class-shorthand/app-a/App.svelte
+++ b/site/content/tutorial/13-classes/02-class-shorthand/app-a/App.svelte
@@ -2,12 +2,6 @@
let big = false;
-
-
big
@@ -15,4 +9,10 @@
some {big ? 'big' : 'small'} text
-
\ No newline at end of file
+
+
+
\ No newline at end of file
diff --git a/site/content/tutorial/13-classes/02-class-shorthand/app-b/App.svelte b/site/content/tutorial/13-classes/02-class-shorthand/app-b/App.svelte
index 0f4e0d9f24..c91385e4e5 100644
--- a/site/content/tutorial/13-classes/02-class-shorthand/app-b/App.svelte
+++ b/site/content/tutorial/13-classes/02-class-shorthand/app-b/App.svelte
@@ -2,12 +2,6 @@
let big = false;
-
-
big
@@ -15,4 +9,10 @@
some {big ? 'big' : 'small'} text
-
\ No newline at end of file
+
+
+
\ No newline at end of file
diff --git a/site/content/tutorial/14-composition/01-slots/app-a/Box.svelte b/site/content/tutorial/14-composition/01-slots/app-a/Box.svelte
index 62f0b92dc0..e199b8ce81 100644
--- a/site/content/tutorial/14-composition/01-slots/app-a/Box.svelte
+++ b/site/content/tutorial/14-composition/01-slots/app-a/Box.svelte
@@ -1,3 +1,7 @@
+
+
+
+
-
-
-
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/site/content/tutorial/14-composition/01-slots/app-b/Box.svelte b/site/content/tutorial/14-composition/01-slots/app-b/Box.svelte
index 7ed13f386f..b17fdbe60d 100644
--- a/site/content/tutorial/14-composition/01-slots/app-b/Box.svelte
+++ b/site/content/tutorial/14-composition/01-slots/app-b/Box.svelte
@@ -1,3 +1,7 @@
+
+
+
+
-
-
-
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/site/content/tutorial/14-composition/02-slot-fallbacks/app-a/Box.svelte b/site/content/tutorial/14-composition/02-slot-fallbacks/app-a/Box.svelte
index 7ed13f386f..b17fdbe60d 100644
--- a/site/content/tutorial/14-composition/02-slot-fallbacks/app-a/Box.svelte
+++ b/site/content/tutorial/14-composition/02-slot-fallbacks/app-a/Box.svelte
@@ -1,3 +1,7 @@
+
+
+
+
-
-
-
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/site/content/tutorial/14-composition/02-slot-fallbacks/app-b/Box.svelte b/site/content/tutorial/14-composition/02-slot-fallbacks/app-b/Box.svelte
index 66c580632c..bdaf61b874 100644
--- a/site/content/tutorial/14-composition/02-slot-fallbacks/app-b/Box.svelte
+++ b/site/content/tutorial/14-composition/02-slot-fallbacks/app-b/Box.svelte
@@ -1,3 +1,9 @@
+
+
+ no content was provided
+
+
+
-
-
-
- no content was provided
-
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/site/content/tutorial/14-composition/03-named-slots/app-a/ContactCard.svelte b/site/content/tutorial/14-composition/03-named-slots/app-a/ContactCard.svelte
index c09404a282..4d8ba30e75 100644
--- a/site/content/tutorial/14-composition/03-named-slots/app-a/ContactCard.svelte
+++ b/site/content/tutorial/14-composition/03-named-slots/app-a/ContactCard.svelte
@@ -1,3 +1,23 @@
+
+
+
+ Unknown name
+
+
+
+
+
+ Unknown address
+
+
+
+
+
+ Unknown email
+
+
+
+
-
-
-
-
- Unknown name
-
-
-
-
-
- Unknown address
-
-
-
-
-
- Unknown email
-
-
-
\ No newline at end of file
+ .address {
+ background-image: url(tutorial/icons/map-marker.svg);
+ }
+ .email {
+ background-image: url(tutorial/icons/email.svg);
+ }
+ .missing {
+ color: #999;
+ }
+
\ No newline at end of file
diff --git a/site/content/tutorial/14-composition/03-named-slots/app-b/ContactCard.svelte b/site/content/tutorial/14-composition/03-named-slots/app-b/ContactCard.svelte
index 1acf290943..0348b70c55 100644
--- a/site/content/tutorial/14-composition/03-named-slots/app-b/ContactCard.svelte
+++ b/site/content/tutorial/14-composition/03-named-slots/app-b/ContactCard.svelte
@@ -1,3 +1,23 @@
+
+
+
+ Unknown name
+
+
+
+
+
+ Unknown address
+
+
+
+
+
+ Unknown email
+
+
+
+
-
-
-
-
- Unknown name
-
-
-
-
-
- Unknown address
-
-
-
-
-
- Unknown email
-
-
-
\ No newline at end of file
+ .address {
+ background-image: url(tutorial/icons/map-marker.svg);
+ }
+ .email {
+ background-image: url(tutorial/icons/email.svg);
+ }
+ .missing {
+ color: #999;
+ }
+
\ No newline at end of file
diff --git a/site/content/tutorial/14-composition/04-optional-slots/app-a/App.svelte b/site/content/tutorial/14-composition/04-optional-slots/app-a/App.svelte
index 80a4df59f8..19537cb4b3 100755
--- a/site/content/tutorial/14-composition/04-optional-slots/app-a/App.svelte
+++ b/site/content/tutorial/14-composition/04-optional-slots/app-a/App.svelte
@@ -3,32 +3,6 @@
import Comment from './Comment.svelte'
-
-
Projects
@@ -55,3 +29,29 @@
/>
+
+
\ No newline at end of file
diff --git a/site/content/tutorial/14-composition/04-optional-slots/app-a/Comment.svelte b/site/content/tutorial/14-composition/04-optional-slots/app-a/Comment.svelte
index 8d15ffa882..b3c10febf5 100755
--- a/site/content/tutorial/14-composition/04-optional-slots/app-a/Comment.svelte
+++ b/site/content/tutorial/14-composition/04-optional-slots/app-a/Comment.svelte
@@ -5,6 +5,19 @@
$: avatar = `https://ui-avatars.com/api/?name=${name.replace(/ /g, '+')}&rounded=true&background=ff3e00&color=fff&bold=true`;
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
\ No newline at end of file
diff --git a/site/content/tutorial/14-composition/04-optional-slots/app-a/Project.svelte b/site/content/tutorial/14-composition/04-optional-slots/app-a/Project.svelte
index 38d19fc638..2d98458966 100755
--- a/site/content/tutorial/14-composition/04-optional-slots/app-a/Project.svelte
+++ b/site/content/tutorial/14-composition/04-optional-slots/app-a/Project.svelte
@@ -4,6 +4,17 @@
export let totalTasks = 0;
+
+
+
{title}
+
{tasksCompleted}/{totalTasks} tasks completed
+
+
+
Comments
+
+
+
+
-
-
-
-
{title}
-
{tasksCompleted}/{totalTasks} tasks completed
-
-
-
Comments
-
-
-
+
\ No newline at end of file
diff --git a/site/content/tutorial/14-composition/04-optional-slots/app-b/App.svelte b/site/content/tutorial/14-composition/04-optional-slots/app-b/App.svelte
index 80a4df59f8..19537cb4b3 100755
--- a/site/content/tutorial/14-composition/04-optional-slots/app-b/App.svelte
+++ b/site/content/tutorial/14-composition/04-optional-slots/app-b/App.svelte
@@ -3,32 +3,6 @@
import Comment from './Comment.svelte'
-
-
Projects
@@ -55,3 +29,29 @@
/>
+
+
\ No newline at end of file
diff --git a/site/content/tutorial/14-composition/04-optional-slots/app-b/Comment.svelte b/site/content/tutorial/14-composition/04-optional-slots/app-b/Comment.svelte
index 8d15ffa882..b3c10febf5 100755
--- a/site/content/tutorial/14-composition/04-optional-slots/app-b/Comment.svelte
+++ b/site/content/tutorial/14-composition/04-optional-slots/app-b/Comment.svelte
@@ -5,6 +5,19 @@
$: avatar = `https://ui-avatars.com/api/?name=${name.replace(/ /g, '+')}&rounded=true&background=ff3e00&color=fff&bold=true`;
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
\ No newline at end of file
diff --git a/site/content/tutorial/14-composition/04-optional-slots/app-b/Project.svelte b/site/content/tutorial/14-composition/04-optional-slots/app-b/Project.svelte
index 87a1d0c3ac..39f55abd18 100755
--- a/site/content/tutorial/14-composition/04-optional-slots/app-b/Project.svelte
+++ b/site/content/tutorial/14-composition/04-optional-slots/app-b/Project.svelte
@@ -4,6 +4,19 @@
export let totalTasks = 0;
+
+
+
{title}
+
{tasksCompleted}/{totalTasks} tasks completed
+
+ {#if $$slots.comments}
+
+
Comments
+
+
+ {/if}
+
+
-
-
-
-
{title}
-
{tasksCompleted}/{totalTasks} tasks completed
-
- {#if $$slots.comments}
-
-
Comments
-
-
- {/if}
-
+
\ No newline at end of file
diff --git a/site/content/tutorial/14-composition/05-slot-props/app-a/App.svelte b/site/content/tutorial/14-composition/05-slot-props/app-a/App.svelte
index 65f714f2c5..e95b4cbe93 100644
--- a/site/content/tutorial/14-composition/05-slot-props/app-a/App.svelte
+++ b/site/content/tutorial/14-composition/05-slot-props/app-a/App.svelte
@@ -2,6 +2,16 @@
import Hoverable from './Hoverable.svelte';
+
+
+ {#if hovering}
+
I am being hovered upon.
+ {:else}
+
Hover over me!
+ {/if}
+
+
+
-
-
-
- {#if hovering}
-
I am being hovered upon.
- {:else}
-
Hover over me!
- {/if}
-
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/site/content/tutorial/14-composition/05-slot-props/app-b/App.svelte b/site/content/tutorial/14-composition/05-slot-props/app-b/App.svelte
index 36772a5077..299cd336a6 100644
--- a/site/content/tutorial/14-composition/05-slot-props/app-b/App.svelte
+++ b/site/content/tutorial/14-composition/05-slot-props/app-b/App.svelte
@@ -2,19 +2,6 @@
import Hoverable from './Hoverable.svelte';
-
-
{#if active}
@@ -43,4 +30,17 @@
Hover over me!
{/if}
-
\ No newline at end of file
+
+
+
\ No newline at end of file
diff --git a/site/content/tutorial/15-context/01-context-api/app-a/Map.svelte b/site/content/tutorial/15-context/01-context-api/app-a/Map.svelte
index 888f42da39..c6a660a49f 100644
--- a/site/content/tutorial/15-context/01-context-api/app-a/Map.svelte
+++ b/site/content/tutorial/15-context/01-context-api/app-a/Map.svelte
@@ -34,15 +34,15 @@
});
+
+ {#if map}
+
+ {/if}
+
+
-
-
- {#if map}
-
- {/if}
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/site/content/tutorial/15-context/01-context-api/app-b/Map.svelte b/site/content/tutorial/15-context/01-context-api/app-b/Map.svelte
index 0282cbc311..059fcca45b 100644
--- a/site/content/tutorial/15-context/01-context-api/app-b/Map.svelte
+++ b/site/content/tutorial/15-context/01-context-api/app-b/Map.svelte
@@ -36,15 +36,15 @@
});
+
+ {#if map}
+
+ {/if}
+
+
-
-
- {#if map}
-
- {/if}
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/site/content/tutorial/15-context/01-context-api/text.md b/site/content/tutorial/15-context/01-context-api/text.md
index 96a716dfb0..dc5f2d7e8b 100644
--- a/site/content/tutorial/15-context/01-context-api/text.md
+++ b/site/content/tutorial/15-context/01-context-api/text.md
@@ -19,7 +19,7 @@ setContext(key, {
});
```
-The context object can be anything you like. Like [lifecycle functions](tutorial/onmount), `setContext` and `getContext` must be called during component initialisation; since `map` isn't created until the component has mounted, our context object contains a `getMap` function rather than `map` itself.
+The context object can be anything you like. Like [lifecycle functions](tutorial/onmount), `setContext` and `getContext` must be called during component initialisation. Calling it afterwards - for example inside `onMount` - will throw an error. In this example, since `map` isn't created until the component has mounted, our context object contains a `getMap` function rather than `map` itself.
On the other side of the equation, in `MapMarker.svelte`, we can now get a reference to the Mapbox instance:
diff --git a/site/content/tutorial/16-special-elements/01-svelte-self/app-a/App.svelte b/site/content/tutorial/16-special-elements/01-svelte-self/app-a/App.svelte
index ff02fa6a42..de0b2e0179 100644
--- a/site/content/tutorial/16-special-elements/01-svelte-self/app-a/App.svelte
+++ b/site/content/tutorial/16-special-elements/01-svelte-self/app-a/App.svelte
@@ -3,39 +3,35 @@
let root = [
{
- type: 'folder',
name: 'Important work stuff',
files: [
- { type: 'file', name: 'quarterly-results.xlsx' }
+ { name: 'quarterly-results.xlsx' }
]
},
{
- type: 'folder',
name: 'Animal GIFs',
files: [
{
- type: 'folder',
name: 'Dogs',
files: [
- { type: 'file', name: 'treadmill.gif' },
- { type: 'file', name: 'rope-jumping.gif' }
+ { name: 'treadmill.gif' },
+ { name: 'rope-jumping.gif' }
]
},
{
- type: 'folder',
name: 'Goats',
files: [
- { type: 'file', name: 'parkour.gif' },
- { type: 'file', name: 'rampage.gif' }
+ { name: 'parkour.gif' },
+ { name: 'rampage.gif' }
]
},
- { type: 'file', name: 'cat-roomba.gif' },
- { type: 'file', name: 'duck-shuffle.gif' },
- { type: 'file', name: 'monkey-on-a-pig.gif' }
+ { name: 'cat-roomba.gif' },
+ { name: 'duck-shuffle.gif' },
+ { name: 'monkey-on-a-pig.gif' }
]
},
- { type: 'file', name: 'TODO.md' }
+ { name: 'TODO.md' }
];
-
\ No newline at end of file
+
diff --git a/site/content/tutorial/16-special-elements/01-svelte-self/app-a/File.svelte b/site/content/tutorial/16-special-elements/01-svelte-self/app-a/File.svelte
index e34686101a..8a0048dd68 100644
--- a/site/content/tutorial/16-special-elements/01-svelte-self/app-a/File.svelte
+++ b/site/content/tutorial/16-special-elements/01-svelte-self/app-a/File.svelte
@@ -3,12 +3,12 @@
$: type = name.slice(name.lastIndexOf('.') + 1);
+{name}
+
-
-{name}
\ No newline at end of file
+
\ No newline at end of file
diff --git a/site/content/tutorial/16-special-elements/01-svelte-self/app-a/Folder.svelte b/site/content/tutorial/16-special-elements/01-svelte-self/app-a/Folder.svelte
index add7fb96d3..1108b3575c 100644
--- a/site/content/tutorial/16-special-elements/01-svelte-self/app-a/Folder.svelte
+++ b/site/content/tutorial/16-special-elements/01-svelte-self/app-a/Folder.svelte
@@ -10,6 +10,22 @@
}
+{name}
+
+{#if expanded}
+
+ {#each files as file}
+
+ {#if file.files}
+
+ {:else}
+
+ {/if}
+
+ {/each}
+
+{/if}
+
-
-{name}
-
-{#if expanded}
-
- {#each files as file}
-
- {#if file.type === 'folder'}
-
- {:else}
-
- {/if}
-
- {/each}
-
-{/if}
\ No newline at end of file
diff --git a/site/content/tutorial/16-special-elements/01-svelte-self/app-b/App.svelte b/site/content/tutorial/16-special-elements/01-svelte-self/app-b/App.svelte
index ff02fa6a42..de0b2e0179 100644
--- a/site/content/tutorial/16-special-elements/01-svelte-self/app-b/App.svelte
+++ b/site/content/tutorial/16-special-elements/01-svelte-self/app-b/App.svelte
@@ -3,39 +3,35 @@
let root = [
{
- type: 'folder',
name: 'Important work stuff',
files: [
- { type: 'file', name: 'quarterly-results.xlsx' }
+ { name: 'quarterly-results.xlsx' }
]
},
{
- type: 'folder',
name: 'Animal GIFs',
files: [
{
- type: 'folder',
name: 'Dogs',
files: [
- { type: 'file', name: 'treadmill.gif' },
- { type: 'file', name: 'rope-jumping.gif' }
+ { name: 'treadmill.gif' },
+ { name: 'rope-jumping.gif' }
]
},
{
- type: 'folder',
name: 'Goats',
files: [
- { type: 'file', name: 'parkour.gif' },
- { type: 'file', name: 'rampage.gif' }
+ { name: 'parkour.gif' },
+ { name: 'rampage.gif' }
]
},
- { type: 'file', name: 'cat-roomba.gif' },
- { type: 'file', name: 'duck-shuffle.gif' },
- { type: 'file', name: 'monkey-on-a-pig.gif' }
+ { name: 'cat-roomba.gif' },
+ { name: 'duck-shuffle.gif' },
+ { name: 'monkey-on-a-pig.gif' }
]
},
- { type: 'file', name: 'TODO.md' }
+ { name: 'TODO.md' }
];
-
\ No newline at end of file
+
diff --git a/site/content/tutorial/16-special-elements/01-svelte-self/app-b/File.svelte b/site/content/tutorial/16-special-elements/01-svelte-self/app-b/File.svelte
index e34686101a..8a0048dd68 100644
--- a/site/content/tutorial/16-special-elements/01-svelte-self/app-b/File.svelte
+++ b/site/content/tutorial/16-special-elements/01-svelte-self/app-b/File.svelte
@@ -3,12 +3,12 @@
$: type = name.slice(name.lastIndexOf('.') + 1);
+{name}
+
-
-{name}
\ No newline at end of file
+
\ No newline at end of file
diff --git a/site/content/tutorial/16-special-elements/01-svelte-self/app-b/Folder.svelte b/site/content/tutorial/16-special-elements/01-svelte-self/app-b/Folder.svelte
index c25bb2a93d..11049c2e52 100644
--- a/site/content/tutorial/16-special-elements/01-svelte-self/app-b/Folder.svelte
+++ b/site/content/tutorial/16-special-elements/01-svelte-self/app-b/Folder.svelte
@@ -10,6 +10,22 @@
}
+{name}
+
+{#if expanded}
+
+ {#each files as file}
+
+ {#if file.files}
+
+ {:else}
+
+ {/if}
+
+ {/each}
+
+{/if}
+
-
-{name}
-
-{#if expanded}
-
- {#each files as file}
-
- {#if file.type === 'folder'}
-
- {:else}
-
- {/if}
-
- {/each}
-
-{/if}
\ No newline at end of file
diff --git a/site/content/tutorial/16-special-elements/01-svelte-self/text.md b/site/content/tutorial/16-special-elements/01-svelte-self/text.md
index c7946f6c6d..894a8efc3d 100644
--- a/site/content/tutorial/16-special-elements/01-svelte-self/text.md
+++ b/site/content/tutorial/16-special-elements/01-svelte-self/text.md
@@ -7,7 +7,7 @@ Svelte provides a variety of built-in elements. The first, ``, allo
It's useful for things like this folder tree view, where folders can contain *other* folders. In `Folder.svelte` we want to be able to do this...
```html
-{#if file.type === 'folder'}
+{#if file.files}
{:else}
@@ -17,7 +17,7 @@ It's useful for things like this folder tree view, where folders can contain *ot
...but that's impossible, because a module can't import itself. Instead, we use ``:
```html
-{#if file.type === 'folder'}
+{#if file.files}
{:else}
diff --git a/site/content/tutorial/16-special-elements/02-svelte-component/app-a/BlueThing.svelte b/site/content/tutorial/16-special-elements/02-svelte-component/app-a/BlueThing.svelte
index f9130d9d65..eb7ba64163 100644
--- a/site/content/tutorial/16-special-elements/02-svelte-component/app-a/BlueThing.svelte
+++ b/site/content/tutorial/16-special-elements/02-svelte-component/app-a/BlueThing.svelte
@@ -1,5 +1,7 @@
-
+Blue thing
-blue thing
\ No newline at end of file
+
\ No newline at end of file
diff --git a/site/content/tutorial/16-special-elements/02-svelte-component/app-a/GreenThing.svelte b/site/content/tutorial/16-special-elements/02-svelte-component/app-a/GreenThing.svelte
index 9cbee235d3..ed2aa49f27 100644
--- a/site/content/tutorial/16-special-elements/02-svelte-component/app-a/GreenThing.svelte
+++ b/site/content/tutorial/16-special-elements/02-svelte-component/app-a/GreenThing.svelte
@@ -1,5 +1,7 @@
-
+Green thing
-green thing
\ No newline at end of file
+
\ No newline at end of file
diff --git a/site/content/tutorial/16-special-elements/02-svelte-component/app-a/RedThing.svelte b/site/content/tutorial/16-special-elements/02-svelte-component/app-a/RedThing.svelte
index 42f5e4c672..365f226492 100644
--- a/site/content/tutorial/16-special-elements/02-svelte-component/app-a/RedThing.svelte
+++ b/site/content/tutorial/16-special-elements/02-svelte-component/app-a/RedThing.svelte
@@ -1,5 +1,7 @@
-
+Red thing
-red thing
\ No newline at end of file
+
\ No newline at end of file
diff --git a/site/content/tutorial/16-special-elements/02-svelte-component/app-b/BlueThing.svelte b/site/content/tutorial/16-special-elements/02-svelte-component/app-b/BlueThing.svelte
index f9130d9d65..eb7ba64163 100644
--- a/site/content/tutorial/16-special-elements/02-svelte-component/app-b/BlueThing.svelte
+++ b/site/content/tutorial/16-special-elements/02-svelte-component/app-b/BlueThing.svelte
@@ -1,5 +1,7 @@
-
+Blue thing
-blue thing
\ No newline at end of file
+
\ No newline at end of file
diff --git a/site/content/tutorial/16-special-elements/02-svelte-component/app-b/GreenThing.svelte b/site/content/tutorial/16-special-elements/02-svelte-component/app-b/GreenThing.svelte
index 9cbee235d3..ed2aa49f27 100644
--- a/site/content/tutorial/16-special-elements/02-svelte-component/app-b/GreenThing.svelte
+++ b/site/content/tutorial/16-special-elements/02-svelte-component/app-b/GreenThing.svelte
@@ -1,5 +1,7 @@
-
+Green thing
-green thing
\ No newline at end of file
+
\ No newline at end of file
diff --git a/site/content/tutorial/16-special-elements/02-svelte-component/app-b/RedThing.svelte b/site/content/tutorial/16-special-elements/02-svelte-component/app-b/RedThing.svelte
index 42f5e4c672..365f226492 100644
--- a/site/content/tutorial/16-special-elements/02-svelte-component/app-b/RedThing.svelte
+++ b/site/content/tutorial/16-special-elements/02-svelte-component/app-b/RedThing.svelte
@@ -1,5 +1,7 @@
-
+Red thing
-red thing
\ No newline at end of file
+
\ No newline at end of file
diff --git a/site/content/tutorial/16-special-elements/03-svelte-window/app-a/App.svelte b/site/content/tutorial/16-special-elements/03-svelte-window/app-a/App.svelte
index 9fe2bf526c..24c9a6368a 100644
--- a/site/content/tutorial/16-special-elements/03-svelte-window/app-a/App.svelte
+++ b/site/content/tutorial/16-special-elements/03-svelte-window/app-a/App.svelte
@@ -8,6 +8,17 @@
}
+
+
+
+ {#if key}
+
{key === ' ' ? 'Space' : key}
+
{keyCode}
+ {:else}
+
Focus this window and press any key
+ {/if}
+
+
-
-
-
-
- {#if key}
-
{key === ' ' ? 'Space' : key}
-
{keyCode}
- {:else}
-
Focus this window and press any key
- {/if}
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/site/content/tutorial/16-special-elements/03-svelte-window/app-b/App.svelte b/site/content/tutorial/16-special-elements/03-svelte-window/app-b/App.svelte
index 845d666dff..026dfa94f7 100644
--- a/site/content/tutorial/16-special-elements/03-svelte-window/app-b/App.svelte
+++ b/site/content/tutorial/16-special-elements/03-svelte-window/app-b/App.svelte
@@ -8,6 +8,17 @@
}
+
+
+
+ {#if key}
+
{key === ' ' ? 'Space' : key}
+
{keyCode}
+ {:else}
+
Focus this window and press any key
+ {/if}
+
+
-
-
-
-
- {#if key}
-
{key === ' ' ? 'Space' : key}
-
{keyCode}
- {:else}
-
Focus this window and press any key
- {/if}
-
\ No newline at end of file
diff --git a/site/content/tutorial/16-special-elements/03-svelte-window/text.md b/site/content/tutorial/16-special-elements/03-svelte-window/text.md
index b581b3ada4..3c6c71a730 100644
--- a/site/content/tutorial/16-special-elements/03-svelte-window/text.md
+++ b/site/content/tutorial/16-special-elements/03-svelte-window/text.md
@@ -4,7 +4,7 @@ title:
Just as you can add event listeners to any DOM element, you can add event listeners to the `window` object with ``.
-On line 33, add the `keydown` listener:
+On line 11, add the `keydown` listener:
```html
diff --git a/site/content/tutorial/16-special-elements/04-svelte-window-bindings/app-a/App.svelte b/site/content/tutorial/16-special-elements/04-svelte-window-bindings/app-a/App.svelte
index 04b4de5cf2..ba51140ff4 100644
--- a/site/content/tutorial/16-special-elements/04-svelte-window-bindings/app-a/App.svelte
+++ b/site/content/tutorial/16-special-elements/04-svelte-window-bindings/app-a/App.svelte
@@ -85,4 +85,4 @@
padding: 0;
background-color: rgb(253, 174, 51);
}
-
+
\ No newline at end of file
diff --git a/site/content/tutorial/16-special-elements/04-svelte-window-bindings/app-b/App.svelte b/site/content/tutorial/16-special-elements/04-svelte-window-bindings/app-b/App.svelte
index 15c2aa0ebc..2fc076b991 100644
--- a/site/content/tutorial/16-special-elements/04-svelte-window-bindings/app-b/App.svelte
+++ b/site/content/tutorial/16-special-elements/04-svelte-window-bindings/app-b/App.svelte
@@ -85,4 +85,4 @@
padding: 0;
background-color: rgb(253, 174, 51);
}
-
+
\ No newline at end of file
diff --git a/site/content/tutorial/16-special-elements/05-svelte-body/app-a/App.svelte b/site/content/tutorial/16-special-elements/05-svelte-body/app-a/App.svelte
index ad616582e5..d9505bb0c9 100644
--- a/site/content/tutorial/16-special-elements/05-svelte-body/app-a/App.svelte
+++ b/site/content/tutorial/16-special-elements/05-svelte-body/app-a/App.svelte
@@ -5,6 +5,15 @@
const handleMouseleave = () => hereKitty = false;
+
+
+
+
+
-
-
-
-
-
\ No newline at end of file
diff --git a/site/content/tutorial/16-special-elements/05-svelte-body/app-b/App.svelte b/site/content/tutorial/16-special-elements/05-svelte-body/app-b/App.svelte
index ac946962eb..238da2ab18 100644
--- a/site/content/tutorial/16-special-elements/05-svelte-body/app-b/App.svelte
+++ b/site/content/tutorial/16-special-elements/05-svelte-body/app-b/App.svelte
@@ -5,6 +5,18 @@
const handleMouseleave = () => hereKitty = false;
+
+
+
+
+
-
-
-
-
-
\ No newline at end of file
diff --git a/site/content/tutorial/16-special-elements/07-svelte-options/app-a/Todo.svelte b/site/content/tutorial/16-special-elements/07-svelte-options/app-a/Todo.svelte
index 5e0dbca300..57d4dcc79a 100644
--- a/site/content/tutorial/16-special-elements/07-svelte-options/app-a/Todo.svelte
+++ b/site/content/tutorial/16-special-elements/07-svelte-options/app-a/Todo.svelte
@@ -11,15 +11,15 @@
});
-
-
{todo.done ? '👍': ''} {todo.text}
+
+
\ No newline at end of file
diff --git a/site/content/tutorial/16-special-elements/07-svelte-options/app-b/Todo.svelte b/site/content/tutorial/16-special-elements/07-svelte-options/app-b/Todo.svelte
index e7ddcedc47..fa81d35989 100644
--- a/site/content/tutorial/16-special-elements/07-svelte-options/app-b/Todo.svelte
+++ b/site/content/tutorial/16-special-elements/07-svelte-options/app-b/Todo.svelte
@@ -13,15 +13,15 @@
});
-
-
{todo.done ? '👍': ''} {todo.text}
+
+
\ No newline at end of file
diff --git a/site/content/tutorial/16-special-elements/07-svelte-options/text.md b/site/content/tutorial/16-special-elements/07-svelte-options/text.md
index 60a9d3b0f8..c3f9f50ce0 100644
--- a/site/content/tutorial/16-special-elements/07-svelte-options/text.md
+++ b/site/content/tutorial/16-special-elements/07-svelte-options/text.md
@@ -2,7 +2,7 @@
title:
---
-Lastly, `` allows you to specify compiler options.
+The `` element allows you to specify compiler options.
We'll use the `immutable` option as an example. In this app, the `` component flashes whenever it receives new data. Clicking on one of the items toggles its `done` state by creating an updated `todos` array. This causes the *other* `` items to flash, even though they don't end up making any changes to the DOM.
@@ -27,4 +27,4 @@ The options that can be set here are:
* `namespace="..."` — the namespace where this component will be used, most commonly `"svg"`
* `tag="..."` — the name to use when compiling this component as a custom element
-Consult the [API reference](docs) for more information on these options.
\ No newline at end of file
+Consult the [API reference](docs) for more information on these options.
diff --git a/site/content/tutorial/16-special-elements/08-svelte-fragment/app-a/App.svelte b/site/content/tutorial/16-special-elements/08-svelte-fragment/app-a/App.svelte
index 35f2586857..442ff07d26 100644
--- a/site/content/tutorial/16-special-elements/08-svelte-fragment/app-a/App.svelte
+++ b/site/content/tutorial/16-special-elements/08-svelte-fragment/app-a/App.svelte
@@ -7,4 +7,4 @@
All rights reserved.
Copyright (c) 2019 Svelte Industries
-
+
\ No newline at end of file
diff --git a/site/content/tutorial/16-special-elements/08-svelte-fragment/app-a/Box.svelte b/site/content/tutorial/16-special-elements/08-svelte-fragment/app-a/Box.svelte
index 16c17f90ef..ed389182a7 100644
--- a/site/content/tutorial/16-special-elements/08-svelte-fragment/app-a/Box.svelte
+++ b/site/content/tutorial/16-special-elements/08-svelte-fragment/app-a/Box.svelte
@@ -1,9 +1,15 @@
+
+
No header was provided
+
Some content between header and footer
+
+
+
-
-
-
No header was provided
-
Some content between header and footer
-
-
+
\ No newline at end of file
diff --git a/site/content/tutorial/16-special-elements/08-svelte-fragment/app-b/App.svelte b/site/content/tutorial/16-special-elements/08-svelte-fragment/app-b/App.svelte
index 6f55903ece..e66b026d90 100644
--- a/site/content/tutorial/16-special-elements/08-svelte-fragment/app-b/App.svelte
+++ b/site/content/tutorial/16-special-elements/08-svelte-fragment/app-b/App.svelte
@@ -7,4 +7,4 @@
All rights reserved.
Copyright (c) 2019 Svelte Industries
-
+
\ No newline at end of file
diff --git a/site/content/tutorial/16-special-elements/08-svelte-fragment/app-b/Box.svelte b/site/content/tutorial/16-special-elements/08-svelte-fragment/app-b/Box.svelte
index 16c17f90ef..ed389182a7 100644
--- a/site/content/tutorial/16-special-elements/08-svelte-fragment/app-b/Box.svelte
+++ b/site/content/tutorial/16-special-elements/08-svelte-fragment/app-b/Box.svelte
@@ -1,9 +1,15 @@
+
+
No header was provided
+
Some content between header and footer
+
+
+
-
-
-
No header was provided
-
Some content between header and footer
-
-
+
\ No newline at end of file
diff --git a/site/content/tutorial/16-special-elements/08-svelte-fragment/text.md b/site/content/tutorial/16-special-elements/08-svelte-fragment/text.md
index fca7aeb844..2103404799 100644
--- a/site/content/tutorial/16-special-elements/08-svelte-fragment/text.md
+++ b/site/content/tutorial/16-special-elements/08-svelte-fragment/text.md
@@ -8,6 +8,12 @@ In the example notice how we applied a flex layout with a gap of `1em` to the bo
```sv
+
+
No header was provided
+
Some content between header and footer
+
+
+
-
-
-
No header was provided
-
Some content between header and footer
-
-
```
However, the content in the footer is not spaced out according to this rhythm because wrapping it in a div created a new flow layout.
diff --git a/site/content/tutorial/17-module-context/01-sharing-code/app-a/AudioPlayer.svelte b/site/content/tutorial/17-module-context/01-sharing-code/app-a/AudioPlayer.svelte
index 12d3a78c41..179bdacffe 100644
--- a/site/content/tutorial/17-module-context/01-sharing-code/app-a/AudioPlayer.svelte
+++ b/site/content/tutorial/17-module-context/01-sharing-code/app-a/AudioPlayer.svelte
@@ -12,13 +12,6 @@
}
-
-
{title}
{composer} / performed by {performer}
@@ -30,4 +23,19 @@
controls
{src}
>
-
\ No newline at end of file
+
+
+
\ No newline at end of file
diff --git a/site/content/tutorial/17-module-context/01-sharing-code/app-b/AudioPlayer.svelte b/site/content/tutorial/17-module-context/01-sharing-code/app-b/AudioPlayer.svelte
index 609f9f1af0..3352074a2c 100644
--- a/site/content/tutorial/17-module-context/01-sharing-code/app-b/AudioPlayer.svelte
+++ b/site/content/tutorial/17-module-context/01-sharing-code/app-b/AudioPlayer.svelte
@@ -17,13 +17,6 @@
}
-
-
{title}
{composer} / performed by {performer}
@@ -35,4 +28,19 @@
controls
{src}
>
-
\ No newline at end of file
+
+
+
\ No newline at end of file
diff --git a/site/content/tutorial/17-module-context/02-module-exports/app-a/AudioPlayer.svelte b/site/content/tutorial/17-module-context/02-module-exports/app-a/AudioPlayer.svelte
index 27dbe1993b..90f3c67551 100644
--- a/site/content/tutorial/17-module-context/02-module-exports/app-a/AudioPlayer.svelte
+++ b/site/content/tutorial/17-module-context/02-module-exports/app-a/AudioPlayer.svelte
@@ -25,13 +25,6 @@
}
-
-
{title}
{composer} / performed by {performer}
@@ -43,4 +36,19 @@
controls
{src}
>
-
\ No newline at end of file
+
+
+
\ No newline at end of file
diff --git a/site/content/tutorial/17-module-context/02-module-exports/app-b/AudioPlayer.svelte b/site/content/tutorial/17-module-context/02-module-exports/app-b/AudioPlayer.svelte
index 4e3d191dbf..f28e8b0c7f 100644
--- a/site/content/tutorial/17-module-context/02-module-exports/app-b/AudioPlayer.svelte
+++ b/site/content/tutorial/17-module-context/02-module-exports/app-b/AudioPlayer.svelte
@@ -31,13 +31,6 @@
}
-
-
{title}
{composer} / performed by {performer}
@@ -49,4 +42,19 @@
controls
{src}
>
-
\ No newline at end of file
+
+
+
\ No newline at end of file
diff --git a/site/content/tutorial/19-next-steps/01-congratulations/app-a/App.svelte b/site/content/tutorial/19-next-steps/01-congratulations/app-a/App.svelte
index 2e72fafe23..9ce2dd648d 100644
--- a/site/content/tutorial/19-next-steps/01-congratulations/app-a/App.svelte
+++ b/site/content/tutorial/19-next-steps/01-congratulations/app-a/App.svelte
@@ -33,6 +33,10 @@
});
+{#each confetti as c}
+ {c.character}
+{/each}
+
-
-{#each confetti as c}
- {c.character}
-{/each}
\ No newline at end of file
diff --git a/site/content/tutorial/19-next-steps/01-congratulations/text.md b/site/content/tutorial/19-next-steps/01-congratulations/text.md
index c4436113bc..558cf6bda6 100644
--- a/site/content/tutorial/19-next-steps/01-congratulations/text.md
+++ b/site/content/tutorial/19-next-steps/01-congratulations/text.md
@@ -6,6 +6,6 @@ You've now finished the Svelte tutorial and are ready to start building apps. Yo
To get set up in your local development environment, check out [the quickstart guide](blog/the-easiest-way-to-get-started).
-If you're looking for a more expansive framework that includes routing, server-side rendering and everything else, take a look at [Sapper](https://sapper.svelte.dev).
+If you're looking for a more expansive framework that includes routing, server-side rendering and everything else, take a look at [SvelteKit](https://kit.svelte.dev).
-Most importantly: since you're now a member of the Svelte community, you should [join our friendly Discord chatroom](chat). That's where you'll find fellow Svelte users, and it's where we plan the future of the framework.
\ No newline at end of file
+Most importantly: since you're now a member of the Svelte community, you should [join our friendly Discord chatroom](chat). That's where you'll find fellow Svelte users, and it's where we plan the future of the framework.
diff --git a/site/package-lock.json b/site/package-lock.json
index 19166e56da..b2eadc2aae 100644
--- a/site/package-lock.json
+++ b/site/package-lock.json
@@ -1427,9 +1427,9 @@
}
},
"@sveltejs/site-kit": {
- "version": "1.2.5",
- "resolved": "https://registry.npmjs.org/@sveltejs/site-kit/-/site-kit-1.2.5.tgz",
- "integrity": "sha512-fA1YWW4tYOxPRVocx+jF4S2LGamku8xeKx/+J5aY7ZCbwuo/c4VF+T0K7WuQRI8U6Dw3pJqdiCra+xH4TnCGRw==",
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/@sveltejs/site-kit/-/site-kit-1.4.0.tgz",
+ "integrity": "sha512-QoIo8KC6G9gInwFyk4+KCzVOiLNdj2aw7T+wGDED+A/SuvICSCyS7W/Ft0WcoAGyQGtgIFRVCcXacubduzA7bg==",
"dev": true,
"requires": {
"@sindresorhus/slugify": "^0.9.1",
@@ -1581,16 +1581,42 @@
"dev": true
},
"browserslist": {
- "version": "4.16.0",
- "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.0.tgz",
- "integrity": "sha512-/j6k8R0p3nxOC6kx5JGAxsnhc9ixaWJfYc+TNTzxg6+ARaESAvQGV7h0uNOB4t+pLQJZWzcrMxXOxjgsCj3dqQ==",
+ "version": "4.16.6",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.6.tgz",
+ "integrity": "sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ==",
"dev": true,
"requires": {
- "caniuse-lite": "^1.0.30001165",
- "colorette": "^1.2.1",
- "electron-to-chromium": "^1.3.621",
+ "caniuse-lite": "^1.0.30001219",
+ "colorette": "^1.2.2",
+ "electron-to-chromium": "^1.3.723",
"escalade": "^3.1.1",
- "node-releases": "^1.1.67"
+ "node-releases": "^1.1.71"
+ },
+ "dependencies": {
+ "caniuse-lite": {
+ "version": "1.0.30001228",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001228.tgz",
+ "integrity": "sha512-QQmLOGJ3DEgokHbMSA8cj2a+geXqmnpyOFT0lhQV6P3/YOJvGDEwoedcwxEQ30gJIwIIunHIicunJ2rzK5gB2A==",
+ "dev": true
+ },
+ "colorette": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz",
+ "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==",
+ "dev": true
+ },
+ "electron-to-chromium": {
+ "version": "1.3.736",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.736.tgz",
+ "integrity": "sha512-DY8dA7gR51MSo66DqitEQoUMQ0Z+A2DSXFi7tK304bdTVqczCAfUuyQw6Wdg8hIoo5zIxkU1L24RQtUce1Ioig==",
+ "dev": true
+ },
+ "node-releases": {
+ "version": "1.1.72",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.72.tgz",
+ "integrity": "sha512-LLUo+PpH3dU6XizX3iVoubUNheF/owjXCZZ5yACDxNnPtgFuludV1ZL3ayK1kVep42Rmm0+R9/Y60NQbZ2bifw==",
+ "dev": true
+ }
}
},
"buffer": {
@@ -1657,12 +1683,6 @@
"integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
"dev": true
},
- "caniuse-lite": {
- "version": "1.0.30001171",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001171.tgz",
- "integrity": "sha512-5Alrh8TTYPG9IH4UkRqEBZoEToWRLvPbSQokvzSz0lii8/FOWKG4keO1HoYfPWs8IF/NH/dyNPg1cmJGvV3Zlg==",
- "dev": true
- },
"chalk": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
@@ -1691,17 +1711,6 @@
}
}
},
- "clipboard": {
- "version": "2.0.6",
- "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.6.tgz",
- "integrity": "sha512-g5zbiixBRk/wyKakSwCKd7vQXDjFnAMGHoEyBogG/bw9kTD9GvdAvaoRR1ALcEzt3pVKxZR0pViekPMIS0QyGg==",
- "optional": true,
- "requires": {
- "good-listener": "^1.2.2",
- "select": "^1.1.2",
- "tiny-emitter": "^2.0.0"
- }
- },
"cliui": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
@@ -1762,12 +1771,6 @@
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
"dev": true
},
- "colorette": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.1.tgz",
- "integrity": "sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw==",
- "dev": true
- },
"commander": {
"version": "2.20.3",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
@@ -1848,19 +1851,6 @@
"integrity": "sha512-Se+LaxqXlVXGvmexKGPvnUIYC1jwXu1H6Pkyb3uBM5d8/NELMYCHs/4/roD7721NxrTLyv7e5nXd5/QLBO+10g==",
"dev": true
},
- "cross-spawn": {
- "version": "6.0.5",
- "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
- "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
- "dev": true,
- "requires": {
- "nice-try": "^1.0.4",
- "path-key": "^2.0.1",
- "semver": "^5.5.0",
- "shebang-command": "^1.2.0",
- "which": "^1.2.9"
- }
- },
"debug": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
@@ -1905,12 +1895,6 @@
"integrity": "sha512-nxQr1Ep4NSGDIqQ3HSMNgnPYaxPfPhHdrpgSNO2EczO86zN7NJJ1i/59GM25vgC45ANQUazZ/3Z+iyeZCmGwhg==",
"dev": true
},
- "delegate": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz",
- "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==",
- "optional": true
- },
"devalue": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/devalue/-/devalue-2.0.1.tgz",
@@ -1947,27 +1931,12 @@
"safe-buffer": "^5.0.1"
}
},
- "electron-to-chromium": {
- "version": "1.3.633",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.633.tgz",
- "integrity": "sha512-bsVCsONiVX1abkWdH7KtpuDAhsQ3N3bjPYhROSAXE78roJKet0Y5wznA14JE9pzbwSZmSMAW6KiKYf1RvbTJkA==",
- "dev": true
- },
"emoji-regex": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
"integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
"dev": true
},
- "error-ex": {
- "version": "1.3.2",
- "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
- "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
- "dev": true,
- "requires": {
- "is-arrayish": "^0.2.1"
- }
- },
"es-abstract": {
"version": "1.18.0-next.1",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz",
@@ -2148,21 +2117,6 @@
"integrity": "sha512-YSwLaGMOgSBx9roJlNLL12c+FRiw7VECphinc6mGucphc/ZxTHgdEz6gmJqH6NOzYEd/yr64hwjom5pZ+tJVpg==",
"dev": true
},
- "good-listener": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz",
- "integrity": "sha1-1TswzfkxPf+33JoNR3CWqm0UXFA=",
- "optional": true,
- "requires": {
- "delegate": "^3.1.2"
- }
- },
- "graceful-fs": {
- "version": "4.2.4",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
- "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==",
- "dev": true
- },
"growl": {
"version": "1.10.5",
"resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz",
@@ -2196,12 +2150,6 @@
"integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
"dev": true
},
- "hosted-git-info": {
- "version": "2.8.8",
- "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz",
- "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==",
- "dev": true
- },
"html-minifier": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-4.0.0.tgz",
@@ -2255,12 +2203,6 @@
"integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==",
"dev": true
},
- "is-arrayish": {
- "version": "0.2.1",
- "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
- "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
- "dev": true
- },
"is-buffer": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz",
@@ -2414,12 +2356,6 @@
"integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
"dev": true
},
- "json-parse-better-errors": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
- "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==",
- "dev": true
- },
"json5": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz",
@@ -2489,18 +2425,6 @@
}
}
},
- "load-json-file": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz",
- "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=",
- "dev": true,
- "requires": {
- "graceful-fs": "^4.1.2",
- "parse-json": "^4.0.0",
- "pify": "^3.0.0",
- "strip-bom": "^3.0.0"
- }
- },
"locate-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
@@ -2512,9 +2436,9 @@
}
},
"lodash": {
- "version": "4.17.20",
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
- "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==",
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
"dev": true
},
"lodash.deburr": {
@@ -2587,12 +2511,6 @@
"resolved": "https://registry.npmjs.org/marked/-/marked-1.2.7.tgz",
"integrity": "sha512-No11hFYcXr/zkBvL6qFmAp1z6BKY3zqLMHny/JN/ey+al7qwCM2+CMBL9BOgqMxZU36fz4cCWfn2poWIf7QRXA=="
},
- "memorystream": {
- "version": "0.3.1",
- "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz",
- "integrity": "sha1-htcJCzDORV1j+64S3aUaR93K+bI=",
- "dev": true
- },
"merge-stream": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
@@ -2742,12 +2660,6 @@
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
},
- "nice-try": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
- "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
- "dev": true
- },
"no-case": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz",
@@ -2870,41 +2782,6 @@
}
}
},
- "node-releases": {
- "version": "1.1.67",
- "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.67.tgz",
- "integrity": "sha512-V5QF9noGFl3EymEwUYzO+3NTDpGfQB4ve6Qfnzf3UNydMhjQRVPR1DZTuvWiLzaFJYw2fmDwAfnRNEVb64hSIg==",
- "dev": true
- },
- "normalize-package-data": {
- "version": "2.5.0",
- "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
- "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
- "dev": true,
- "requires": {
- "hosted-git-info": "^2.1.4",
- "resolve": "^1.10.0",
- "semver": "2 || 3 || 4 || 5",
- "validate-npm-package-license": "^3.0.1"
- }
- },
- "npm-run-all": {
- "version": "4.1.5",
- "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz",
- "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==",
- "dev": true,
- "requires": {
- "ansi-styles": "^3.2.1",
- "chalk": "^2.4.1",
- "cross-spawn": "^6.0.5",
- "memorystream": "^0.3.1",
- "minimatch": "^3.0.4",
- "pidtree": "^0.3.0",
- "read-pkg": "^3.0.0",
- "shell-quote": "^1.6.1",
- "string.prototype.padend": "^3.0.0"
- }
- },
"object-inspect": {
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.9.0.tgz",
@@ -3027,16 +2904,6 @@
"integrity": "sha512-QhhZ+DCCit2Coi2vmAKbq5RGTRcQUOE2+REgv8vdyu7MnYx2eZztegqtTx99TZ86GTIwqiy3+4nQTWZ2tgmdCA==",
"dev": true
},
- "parse-json": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
- "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
- "dev": true,
- "requires": {
- "error-ex": "^1.3.1",
- "json-parse-better-errors": "^1.0.1"
- }
- },
"path-exists": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
@@ -3049,27 +2916,12 @@
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
"dev": true
},
- "path-key": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
- "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=",
- "dev": true
- },
"path-parse": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
- "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
"dev": true
},
- "path-type": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz",
- "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==",
- "dev": true,
- "requires": {
- "pify": "^3.0.0"
- }
- },
"pg": {
"version": "7.18.2",
"resolved": "https://registry.npmjs.org/pg/-/pg-7.18.2.tgz",
@@ -3144,18 +2996,6 @@
"integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==",
"dev": true
},
- "pidtree": {
- "version": "0.3.1",
- "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.1.tgz",
- "integrity": "sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==",
- "dev": true
- },
- "pify": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
- "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
- "dev": true
- },
"pixelmatch": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/pixelmatch/-/pixelmatch-4.0.2.tgz",
@@ -3209,12 +3049,9 @@
"integrity": "sha512-yABh19CYbM24V7aS7TuPYRNMqthxwbvx6FF/Rw920YbyBWO3tnyPIqRMgHuSVsLmuHkkBS1Akyof463FVdkeDQ=="
},
"prismjs": {
- "version": "1.23.0",
- "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.23.0.tgz",
- "integrity": "sha512-c29LVsqOaLbBHuIbsTxaKENh1N2EQBOHaWv7gkHN4dgRbxSREqDnDbtFJYdpPauS4YCplMSNCABQ6Eeor69bAA==",
- "requires": {
- "clipboard": "^2.0.0"
- }
+ "version": "1.25.0",
+ "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.25.0.tgz",
+ "integrity": "sha512-WCjJHl1KEWbnkQom1+SzftbtXMKQoezOCYs5rECqMN+jP+apI7ftoflyqigqzopSO3hMhTEb0mFClA8lkolgEg=="
},
"process": {
"version": "0.11.10",
@@ -3231,17 +3068,6 @@
"safe-buffer": "^5.1.0"
}
},
- "read-pkg": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz",
- "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=",
- "dev": true,
- "requires": {
- "load-json-file": "^4.0.0",
- "normalize-package-data": "^2.3.2",
- "path-type": "^3.0.0"
- }
- },
"readable-stream": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
@@ -3448,12 +3274,6 @@
"integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==",
"dev": true
},
- "select": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz",
- "integrity": "sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0=",
- "optional": true
- },
"semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
@@ -3474,27 +3294,6 @@
"integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
"dev": true
},
- "shebang-command": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
- "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
- "dev": true,
- "requires": {
- "shebang-regex": "^1.0.0"
- }
- },
- "shebang-regex": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
- "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=",
- "dev": true
- },
- "shell-quote": {
- "version": "1.7.2",
- "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.2.tgz",
- "integrity": "sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==",
- "dev": true
- },
"shelljs": {
"version": "0.8.4",
"resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.4.tgz",
@@ -3552,38 +3351,6 @@
"integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==",
"dev": true
},
- "spdx-correct": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz",
- "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==",
- "dev": true,
- "requires": {
- "spdx-expression-parse": "^3.0.0",
- "spdx-license-ids": "^3.0.0"
- }
- },
- "spdx-exceptions": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz",
- "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==",
- "dev": true
- },
- "spdx-expression-parse": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
- "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
- "dev": true,
- "requires": {
- "spdx-exceptions": "^2.1.0",
- "spdx-license-ids": "^3.0.0"
- }
- },
- "spdx-license-ids": {
- "version": "3.0.7",
- "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.7.tgz",
- "integrity": "sha512-U+MTEOO0AiDzxwFvoa4JVnMV6mZlJKk2sBLt90s7G0Gd0Mlknc7kxEn3nuDPNZRta7O2uy8oLcZLVT+4sqNZHQ==",
- "dev": true
- },
"split2": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz",
@@ -3614,17 +3381,6 @@
"strip-ansi": "^4.0.0"
}
},
- "string.prototype.padend": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.1.tgz",
- "integrity": "sha512-eCzTASPnoCr5Ht+Vn1YXgm8SB015hHKgEIMu9Nr9bQmLhRBxKRfmzSj/IQsxDFc8JInJDDFA0qXwK+xxI7wDkg==",
- "dev": true,
- "requires": {
- "call-bind": "^1.0.0",
- "define-properties": "^1.1.3",
- "es-abstract": "^1.18.0-next.1"
- }
- },
"string.prototype.trimend": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.3.tgz",
@@ -3662,12 +3418,6 @@
"ansi-regex": "^3.0.0"
}
},
- "strip-bom": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
- "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
- "dev": true
- },
"strip-json-comments": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
@@ -3684,9 +3434,9 @@
}
},
"svelte": {
- "version": "3.31.0",
- "resolved": "https://registry.npmjs.org/svelte/-/svelte-3.31.0.tgz",
- "integrity": "sha512-r+n8UJkDqoQm1b+3tA3Lh6mHXKpcfOSOuEuIo5gE2W9wQYi64RYX/qE6CZBDDsP/H4M+N426JwY7XGH4xASvGQ==",
+ "version": "3.39.0",
+ "resolved": "https://registry.npmjs.org/svelte/-/svelte-3.39.0.tgz",
+ "integrity": "sha512-dcJCongL0cRkZWe9q+fde0T4HX8PksBywz2+EGDVIrdYdJaxTzrJu0RVeuDtL8Mx2hs4yn3W8zKPScuzG63hTg==",
"dev": true
},
"svelte-json-tree": {
@@ -3720,12 +3470,6 @@
"integrity": "sha512-IjZc9KIotudix8bMaBW6QvMuq64BrJWFs1+4V0lXwWGQZwH+LnX87doAYhem4caOEusRP9/g6jVDQmZ8XOk1nw==",
"dev": true
},
- "tiny-emitter": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz",
- "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==",
- "optional": true
- },
"tinycolor2": {
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.4.2.tgz",
@@ -3805,16 +3549,6 @@
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
},
- "validate-npm-package-license": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
- "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
- "dev": true,
- "requires": {
- "spdx-correct": "^3.0.0",
- "spdx-expression-parse": "^3.0.0"
- }
- },
"which": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
diff --git a/site/package.json b/site/package.json
index 6c1513b61d..1ece3a0d4b 100644
--- a/site/package.json
+++ b/site/package.json
@@ -3,11 +3,11 @@
"version": "1.0.0",
"description": "Docs and examples for Svelte",
"scripts": {
- "dev": "npm run copy-workers && sapper dev",
+ "dev": "node scripts/update.js && npm run copy-workers && sapper dev",
"copy-workers": "node scripts/copy-workers.js",
"migrate": "node-pg-migrate -r dotenv/config",
- "build": "npm run copy-workers && sapper build --legacy",
- "update": "node scripts/update_template.js && node scripts/get-contributors.js && node scripts/update_whos_using.js",
+ "build": "node scripts/update.js && npm run copy-workers && sapper build --legacy",
+ "update": "node scripts/update.js --force=true",
"start": "node __sapper__/build",
"test": "mocha -r esm test/**",
"deploy": "make deploy"
@@ -25,7 +25,7 @@
"pg": "^7.12.1",
"polka": "^1.0.0-next.9",
"prism-svelte": "^0.4.3",
- "prismjs": "^1.21.0",
+ "prismjs": "^1.25.0",
"sirv": "^1.0.0",
"yootils": "0.0.16"
},
@@ -41,7 +41,7 @@
"@rollup/plugin-node-resolve": "^11.0.0",
"@rollup/plugin-replace": "^2.2.0",
"@sindresorhus/slugify": "^0.9.1",
- "@sveltejs/site-kit": "^1.2.5",
+ "@sveltejs/site-kit": "^1.4.0",
"@sveltejs/svelte-repl": "^0.2.1",
"degit": "^2.1.4",
"dotenv": "^8.1.0",
@@ -50,13 +50,12 @@
"mocha": "^6.2.0",
"node-fetch": "^2.6.1",
"node-pg-migrate": "^3.22.0",
- "npm-run-all": "^4.1.5",
"rollup": "^2.30.0",
"rollup-plugin-svelte": "^7.0.0",
"rollup-plugin-terser": "^7.0.0",
"sapper": "^0.28.10",
"shelljs": "^0.8.3",
- "svelte": "^3.12.0"
+ "svelte": "^3.39.0"
},
"engines": {
"node": ">=10.0.0"
diff --git a/site/scripts/get-contributors.js b/site/scripts/get_contributors.js
similarity index 80%
rename from site/scripts/get-contributors.js
rename to site/scripts/get_contributors.js
index cb1facb874..4e360a019f 100644
--- a/site/scripts/get-contributors.js
+++ b/site/scripts/get_contributors.js
@@ -3,8 +3,16 @@ const fs = require('fs');
const fetch = require('node-fetch');
const Jimp = require('jimp');
+const force = process.env.FORCE_UPDATE === 'true';
+
process.chdir(__dirname);
+const outputFile = `../src/routes/_contributors.js`;
+if (!force && fs.existsSync(outputFile)) {
+ console.info(`[update/contributors] ${outputFile} exists. Skipping`);
+ process.exit(0);
+}
+
const base = `https://api.github.com/repos/sveltejs/svelte/contributors`;
const { GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET } = process.env;
@@ -24,6 +32,7 @@ async function main() {
}
const authors = contributors
+ .filter(({ login }) => !login.includes('[bot]'))
.sort((a, b) => b.contributions - a.contributions);
const sprite = new Jimp(SIZE * authors.length, SIZE);
@@ -47,7 +56,7 @@ async function main() {
const str = `[\n\t${authors.map(a => `'${a.login}'`).join(',\n\t')}\n]`;
- fs.writeFileSync(`../src/routes/_contributors.js`, `export default ${str};`);
+ fs.writeFileSync(outputFile, `export default ${str};`);
}
-main();
\ No newline at end of file
+main();
diff --git a/site/scripts/update.js b/site/scripts/update.js
new file mode 100644
index 0000000000..904e11bbd9
--- /dev/null
+++ b/site/scripts/update.js
@@ -0,0 +1,8 @@
+const sh = require('shelljs');
+
+sh.env['FORCE_UPDATE'] = process.argv.includes('--force=true');
+
+Promise.all([
+ sh.exec('node ./scripts/get_contributors.js'),
+ sh.exec('node ./scripts/update_template.js')
+]);
diff --git a/site/scripts/update_template.js b/site/scripts/update_template.js
index 9d897c064f..e683fad08e 100644
--- a/site/scripts/update_template.js
+++ b/site/scripts/update_template.js
@@ -1,7 +1,16 @@
const sh = require('shelljs');
const fs = require('fs');
+const path = require('path');
-sh.cd(__dirname + '/../');
+const force = process.env.FORCE_UPDATE === 'true';
+
+sh.cd(path.join(__dirname, '..'));
+
+const outputFile = 'static/svelte-app.json';
+if (!force && fs.existsSync(outputFile)) {
+ console.info(`[update/template] ${outputFile} exists. Skipping`);
+ process.exit(0);
+}
// fetch svelte app
sh.rm('-rf','scripts/svelte-app');
@@ -22,4 +31,4 @@ for (const path of sh.find(appPath).filter(p => fs.lstatSync(p).isFile()) ) {
files.push({ path: path.slice(appPath.length + 1), data });
}
-fs.writeFileSync('static/svelte-app.json', JSON.stringify(files));
\ No newline at end of file
+fs.writeFileSync(outputFile, JSON.stringify(files));
diff --git a/site/scripts/update_whos_using.js b/site/scripts/update_whos_using.js
deleted file mode 100644
index 36bc3bdc53..0000000000
--- a/site/scripts/update_whos_using.js
+++ /dev/null
@@ -1,13 +0,0 @@
-const sh = require('shelljs');
-
-sh.cd(__dirname + '/../');
-
-// fetch community repo
-sh.rm('-rf','scripts/community');
-sh.exec('npx degit sveltejs/community scripts/community');
-
-// copy over relevant files
-sh.cp('scripts/community/whos-using-svelte/WhosUsingSvelte.svelte', 'src/routes/_components/WhosUsingSvelte.svelte');
-sh.cp('scripts/community/whos-using-svelte/WhosUsingSvelte.js', 'src/routes/_components/WhosUsingSvelte.js');
-sh.rm('-rf', 'static/organisations');
-sh.cp('-r', 'scripts/community/whos-using-svelte/organisations', 'static');
diff --git a/site/src/components/ScreenToggle.svelte b/site/src/components/ScreenToggle.svelte
index a70d35bdeb..87d90aa7a8 100644
--- a/site/src/components/ScreenToggle.svelte
+++ b/site/src/components/ScreenToggle.svelte
@@ -20,9 +20,9 @@
margin: 0 .15em;
width: 4em;
height: 1em;
- padding: .2em .4em .3em;
+ padding: .3em .4em;
border-radius: var(--border-r);
- line-height: normal;
+ line-height: 1em;
box-sizing: content-box;
color: #888;
border: 1px solid var(--back-light);
diff --git a/site/src/routes/_components/WhosUsingSvelte.js b/site/src/routes/_components/WhosUsingSvelte.js
new file mode 100644
index 0000000000..430bc95867
--- /dev/null
+++ b/site/src/routes/_components/WhosUsingSvelte.js
@@ -0,0 +1,80 @@
+export const companies = [
+ {
+ href: "https://1password.com",
+ filename: "1password.svg",
+ alt: "1Password logo",
+ },
+ {
+ href: "https://www.alaskaair.com/",
+ style: "background-color: #01426a;",
+ filename: "alaskaairlines.svg",
+ alt: "Alaska Airlines logo",
+ },
+ {
+ href: "https://avast.com",
+ filename: "avast.svg",
+ alt: "Avast logo",
+ },
+ {
+ href: "https://chess.com",
+ style: "background-color: #312e2b;",
+ filename: "chess.svg",
+ alt: "Chess.com logo",
+ },
+ {
+ href: "https://fusioncharts.com",
+ filename: "fusioncharts.svg",
+ alt: "FusionCharts logo",
+ },
+ {
+ href: "https://godaddy.com",
+ filename: "godaddy.svg",
+ alt: "GoDaddy logo",
+ },
+ {
+ href: "https://www.ibm.com/",
+ filename: "ibm.svg",
+ alt: "IBM logo",
+ },
+ {
+ href: "https://media.lesechos.fr/infographie",
+ filename: "les-echos.svg",
+ alt: "Les Echos",
+ },
+ {
+ href: "https://www.philips.co.uk",
+ filename: "philips.svg",
+ alt: "Philips logo",
+ },
+ {
+ href: "https://global.rakuten.com/corp/",
+ filename: "rakuten.svg",
+ alt: "Rakuten logo",
+ },
+ {
+ href: "https://razorpay.com",
+ filename: "razorpay.svg",
+ alt: "Razorpay logo",
+ },
+ {
+ href: "https://www.se.com",
+ style: " background-color: #3dcd58; ",
+ filename: "Schneider_Electric.svg",
+ alt: "Schneider Electric",
+ },
+ {
+ href: "https://squareup.com",
+ filename: "square.svg",
+ alt: "Square",
+ },
+ {
+ href: "https://nytimes.com",
+ filename: "nyt.svg",
+ alt: "The New York Times logo",
+ },
+ {
+ href: "https://transloadit.com",
+ filename: "transloadit.svg",
+ alt: "Transloadit",
+ },
+];
diff --git a/site/src/routes/_components/WhosUsingSvelte.svelte b/site/src/routes/_components/WhosUsingSvelte.svelte
new file mode 100644
index 0000000000..d1de57fd2a
--- /dev/null
+++ b/site/src/routes/_components/WhosUsingSvelte.svelte
@@ -0,0 +1,65 @@
+
+
+
+
+
diff --git a/site/src/routes/_layout.svelte b/site/src/routes/_layout.svelte
index 55f4861880..936db61f8b 100644
--- a/site/src/routes/_layout.svelte
+++ b/site/src/routes/_layout.svelte
@@ -38,13 +38,13 @@
{#if $page.path !== '/repl/embed'}
Tutorial
- API
+ Docs
Examples
REPL
Blog
FAQ
- Sapper
+ SvelteKit
diff --git a/site/src/routes/docs/index.svelte b/site/src/routes/docs/index.svelte
index a276b0edb7..ea79d7f5c9 100644
--- a/site/src/routes/docs/index.svelte
+++ b/site/src/routes/docs/index.svelte
@@ -1,6 +1,23 @@
diff --git a/site/src/routes/repl/[id]/_components/AppControls/index.svelte b/site/src/routes/repl/[id]/_components/AppControls/index.svelte
index c2e5684944..55a1d24e28 100644
--- a/site/src/routes/repl/[id]/_components/AppControls/index.svelte
+++ b/site/src/routes/repl/[id]/_components/AppControls/index.svelte
@@ -16,7 +16,6 @@
export let gist;
export let name;
export let zen_mode;
- export let bundle;
let saving = false;
let downloading = false;
diff --git a/site/src/routes/repl/[id]/index.svelte b/site/src/routes/repl/[id]/index.svelte
index 945678ba33..70b843724c 100644
--- a/site/src/routes/repl/[id]/index.svelte
+++ b/site/src/routes/repl/[id]/index.svelte
@@ -167,27 +167,10 @@
z-index: 111;
}
- .pane { width: 100%; height: 100% }
-
- .loading {
- text-align: center;
- color: var(--second);
- font-weight: 400;
- margin: 2em 0 0 0;
- opacity: 0;
- animation: fade-in .4s;
- animation-delay: .2s;
- animation-fill-mode: both;
- }
-
@keyframes fade-in {
0% { opacity: 0 }
100% { opacity: 1 }
}
-
- .input {
- padding: 2.4em 0 0 0;
- }
diff --git a/site/src/routes/tutorial/[slug]/index.svelte b/site/src/routes/tutorial/[slug]/index.svelte
index bcb9a9b24a..bc7ed6bfe5 100644
--- a/site/src/routes/tutorial/[slug]/index.svelte
+++ b/site/src/routes/tutorial/[slug]/index.svelte
@@ -243,11 +243,10 @@
}
.improve-chapter a {
- padding: 0 .1em;
font-size: 14px;
text-decoration: none;
opacity: .3;
- padding-left: 1.2em;
+ padding: 0 .1em 0 1.2em;
background: no-repeat 0 50% url(/icons/edit.svg);
background-size: 1em 1em;
}
diff --git a/site/src/server.js b/site/src/server.js
index 6990d94265..cb40b56fa5 100644
--- a/site/src/server.js
+++ b/site/src/server.js
@@ -4,7 +4,11 @@ import sirv from 'sirv';
import * as sapper from '@sapper/server';
import { sanitize_user, authenticate } from './utils/auth';
-const { PORT = 3000 } = process.env;
+if (!process.env.PORT) {
+ process.env.PORT = 3000;
+}
+
+const { PORT } = process.env;
const app = polka({
onError: (err, req, res) => {
diff --git a/site/static/whos-using-svelte/1password.svg b/site/static/whos-using-svelte/1password.svg
new file mode 100644
index 0000000000..ba8a63c014
--- /dev/null
+++ b/site/static/whos-using-svelte/1password.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/site/static/whos-using-svelte/Schneider_Electric.svg b/site/static/whos-using-svelte/Schneider_Electric.svg
new file mode 100644
index 0000000000..c70ca1fceb
--- /dev/null
+++ b/site/static/whos-using-svelte/Schneider_Electric.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/site/static/whos-using-svelte/alaskaairlines.svg b/site/static/whos-using-svelte/alaskaairlines.svg
new file mode 100644
index 0000000000..15d172c08b
--- /dev/null
+++ b/site/static/whos-using-svelte/alaskaairlines.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/site/static/whos-using-svelte/avast.svg b/site/static/whos-using-svelte/avast.svg
new file mode 100644
index 0000000000..736eeff3d9
--- /dev/null
+++ b/site/static/whos-using-svelte/avast.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/site/static/whos-using-svelte/chess.svg b/site/static/whos-using-svelte/chess.svg
new file mode 100644
index 0000000000..bd85352a52
--- /dev/null
+++ b/site/static/whos-using-svelte/chess.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/site/static/whos-using-svelte/fusioncharts.svg b/site/static/whos-using-svelte/fusioncharts.svg
new file mode 100644
index 0000000000..147dd9e026
--- /dev/null
+++ b/site/static/whos-using-svelte/fusioncharts.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/site/static/whos-using-svelte/godaddy.svg b/site/static/whos-using-svelte/godaddy.svg
new file mode 100644
index 0000000000..df39638281
--- /dev/null
+++ b/site/static/whos-using-svelte/godaddy.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/site/static/whos-using-svelte/ibm.svg b/site/static/whos-using-svelte/ibm.svg
new file mode 100644
index 0000000000..d8982a47ab
--- /dev/null
+++ b/site/static/whos-using-svelte/ibm.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/site/static/whos-using-svelte/les-echos.svg b/site/static/whos-using-svelte/les-echos.svg
new file mode 100644
index 0000000000..6ab7eddeef
--- /dev/null
+++ b/site/static/whos-using-svelte/les-echos.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/site/static/whos-using-svelte/nyt.svg b/site/static/whos-using-svelte/nyt.svg
new file mode 100644
index 0000000000..cef76f1afb
--- /dev/null
+++ b/site/static/whos-using-svelte/nyt.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/site/static/whos-using-svelte/philips.svg b/site/static/whos-using-svelte/philips.svg
new file mode 100644
index 0000000000..5f6c7fa343
--- /dev/null
+++ b/site/static/whos-using-svelte/philips.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/site/static/whos-using-svelte/rakuten.svg b/site/static/whos-using-svelte/rakuten.svg
new file mode 100644
index 0000000000..67b59c8354
--- /dev/null
+++ b/site/static/whos-using-svelte/rakuten.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/site/static/whos-using-svelte/razorpay.svg b/site/static/whos-using-svelte/razorpay.svg
new file mode 100644
index 0000000000..b430dc5a5b
--- /dev/null
+++ b/site/static/whos-using-svelte/razorpay.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/site/static/whos-using-svelte/square.svg b/site/static/whos-using-svelte/square.svg
new file mode 100644
index 0000000000..d1b0689c61
--- /dev/null
+++ b/site/static/whos-using-svelte/square.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/site/static/whos-using-svelte/transloadit.svg b/site/static/whos-using-svelte/transloadit.svg
new file mode 100644
index 0000000000..f3383655bb
--- /dev/null
+++ b/site/static/whos-using-svelte/transloadit.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/compiler/compile/Component.ts b/src/compiler/compile/Component.ts
index 155b64778b..202e14fd98 100644
--- a/src/compiler/compile/Component.ts
+++ b/src/compiler/compile/Component.ts
@@ -19,20 +19,23 @@ import error from '../utils/error';
import get_code_frame from '../utils/get_code_frame';
import flatten_reference from './utils/flatten_reference';
import is_used_as_reference from './utils/is_used_as_reference';
-import is_reference from 'is-reference';
+import is_reference, { NodeWithPropertyDefinition } from 'is-reference';
import TemplateScope from './nodes/shared/TemplateScope';
import fuzzymatch from '../utils/fuzzymatch';
import get_object from './utils/get_object';
import Slot from './nodes/Slot';
-import { Node, ImportDeclaration, Identifier, Program, ExpressionStatement, AssignmentExpression, Literal } from 'estree';
+import { Node, ImportDeclaration, ExportNamedDeclaration, Identifier, ExpressionStatement, AssignmentExpression, Literal, Property, RestElement, ExportDefaultDeclaration, ExportAllDeclaration } from 'estree';
import add_to_set from './utils/add_to_set';
import check_graph_for_cycles from './utils/check_graph_for_cycles';
-import { print, x, b } from 'code-red';
+import { print, b } from 'code-red';
import { is_reserved_keyword } from './utils/reserved_keywords';
import { apply_preprocessor_sourcemap } from '../utils/mapped_code';
import Element from './nodes/Element';
import { DecodedSourceMap, RawSourceMap } from '@ampproject/remapping/dist/types/types';
import { clone } from '../utils/clone';
+import compiler_warnings from './compiler_warnings';
+import compiler_errors from './compiler_errors';
+import { extract_ignores_above_position, extract_svelte_ignore_from_comments } from '../utils/extract_svelte_ignore';
interface ComponentOptions {
namespace?: string;
@@ -67,6 +70,8 @@ export default class Component {
var_lookup: Map = new Map();
imports: ImportDeclaration[] = [];
+ exports_from: ExportNamedDeclaration[] = [];
+ instance_exports_from: ExportNamedDeclaration[] = [];
hoistable_nodes: Set = new Set();
node_for_declaration: Map = new Map();
@@ -160,10 +165,7 @@ export default class Component {
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.warn(svelteOptions, compiler_warnings.custom_element_no_tag);
}
this.tag = this.component_options.tag || compile_options.tag;
} else {
@@ -171,21 +173,29 @@ export default class Component {
}
this.walk_module_js();
+
+ this.push_ignores(this.ast.instance ? extract_ignores_above_position(this.ast.instance.start, this.ast.html.children) : []);
this.walk_instance_js_pre_template();
+ this.pop_ignores();
this.fragment = new Fragment(this, ast.html);
this.name = this.get_unique_name(name);
+ this.push_ignores(this.ast.instance ? extract_ignores_above_position(this.ast.instance.start, this.ast.html.children) : []);
this.walk_instance_js_post_template();
+ this.pop_ignores();
this.elements.forEach(element => this.stylesheet.apply(element));
if (!compile_options.customElement) this.stylesheet.reify();
this.stylesheet.warn_on_unused_selectors(this);
}
- add_var(variable: Var) {
+ add_var(variable: Var, add_to_lookup = true) {
this.vars.push(variable);
- this.var_lookup.set(variable.name, variable);
+
+ if (add_to_lookup) {
+ this.var_lookup.set(variable.name, variable);
+ }
}
add_reference(name: string) {
@@ -216,6 +226,10 @@ export default class Component {
variable.subscribable = true;
}
} else {
+ if (this.compile_options.varsReport === 'full') {
+ this.add_var({ name, referenced: true }, false);
+ }
+
this.used_names.add(name);
}
}
@@ -260,6 +274,14 @@ export default class Component {
} else {
let name = node.name.slice(1);
+ if (compile_options.hydratable) {
+ if (internal_exports.has(`${name}_hydration`)) {
+ name += '_hydration';
+ } else if (internal_exports.has(`${name}Hydration`)) {
+ name += 'Hydration';
+ }
+ }
+
if (compile_options.dev) {
if (internal_exports.has(`${name}_dev`)) {
name += '_dev';
@@ -313,26 +335,29 @@ export default class Component {
.map(variable => ({
name: variable.name,
as: variable.export_name
- }))
+ })),
+ this.exports_from
);
css = compile_options.customElement
? { code: null, map: null }
: result.css;
+ const sourcemap_source_filename = get_sourcemap_source_filename(compile_options);
+
js = print(program, {
- sourceMapSource: compile_options.filename
+ sourceMapSource: sourcemap_source_filename
});
js.map.sources = [
- compile_options.filename ? get_relative_path(compile_options.outputFilename || '', compile_options.filename) : null
+ sourcemap_source_filename
];
js.map.sourcesContent = [
this.source
];
- js.map = apply_preprocessor_sourcemap(this.file, js.map, compile_options.sourcemap as (string | RawSourceMap | DecodedSourceMap));
+ js.map = apply_preprocessor_sourcemap(sourcemap_source_filename, js.map, compile_options.sourcemap as (string | RawSourceMap | DecodedSourceMap));
}
return {
@@ -340,19 +365,7 @@ export default class Component {
css,
ast: this.original_ast,
warnings: this.warnings,
- vars: this.vars
- .filter(v => !v.global && !v.internal)
- .map(v => ({
- name: v.name,
- export_name: v.export_name || null,
- injected: v.injected || false,
- module: v.module || false,
- mutated: v.mutated || false,
- reassigned: v.reassigned || false,
- referenced: v.referenced || false,
- writable: v.writable || false,
- referenced_from_script: v.referenced_from_script || false
- })),
+ vars: this.get_vars_report(),
stats: this.stats.render()
};
}
@@ -402,6 +415,28 @@ export default class Component {
};
}
+ get_vars_report(): Var[] {
+ const { compile_options, vars } = this;
+
+ const vars_report = compile_options.varsReport === false
+ ? []
+ : compile_options.varsReport === 'full'
+ ? vars
+ : vars.filter(v => !v.global && !v.internal);
+
+ return vars_report.map(v => ({
+ name: v.name,
+ export_name: v.export_name || null,
+ injected: v.injected || false,
+ module: v.module || false,
+ mutated: v.mutated || false,
+ reassigned: v.reassigned || false,
+ referenced: v.referenced || false,
+ writable: v.writable || false,
+ referenced_from_script: v.referenced_from_script || false
+ }));
+ }
+
error(
pos: {
start: number;
@@ -412,14 +447,18 @@ export default class Component {
message: string;
}
) {
- error(e.message, {
- name: 'ValidationError',
- code: e.code,
- source: this.source,
- start: pos.start,
- end: pos.end,
- filename: this.compile_options.filename
- });
+ if (this.compile_options.errorMode === 'warn') {
+ this.warn(pos, e);
+ } else {
+ error(e.message, {
+ name: 'ValidationError',
+ code: e.code,
+ source: this.source,
+ start: pos.start,
+ end: pos.end,
+ filename: this.compile_options.filename
+ });
+ }
}
warn(
@@ -458,20 +497,27 @@ export default class Component {
this.imports.push(node);
}
- extract_exports(node) {
+ extract_exports(node, module_script = false) {
+ const ignores = extract_svelte_ignore_from_comments(node);
+ if (ignores.length) this.push_ignores(ignores);
+ const result = this._extract_exports(node, module_script);
+ if (ignores.length) this.pop_ignores();
+ return result;
+ }
+
+ private _extract_exports(node: ExportDefaultDeclaration | ExportNamedDeclaration | ExportAllDeclaration, module_script) {
if (node.type === 'ExportDefaultDeclaration') {
- this.error(node, {
- code: 'default-export',
- message: 'A component cannot have a default export'
- });
+ return this.error(node as any, compiler_errors.default_export);
}
if (node.type === 'ExportNamedDeclaration') {
if (node.source) {
- this.error(node, {
- code: 'not-implemented',
- message: 'A component currently cannot have an export ... from'
- });
+ if (module_script) {
+ this.exports_from.push(node);
+ } else {
+ this.instance_exports_from.push(node);
+ }
+ return null;
}
if (node.declaration) {
if (node.declaration.type === 'VariableDeclaration') {
@@ -480,10 +526,7 @@ export default class Component {
const variable = this.var_lookup.get(name);
variable.export_name = name;
if (variable.writable && !(variable.referenced || variable.referenced_from_script || variable.subscribable)) {
- this.warn(declarator, {
- code: 'unused-export-let',
- message: `${this.name.name} has unused export property '${name}'. If it is for external reference only, please consider using \`export const ${name}\``
- });
+ this.warn(declarator as any, compiler_warnings.unused_export_let(this.name.name, name));
}
});
});
@@ -503,10 +546,7 @@ export default class Component {
variable.export_name = specifier.exported.name;
if (variable.writable && !(variable.referenced || variable.referenced_from_script || variable.subscribable)) {
- this.warn(specifier, {
- code: 'unused-export-let',
- message: `${this.name.name} has unused export property '${specifier.exported.name}'. If it is for external reference only, please consider using \`export const ${specifier.exported.name}\``
- });
+ this.warn(specifier as any, compiler_warnings.unused_export_let(this.name.name, specifier.exported.name));
}
}
});
@@ -537,10 +577,7 @@ export default class Component {
walk(script.content, {
enter(node: Node) {
if (node.type === 'LabeledStatement' && node.label.name === '$') {
- component.warn(node as any, {
- code: 'module-script-reactive-declaration',
- message: '$: has no effect in a module script'
- });
+ component.warn(node as any, compiler_warnings.module_script_reactive_declaration);
}
}
});
@@ -550,10 +587,7 @@ export default class Component {
scope.declarations.forEach((node, name) => {
if (name[0] === '$') {
- this.error(node as any, {
- code: 'illegal-declaration',
- message: 'The $ prefix is reserved, and cannot be used for variable and import names'
- });
+ return this.error(node as any, compiler_errors.illegal_declaration);
}
const writable = node.type === 'VariableDeclaration' && (node.kind === 'var' || node.kind === 'let');
@@ -568,10 +602,7 @@ export default class Component {
globals.forEach((node, name) => {
if (name[0] === '$') {
- this.error(node as any, {
- code: 'illegal-subscription',
- message: 'Cannot reference store value inside ';
+import parser_errors from '../errors';
function get_context(parser: Parser, attributes: any[], start: number): string {
const context = attributes.find(attribute => attribute.name === 'context');
if (!context) return 'default';
if (context.value.length !== 1 || context.value[0].type !== 'Text') {
- parser.error({
- code: 'invalid-script',
- message: 'context attribute must be static'
- }, start);
+ parser.error(parser_errors.invalid_script_context_attribute, start);
}
const value = context.value[0].data;
if (value !== 'module') {
- parser.error({
- code: 'invalid-script',
- message: 'If the context attribute is supplied, its value must be "module"'
- }, context.start);
+ parser.error(parser_errors.invalid_script_context_value, context.start);
}
return value;
@@ -30,18 +23,13 @@ function get_context(parser: Parser, attributes: any[], start: number): string {
export default function read_script(parser: Parser, start: number, attributes: Node[]): Script {
const script_start = parser.index;
- const script_end = parser.template.indexOf(script_closing_tag, script_start);
-
- if (script_end === -1) {
- parser.error({
- code: 'unclosed-script',
- message: '
*
* ```
- *
+ *
* #### Why not make this part of `SvelteComponent(Dev)`?
* Because
* ```ts
* class ASubclassOfSvelteComponent extends SvelteComponent<{foo: string}> {}
* const component: typeof SvelteComponent = ASubclassOfSvelteComponent;
* ```
- * will throw a type error, so we need to seperate the more strictly typed class.
+ * will throw a type error, so we need to separate the more strictly typed class.
*/
export class SvelteComponentTyped<
Props extends Record = any,
@@ -235,14 +248,7 @@ export class SvelteComponentTyped<
*/
$$slot_def: Slots;
- constructor(options: {
- target: Element;
- anchor?: Element;
- props?: Props;
- hydrate?: boolean;
- intro?: boolean;
- $$inline?: boolean;
- }) {
+ constructor(options: IComponentOptions) {
super(options);
}
}
diff --git a/src/runtime/internal/dom.ts b/src/runtime/internal/dom.ts
index 8d99234c9d..eb3389e3f8 100644
--- a/src/runtime/internal/dom.ts
+++ b/src/runtime/internal/dom.ts
@@ -1,13 +1,207 @@
import { has_prop } from './utils';
+// Track which nodes are claimed during hydration. Unclaimed nodes can then be removed from the DOM
+// at the end of hydration without touching the remaining nodes.
+let is_hydrating = false;
+
+export function start_hydrating() {
+ is_hydrating = true;
+}
+export function end_hydrating() {
+ is_hydrating = false;
+}
+
+type NodeEx = Node & {
+ claim_order?: number,
+ hydrate_init? : true,
+ actual_end_child?: NodeEx,
+ childNodes: NodeListOf,
+};
+
+function upper_bound(low: number, high: number, key: (index: number) => number, value: number) {
+ // Return first index of value larger than input value in the range [low, high)
+ while (low < high) {
+ const mid = low + ((high - low) >> 1);
+ if (key(mid) <= value) {
+ low = mid + 1;
+ } else {
+ high = mid;
+ }
+ }
+ return low;
+}
+
+function init_hydrate(target: NodeEx) {
+ if (target.hydrate_init) return;
+ target.hydrate_init = true;
+
+ type NodeEx2 = NodeEx & {claim_order: number};
+
+ // We know that all children have claim_order values since the unclaimed have been detached if target is not
+ let children: ArrayLike = target.childNodes as NodeListOf;
+
+ // If target is , there may be children without claim_order
+ if (target.nodeName === 'HEAD') {
+ const myChildren = [];
+ for (let i = 0; i < children.length; i++) {
+ const node = children[i];
+ if (node.claim_order !== undefined) {
+ myChildren.push(node);
+ }
+ }
+ children = myChildren;
+ }
+
+ /*
+ * Reorder claimed children optimally.
+ * We can reorder claimed children optimally by finding the longest subsequence of
+ * nodes that are already claimed in order and only moving the rest. The longest
+ * subsequence subsequence of nodes that are claimed in order can be found by
+ * computing the longest increasing subsequence of .claim_order values.
+ *
+ * This algorithm is optimal in generating the least amount of reorder operations
+ * possible.
+ *
+ * Proof:
+ * We know that, given a set of reordering operations, the nodes that do not move
+ * always form an increasing subsequence, since they do not move among each other
+ * meaning that they must be already ordered among each other. Thus, the maximal
+ * set of nodes that do not move form a longest increasing subsequence.
+ */
+
+ // Compute longest increasing subsequence
+ // m: subsequence length j => index k of smallest value that ends an increasing subsequence of length j
+ const m = new Int32Array(children.length + 1);
+ // Predecessor indices + 1
+ const p = new Int32Array(children.length);
+
+ m[0] = -1;
+ let longest = 0;
+ for (let i = 0; i < children.length; i++) {
+ const current = children[i].claim_order;
+ // Find the largest subsequence length such that it ends in a value less than our current value
+
+ // upper_bound returns first greater value, so we subtract one
+ // with fast path for when we are on the current longest subsequence
+ const seqLen = ((longest > 0 && children[m[longest]].claim_order <= current) ? longest + 1 : upper_bound(1, longest, idx => children[m[idx]].claim_order, current)) - 1;
+
+ p[i] = m[seqLen] + 1;
+
+ const newLen = seqLen + 1;
+
+ // We can guarantee that current is the smallest value. Otherwise, we would have generated a longer sequence.
+ m[newLen] = i;
+
+ longest = Math.max(newLen, longest);
+ }
+
+ // The longest increasing subsequence of nodes (initially reversed)
+ const lis: NodeEx2[] = [];
+ // The rest of the nodes, nodes that will be moved
+ const toMove: NodeEx2[] = [];
+ let last = children.length - 1;
+ for (let cur = m[longest] + 1; cur != 0; cur = p[cur - 1]) {
+ lis.push(children[cur - 1]);
+ for (; last >= cur; last--) {
+ toMove.push(children[last]);
+ }
+ last--;
+ }
+ for (; last >= 0; last--) {
+ toMove.push(children[last]);
+ }
+ lis.reverse();
+
+ // We sort the nodes being moved to guarantee that their insertion order matches the claim order
+ toMove.sort((a, b) => a.claim_order - b.claim_order);
+
+ // Finally, we move the nodes
+ for (let i = 0, j = 0; i < toMove.length; i++) {
+ while (j < lis.length && toMove[i].claim_order >= lis[j].claim_order) {
+ j++;
+ }
+ const anchor = j < lis.length ? lis[j] : null;
+ target.insertBefore(toMove[i], anchor);
+ }
+}
+
export function append(target: Node, node: Node) {
target.appendChild(node);
}
+export function append_styles(
+ target: Node,
+ style_sheet_id: string,
+ styles: string
+) {
+ const append_styles_to = get_root_for_style(target);
+
+ if (!append_styles_to.getElementById(style_sheet_id)) {
+ const style = element('style');
+ style.id = style_sheet_id;
+ style.textContent = styles;
+ append_stylesheet(append_styles_to, style);
+ }
+}
+
+export function get_root_for_style(node: Node): ShadowRoot | Document {
+ if (!node) return document;
+
+ const root = node.getRootNode ? node.getRootNode() : node.ownerDocument;
+ if (root && (root as ShadowRoot).host) {
+ return root as ShadowRoot;
+ }
+ return node.ownerDocument;
+}
+
+export function append_empty_stylesheet(node: Node) {
+ const style_element = element('style') as HTMLStyleElement;
+ append_stylesheet(get_root_for_style(node), style_element);
+ return style_element;
+}
+
+function append_stylesheet(node: ShadowRoot | Document, style: HTMLStyleElement) {
+ append((node as Document).head || node, style);
+}
+
+export function append_hydration(target: NodeEx, node: NodeEx) {
+ if (is_hydrating) {
+ init_hydrate(target);
+
+ if ((target.actual_end_child === undefined) || ((target.actual_end_child !== null) && (target.actual_end_child.parentElement !== target))) {
+ target.actual_end_child = target.firstChild;
+ }
+
+ // Skip nodes of undefined ordering
+ while ((target.actual_end_child !== null) && (target.actual_end_child.claim_order === undefined)) {
+ target.actual_end_child = target.actual_end_child.nextSibling;
+ }
+
+ if (node !== target.actual_end_child) {
+ // We only insert if the ordering of this node should be modified or the parent node is not target
+ if (node.claim_order !== undefined || node.parentNode !== target) {
+ target.insertBefore(node, target.actual_end_child);
+ }
+ } else {
+ target.actual_end_child = node.nextSibling;
+ }
+ } else if (node.parentNode !== target || node.nextSibling !== null) {
+ target.appendChild(node);
+ }
+}
+
export function insert(target: Node, node: Node, anchor?: Node) {
target.insertBefore(node, anchor || null);
}
+export function insert_hydration(target: NodeEx, node: NodeEx, anchor?: NodeEx) {
+ if (is_hydrating && !anchor) {
+ append_hydration(target, node);
+ } else if (node.parentNode !== target || node.nextSibling != anchor) {
+ target.insertBefore(node, anchor || null);
+ }
+}
+
export function detach(node: Node) {
node.parentNode.removeChild(node);
}
@@ -85,6 +279,13 @@ export function self(fn) {
};
}
+export function trusted(fn) {
+ return function(event) {
+ // @ts-ignore
+ if (event.isTrusted) fn.call(this, event);
+ };
+}
+
export function attr(node: Element, attribute: string, value?: string) {
if (value == null) node.removeAttribute(attribute);
else if (node.getAttribute(attribute) !== value) node.setAttribute(attribute, value);
@@ -116,7 +317,7 @@ export function set_svg_attributes(node: Element & ElementCSSInlineStyle, attrib
export function set_custom_element_data(node, prop, value) {
if (prop in node) {
- node[prop] = value;
+ node[prop] = typeof node[prop] === 'boolean' && value === '' ? true : value;
} else {
attr(node, prop, value);
}
@@ -149,46 +350,166 @@ export function time_ranges_to_array(ranges) {
return array;
}
-export function children(element) {
+type ChildNodeEx = ChildNode & NodeEx;
+
+type ChildNodeArray = ChildNodeEx[] & {
+ claim_info?: {
+ /**
+ * The index of the last claimed element
+ */
+ last_index: number;
+ /**
+ * The total number of elements claimed
+ */
+ total_claimed: number;
+ }
+};
+
+export function children(element: Element) {
return Array.from(element.childNodes);
}
-export function claim_element(nodes, name, attributes, svg) {
- for (let i = 0; i < nodes.length; i += 1) {
- const node = nodes[i];
- if (node.nodeName === name) {
- let j = 0;
+function init_claim_info(nodes: ChildNodeArray) {
+ if (nodes.claim_info === undefined) {
+ nodes.claim_info = {last_index: 0, total_claimed: 0};
+ }
+}
+
+function claim_node(nodes: ChildNodeArray, predicate: (node: ChildNodeEx) => node is R, processNode: (node: ChildNodeEx) => ChildNodeEx | undefined, createNode: () => R, dontUpdateLastIndex: boolean = false) {
+ // Try to find nodes in an order such that we lengthen the longest increasing subsequence
+ init_claim_info(nodes);
+
+ const resultNode = (() => {
+ // We first try to find an element after the previous one
+ for (let i = nodes.claim_info.last_index; i < nodes.length; i++) {
+ const node = nodes[i];
+
+ if (predicate(node)) {
+ const replacement = processNode(node);
+
+ if (replacement === undefined) {
+ nodes.splice(i, 1);
+ } else {
+ nodes[i] = replacement;
+ }
+ if (!dontUpdateLastIndex) {
+ nodes.claim_info.last_index = i;
+ }
+ return node;
+ }
+ }
+
+
+ // Otherwise, we try to find one before
+ // We iterate in reverse so that we don't go too far back
+ for (let i = nodes.claim_info.last_index - 1; i >= 0; i--) {
+ const node = nodes[i];
+
+ if (predicate(node)) {
+ const replacement = processNode(node);
+
+ if (replacement === undefined) {
+ nodes.splice(i, 1);
+ } else {
+ nodes[i] = replacement;
+ }
+ if (!dontUpdateLastIndex) {
+ nodes.claim_info.last_index = i;
+ } else if (replacement === undefined) {
+ // Since we spliced before the last_index, we decrease it
+ nodes.claim_info.last_index--;
+ }
+ return node;
+ }
+ }
+
+ // If we can't find any matching node, we create a new one
+ return createNode();
+ })();
+
+ resultNode.claim_order = nodes.claim_info.total_claimed;
+ nodes.claim_info.total_claimed += 1;
+ return resultNode;
+}
+
+function claim_element_base(nodes: ChildNodeArray, name: string, attributes: { [key: string]: boolean }, create_element: (name: string) => Element | SVGElement) {
+ return claim_node(
+ nodes,
+ (node: ChildNode): node is Element | SVGElement => node.nodeName === name,
+ (node: Element) => {
const remove = [];
- while (j < node.attributes.length) {
- const attribute = node.attributes[j++];
+ for (let j = 0; j < node.attributes.length; j++) {
+ const attribute = node.attributes[j];
if (!attributes[attribute.name]) {
remove.push(attribute.name);
}
}
- for (let k = 0; k < remove.length; k++) {
- node.removeAttribute(remove[k]);
+ remove.forEach(v => node.removeAttribute(v));
+ return undefined;
+ },
+ () => create_element(name)
+ );
+}
+
+export function claim_element(nodes: ChildNodeArray, name: string, attributes: { [key: string]: boolean }) {
+ return claim_element_base(nodes, name, attributes, element);
+}
+
+export function claim_svg_element(nodes: ChildNodeArray, name: string, attributes: { [key: string]: boolean }) {
+ return claim_element_base(nodes, name, attributes, svg_element);
+}
+
+export function claim_text(nodes: ChildNodeArray, data) {
+ return claim_node(
+ nodes,
+ (node: ChildNode): node is Text => node.nodeType === 3,
+ (node: Text) => {
+ const dataStr = '' + data;
+ if (node.data.startsWith(dataStr)) {
+ if (node.data.length !== dataStr.length) {
+ return node.splitText(dataStr.length);
+ }
+ } else {
+ node.data = dataStr;
}
- return nodes.splice(i, 1)[0];
- }
- }
+ },
+ () => text(data),
+ true // Text nodes should not update last index since it is likely not worth it to eliminate an increasing subsequence of actual elements
+ );
+}
- return svg ? svg_element(name) : element(name);
+export function claim_space(nodes) {
+ return claim_text(nodes, ' ');
}
-export function claim_text(nodes, data) {
- for (let i = 0; i < nodes.length; i += 1) {
+function find_comment(nodes, text, start) {
+ for (let i = start; i < nodes.length; i += 1) {
const node = nodes[i];
- if (node.nodeType === 3) {
- node.data = '' + data;
- return nodes.splice(i, 1)[0];
+ if (node.nodeType === 8 /* comment node */ && node.textContent.trim() === text) {
+ return i;
}
}
-
- return text(data);
+ return nodes.length;
}
-export function claim_space(nodes) {
- return claim_text(nodes, ' ');
+export function claim_html_tag(nodes) {
+ // find html opening tag
+ const start_index = find_comment(nodes, 'HTML_TAG_START', 0);
+ const end_index = find_comment(nodes, 'HTML_TAG_END', start_index);
+ if (start_index === end_index) {
+ return new HtmlTagHydration();
+ }
+
+ init_claim_info(nodes);
+ const html_tag_nodes = nodes.splice(start_index, end_index + 1);
+ detach(html_tag_nodes[0]);
+ detach(html_tag_nodes[html_tag_nodes.length - 1]);
+ const claimed_nodes = html_tag_nodes.slice(1, html_tag_nodes.length - 1);
+ for (const n of claimed_nodes) {
+ n.claim_order = nodes.claim_info.total_claimed;
+ nodes.claim_info.total_claimed += 1;
+ }
+ return new HtmlTagHydration(claimed_nodes);
}
export function set_data(text, data) {
@@ -221,6 +542,8 @@ export function select_option(select, value) {
return;
}
}
+
+ select.selectedIndex = -1; // no option should be selected
}
export function select_options(select, value) {
@@ -307,38 +630,45 @@ export function toggle_class(element, name, toggle) {
element.classList[toggle ? 'add' : 'remove'](name);
}
-export function custom_event(type: string, detail?: T) {
+export function custom_event(type: string, detail?: T, bubbles: boolean = false) {
const e: CustomEvent = document.createEvent('CustomEvent');
- e.initCustomEvent(type, false, false, detail);
+ e.initCustomEvent(type, bubbles, false, detail);
return e;
}
export function query_selector_all(selector: string, parent: HTMLElement = document.body) {
- return Array.from(parent.querySelectorAll(selector));
+ return Array.from(parent.querySelectorAll(selector)) as ChildNodeArray;
}
export class HtmlTag {
+ // parent for creating node
e: HTMLElement;
+ // html tag nodes
n: ChildNode[];
+ // target
t: HTMLElement;
+ // anchor
a: HTMLElement;
- constructor(anchor: HTMLElement = null) {
- this.a = anchor;
+ constructor() {
this.e = this.n = null;
}
+ c(html: string) {
+ this.h(html);
+ }
+
m(html: string, target: HTMLElement, anchor: HTMLElement = null) {
if (!this.e) {
this.e = element(target.nodeName as keyof HTMLElementTagNameMap);
this.t = target;
- this.h(html);
+ this.c(html);
}
this.i(anchor);
}
- h(html) {
+ h(html: string) {
this.e.innerHTML = html;
this.n = Array.from(this.e.childNodes);
}
@@ -360,6 +690,29 @@ export class HtmlTag {
}
}
+export class HtmlTagHydration extends HtmlTag {
+ // hydration claimed nodes
+ l: ChildNode[] | void;
+
+ constructor(claimed_nodes?: ChildNode[]) {
+ super();
+ this.e = this.n = null;
+ this.l = claimed_nodes;
+ }
+ c(html: string) {
+ if (this.l) {
+ this.n = this.l;
+ } else {
+ super.c(html);
+ }
+ }
+ i(anchor) {
+ for (let i = 0; i < this.n.length; i += 1) {
+ insert_hydration(this.t, this.n[i], anchor);
+ }
+ }
+}
+
export function attribute_to_object(attributes: NamedNodeMap) {
const result = {};
for (const attribute of attributes) {
diff --git a/src/runtime/internal/lifecycle.ts b/src/runtime/internal/lifecycle.ts
index 002bd78d24..bb3df3d295 100644
--- a/src/runtime/internal/lifecycle.ts
+++ b/src/runtime/internal/lifecycle.ts
@@ -54,6 +54,10 @@ export function getContext(key): T {
return get_current_component().$$.context.get(key);
}
+export function getAllContexts = Map>(): T {
+ return get_current_component().$$.context;
+}
+
export function hasContext(key): boolean {
return get_current_component().$$.context.has(key);
}
@@ -65,6 +69,7 @@ export function bubble(component, event) {
const callbacks = component.$$.callbacks[event.type];
if (callbacks) {
- callbacks.slice().forEach(fn => fn(event));
+ // @ts-ignore
+ callbacks.slice().forEach(fn => fn.call(this, event));
}
}
diff --git a/src/runtime/internal/ssr.ts b/src/runtime/internal/ssr.ts
index 5e7977571c..fd72aa1548 100644
--- a/src/runtime/internal/ssr.ts
+++ b/src/runtime/internal/ssr.ts
@@ -25,7 +25,7 @@ export function spread(args, classes_to_add) {
else if (boolean_attributes.has(name.toLowerCase())) {
if (value) str += ' ' + name;
} else if (value != null) {
- str += ` ${name}="${String(value).replace(/"/g, '"').replace(/'/g, ''')}"`;
+ str += ` ${name}="${value}"`;
}
});
@@ -44,6 +44,18 @@ export function escape(html) {
return String(html).replace(/["'&<>]/g, match => escaped[match]);
}
+export function escape_attribute_value(value) {
+ return typeof value === 'string' ? escape(value) : value;
+}
+
+export function escape_object(obj) {
+ const result = {};
+ for (const key in obj) {
+ result[key] = escape_attribute_value(obj[key]);
+ }
+ return result;
+}
+
export function each(items, fn) {
let str = '';
for (let i = 0; i < items.length; i += 1) {
@@ -79,7 +91,7 @@ export function create_ssr_component(fn) {
const $$ = {
on_destroy,
- context: new Map(parent_component ? parent_component.$$.context : context || []),
+ context: new Map(context || (parent_component ? parent_component.$$.context : [])),
// these will be immediately discarded
on_mount: [],
diff --git a/src/runtime/internal/style_manager.ts b/src/runtime/internal/style_manager.ts
index 8060e65a5d..0993b3bf18 100644
--- a/src/runtime/internal/style_manager.ts
+++ b/src/runtime/internal/style_manager.ts
@@ -1,4 +1,4 @@
-import { element } from './dom';
+import { append_empty_stylesheet, get_root_for_style } from './dom';
import { raf } from './environment';
interface ExtendedDoc extends Document {
@@ -29,9 +29,9 @@ export function create_rule(node: Element & ElementCSSInlineStyle, a: number, b:
const rule = keyframes + `100% {${fn(b, 1 - b)}}\n}`;
const name = `__svelte_${hash(rule)}_${uid}`;
- const doc = node.ownerDocument as ExtendedDoc;
+ const doc = get_root_for_style(node) as ExtendedDoc;
active_docs.add(doc);
- const stylesheet = doc.__svelte_stylesheet || (doc.__svelte_stylesheet = doc.head.appendChild(element('style') as HTMLStyleElement).sheet as CSSStyleSheet);
+ const stylesheet = doc.__svelte_stylesheet || (doc.__svelte_stylesheet = append_empty_stylesheet(node).sheet as CSSStyleSheet);
const current_rules = doc.__svelte_rules || (doc.__svelte_rules = {});
if (!current_rules[name]) {
diff --git a/src/runtime/internal/transitions.ts b/src/runtime/internal/transitions.ts
index 2fc81cc21f..a0134668ef 100644
--- a/src/runtime/internal/transitions.ts
+++ b/src/runtime/internal/transitions.ts
@@ -5,8 +5,25 @@ import { create_rule, delete_rule } from './style_manager';
import { custom_event } from './dom';
import { add_render_callback } from './scheduler';
import { TransitionConfig } from '../transition';
-
-let promise: Promise|null;
+import { Fragment } from './Component';
+
+let promise: Promise | null;
+type INTRO = 1;
+type OUTRO = 0;
+interface Outro {
+ /**
+ * remaining outros
+ */
+ r: number;
+ /**
+ * callbacks
+ */
+ c: Function[];
+ /**
+ * parent outro
+ */
+ p: Outro;
+}
function wait() {
if (!promise) {
@@ -19,12 +36,12 @@ function wait() {
return promise;
}
-function dispatch(node: Element, direction: boolean, kind: 'start' | 'end') {
+function dispatch(node: Element, direction: INTRO | OUTRO | boolean, kind: 'start' | 'end') {
node.dispatchEvent(custom_event(`${direction ? 'intro' : 'outro'}${kind}`));
}
const outroing = new Set();
-let outros;
+let outros: Outro;
export function group_outros() {
outros = {
@@ -41,14 +58,14 @@ export function check_outros() {
outros = outros.p;
}
-export function transition_in(block, local?: 0 | 1) {
+export function transition_in(block: Fragment, local?: 0 | 1) {
if (block && block.i) {
outroing.delete(block);
block.i(local);
}
}
-export function transition_out(block, local: 0 | 1, detach?: 0 | 1, callback?) {
+export function transition_out(block: Fragment, local: 0 | 1, detach?: 0 | 1, callback?) {
if (block && block.o) {
if (outroing.has(block)) return;
outroing.add(block);
@@ -126,7 +143,8 @@ export function create_in_transition(node: Element & ElementCSSInlineStyle, fn:
return {
start() {
if (started) return;
-
+
+ started = true;
delete_rule(node);
if (is_function(config)) {
@@ -225,21 +243,39 @@ export function create_out_transition(node: Element & ElementCSSInlineStyle, fn:
};
}
+interface PendingProgram {
+ start: number;
+ b: INTRO | OUTRO;
+ group?: Outro;
+}
+interface Program {
+ a: number;
+ b: INTRO | OUTRO;
+ /**
+ * direction
+ */
+ d: 1 | -1;
+ duration: number;
+ start: number;
+ end: number;
+ group?: Outro;
+}
+
export function create_bidirectional_transition(node: Element & ElementCSSInlineStyle, fn: TransitionFn, params: any, intro: boolean) {
let config = fn(node, params);
let t = intro ? 0 : 1;
- let running_program = null;
- let pending_program = null;
+ let running_program: Program | null = null;
+ let pending_program: PendingProgram | null = null;
let animation_name = null;
function clear_animation() {
if (animation_name) delete_rule(node, animation_name);
}
- function init(program, duration) {
- const d = program.b - t;
+ function init(program: PendingProgram, duration: number): Program {
+ const d = (program.b - t) as Program['d'];
duration *= Math.abs(d);
return {
@@ -253,7 +289,7 @@ export function create_bidirectional_transition(node: Element & ElementCSSInline
};
}
- function go(b) {
+ function go(b: INTRO | OUTRO) {
const {
delay = 0,
duration = 300,
@@ -262,7 +298,7 @@ export function create_bidirectional_transition(node: Element & ElementCSSInline
css
} = config || null_transition;
- const program = {
+ const program: PendingProgram = {
start: now() + delay,
b
};
@@ -331,7 +367,7 @@ export function create_bidirectional_transition(node: Element & ElementCSSInline
}
return {
- run(b) {
+ run(b: INTRO | OUTRO) {
if (is_function(config)) {
wait().then(() => {
// @ts-ignore
diff --git a/src/runtime/internal/utils.ts b/src/runtime/internal/utils.ts
index 084019fb59..8868e38ee2 100644
--- a/src/runtime/internal/utils.ts
+++ b/src/runtime/internal/utils.ts
@@ -28,7 +28,7 @@ export function blank_object() {
return Object.create(null);
}
-export function run_all(fns) {
+export function run_all(fns: Function[]) {
fns.forEach(run);
}
@@ -40,6 +40,16 @@ export function safe_not_equal(a, b) {
return a != a ? b == b : a !== b || ((a && typeof a === 'object') || typeof a === 'function');
}
+let src_url_equal_anchor;
+
+export function src_url_equal(element_src, url) {
+ if (!src_url_equal_anchor) {
+ src_url_equal_anchor = document.createElement('a');
+ }
+ src_url_equal_anchor.href = url;
+ return element_src === src_url_equal_anchor.href;
+}
+
export function not_equal(a, b) {
return a != a ? b == b : a !== b;
}
@@ -79,7 +89,7 @@ export function create_slot(definition, ctx, $$scope, fn) {
}
}
-export function get_slot_context(definition, ctx, $$scope, fn) {
+function get_slot_context(definition, ctx, $$scope, fn) {
return definition[1] && fn
? assign($$scope.ctx.slice(), definition[1](fn(ctx)))
: $$scope.ctx;
@@ -109,20 +119,28 @@ export function get_slot_changes(definition, $$scope, dirty, fn) {
return $$scope.dirty;
}
-export function update_slot(slot, slot_definition, ctx, $$scope, dirty, get_slot_changes_fn, get_slot_context_fn) {
- const slot_changes = get_slot_changes(slot_definition, $$scope, dirty, get_slot_changes_fn);
+export function update_slot_base(slot, slot_definition, ctx, $$scope, slot_changes, get_slot_context_fn) {
if (slot_changes) {
const slot_context = get_slot_context(slot_definition, ctx, $$scope, get_slot_context_fn);
slot.p(slot_context, slot_changes);
}
}
-export function update_slot_spread(slot, slot_definition, ctx, $$scope, dirty, get_slot_changes_fn, get_slot_spread_changes_fn, get_slot_context_fn) {
- const slot_changes = get_slot_spread_changes_fn(dirty) | get_slot_changes(slot_definition, $$scope, dirty, get_slot_changes_fn);
- if (slot_changes) {
- const slot_context = get_slot_context(slot_definition, ctx, $$scope, get_slot_context_fn);
- slot.p(slot_context, slot_changes);
+export function update_slot(slot, slot_definition, ctx, $$scope, dirty, get_slot_changes_fn, get_slot_context_fn) {
+ const slot_changes = get_slot_changes(slot_definition, $$scope, dirty, get_slot_changes_fn);
+ update_slot_base(slot, slot_definition, ctx, $$scope, slot_changes, get_slot_context_fn);
+}
+
+export function get_all_dirty_from_scope($$scope) {
+ if ($$scope.ctx.length > 32) {
+ const dirty = [];
+ const length = $$scope.ctx.length / 32;
+ for (let i = 0; i < length; i++) {
+ dirty[i] = -1;
+ }
+ return dirty;
}
+ return -1;
}
export function exclude_internal_props(props) {
@@ -159,7 +177,7 @@ export function null_to_empty(value) {
return value == null ? '' : value;
}
-export function set_store_value(store, ret, value = ret) {
+export function set_store_value(store, ret, value) {
store.set(value);
return ret;
}
diff --git a/src/runtime/ssr.ts b/src/runtime/ssr.ts
new file mode 100644
index 0000000000..cbac1f3ef8
--- /dev/null
+++ b/src/runtime/ssr.ts
@@ -0,0 +1,15 @@
+export {
+ onDestroy,
+ setContext,
+ getContext,
+ getAllContexts,
+ hasContext,
+ tick,
+ createEventDispatcher,
+ SvelteComponent,
+ SvelteComponentTyped
+} from './index';
+
+export function onMount() {}
+export function beforeUpdate() {}
+export function afterUpdate() {}
diff --git a/src/runtime/store/index.ts b/src/runtime/store/index.ts
index 45877d861f..e947fa0740 100644
--- a/src/runtime/store/index.ts
+++ b/src/runtime/store/index.ts
@@ -50,7 +50,7 @@ const subscriber_queue = [];
* @param value initial value
* @param {StartStopNotifier}start start and stop notifications for subscriptions
*/
-export function readable(value: T, start: StartStopNotifier): Readable {
+export function readable(value?: T, start?: StartStopNotifier): Readable {
return {
subscribe: writable(value, start).subscribe
};
@@ -61,19 +61,18 @@ export function readable(value: T, start: StartStopNotifier): Readable
* @param {*=}value initial value
* @param {StartStopNotifier=}start start and stop notifications for subscriptions
*/
-export function writable(value: T, start: StartStopNotifier = noop): Writable {
+export function writable(value?: T, start: StartStopNotifier = noop): Writable {
let stop: Unsubscriber;
- const subscribers: Array> = [];
+ const subscribers: Set> = new Set();
function set(new_value: T): void {
if (safe_not_equal(value, new_value)) {
value = new_value;
if (stop) { // store is ready
const run_queue = !subscriber_queue.length;
- for (let i = 0; i < subscribers.length; i += 1) {
- const s = subscribers[i];
- s[1]();
- subscriber_queue.push(s, value);
+ for (const subscriber of subscribers) {
+ subscriber[1]();
+ subscriber_queue.push(subscriber, value);
}
if (run_queue) {
for (let i = 0; i < subscriber_queue.length; i += 2) {
@@ -91,18 +90,15 @@ export function writable(value: T, start: StartStopNotifier = noop): Writa
function subscribe(run: Subscriber, invalidate: Invalidator = noop): Unsubscriber {
const subscriber: SubscribeInvalidateTuple = [run, invalidate];
- subscribers.push(subscriber);
- if (subscribers.length === 1) {
+ subscribers.add(subscriber);
+ if (subscribers.size === 1) {
stop = start(set) || noop;
}
run(value);
return () => {
- const index = subscribers.indexOf(subscriber);
- if (index !== -1) {
- subscribers.splice(index, 1);
- }
- if (subscribers.length === 0) {
+ subscribers.delete(subscriber);
+ if (subscribers.size === 0) {
stop();
stop = null;
}
@@ -113,7 +109,7 @@ export function writable(value: T, start: StartStopNotifier = noop): Writa
}
/** One or more `Readable`s. */
-type Stores = Readable | [Readable, ...Array>];
+type Stores = Readable | [Readable, ...Array>] | Array>;
/** One or more values from `Readable` stores. */
type StoresValues = T extends Readable ? U :
@@ -133,6 +129,20 @@ export function derived(
initial_value?: T
): Readable;
+/**
+ * Derived value store by synchronizing one or more readable stores and
+ * applying an aggregation function over its input values.
+ *
+ * @param stores - input stores
+ * @param fn - function callback that aggregates the values
+ * @param initial_value - initial value
+ */
+export function derived(
+ stores: S,
+ fn: (values: StoresValues) => T,
+ initial_value?: T
+): Readable;
+
/**
* Derived value store by synchronizing one or more readable stores and
* applying an aggregation function over its input values.
diff --git a/src/runtime/transition/index.ts b/src/runtime/transition/index.ts
index 3a978a146a..8f5a9521b6 100644
--- a/src/runtime/transition/index.ts
+++ b/src/runtime/transition/index.ts
@@ -178,7 +178,11 @@ export function draw(node: SVGElement & { getTotalLength(): number }, {
duration,
easing = cubicInOut
}: DrawParams = {}): TransitionConfig {
- const len = node.getTotalLength();
+ let len = node.getTotalLength();
+ const style = getComputedStyle(node);
+ if (style.strokeLinecap !== 'butt') {
+ len += parseInt(style.strokeWidth);
+ }
if (duration === undefined) {
if (speed === undefined) {
@@ -207,7 +211,7 @@ export interface CrossfadeParams {
type ClientRectMap = Map;
export function crossfade({ fallback, ...defaults }: CrossfadeParams & {
- fallback: (node: Element, params: CrossfadeParams, intro: boolean) => TransitionConfig;
+ fallback?: (node: Element, params: CrossfadeParams, intro: boolean) => TransitionConfig;
}) {
const to_receive: ClientRectMap = new Map();
const to_send: ClientRectMap = new Map();
diff --git a/test/css/samples/global-compound-selector/_config.js b/test/css/samples/global-compound-selector/_config.js
new file mode 100644
index 0000000000..0a95b541c8
--- /dev/null
+++ b/test/css/samples/global-compound-selector/_config.js
@@ -0,0 +1,27 @@
+export default {
+ warnings: [
+ {
+ code: 'css-unused-selector',
+ frame: `
+ 16: }
+ 17:
+ 18: .bar:global(.foo) {
+ ^
+ 19: color: blue;
+ 20: }
+ `,
+ message: 'Unused CSS selector ".bar:global(.foo)"',
+ pos: 210,
+ start: {
+ character: 210,
+ column: 1,
+ line: 18
+ },
+ end: {
+ character: 227,
+ column: 18,
+ line: 18
+ }
+ }
+ ]
+};
diff --git a/test/css/samples/global-compound-selector/expected.css b/test/css/samples/global-compound-selector/expected.css
new file mode 100644
index 0000000000..ff9bed9c34
--- /dev/null
+++ b/test/css/samples/global-compound-selector/expected.css
@@ -0,0 +1 @@
+div.svelte-xyz.svelte-xyz.bar{color:red}.foo.svelte-xyz.svelte-xyz.bar{color:red}.foo.svelte-xyz.bar span.svelte-xyz{color:red}
\ No newline at end of file
diff --git a/test/css/samples/global-compound-selector/expected.html b/test/css/samples/global-compound-selector/expected.html
new file mode 100644
index 0000000000..ca16db5456
--- /dev/null
+++ b/test/css/samples/global-compound-selector/expected.html
@@ -0,0 +1,3 @@
+text
+texttext
+text
\ No newline at end of file
diff --git a/test/css/samples/global-compound-selector/input.svelte b/test/css/samples/global-compound-selector/input.svelte
new file mode 100644
index 0000000000..347ae3ac55
--- /dev/null
+++ b/test/css/samples/global-compound-selector/input.svelte
@@ -0,0 +1,21 @@
+text
+texttext
+text
+
+
\ No newline at end of file
diff --git a/test/css/samples/global-with-child-combinator-2/_config.js b/test/css/samples/global-with-child-combinator-2/_config.js
new file mode 100644
index 0000000000..2286f4fe3c
--- /dev/null
+++ b/test/css/samples/global-with-child-combinator-2/_config.js
@@ -0,0 +1,27 @@
+export default {
+ warnings: [
+ {
+ code: 'css-unused-selector',
+ end: {
+ character: 111,
+ column: 21,
+ line: 8
+ },
+ frame: `
+ 6: color: red;
+ 7: }
+ 8: a:global(.foo) > div {
+ ^
+ 9: color: red;
+ 10: }
+ `,
+ message: 'Unused CSS selector "a:global(.foo) > div"',
+ pos: 91,
+ start: {
+ character: 91,
+ column: 1,
+ line: 8
+ }
+ }
+ ]
+};
diff --git a/test/css/samples/global-with-child-combinator-2/expected.css b/test/css/samples/global-with-child-combinator-2/expected.css
new file mode 100644
index 0000000000..3f406244a3
--- /dev/null
+++ b/test/css/samples/global-with-child-combinator-2/expected.css
@@ -0,0 +1 @@
+div>div.svelte-xyz.svelte-xyz{color:red}div.svelte-xyz.foo>div.svelte-xyz{color:red}
\ No newline at end of file
diff --git a/test/css/samples/global-with-child-combinator-2/expected.html b/test/css/samples/global-with-child-combinator-2/expected.html
new file mode 100644
index 0000000000..32ff99e34f
--- /dev/null
+++ b/test/css/samples/global-with-child-combinator-2/expected.html
@@ -0,0 +1,3 @@
+
\ No newline at end of file
diff --git a/test/css/samples/global-with-child-combinator-2/input.svelte b/test/css/samples/global-with-child-combinator-2/input.svelte
new file mode 100644
index 0000000000..caf7c5869a
--- /dev/null
+++ b/test/css/samples/global-with-child-combinator-2/input.svelte
@@ -0,0 +1,15 @@
+
+
+
\ No newline at end of file
diff --git a/test/runtime/samples/numeric-seperator/_config.js b/test/css/samples/global-with-child-combinator-3/_config.js
similarity index 51%
rename from test/runtime/samples/numeric-seperator/_config.js
rename to test/css/samples/global-with-child-combinator-3/_config.js
index 2b1b5168ee..c81f1a9f82 100644
--- a/test/runtime/samples/numeric-seperator/_config.js
+++ b/test/css/samples/global-with-child-combinator-3/_config.js
@@ -1,3 +1,3 @@
export default {
- html: '2048 2048'
+ warnings: []
};
diff --git a/test/css/samples/global-with-child-combinator-3/expected.css b/test/css/samples/global-with-child-combinator-3/expected.css
new file mode 100644
index 0000000000..11c60c7147
--- /dev/null
+++ b/test/css/samples/global-with-child-combinator-3/expected.css
@@ -0,0 +1 @@
+a>b>div.svelte-xyz{color:red}
\ No newline at end of file
diff --git a/test/css/samples/global-with-child-combinator-3/expected.html b/test/css/samples/global-with-child-combinator-3/expected.html
new file mode 100644
index 0000000000..32ff99e34f
--- /dev/null
+++ b/test/css/samples/global-with-child-combinator-3/expected.html
@@ -0,0 +1,3 @@
+
\ No newline at end of file
diff --git a/test/css/samples/global-with-child-combinator-3/input.svelte b/test/css/samples/global-with-child-combinator-3/input.svelte
new file mode 100644
index 0000000000..146f302633
--- /dev/null
+++ b/test/css/samples/global-with-child-combinator-3/input.svelte
@@ -0,0 +1,9 @@
+
+
+
\ No newline at end of file
diff --git a/test/css/samples/global-with-child-combinator/_config.js b/test/css/samples/global-with-child-combinator/_config.js
new file mode 100644
index 0000000000..c81f1a9f82
--- /dev/null
+++ b/test/css/samples/global-with-child-combinator/_config.js
@@ -0,0 +1,3 @@
+export default {
+ warnings: []
+};
diff --git a/test/css/samples/global-with-child-combinator/expected.css b/test/css/samples/global-with-child-combinator/expected.css
new file mode 100644
index 0000000000..9d8989b63b
--- /dev/null
+++ b/test/css/samples/global-with-child-combinator/expected.css
@@ -0,0 +1 @@
+div>div.svelte-xyz{color:red}
\ No newline at end of file
diff --git a/test/css/samples/global-with-child-combinator/expected.html b/test/css/samples/global-with-child-combinator/expected.html
new file mode 100644
index 0000000000..32ff99e34f
--- /dev/null
+++ b/test/css/samples/global-with-child-combinator/expected.html
@@ -0,0 +1,3 @@
+
\ No newline at end of file
diff --git a/test/css/samples/global-with-child-combinator/input.svelte b/test/css/samples/global-with-child-combinator/input.svelte
new file mode 100644
index 0000000000..3b5ff160c3
--- /dev/null
+++ b/test/css/samples/global-with-child-combinator/input.svelte
@@ -0,0 +1,9 @@
+
+
+
\ No newline at end of file
diff --git a/test/css/samples/global/expected.css b/test/css/samples/global/expected.css
index 698a44038b..64891e17fd 100644
--- a/test/css/samples/global/expected.css
+++ b/test/css/samples/global/expected.css
@@ -1 +1 @@
-div{color:red}div.foo{color:blue}.foo{font-weight:bold}
\ No newline at end of file
+div{color:red}div.foo.svelte-xyz{color:blue}div.foo{color:pink}.foo{font-weight:bold}
\ No newline at end of file
diff --git a/test/css/samples/global/input.svelte b/test/css/samples/global/input.svelte
index 0350c826f5..31ac143940 100644
--- a/test/css/samples/global/input.svelte
+++ b/test/css/samples/global/input.svelte
@@ -10,6 +10,10 @@
color: blue;
}
+ :global(div.foo) {
+ color: pink;
+ }
+
:global(.foo) {
font-weight: bold;
}
diff --git a/test/css/samples/root/_config.js b/test/css/samples/root/_config.js
new file mode 100644
index 0000000000..ff8b4c5632
--- /dev/null
+++ b/test/css/samples/root/_config.js
@@ -0,0 +1 @@
+export default {};
diff --git a/test/css/samples/root/expected.css b/test/css/samples/root/expected.css
new file mode 100644
index 0000000000..ce35d8835f
--- /dev/null
+++ b/test/css/samples/root/expected.css
@@ -0,0 +1 @@
+:root{color:red}.foo:root{color:blue}:root.foo{color:green}
\ No newline at end of file
diff --git a/test/css/samples/root/expected.html b/test/css/samples/root/expected.html
new file mode 100644
index 0000000000..1d90ab5df7
--- /dev/null
+++ b/test/css/samples/root/expected.html
@@ -0,0 +1 @@
+Hello!
\ No newline at end of file
diff --git a/test/css/samples/root/input.svelte b/test/css/samples/root/input.svelte
new file mode 100644
index 0000000000..979c9d4f0a
--- /dev/null
+++ b/test/css/samples/root/input.svelte
@@ -0,0 +1,13 @@
+
+
+Hello!
diff --git a/test/custom-elements/samples/props/main.svelte b/test/custom-elements/samples/props/main.svelte
index 80b483bf6e..cf47b436b5 100644
--- a/test/custom-elements/samples/props/main.svelte
+++ b/test/custom-elements/samples/props/main.svelte
@@ -4,6 +4,7 @@
import './my-widget.svelte';
export let items = ['a', 'b', 'c'];
+ export let flagged = false;
-
+
diff --git a/test/custom-elements/samples/props/my-widget.svelte b/test/custom-elements/samples/props/my-widget.svelte
index cf512e0ff8..970acf84b2 100644
--- a/test/custom-elements/samples/props/my-widget.svelte
+++ b/test/custom-elements/samples/props/my-widget.svelte
@@ -2,7 +2,11 @@
{items.length} items
{items.join(', ')}
+{flag1 ? 'flagged (dynamic attribute)' : 'not flagged'}
+{flag2 ? 'flagged (static attribute)' : 'not flagged'}
diff --git a/test/custom-elements/samples/props/test.js b/test/custom-elements/samples/props/test.js
index fc8c01c623..41ca77d29d 100644
--- a/test/custom-elements/samples/props/test.js
+++ b/test/custom-elements/samples/props/test.js
@@ -11,13 +11,17 @@ export default function (target) {
const el = target.querySelector('custom-element');
const widget = el.shadowRoot.querySelector('my-widget');
- const [p1, p2] = widget.shadowRoot.querySelectorAll('p');
+ const [p1, p2, p3, p4] = widget.shadowRoot.querySelectorAll('p');
assert.equal(p1.textContent, '3 items');
assert.equal(p2.textContent, 'a, b, c');
+ assert.equal(p3.textContent, 'not flagged');
+ assert.equal(p4.textContent, 'flagged (static attribute)');
el.items = ['d', 'e', 'f', 'g', 'h'];
+ el.flagged = true;
assert.equal(p1.textContent, '5 items');
assert.equal(p2.textContent, 'd, e, f, g, h');
+ assert.equal(p3.textContent, 'flagged (dynamic attribute)');
}
diff --git a/test/helpers.ts b/test/helpers.ts
index 78f000c274..101490d4dc 100644
--- a/test/helpers.ts
+++ b/test/helpers.ts
@@ -4,7 +4,7 @@ import glob from 'tiny-glob/sync';
import * as path from 'path';
import * as fs from 'fs';
import * as colors from 'kleur';
-export const assert = (assert$1 as unknown) as typeof assert$1 & { htmlEqual: (actual, expected, message?) => void };
+export const assert = (assert$1 as unknown) as typeof assert$1 & { htmlEqual: (actual, expected, message?) => void, htmlEqualWithComments: (actual, expected, message?) => void };
// for coverage purposes, we need to test source files,
// but for sanity purposes, we need to test dist files
@@ -118,6 +118,9 @@ function cleanChildren(node) {
node.removeChild(child);
child = previous;
}
+ } else if (child.nodeType === 8) {
+ // comment
+ // do nothing
} else {
cleanChildren(child);
}
@@ -137,11 +140,11 @@ function cleanChildren(node) {
}
}
-export function normalizeHtml(window, html) {
+export function normalizeHtml(window, html, preserveComments = false) {
try {
const node = window.document.createElement('div');
node.innerHTML = html
- .replace(//g, '')
+ .replace(/()/g, preserveComments ? '$1' : '')
.replace(/>[\s\r\n]+<')
.trim();
cleanChildren(node);
@@ -162,6 +165,14 @@ export function setupHtmlEqual() {
message
);
};
+ // eslint-disable-next-line no-import-assign
+ assert.htmlEqualWithComments = (actual, expected, message) => {
+ assert.deepEqual(
+ normalizeHtml(window, actual, true),
+ normalizeHtml(window, expected, true),
+ message
+ );
+ };
}
export function loadConfig(file) {
@@ -260,3 +271,11 @@ export function mkdirp(dir) {
// do nothing
}
}
+
+export function prettyPrintPuppeteerAssertionError(message) {
+ const match = /Error: Expected "(.+)" to equal "(.+)"/.exec(message);
+
+ if (match) {
+ assert.equal(match[1], match[2]);
+ }
+}
diff --git a/test/hydration/samples/claim-text/Component.svelte b/test/hydration/samples/claim-text/Component.svelte
new file mode 100644
index 0000000000..c4a56edceb
--- /dev/null
+++ b/test/hydration/samples/claim-text/Component.svelte
@@ -0,0 +1,5 @@
+
+ Title
+
+
+There should be one
diff --git a/test/hydration/samples/claim-text/Layout.svelte b/test/hydration/samples/claim-text/Layout.svelte
new file mode 100644
index 0000000000..b37cf18832
--- /dev/null
+++ b/test/hydration/samples/claim-text/Layout.svelte
@@ -0,0 +1,2 @@
+This p and the slot below are direct children of the root.
+
diff --git a/test/hydration/samples/claim-text/_after.html b/test/hydration/samples/claim-text/_after.html
new file mode 100644
index 0000000000..6f79ed7159
--- /dev/null
+++ b/test/hydration/samples/claim-text/_after.html
@@ -0,0 +1,3 @@
+This p and the slot below are direct children of the root.
+
+There should be one
\ No newline at end of file
diff --git a/test/hydration/samples/claim-text/_before.html b/test/hydration/samples/claim-text/_before.html
new file mode 100644
index 0000000000..e5653f47fe
--- /dev/null
+++ b/test/hydration/samples/claim-text/_before.html
@@ -0,0 +1,5 @@
+This p and the slot below are direct children of the root.
+
+There should be one
+
+
\ No newline at end of file
diff --git a/test/hydration/samples/claim-text/main.svelte b/test/hydration/samples/claim-text/main.svelte
new file mode 100644
index 0000000000..46c001589d
--- /dev/null
+++ b/test/hydration/samples/claim-text/main.svelte
@@ -0,0 +1,8 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/test/hydration/samples/element-nested-sibling/_after.html b/test/hydration/samples/element-nested-sibling/_after.html
new file mode 100644
index 0000000000..d011cf6e38
--- /dev/null
+++ b/test/hydration/samples/element-nested-sibling/_after.html
@@ -0,0 +1,4 @@
+
+ 1
+ 2
+
diff --git a/test/hydration/samples/element-nested-sibling/_before.html b/test/hydration/samples/element-nested-sibling/_before.html
new file mode 100644
index 0000000000..d011cf6e38
--- /dev/null
+++ b/test/hydration/samples/element-nested-sibling/_before.html
@@ -0,0 +1,4 @@
+
+ 1
+ 2
+
diff --git a/test/hydration/samples/element-nested-sibling/_config.js b/test/hydration/samples/element-nested-sibling/_config.js
new file mode 100644
index 0000000000..8410fc189d
--- /dev/null
+++ b/test/hydration/samples/element-nested-sibling/_config.js
@@ -0,0 +1,19 @@
+export default {
+ snapshot(target) {
+ const p = target.querySelector('p');
+
+ return {
+ p,
+ span: p.querySelector('span'),
+ code: p.querySelector('code')
+ };
+ },
+
+ test(assert, target, snapshot) {
+ const p = target.querySelector('p');
+
+ assert.equal(p, snapshot.p);
+ assert.equal(p.querySelector('span'), snapshot.span);
+ assert.equal(p.querySelector('code'), snapshot.code);
+ }
+};
diff --git a/test/hydration/samples/element-nested-sibling/main.svelte b/test/hydration/samples/element-nested-sibling/main.svelte
new file mode 100644
index 0000000000..d6e02107e2
--- /dev/null
+++ b/test/hydration/samples/element-nested-sibling/main.svelte
@@ -0,0 +1,6 @@
+
+ 1
+ {#if true}
+ 2
+ {/if}
+
diff --git a/test/hydration/samples/expression-sibling/_after.html b/test/hydration/samples/expression-sibling/_after.html
new file mode 100644
index 0000000000..9c0a0b5778
--- /dev/null
+++ b/test/hydration/samples/expression-sibling/_after.html
@@ -0,0 +1 @@
+1 2 3
diff --git a/test/hydration/samples/expression-sibling/_before.html b/test/hydration/samples/expression-sibling/_before.html
new file mode 100644
index 0000000000..9c0a0b5778
--- /dev/null
+++ b/test/hydration/samples/expression-sibling/_before.html
@@ -0,0 +1 @@
+1 2 3
diff --git a/test/hydration/samples/expression-sibling/_config.js b/test/hydration/samples/expression-sibling/_config.js
new file mode 100644
index 0000000000..c6d3ef3f2f
--- /dev/null
+++ b/test/hydration/samples/expression-sibling/_config.js
@@ -0,0 +1,19 @@
+export default {
+ snapshot(target) {
+ const p = target.querySelector('p');
+
+ return {
+ p,
+ text: p.childNodes[0],
+ span: p.querySelector('span')
+ };
+ },
+
+ test(assert, target, snapshot) {
+ const p = target.querySelector('p');
+
+ assert.equal(p, snapshot.p);
+ assert.equal(p.childNodes[0], snapshot.text);
+ assert.equal(p.querySelector('span'), snapshot.span);
+ }
+};
diff --git a/test/hydration/samples/expression-sibling/main.svelte b/test/hydration/samples/expression-sibling/main.svelte
new file mode 100644
index 0000000000..65aa541e9c
--- /dev/null
+++ b/test/hydration/samples/expression-sibling/main.svelte
@@ -0,0 +1 @@
+{1} 2 3
diff --git a/test/hydration/samples/head-meta-hydrate-duplicate/_after_head.html b/test/hydration/samples/head-meta-hydrate-duplicate/_after_head.html
index 10cf2c8b9a..be7a01ba4f 100644
--- a/test/hydration/samples/head-meta-hydrate-duplicate/_after_head.html
+++ b/test/hydration/samples/head-meta-hydrate-duplicate/_after_head.html
@@ -1,4 +1,4 @@
Some Title
-
\ No newline at end of file
+
diff --git a/test/js/samples/action-custom-event-handler/expected.js b/test/js/samples/action-custom-event-handler/expected.js
index 51656290d6..6433d5b04a 100644
--- a/test/js/samples/action-custom-event-handler/expected.js
+++ b/test/js/samples/action-custom-event-handler/expected.js
@@ -56,7 +56,7 @@ function instance($$self, $$props, $$invalidate) {
const foo_function = () => handleFoo(bar);
$$self.$$set = $$props => {
- if ("bar" in $$props) $$invalidate(0, bar = $$props.bar);
+ if ('bar' in $$props) $$invalidate(0, bar = $$props.bar);
};
return [bar, foo_function];
diff --git a/test/js/samples/action/expected.js b/test/js/samples/action/expected.js
index d52960bddd..689669c5bc 100644
--- a/test/js/samples/action/expected.js
+++ b/test/js/samples/action/expected.js
@@ -48,11 +48,11 @@ function link(node) {
history.pushState(null, null, event.target.href);
}
- node.addEventListener("click", onClick);
+ node.addEventListener('click', onClick);
return {
destroy() {
- node.removeEventListener("click", onClick);
+ node.removeEventListener('click', onClick);
}
};
}
diff --git a/test/js/samples/bind-open/expected.js b/test/js/samples/bind-open/expected.js
index 56ff302845..669cb41405 100644
--- a/test/js/samples/bind-open/expected.js
+++ b/test/js/samples/bind-open/expected.js
@@ -53,7 +53,7 @@ function instance($$self, $$props, $$invalidate) {
}
$$self.$$set = $$props => {
- if ("open" in $$props) $$invalidate(0, open = $$props.open);
+ if ('open' in $$props) $$invalidate(0, open = $$props.open);
};
return [open, details_toggle_handler];
diff --git a/test/js/samples/bind-width-height/expected.js b/test/js/samples/bind-width-height/expected.js
index f23c20b683..8966e57c9c 100644
--- a/test/js/samples/bind-width-height/expected.js
+++ b/test/js/samples/bind-width-height/expected.js
@@ -47,8 +47,8 @@ function instance($$self, $$props, $$invalidate) {
}
$$self.$$set = $$props => {
- if ("w" in $$props) $$invalidate(0, w = $$props.w);
- if ("h" in $$props) $$invalidate(1, h = $$props.h);
+ if ('w' in $$props) $$invalidate(0, w = $$props.w);
+ if ('h' in $$props) $$invalidate(1, h = $$props.h);
};
return [w, h, div_elementresize_handler];
diff --git a/test/js/samples/bindings-readonly-order/expected.js b/test/js/samples/bindings-readonly-order/expected.js
index 78a71dcd84..ea83573ee3 100644
--- a/test/js/samples/bindings-readonly-order/expected.js
+++ b/test/js/samples/bindings-readonly-order/expected.js
@@ -69,7 +69,7 @@ function instance($$self, $$props, $$invalidate) {
}
$$self.$$set = $$props => {
- if ("files" in $$props) $$invalidate(0, files = $$props.files);
+ if ('files' in $$props) $$invalidate(0, files = $$props.files);
};
return [files, input0_change_handler, input1_change_handler];
diff --git a/test/js/samples/capture-inject-state/expected.js b/test/js/samples/capture-inject-state/expected.js
index 854e0b3265..58e1879553 100644
--- a/test/js/samples/capture-inject-state/expected.js
+++ b/test/js/samples/capture-inject-state/expected.js
@@ -95,7 +95,7 @@ const moduleContantProps = 4;
let moduleLet;
const moduleConst = 2;
let shadowedByModule;
-const priv = "priv";
+const priv = 'priv';
function instance($$self, $$props, $$invalidate) {
let computed;
@@ -106,22 +106,22 @@ function instance($$self, $$props, $$invalidate) {
$$self.$$.on_destroy.push(() => $$unsubscribe_prop());
let { $$slots: slots = {}, $$scope } = $$props;
- validate_slots("Component", slots, []);
+ validate_slots('Component', slots, []);
let { prop } = $$props;
- validate_store(prop, "prop");
+ validate_store(prop, 'prop');
$$subscribe_prop();
let { alias: realName } = $$props;
let local;
let shadowedByModule;
- const writable_props = ["prop", "alias"];
+ const writable_props = ['prop', 'alias'];
Object.keys($$props).forEach(key => {
- if (!~writable_props.indexOf(key) && key.slice(0, 2) !== "$$") console.warn(` was created with unknown prop '${key}'`);
+ if (!~writable_props.indexOf(key) && key.slice(0, 2) !== '$$' && key !== 'slot') console.warn(` was created with unknown prop '${key}'`);
});
$$self.$$set = $$props => {
- if ("prop" in $$props) $$subscribe_prop($$invalidate(0, prop = $$props.prop));
- if ("alias" in $$props) $$invalidate(1, realName = $$props.alias);
+ if ('prop' in $$props) $$subscribe_prop($$invalidate(0, prop = $$props.prop));
+ if ('alias' in $$props) $$invalidate(1, realName = $$props.alias);
};
$$self.$capture_state = () => ({
@@ -140,11 +140,11 @@ function instance($$self, $$props, $$invalidate) {
});
$$self.$inject_state = $$props => {
- if ("prop" in $$props) $$subscribe_prop($$invalidate(0, prop = $$props.prop));
- if ("realName" in $$props) $$invalidate(1, realName = $$props.realName);
- if ("local" in $$props) $$invalidate(3, local = $$props.local);
- if ("shadowedByModule" in $$props) $$invalidate(4, shadowedByModule = $$props.shadowedByModule);
- if ("computed" in $$props) computed = $$props.computed;
+ if ('prop' in $$props) $$subscribe_prop($$invalidate(0, prop = $$props.prop));
+ if ('realName' in $$props) $$invalidate(1, realName = $$props.realName);
+ if ('local' in $$props) $$invalidate(3, local = $$props.local);
+ if ('shadowedByModule' in $$props) $$invalidate(4, shadowedByModule = $$props.shadowedByModule);
+ if ('computed' in $$props) computed = $$props.computed;
};
if ($$props && "$$inject" in $$props) {
@@ -170,11 +170,11 @@ class Component extends SvelteComponentDev {
const { ctx } = this.$$;
const props = options.props || {};
- if (/*prop*/ ctx[0] === undefined && !("prop" in props)) {
+ if (/*prop*/ ctx[0] === undefined && !('prop' in props)) {
console.warn(" was created without expected prop 'prop'");
}
- if (/*realName*/ ctx[1] === undefined && !("alias" in props)) {
+ if (/*realName*/ ctx[1] === undefined && !('alias' in props)) {
console.warn(" was created without expected prop 'alias'");
}
}
diff --git a/test/js/samples/collapse-element-class-name/expected.js b/test/js/samples/collapse-element-class-name/expected.js
new file mode 100644
index 0000000000..a55affe76e
--- /dev/null
+++ b/test/js/samples/collapse-element-class-name/expected.js
@@ -0,0 +1,114 @@
+/* generated by Svelte vX.Y.Z */
+import {
+ SvelteComponent,
+ assign,
+ attr,
+ compute_rest_props,
+ create_component,
+ destroy_component,
+ detach,
+ element,
+ exclude_internal_props,
+ init,
+ insert,
+ mount_component,
+ safe_not_equal,
+ space,
+ transition_in,
+ transition_out
+} from "svelte/internal";
+
+import Component from "./Component.svelte";
+
+function create_fragment(ctx) {
+ let div;
+ let div_class_value;
+ let div_style_value;
+ let div_other_value;
+ let t;
+ let component;
+ let current;
+
+ component = new Component({
+ props: {
+ class: "\n\t\tbutton\n\t\tbutton--size--" + /*size*/ ctx[0] + "\n\t\tbutton--theme--" + /*theme*/ ctx[1] + "\n \t" + (/*$$restProps*/ ctx[2].class || ''),
+ style: "\n\t\tcolor: green;\n\t\tbackground: white;\n\t\tfont-size: " + /*size*/ ctx[0] + ";\n \ttransform: " + /*$$restProps*/ ctx[2].scale + " " + /*$$restProps*/ ctx[2].rotate + ";\n\t\t" + /*$$restProps*/ ctx[2].styles,
+ other: "\n\t\tbutton\n\t\tbutton--size--" + /*size*/ ctx[0] + "\n\t\tbutton--theme--" + /*theme*/ ctx[1] + "\n \t" + (/*$$restProps*/ ctx[2].class || '')
+ }
+ });
+
+ return {
+ c() {
+ div = element("div");
+ t = space();
+ create_component(component.$$.fragment);
+ attr(div, "class", div_class_value = "button button--size--" + /*size*/ ctx[0] + " button--theme--" + /*theme*/ ctx[1] + " " + (/*$$restProps*/ ctx[2].class || ''));
+ attr(div, "style", div_style_value = "color: green; background: white; font-size: " + /*size*/ ctx[0] + "; transform: " + /*$$restProps*/ ctx[2].scale + " " + /*$$restProps*/ ctx[2].rotate + "; " + /*$$restProps*/ ctx[2].styles);
+ attr(div, "other", div_other_value = "\n\t\tbutton\n\t\tbutton--size--" + /*size*/ ctx[0] + "\n\t\tbutton--theme--" + /*theme*/ ctx[1] + "\n \t" + (/*$$restProps*/ ctx[2].class || ''));
+ },
+ m(target, anchor) {
+ insert(target, div, anchor);
+ insert(target, t, anchor);
+ mount_component(component, target, anchor);
+ current = true;
+ },
+ p(ctx, [dirty]) {
+ if (!current || dirty & /*size, theme, $$restProps*/ 7 && div_class_value !== (div_class_value = "button button--size--" + /*size*/ ctx[0] + " button--theme--" + /*theme*/ ctx[1] + " " + (/*$$restProps*/ ctx[2].class || ''))) {
+ attr(div, "class", div_class_value);
+ }
+
+ if (!current || dirty & /*size, $$restProps*/ 5 && div_style_value !== (div_style_value = "color: green; background: white; font-size: " + /*size*/ ctx[0] + "; transform: " + /*$$restProps*/ ctx[2].scale + " " + /*$$restProps*/ ctx[2].rotate + "; " + /*$$restProps*/ ctx[2].styles)) {
+ attr(div, "style", div_style_value);
+ }
+
+ if (!current || dirty & /*size, theme, $$restProps*/ 7 && div_other_value !== (div_other_value = "\n\t\tbutton\n\t\tbutton--size--" + /*size*/ ctx[0] + "\n\t\tbutton--theme--" + /*theme*/ ctx[1] + "\n \t" + (/*$$restProps*/ ctx[2].class || ''))) {
+ attr(div, "other", div_other_value);
+ }
+
+ const component_changes = {};
+ if (dirty & /*size, theme, $$restProps*/ 7) component_changes.class = "\n\t\tbutton\n\t\tbutton--size--" + /*size*/ ctx[0] + "\n\t\tbutton--theme--" + /*theme*/ ctx[1] + "\n \t" + (/*$$restProps*/ ctx[2].class || '');
+ if (dirty & /*size, $$restProps*/ 5) component_changes.style = "\n\t\tcolor: green;\n\t\tbackground: white;\n\t\tfont-size: " + /*size*/ ctx[0] + ";\n \ttransform: " + /*$$restProps*/ ctx[2].scale + " " + /*$$restProps*/ ctx[2].rotate + ";\n\t\t" + /*$$restProps*/ ctx[2].styles;
+ if (dirty & /*size, theme, $$restProps*/ 7) component_changes.other = "\n\t\tbutton\n\t\tbutton--size--" + /*size*/ ctx[0] + "\n\t\tbutton--theme--" + /*theme*/ ctx[1] + "\n \t" + (/*$$restProps*/ ctx[2].class || '');
+ component.$set(component_changes);
+ },
+ i(local) {
+ if (current) return;
+ transition_in(component.$$.fragment, local);
+ current = true;
+ },
+ o(local) {
+ transition_out(component.$$.fragment, local);
+ current = false;
+ },
+ d(detaching) {
+ if (detaching) detach(div);
+ if (detaching) detach(t);
+ destroy_component(component, detaching);
+ }
+ };
+}
+
+function instance($$self, $$props, $$invalidate) {
+ const omit_props_names = ["size","theme"];
+ let $$restProps = compute_rest_props($$props, omit_props_names);
+ let { size } = $$props;
+ let { theme } = $$props;
+
+ $$self.$$set = $$new_props => {
+ $$props = assign(assign({}, $$props), exclude_internal_props($$new_props));
+ $$invalidate(2, $$restProps = compute_rest_props($$props, omit_props_names));
+ if ('size' in $$new_props) $$invalidate(0, size = $$new_props.size);
+ if ('theme' in $$new_props) $$invalidate(1, theme = $$new_props.theme);
+ };
+
+ return [size, theme, $$restProps];
+}
+
+class Component_1 extends SvelteComponent {
+ constructor(options) {
+ super();
+ init(this, options, instance, create_fragment, safe_not_equal, { size: 0, theme: 1 });
+ }
+}
+
+export default Component_1;
\ No newline at end of file
diff --git a/test/js/samples/collapse-element-class-name/input.svelte b/test/js/samples/collapse-element-class-name/input.svelte
new file mode 100644
index 0000000000..a4cb283778
--- /dev/null
+++ b/test/js/samples/collapse-element-class-name/input.svelte
@@ -0,0 +1,41 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/test/js/samples/collapses-text-around-comments/expected.js b/test/js/samples/collapses-text-around-comments/expected.js
index 67335ce246..63a32bbf38 100644
--- a/test/js/samples/collapses-text-around-comments/expected.js
+++ b/test/js/samples/collapses-text-around-comments/expected.js
@@ -2,6 +2,7 @@
import {
SvelteComponent,
append,
+ append_styles,
attr,
detach,
element,
@@ -13,11 +14,8 @@ import {
text
} from "svelte/internal";
-function add_css() {
- var style = element("style");
- style.id = "svelte-1a7i8ec-style";
- style.textContent = "p.svelte-1a7i8ec{color:red}";
- append(document.head, style);
+function add_css(target) {
+ append_styles(target, "svelte-1a7i8ec", "p.svelte-1a7i8ec{color:red}");
}
function create_fragment(ctx) {
@@ -49,7 +47,7 @@ function instance($$self, $$props, $$invalidate) {
let { foo = 42 } = $$props;
$$self.$$set = $$props => {
- if ("foo" in $$props) $$invalidate(0, foo = $$props.foo);
+ if ('foo' in $$props) $$invalidate(0, foo = $$props.foo);
};
return [foo];
@@ -58,9 +56,8 @@ function instance($$self, $$props, $$invalidate) {
class Component extends SvelteComponent {
constructor(options) {
super();
- if (!document.getElementById("svelte-1a7i8ec-style")) add_css();
- init(this, options, instance, create_fragment, safe_not_equal, { foo: 0 });
+ init(this, options, instance, create_fragment, safe_not_equal, { foo: 0 }, add_css);
}
}
-export default Component;
\ No newline at end of file
+export default Component;
diff --git a/test/js/samples/component-static-var/expected.js b/test/js/samples/component-static-var/expected.js
index 2cd5ed386f..9e481a25c3 100644
--- a/test/js/samples/component-static-var/expected.js
+++ b/test/js/samples/component-static-var/expected.js
@@ -16,8 +16,8 @@ import {
transition_out
} from "svelte/internal";
-import Foo from "./Foo.svelte";
-import Bar from "./Bar.svelte";
+import Foo from './Foo.svelte';
+import Bar from './Bar.svelte';
function create_fragment(ctx) {
let foo;
diff --git a/test/js/samples/component-store-access-invalidate/expected.js b/test/js/samples/component-store-access-invalidate/expected.js
index 4c7bfd7009..2742481aef 100644
--- a/test/js/samples/component-store-access-invalidate/expected.js
+++ b/test/js/samples/component-store-access-invalidate/expected.js
@@ -13,7 +13,7 @@ import {
text
} from "svelte/internal";
-import { writable } from "svelte/store";
+import { writable } from 'svelte/store';
function create_fragment(ctx) {
let h1;
diff --git a/test/js/samples/component-store-file-invalidate/expected.js b/test/js/samples/component-store-file-invalidate/expected.js
index d2fb3d0be4..86a467f368 100644
--- a/test/js/samples/component-store-file-invalidate/expected.js
+++ b/test/js/samples/component-store-file-invalidate/expected.js
@@ -7,7 +7,7 @@ import {
set_store_value
} from "svelte/internal";
-import { count } from "./store.js";
+import { count } from './store.js';
function instance($$self, $$props, $$invalidate) {
let $count;
diff --git a/test/js/samples/component-store-reassign-invalidate/expected.js b/test/js/samples/component-store-reassign-invalidate/expected.js
index 0cf555bf0d..9047316cef 100644
--- a/test/js/samples/component-store-reassign-invalidate/expected.js
+++ b/test/js/samples/component-store-reassign-invalidate/expected.js
@@ -15,7 +15,7 @@ import {
text
} from "svelte/internal";
-import { writable } from "svelte/store";
+import { writable } from 'svelte/store';
function create_fragment(ctx) {
let h1;
diff --git a/test/js/samples/computed-collapsed-if/expected.js b/test/js/samples/computed-collapsed-if/expected.js
index 3e70d6a7ae..8bcb5ed8b7 100644
--- a/test/js/samples/computed-collapsed-if/expected.js
+++ b/test/js/samples/computed-collapsed-if/expected.js
@@ -13,7 +13,7 @@ function instance($$self, $$props, $$invalidate) {
}
$$self.$$set = $$props => {
- if ("x" in $$props) $$invalidate(0, x = $$props.x);
+ if ('x' in $$props) $$invalidate(0, x = $$props.x);
};
return [x, a, b];
diff --git a/test/js/samples/css-media-query/expected.js b/test/js/samples/css-media-query/expected.js
index f477670059..d743432206 100644
--- a/test/js/samples/css-media-query/expected.js
+++ b/test/js/samples/css-media-query/expected.js
@@ -1,7 +1,7 @@
/* generated by Svelte vX.Y.Z */
import {
SvelteComponent,
- append,
+ append_styles,
attr,
detach,
element,
@@ -11,11 +11,8 @@ import {
safe_not_equal
} from "svelte/internal";
-function add_css() {
- var style = element("style");
- style.id = "svelte-1slhpfn-style";
- style.textContent = "@media(min-width: 1px){div.svelte-1slhpfn{color:red}}";
- append(document.head, style);
+function add_css(target) {
+ append_styles(target, "svelte-1slhpfn", "@media(min-width: 1px){div.svelte-1slhpfn{color:red}}");
}
function create_fragment(ctx) {
@@ -41,9 +38,8 @@ function create_fragment(ctx) {
class Component extends SvelteComponent {
constructor(options) {
super();
- if (!document.getElementById("svelte-1slhpfn-style")) add_css();
- init(this, options, null, create_fragment, safe_not_equal, {});
+ init(this, options, null, create_fragment, safe_not_equal, {}, add_css);
}
}
-export default Component;
\ No newline at end of file
+export default Component;
diff --git a/test/js/samples/css-shadow-dom-keyframes/expected.js b/test/js/samples/css-shadow-dom-keyframes/expected.js
index 4d188201eb..5d65949488 100644
--- a/test/js/samples/css-shadow-dom-keyframes/expected.js
+++ b/test/js/samples/css-shadow-dom-keyframes/expected.js
@@ -46,7 +46,8 @@ class Component extends SvelteElement {
null,
create_fragment,
safe_not_equal,
- {}
+ {},
+ null
);
if (options) {
@@ -58,4 +59,4 @@ class Component extends SvelteElement {
}
customElements.define("custom-element", Component);
-export default Component;
\ No newline at end of file
+export default Component;
diff --git a/test/js/samples/data-attribute/expected.js b/test/js/samples/data-attribute/expected.js
index 8c30e6f6db..2b2f8870e4 100644
--- a/test/js/samples/data-attribute/expected.js
+++ b/test/js/samples/data-attribute/expected.js
@@ -48,7 +48,7 @@ function instance($$self, $$props, $$invalidate) {
let { bar } = $$props;
$$self.$$set = $$props => {
- if ("bar" in $$props) $$invalidate(0, bar = $$props.bar);
+ if ('bar' in $$props) $$invalidate(0, bar = $$props.bar);
};
return [bar];
diff --git a/test/js/samples/debug-empty/expected.js b/test/js/samples/debug-empty/expected.js
index f427f1bf45..55303b41b7 100644
--- a/test/js/samples/debug-empty/expected.js
+++ b/test/js/samples/debug-empty/expected.js
@@ -70,22 +70,22 @@ function create_fragment(ctx) {
function instance($$self, $$props, $$invalidate) {
let { $$slots: slots = {}, $$scope } = $$props;
- validate_slots("Component", slots, []);
+ validate_slots('Component', slots, []);
let { name } = $$props;
- const writable_props = ["name"];
+ const writable_props = ['name'];
Object.keys($$props).forEach(key => {
- if (!~writable_props.indexOf(key) && key.slice(0, 2) !== "$$") console.warn(` was created with unknown prop '${key}'`);
+ if (!~writable_props.indexOf(key) && key.slice(0, 2) !== '$$' && key !== 'slot') console.warn(` was created with unknown prop '${key}'`);
});
$$self.$$set = $$props => {
- if ("name" in $$props) $$invalidate(0, name = $$props.name);
+ if ('name' in $$props) $$invalidate(0, name = $$props.name);
};
$$self.$capture_state = () => ({ name });
$$self.$inject_state = $$props => {
- if ("name" in $$props) $$invalidate(0, name = $$props.name);
+ if ('name' in $$props) $$invalidate(0, name = $$props.name);
};
if ($$props && "$$inject" in $$props) {
@@ -110,7 +110,7 @@ class Component extends SvelteComponentDev {
const { ctx } = this.$$;
const props = options.props || {};
- if (/*name*/ ctx[0] === undefined && !("name" in props)) {
+ if (/*name*/ ctx[0] === undefined && !('name' in props)) {
console.warn(" was created without expected prop 'name'");
}
}
diff --git a/test/js/samples/debug-foo-bar-baz-things/expected.js b/test/js/samples/debug-foo-bar-baz-things/expected.js
index 7439b3310b..3377d35018 100644
--- a/test/js/samples/debug-foo-bar-baz-things/expected.js
+++ b/test/js/samples/debug-foo-bar-baz-things/expected.js
@@ -171,31 +171,31 @@ function create_fragment(ctx) {
function instance($$self, $$props, $$invalidate) {
let { $$slots: slots = {}, $$scope } = $$props;
- validate_slots("Component", slots, []);
+ validate_slots('Component', slots, []);
let { things } = $$props;
let { foo } = $$props;
let { bar } = $$props;
let { baz } = $$props;
- const writable_props = ["things", "foo", "bar", "baz"];
+ const writable_props = ['things', 'foo', 'bar', 'baz'];
Object.keys($$props).forEach(key => {
- if (!~writable_props.indexOf(key) && key.slice(0, 2) !== "$$") console.warn(` was created with unknown prop '${key}'`);
+ if (!~writable_props.indexOf(key) && key.slice(0, 2) !== '$$' && key !== 'slot') console.warn(` was created with unknown prop '${key}'`);
});
$$self.$$set = $$props => {
- if ("things" in $$props) $$invalidate(0, things = $$props.things);
- if ("foo" in $$props) $$invalidate(1, foo = $$props.foo);
- if ("bar" in $$props) $$invalidate(2, bar = $$props.bar);
- if ("baz" in $$props) $$invalidate(3, baz = $$props.baz);
+ if ('things' in $$props) $$invalidate(0, things = $$props.things);
+ if ('foo' in $$props) $$invalidate(1, foo = $$props.foo);
+ if ('bar' in $$props) $$invalidate(2, bar = $$props.bar);
+ if ('baz' in $$props) $$invalidate(3, baz = $$props.baz);
};
$$self.$capture_state = () => ({ things, foo, bar, baz });
$$self.$inject_state = $$props => {
- if ("things" in $$props) $$invalidate(0, things = $$props.things);
- if ("foo" in $$props) $$invalidate(1, foo = $$props.foo);
- if ("bar" in $$props) $$invalidate(2, bar = $$props.bar);
- if ("baz" in $$props) $$invalidate(3, baz = $$props.baz);
+ if ('things' in $$props) $$invalidate(0, things = $$props.things);
+ if ('foo' in $$props) $$invalidate(1, foo = $$props.foo);
+ if ('bar' in $$props) $$invalidate(2, bar = $$props.bar);
+ if ('baz' in $$props) $$invalidate(3, baz = $$props.baz);
};
if ($$props && "$$inject" in $$props) {
@@ -220,19 +220,19 @@ class Component extends SvelteComponentDev {
const { ctx } = this.$$;
const props = options.props || {};
- if (/*things*/ ctx[0] === undefined && !("things" in props)) {
+ if (/*things*/ ctx[0] === undefined && !('things' in props)) {
console.warn(" was created without expected prop 'things'");
}
- if (/*foo*/ ctx[1] === undefined && !("foo" in props)) {
+ if (/*foo*/ ctx[1] === undefined && !('foo' in props)) {
console.warn(" was created without expected prop 'foo'");
}
- if (/*bar*/ ctx[2] === undefined && !("bar" in props)) {
+ if (/*bar*/ ctx[2] === undefined && !('bar' in props)) {
console.warn(" was created without expected prop 'bar'");
}
- if (/*baz*/ ctx[3] === undefined && !("baz" in props)) {
+ if (/*baz*/ ctx[3] === undefined && !('baz' in props)) {
console.warn(" was created without expected prop 'baz'");
}
}
diff --git a/test/js/samples/debug-foo/expected.js b/test/js/samples/debug-foo/expected.js
index d869a5cf9e..518897c237 100644
--- a/test/js/samples/debug-foo/expected.js
+++ b/test/js/samples/debug-foo/expected.js
@@ -165,25 +165,25 @@ function create_fragment(ctx) {
function instance($$self, $$props, $$invalidate) {
let { $$slots: slots = {}, $$scope } = $$props;
- validate_slots("Component", slots, []);
+ validate_slots('Component', slots, []);
let { things } = $$props;
let { foo } = $$props;
- const writable_props = ["things", "foo"];
+ const writable_props = ['things', 'foo'];
Object.keys($$props).forEach(key => {
- if (!~writable_props.indexOf(key) && key.slice(0, 2) !== "$$") console.warn(` was created with unknown prop '${key}'`);
+ if (!~writable_props.indexOf(key) && key.slice(0, 2) !== '$$' && key !== 'slot') console.warn(` was created with unknown prop '${key}'`);
});
$$self.$$set = $$props => {
- if ("things" in $$props) $$invalidate(0, things = $$props.things);
- if ("foo" in $$props) $$invalidate(1, foo = $$props.foo);
+ if ('things' in $$props) $$invalidate(0, things = $$props.things);
+ if ('foo' in $$props) $$invalidate(1, foo = $$props.foo);
};
$$self.$capture_state = () => ({ things, foo });
$$self.$inject_state = $$props => {
- if ("things" in $$props) $$invalidate(0, things = $$props.things);
- if ("foo" in $$props) $$invalidate(1, foo = $$props.foo);
+ if ('things' in $$props) $$invalidate(0, things = $$props.things);
+ if ('foo' in $$props) $$invalidate(1, foo = $$props.foo);
};
if ($$props && "$$inject" in $$props) {
@@ -208,11 +208,11 @@ class Component extends SvelteComponentDev {
const { ctx } = this.$$;
const props = options.props || {};
- if (/*things*/ ctx[0] === undefined && !("things" in props)) {
+ if (/*things*/ ctx[0] === undefined && !('things' in props)) {
console.warn(" was created without expected prop 'things'");
}
- if (/*foo*/ ctx[1] === undefined && !("foo" in props)) {
+ if (/*foo*/ ctx[1] === undefined && !('foo' in props)) {
console.warn(" was created without expected prop 'foo'");
}
}
diff --git a/test/js/samples/debug-hoisted/expected.js b/test/js/samples/debug-hoisted/expected.js
index c6257ac90d..9fc4f7cf4f 100644
--- a/test/js/samples/debug-hoisted/expected.js
+++ b/test/js/samples/debug-hoisted/expected.js
@@ -50,20 +50,20 @@ function create_fragment(ctx) {
function instance($$self, $$props, $$invalidate) {
let { $$slots: slots = {}, $$scope } = $$props;
- validate_slots("Component", slots, []);
+ validate_slots('Component', slots, []);
let obj = { x: 5 };
let kobzol = 5;
const writable_props = [];
Object.keys($$props).forEach(key => {
- if (!~writable_props.indexOf(key) && key.slice(0, 2) !== "$$") console.warn(` was created with unknown prop '${key}'`);
+ if (!~writable_props.indexOf(key) && key.slice(0, 2) !== '$$' && key !== 'slot') console.warn(` was created with unknown prop '${key}'`);
});
$$self.$capture_state = () => ({ obj, kobzol });
$$self.$inject_state = $$props => {
- if ("obj" in $$props) $$invalidate(0, obj = $$props.obj);
- if ("kobzol" in $$props) $$invalidate(1, kobzol = $$props.kobzol);
+ if ('obj' in $$props) $$invalidate(0, obj = $$props.obj);
+ if ('kobzol' in $$props) $$invalidate(1, kobzol = $$props.kobzol);
};
if ($$props && "$$inject" in $$props) {
diff --git a/test/js/samples/debug-no-dependencies/expected.js b/test/js/samples/debug-no-dependencies/expected.js
index 4d8d05d3aa..8107b890a6 100644
--- a/test/js/samples/debug-no-dependencies/expected.js
+++ b/test/js/samples/debug-no-dependencies/expected.js
@@ -137,11 +137,11 @@ function create_fragment(ctx) {
function instance($$self, $$props) {
let { $$slots: slots = {}, $$scope } = $$props;
- validate_slots("Component", slots, []);
+ validate_slots('Component', slots, []);
const writable_props = [];
Object.keys($$props).forEach(key => {
- if (!~writable_props.indexOf(key) && key.slice(0, 2) !== "$$") console.warn(` was created with unknown prop '${key}'`);
+ if (!~writable_props.indexOf(key) && key.slice(0, 2) !== '$$' && key !== 'slot') console.warn(` was created with unknown prop '${key}'`);
});
return [];
diff --git a/test/js/samples/deconflict-builtins/expected.js b/test/js/samples/deconflict-builtins/expected.js
index 6bc60194aa..8c9bb83b5b 100644
--- a/test/js/samples/deconflict-builtins/expected.js
+++ b/test/js/samples/deconflict-builtins/expected.js
@@ -105,7 +105,7 @@ function instance($$self, $$props, $$invalidate) {
let { createElement } = $$props;
$$self.$$set = $$props => {
- if ("createElement" in $$props) $$invalidate(0, createElement = $$props.createElement);
+ if ('createElement' in $$props) $$invalidate(0, createElement = $$props.createElement);
};
return [createElement];
diff --git a/test/js/samples/deconflict-globals/expected.js b/test/js/samples/deconflict-globals/expected.js
index 7168eba6a5..c048cc2ddd 100644
--- a/test/js/samples/deconflict-globals/expected.js
+++ b/test/js/samples/deconflict-globals/expected.js
@@ -1,17 +1,17 @@
/* generated by Svelte vX.Y.Z */
import { SvelteComponent, init, safe_not_equal } from "svelte/internal";
-import { onMount } from "svelte";
+import { onMount } from 'svelte';
function instance($$self, $$props, $$invalidate) {
- let { foo = "bar" } = $$props;
+ let { foo = 'bar' } = $$props;
onMount(() => {
alert(JSON.stringify(data()));
});
$$self.$$set = $$props => {
- if ("foo" in $$props) $$invalidate(0, foo = $$props.foo);
+ if ('foo' in $$props) $$invalidate(0, foo = $$props.foo);
};
return [foo];
diff --git a/test/js/samples/dev-warning-missing-data-computed/expected.js b/test/js/samples/dev-warning-missing-data-computed/expected.js
index 8c7f8bb1cf..5e10ec55f8 100644
--- a/test/js/samples/dev-warning-missing-data-computed/expected.js
+++ b/test/js/samples/dev-warning-missing-data-computed/expected.js
@@ -66,24 +66,24 @@ function create_fragment(ctx) {
function instance($$self, $$props, $$invalidate) {
let { $$slots: slots = {}, $$scope } = $$props;
- validate_slots("Component", slots, []);
+ validate_slots('Component', slots, []);
let { foo } = $$props;
let bar;
- const writable_props = ["foo"];
+ const writable_props = ['foo'];
Object.keys($$props).forEach(key => {
- if (!~writable_props.indexOf(key) && key.slice(0, 2) !== "$$") console.warn(` was created with unknown prop '${key}'`);
+ if (!~writable_props.indexOf(key) && key.slice(0, 2) !== '$$' && key !== 'slot') console.warn(` was created with unknown prop '${key}'`);
});
$$self.$$set = $$props => {
- if ("foo" in $$props) $$invalidate(0, foo = $$props.foo);
+ if ('foo' in $$props) $$invalidate(0, foo = $$props.foo);
};
$$self.$capture_state = () => ({ foo, bar });
$$self.$inject_state = $$props => {
- if ("foo" in $$props) $$invalidate(0, foo = $$props.foo);
- if ("bar" in $$props) $$invalidate(1, bar = $$props.bar);
+ if ('foo' in $$props) $$invalidate(0, foo = $$props.foo);
+ if ('bar' in $$props) $$invalidate(1, bar = $$props.bar);
};
if ($$props && "$$inject" in $$props) {
@@ -114,7 +114,7 @@ class Component extends SvelteComponentDev {
const { ctx } = this.$$;
const props = options.props || {};
- if (/*foo*/ ctx[0] === undefined && !("foo" in props)) {
+ if (/*foo*/ ctx[0] === undefined && !('foo' in props)) {
console.warn(" was created without expected prop 'foo'");
}
}
diff --git a/test/js/samples/dynamic-import/expected.js b/test/js/samples/dynamic-import/expected.js
index d1085f431b..d25a825d3b 100644
--- a/test/js/samples/dynamic-import/expected.js
+++ b/test/js/samples/dynamic-import/expected.js
@@ -11,7 +11,7 @@ import {
transition_out
} from "svelte/internal";
-import LazyLoad from "./LazyLoad.svelte";
+import LazyLoad from './LazyLoad.svelte';
function create_fragment(ctx) {
let lazyload;
@@ -42,7 +42,7 @@ function create_fragment(ctx) {
};
}
-const func = () => import("./Foo.svelte");
+const func = () => import('./Foo.svelte');
class Component extends SvelteComponent {
constructor(options) {
diff --git a/test/js/samples/each-block-array-literal/expected.js b/test/js/samples/each-block-array-literal/expected.js
index fe51ac5bc3..bb5a04e952 100644
--- a/test/js/samples/each-block-array-literal/expected.js
+++ b/test/js/samples/each-block-array-literal/expected.js
@@ -107,11 +107,11 @@ function instance($$self, $$props, $$invalidate) {
let { e } = $$props;
$$self.$$set = $$props => {
- if ("a" in $$props) $$invalidate(0, a = $$props.a);
- if ("b" in $$props) $$invalidate(1, b = $$props.b);
- if ("c" in $$props) $$invalidate(2, c = $$props.c);
- if ("d" in $$props) $$invalidate(3, d = $$props.d);
- if ("e" in $$props) $$invalidate(4, e = $$props.e);
+ if ('a' in $$props) $$invalidate(0, a = $$props.a);
+ if ('b' in $$props) $$invalidate(1, b = $$props.b);
+ if ('c' in $$props) $$invalidate(2, c = $$props.c);
+ if ('d' in $$props) $$invalidate(3, d = $$props.d);
+ if ('e' in $$props) $$invalidate(4, e = $$props.e);
};
return [a, b, c, d, e];
diff --git a/test/js/samples/each-block-changed-check/expected.js b/test/js/samples/each-block-changed-check/expected.js
index 63bc1d8607..19947edbbb 100644
--- a/test/js/samples/each-block-changed-check/expected.js
+++ b/test/js/samples/each-block-changed-check/expected.js
@@ -52,8 +52,9 @@ function create_each_block(ctx) {
t4 = text(t4_value);
t5 = text(" ago:");
t6 = space();
+ html_tag = new HtmlTag();
attr(span, "class", "meta");
- html_tag = new HtmlTag(null);
+ html_tag.a = null;
attr(div, "class", "comment");
},
m(target, anchor) {
@@ -153,10 +154,10 @@ function instance($$self, $$props, $$invalidate) {
let { foo } = $$props;
$$self.$$set = $$props => {
- if ("comments" in $$props) $$invalidate(0, comments = $$props.comments);
- if ("elapsed" in $$props) $$invalidate(1, elapsed = $$props.elapsed);
- if ("time" in $$props) $$invalidate(2, time = $$props.time);
- if ("foo" in $$props) $$invalidate(3, foo = $$props.foo);
+ if ('comments' in $$props) $$invalidate(0, comments = $$props.comments);
+ if ('elapsed' in $$props) $$invalidate(1, elapsed = $$props.elapsed);
+ if ('time' in $$props) $$invalidate(2, time = $$props.time);
+ if ('foo' in $$props) $$invalidate(3, foo = $$props.foo);
};
return [comments, elapsed, time, foo];
diff --git a/test/js/samples/each-block-keyed-animated/expected.js b/test/js/samples/each-block-keyed-animated/expected.js
index b48073f5a7..6f7c22a086 100644
--- a/test/js/samples/each-block-keyed-animated/expected.js
+++ b/test/js/samples/each-block-keyed-animated/expected.js
@@ -130,7 +130,7 @@ function instance($$self, $$props, $$invalidate) {
let { things } = $$props;
$$self.$$set = $$props => {
- if ("things" in $$props) $$invalidate(0, things = $$props.things);
+ if ('things' in $$props) $$invalidate(0, things = $$props.things);
};
return [things];
diff --git a/test/js/samples/each-block-keyed/expected.js b/test/js/samples/each-block-keyed/expected.js
index 7808ed677f..a275697d8e 100644
--- a/test/js/samples/each-block-keyed/expected.js
+++ b/test/js/samples/each-block-keyed/expected.js
@@ -99,7 +99,7 @@ function instance($$self, $$props, $$invalidate) {
let { things } = $$props;
$$self.$$set = $$props => {
- if ("things" in $$props) $$invalidate(0, things = $$props.things);
+ if ('things' in $$props) $$invalidate(0, things = $$props.things);
};
return [things];
diff --git a/test/js/samples/export-from-accessors/_config.js b/test/js/samples/export-from-accessors/_config.js
new file mode 100644
index 0000000000..7f9293a560
--- /dev/null
+++ b/test/js/samples/export-from-accessors/_config.js
@@ -0,0 +1,5 @@
+export default {
+ options: {
+ accessors: true
+ }
+};
diff --git a/test/js/samples/export-from-accessors/expected.js b/test/js/samples/export-from-accessors/expected.js
new file mode 100644
index 0000000000..20b0524ca7
--- /dev/null
+++ b/test/js/samples/export-from-accessors/expected.js
@@ -0,0 +1,34 @@
+/* generated by Svelte vX.Y.Z */
+import { SvelteComponent, init, safe_not_equal } from "svelte/internal";
+
+import { f as f_1, g as g_1 } from './d';
+import { h as h_1 } from './e';
+import { i as j } from './f';
+export { d as e } from './c';
+export { c } from './b';
+export { a, b } from './a';
+
+class Component extends SvelteComponent {
+ constructor(options) {
+ super();
+ init(this, options, null, null, safe_not_equal, {});
+ }
+
+ get f() {
+ return f_1;
+ }
+
+ get g() {
+ return g_1;
+ }
+
+ get h() {
+ return h_1;
+ }
+
+ get j() {
+ return j;
+ }
+}
+
+export default Component;
\ No newline at end of file
diff --git a/test/js/samples/export-from-accessors/input.svelte b/test/js/samples/export-from-accessors/input.svelte
new file mode 100644
index 0000000000..66957806a2
--- /dev/null
+++ b/test/js/samples/export-from-accessors/input.svelte
@@ -0,0 +1,11 @@
+
+
+
diff --git a/test/js/samples/export-from-cjs/_config.js b/test/js/samples/export-from-cjs/_config.js
new file mode 100644
index 0000000000..2506f1d5fc
--- /dev/null
+++ b/test/js/samples/export-from-cjs/_config.js
@@ -0,0 +1,6 @@
+export default {
+ options: {
+ accessors: true,
+ format: 'cjs'
+ }
+};
diff --git a/test/js/samples/export-from-cjs/expected.js b/test/js/samples/export-from-cjs/expected.js
new file mode 100644
index 0000000000..d40f986635
--- /dev/null
+++ b/test/js/samples/export-from-cjs/expected.js
@@ -0,0 +1,36 @@
+/* generated by Svelte vX.Y.Z */
+"use strict";
+
+const { SvelteComponent, init, safe_not_equal } = require("svelte/internal");
+const { f: f_1, g: g_1 } = require("./d");
+const { h: h_1 } = require("./e");
+const { i: j } = require("./f");
+exports.e = require("./c").d;
+exports.c = require("./b").c;
+exports.a = require("./a").a;
+exports.b = require("./a").b;
+
+class Component extends SvelteComponent {
+ constructor(options) {
+ super();
+ init(this, options, null, null, safe_not_equal, {});
+ }
+
+ get f() {
+ return f_1;
+ }
+
+ get g() {
+ return g_1;
+ }
+
+ get h() {
+ return h_1;
+ }
+
+ get j() {
+ return j;
+ }
+}
+
+exports.default = Component;
\ No newline at end of file
diff --git a/test/js/samples/export-from-cjs/input.svelte b/test/js/samples/export-from-cjs/input.svelte
new file mode 100644
index 0000000000..66957806a2
--- /dev/null
+++ b/test/js/samples/export-from-cjs/input.svelte
@@ -0,0 +1,11 @@
+
+
+
diff --git a/test/js/samples/export-from/expected.js b/test/js/samples/export-from/expected.js
new file mode 100644
index 0000000000..04fb47605f
--- /dev/null
+++ b/test/js/samples/export-from/expected.js
@@ -0,0 +1,18 @@
+/* generated by Svelte vX.Y.Z */
+import { SvelteComponent, init, safe_not_equal } from "svelte/internal";
+
+import './d';
+import './e';
+import './f';
+export { d as e } from './c';
+export { c } from './b';
+export { a, b } from './a';
+
+class Component extends SvelteComponent {
+ constructor(options) {
+ super();
+ init(this, options, null, null, safe_not_equal, {});
+ }
+}
+
+export default Component;
\ No newline at end of file
diff --git a/test/js/samples/export-from/input.svelte b/test/js/samples/export-from/input.svelte
new file mode 100644
index 0000000000..66957806a2
--- /dev/null
+++ b/test/js/samples/export-from/input.svelte
@@ -0,0 +1,11 @@
+
+
+
diff --git a/test/js/samples/hydrated-void-element/expected.js b/test/js/samples/hydrated-void-element/expected.js
index e53d16d925..e84b9ad58e 100644
--- a/test/js/samples/hydrated-void-element/expected.js
+++ b/test/js/samples/hydrated-void-element/expected.js
@@ -8,10 +8,11 @@ import {
detach,
element,
init,
- insert,
+ insert_hydration,
noop,
safe_not_equal,
- space
+ space,
+ src_url_equal
} from "svelte/internal";
function create_fragment(ctx) {
@@ -35,13 +36,13 @@ function create_fragment(ctx) {
this.h();
},
h() {
- if (img.src !== (img_src_value = "donuts.jpg")) attr(img, "src", img_src_value);
+ if (!src_url_equal(img.src, img_src_value = "donuts.jpg")) attr(img, "src", img_src_value);
attr(img, "alt", "donuts");
},
m(target, anchor) {
- insert(target, img, anchor);
- insert(target, t, anchor);
- insert(target, div, anchor);
+ insert_hydration(target, img, anchor);
+ insert_hydration(target, t, anchor);
+ insert_hydration(target, div, anchor);
},
p: noop,
i: noop,
@@ -61,4 +62,4 @@ class Component extends SvelteComponent {
}
}
-export default Component;
\ No newline at end of file
+export default Component;
diff --git a/test/js/samples/hydrated-void-svg-element/_config.js b/test/js/samples/hydrated-void-svg-element/_config.js
new file mode 100644
index 0000000000..af1bf11a52
--- /dev/null
+++ b/test/js/samples/hydrated-void-svg-element/_config.js
@@ -0,0 +1,5 @@
+export default {
+ options: {
+ hydratable: true
+ }
+};
diff --git a/test/js/samples/hydrated-void-svg-element/expected.js b/test/js/samples/hydrated-void-svg-element/expected.js
new file mode 100644
index 0000000000..e3b525bcdd
--- /dev/null
+++ b/test/js/samples/hydrated-void-svg-element/expected.js
@@ -0,0 +1,58 @@
+/* generated by Svelte vX.Y.Z */
+import {
+ SvelteComponent,
+ append_hydration,
+ children,
+ claim_svg_element,
+ claim_text,
+ detach,
+ init,
+ insert_hydration,
+ noop,
+ safe_not_equal,
+ svg_element,
+ text
+} from "svelte/internal";
+
+function create_fragment(ctx) {
+ let svg;
+ let title;
+ let t;
+
+ return {
+ c() {
+ svg = svg_element("svg");
+ title = svg_element("title");
+ t = text("a title");
+ },
+ l(nodes) {
+ svg = claim_svg_element(nodes, "svg", {});
+ var svg_nodes = children(svg);
+ title = claim_svg_element(svg_nodes, "title", {});
+ var title_nodes = children(title);
+ t = claim_text(title_nodes, "a title");
+ title_nodes.forEach(detach);
+ svg_nodes.forEach(detach);
+ },
+ m(target, anchor) {
+ insert_hydration(target, svg, anchor);
+ append_hydration(svg, title);
+ append_hydration(title, t);
+ },
+ p: noop,
+ i: noop,
+ o: noop,
+ d(detaching) {
+ if (detaching) detach(svg);
+ }
+ };
+}
+
+class Component extends SvelteComponent {
+ constructor(options) {
+ super();
+ init(this, options, null, create_fragment, safe_not_equal, {});
+ }
+}
+
+export default Component;
diff --git a/test/js/samples/hydrated-void-svg-element/input.svelte b/test/js/samples/hydrated-void-svg-element/input.svelte
new file mode 100644
index 0000000000..7ec3f98b64
--- /dev/null
+++ b/test/js/samples/hydrated-void-svg-element/input.svelte
@@ -0,0 +1,3 @@
+
+ a title
+
\ No newline at end of file
diff --git a/test/js/samples/if-block-no-update/expected.js b/test/js/samples/if-block-no-update/expected.js
index c67b33fa85..25f197eb1a 100644
--- a/test/js/samples/if-block-no-update/expected.js
+++ b/test/js/samples/if-block-no-update/expected.js
@@ -89,7 +89,7 @@ function instance($$self, $$props, $$invalidate) {
let { foo } = $$props;
$$self.$$set = $$props => {
- if ("foo" in $$props) $$invalidate(0, foo = $$props.foo);
+ if ('foo' in $$props) $$invalidate(0, foo = $$props.foo);
};
return [foo];
diff --git a/test/js/samples/if-block-simple/expected.js b/test/js/samples/if-block-simple/expected.js
index 4cdd73cddb..6debe92c24 100644
--- a/test/js/samples/if-block-simple/expected.js
+++ b/test/js/samples/if-block-simple/expected.js
@@ -67,7 +67,7 @@ function instance($$self, $$props, $$invalidate) {
let { foo } = $$props;
$$self.$$set = $$props => {
- if ("foo" in $$props) $$invalidate(0, foo = $$props.foo);
+ if ('foo' in $$props) $$invalidate(0, foo = $$props.foo);
};
return [foo];
diff --git a/test/js/samples/inline-style-optimized-multiple/expected.js b/test/js/samples/inline-style-optimized-multiple/expected.js
index 0a9d0a1e8e..4e4dba16d5 100644
--- a/test/js/samples/inline-style-optimized-multiple/expected.js
+++ b/test/js/samples/inline-style-optimized-multiple/expected.js
@@ -45,9 +45,9 @@ function instance($$self, $$props, $$invalidate) {
let { y } = $$props;
$$self.$$set = $$props => {
- if ("color" in $$props) $$invalidate(0, color = $$props.color);
- if ("x" in $$props) $$invalidate(1, x = $$props.x);
- if ("y" in $$props) $$invalidate(2, y = $$props.y);
+ if ('color' in $$props) $$invalidate(0, color = $$props.color);
+ if ('x' in $$props) $$invalidate(1, x = $$props.x);
+ if ('y' in $$props) $$invalidate(2, y = $$props.y);
};
return [color, x, y];
diff --git a/test/js/samples/inline-style-optimized-url/expected.js b/test/js/samples/inline-style-optimized-url/expected.js
index 0debb03585..a861e9dc7e 100644
--- a/test/js/samples/inline-style-optimized-url/expected.js
+++ b/test/js/samples/inline-style-optimized-url/expected.js
@@ -38,7 +38,7 @@ function instance($$self, $$props, $$invalidate) {
let { data } = $$props;
$$self.$$set = $$props => {
- if ("data" in $$props) $$invalidate(0, data = $$props.data);
+ if ('data' in $$props) $$invalidate(0, data = $$props.data);
};
return [data];
diff --git a/test/js/samples/inline-style-optimized/expected.js b/test/js/samples/inline-style-optimized/expected.js
index b7db0f1cf3..ea4f39ab47 100644
--- a/test/js/samples/inline-style-optimized/expected.js
+++ b/test/js/samples/inline-style-optimized/expected.js
@@ -38,7 +38,7 @@ function instance($$self, $$props, $$invalidate) {
let { color } = $$props;
$$self.$$set = $$props => {
- if ("color" in $$props) $$invalidate(0, color = $$props.color);
+ if ('color' in $$props) $$invalidate(0, color = $$props.color);
};
return [color];
diff --git a/test/js/samples/inline-style-unoptimized/expected.js b/test/js/samples/inline-style-unoptimized/expected.js
index 0688f14b9b..2900fb6ce7 100644
--- a/test/js/samples/inline-style-unoptimized/expected.js
+++ b/test/js/samples/inline-style-unoptimized/expected.js
@@ -55,9 +55,9 @@ function instance($$self, $$props, $$invalidate) {
let { value } = $$props;
$$self.$$set = $$props => {
- if ("style" in $$props) $$invalidate(0, style = $$props.style);
- if ("key" in $$props) $$invalidate(1, key = $$props.key);
- if ("value" in $$props) $$invalidate(2, value = $$props.value);
+ if ('style' in $$props) $$invalidate(0, style = $$props.style);
+ if ('key' in $$props) $$invalidate(1, key = $$props.key);
+ if ('value' in $$props) $$invalidate(2, value = $$props.value);
};
return [style, key, value];
diff --git a/test/js/samples/inline-style-without-updates/expected.js b/test/js/samples/inline-style-without-updates/expected.js
index 375896f259..ebfffe902c 100644
--- a/test/js/samples/inline-style-without-updates/expected.js
+++ b/test/js/samples/inline-style-without-updates/expected.js
@@ -30,7 +30,7 @@ function create_fragment(ctx) {
};
}
-let color = "red";
+let color = 'red';
class Component extends SvelteComponent {
constructor(options) {
diff --git a/test/js/samples/input-files/expected.js b/test/js/samples/input-files/expected.js
index 8adc7443f5..42ddddbcb3 100644
--- a/test/js/samples/input-files/expected.js
+++ b/test/js/samples/input-files/expected.js
@@ -50,7 +50,7 @@ function instance($$self, $$props, $$invalidate) {
}
$$self.$$set = $$props => {
- if ("files" in $$props) $$invalidate(0, files = $$props.files);
+ if ('files' in $$props) $$invalidate(0, files = $$props.files);
};
return [files, input_change_handler];
diff --git a/test/js/samples/input-no-initial-value/expected.js b/test/js/samples/input-no-initial-value/expected.js
index 3354aa3111..a91a95bde2 100644
--- a/test/js/samples/input-no-initial-value/expected.js
+++ b/test/js/samples/input-no-initial-value/expected.js
@@ -69,7 +69,7 @@ function instance($$self, $$props, $$invalidate) {
function handleSubmit(event) {
event.preventDefault();
- console.log("value", test);
+ console.log('value', test);
}
function input_input_handler() {
diff --git a/test/js/samples/input-range/expected.js b/test/js/samples/input-range/expected.js
index a855ca3653..7ced4b176b 100644
--- a/test/js/samples/input-range/expected.js
+++ b/test/js/samples/input-range/expected.js
@@ -61,7 +61,7 @@ function instance($$self, $$props, $$invalidate) {
}
$$self.$$set = $$props => {
- if ("value" in $$props) $$invalidate(0, value = $$props.value);
+ if ('value' in $$props) $$invalidate(0, value = $$props.value);
};
return [value, input_change_input_handler];
diff --git a/test/js/samples/input-value/expected.js b/test/js/samples/input-value/expected.js
index 781a2ae603..2491a24256 100644
--- a/test/js/samples/input-value/expected.js
+++ b/test/js/samples/input-value/expected.js
@@ -64,7 +64,7 @@ function create_fragment(ctx) {
}
function instance($$self, $$props, $$invalidate) {
- let name = "change me";
+ let name = 'change me';
function onInput(event) {
$$invalidate(0, name = event.target.value);
diff --git a/test/js/samples/input-without-blowback-guard/expected.js b/test/js/samples/input-without-blowback-guard/expected.js
index 6c5b215623..007177bda5 100644
--- a/test/js/samples/input-without-blowback-guard/expected.js
+++ b/test/js/samples/input-without-blowback-guard/expected.js
@@ -54,7 +54,7 @@ function instance($$self, $$props, $$invalidate) {
}
$$self.$$set = $$props => {
- if ("foo" in $$props) $$invalidate(0, foo = $$props.foo);
+ if ('foo' in $$props) $$invalidate(0, foo = $$props.foo);
};
return [foo, input_change_handler];
diff --git a/test/js/samples/loop-protect/expected.js b/test/js/samples/loop-protect/expected.js
index 1042b20823..04033d0d95 100644
--- a/test/js/samples/loop-protect/expected.js
+++ b/test/js/samples/loop-protect/expected.js
@@ -54,7 +54,7 @@ function create_fragment(ctx) {
}
function foo() {
- const guard = "foo";
+ const guard = 'foo';
{
const guard_1 = loop_guard(100);
@@ -68,7 +68,7 @@ function foo() {
function instance($$self, $$props, $$invalidate) {
let { $$slots: slots = {}, $$scope } = $$props;
- validate_slots("Component", slots, []);
+ validate_slots('Component', slots, []);
let node;
{
@@ -110,11 +110,11 @@ function instance($$self, $$props, $$invalidate) {
const writable_props = [];
Object.keys($$props).forEach(key => {
- if (!~writable_props.indexOf(key) && key.slice(0, 2) !== "$$") console_1.warn(` was created with unknown prop '${key}'`);
+ if (!~writable_props.indexOf(key) && key.slice(0, 2) !== '$$' && key !== 'slot') console_1.warn(` was created with unknown prop '${key}'`);
});
function div_binding($$value) {
- binding_callbacks[$$value ? "unshift" : "push"](() => {
+ binding_callbacks[$$value ? 'unshift' : 'push'](() => {
node = $$value;
$$invalidate(0, node);
});
@@ -123,7 +123,7 @@ function instance($$self, $$props, $$invalidate) {
$$self.$capture_state = () => ({ node, foo });
$$self.$inject_state = $$props => {
- if ("node" in $$props) $$invalidate(0, node = $$props.node);
+ if ('node' in $$props) $$invalidate(0, node = $$props.node);
};
if ($$props && "$$inject" in $$props) {
diff --git a/test/js/samples/media-bindings/expected.js b/test/js/samples/media-bindings/expected.js
index 867d4a7dad..5005eb47d1 100644
--- a/test/js/samples/media-bindings/expected.js
+++ b/test/js/samples/media-bindings/expected.js
@@ -174,17 +174,17 @@ function instance($$self, $$props, $$invalidate) {
}
$$self.$$set = $$props => {
- if ("buffered" in $$props) $$invalidate(0, buffered = $$props.buffered);
- if ("seekable" in $$props) $$invalidate(1, seekable = $$props.seekable);
- if ("played" in $$props) $$invalidate(2, played = $$props.played);
- if ("currentTime" in $$props) $$invalidate(3, currentTime = $$props.currentTime);
- if ("duration" in $$props) $$invalidate(4, duration = $$props.duration);
- if ("paused" in $$props) $$invalidate(5, paused = $$props.paused);
- if ("volume" in $$props) $$invalidate(6, volume = $$props.volume);
- if ("muted" in $$props) $$invalidate(7, muted = $$props.muted);
- if ("playbackRate" in $$props) $$invalidate(8, playbackRate = $$props.playbackRate);
- if ("seeking" in $$props) $$invalidate(9, seeking = $$props.seeking);
- if ("ended" in $$props) $$invalidate(10, ended = $$props.ended);
+ if ('buffered' in $$props) $$invalidate(0, buffered = $$props.buffered);
+ if ('seekable' in $$props) $$invalidate(1, seekable = $$props.seekable);
+ if ('played' in $$props) $$invalidate(2, played = $$props.played);
+ if ('currentTime' in $$props) $$invalidate(3, currentTime = $$props.currentTime);
+ if ('duration' in $$props) $$invalidate(4, duration = $$props.duration);
+ if ('paused' in $$props) $$invalidate(5, paused = $$props.paused);
+ if ('volume' in $$props) $$invalidate(6, volume = $$props.volume);
+ if ('muted' in $$props) $$invalidate(7, muted = $$props.muted);
+ if ('playbackRate' in $$props) $$invalidate(8, playbackRate = $$props.playbackRate);
+ if ('seeking' in $$props) $$invalidate(9, seeking = $$props.seeking);
+ if ('ended' in $$props) $$invalidate(10, ended = $$props.ended);
};
return [
diff --git a/test/js/samples/non-imported-component/expected.js b/test/js/samples/non-imported-component/expected.js
index 5a6b8e8bb7..e3f2760ce0 100644
--- a/test/js/samples/non-imported-component/expected.js
+++ b/test/js/samples/non-imported-component/expected.js
@@ -14,7 +14,7 @@ import {
transition_out
} from "svelte/internal";
-import Imported from "Imported.svelte";
+import Imported from 'Imported.svelte';
function create_fragment(ctx) {
let imported;
diff --git a/test/js/samples/non-mutable-reference/expected.js b/test/js/samples/non-mutable-reference/expected.js
index 93f2145a2e..adc67b9bc4 100644
--- a/test/js/samples/non-mutable-reference/expected.js
+++ b/test/js/samples/non-mutable-reference/expected.js
@@ -29,7 +29,7 @@ function create_fragment(ctx) {
};
}
-let name = "world";
+let name = 'world';
class Component extends SvelteComponent {
constructor(options) {
diff --git a/test/js/samples/optional-chaining/expected.js b/test/js/samples/optional-chaining/expected.js
index 8aa94796c1..57369ddb72 100644
--- a/test/js/samples/optional-chaining/expected.js
+++ b/test/js/samples/optional-chaining/expected.js
@@ -23,9 +23,9 @@ function create_fragment(ctx) {
let t1_value = /*b*/ ctx[1]?.optional + "";
let t1;
let t2;
- let t3_value = /*c*/ ctx[2]["computed"] + "";
+ let t3_value = /*c*/ ctx[2]['computed'] + "";
let t3;
- let t4_value = /*d*/ ctx[3]?.["computed_optional"] + "";
+ let t4_value = /*d*/ ctx[3]?.['computed_optional'] + "";
let t4;
let t5;
let t6_value = /*e*/ ctx[4]() + "";
@@ -48,8 +48,8 @@ function create_fragment(ctx) {
props: {
a: /*a*/ ctx[0].normal,
b: /*b*/ ctx[1]?.optional,
- c: /*c*/ ctx[2]["computed"],
- d: /*d*/ ctx[3]?.["computed_optional"],
+ c: /*c*/ ctx[2]['computed'],
+ d: /*d*/ ctx[3]?.['computed_optional'],
e: /*e*/ ctx[4](),
f: /*f*/ ctx[5]?.()
}
@@ -71,8 +71,8 @@ function create_fragment(ctx) {
create_component(component.$$.fragment);
attr(div, "a", div_a_value = /*a*/ ctx[0].normal);
attr(div, "b", div_b_value = /*b*/ ctx[1]?.optional);
- attr(div, "c", div_c_value = /*c*/ ctx[2]["computed"]);
- attr(div, "d", div_d_value = /*d*/ ctx[3]?.["computed_optional"]);
+ attr(div, "c", div_c_value = /*c*/ ctx[2]['computed']);
+ attr(div, "d", div_d_value = /*d*/ ctx[3]?.['computed_optional']);
attr(div, "e", div_e_value = /*e*/ ctx[4]());
attr(div, "f", div_f_value = /*f*/ ctx[5]?.());
},
@@ -94,8 +94,8 @@ function create_fragment(ctx) {
p(ctx, [dirty]) {
if ((!current || dirty & /*a*/ 1) && t0_value !== (t0_value = /*a*/ ctx[0].normal + "")) set_data(t0, t0_value);
if ((!current || dirty & /*b*/ 2) && t1_value !== (t1_value = /*b*/ ctx[1]?.optional + "")) set_data(t1, t1_value);
- if ((!current || dirty & /*c*/ 4) && t3_value !== (t3_value = /*c*/ ctx[2]["computed"] + "")) set_data(t3, t3_value);
- if ((!current || dirty & /*d*/ 8) && t4_value !== (t4_value = /*d*/ ctx[3]?.["computed_optional"] + "")) set_data(t4, t4_value);
+ if ((!current || dirty & /*c*/ 4) && t3_value !== (t3_value = /*c*/ ctx[2]['computed'] + "")) set_data(t3, t3_value);
+ if ((!current || dirty & /*d*/ 8) && t4_value !== (t4_value = /*d*/ ctx[3]?.['computed_optional'] + "")) set_data(t4, t4_value);
if ((!current || dirty & /*e*/ 16) && t6_value !== (t6_value = /*e*/ ctx[4]() + "")) set_data(t6, t6_value);
if ((!current || dirty & /*f*/ 32) && t7_value !== (t7_value = /*f*/ ctx[5]?.() + "")) set_data(t7, t7_value);
@@ -107,11 +107,11 @@ function create_fragment(ctx) {
attr(div, "b", div_b_value);
}
- if (!current || dirty & /*c*/ 4 && div_c_value !== (div_c_value = /*c*/ ctx[2]["computed"])) {
+ if (!current || dirty & /*c*/ 4 && div_c_value !== (div_c_value = /*c*/ ctx[2]['computed'])) {
attr(div, "c", div_c_value);
}
- if (!current || dirty & /*d*/ 8 && div_d_value !== (div_d_value = /*d*/ ctx[3]?.["computed_optional"])) {
+ if (!current || dirty & /*d*/ 8 && div_d_value !== (div_d_value = /*d*/ ctx[3]?.['computed_optional'])) {
attr(div, "d", div_d_value);
}
@@ -126,8 +126,8 @@ function create_fragment(ctx) {
const component_changes = {};
if (dirty & /*a*/ 1) component_changes.a = /*a*/ ctx[0].normal;
if (dirty & /*b*/ 2) component_changes.b = /*b*/ ctx[1]?.optional;
- if (dirty & /*c*/ 4) component_changes.c = /*c*/ ctx[2]["computed"];
- if (dirty & /*d*/ 8) component_changes.d = /*d*/ ctx[3]?.["computed_optional"];
+ if (dirty & /*c*/ 4) component_changes.c = /*c*/ ctx[2]['computed'];
+ if (dirty & /*d*/ 8) component_changes.d = /*d*/ ctx[3]?.['computed_optional'];
if (dirty & /*e*/ 16) component_changes.e = /*e*/ ctx[4]();
if (dirty & /*f*/ 32) component_changes.f = /*f*/ ctx[5]?.();
component.$set(component_changes);
@@ -168,12 +168,12 @@ function instance($$self, $$props, $$invalidate) {
let Component;
$$self.$$set = $$props => {
- if ("a" in $$props) $$invalidate(0, a = $$props.a);
- if ("b" in $$props) $$invalidate(1, b = $$props.b);
- if ("c" in $$props) $$invalidate(2, c = $$props.c);
- if ("d" in $$props) $$invalidate(3, d = $$props.d);
- if ("e" in $$props) $$invalidate(4, e = $$props.e);
- if ("f" in $$props) $$invalidate(5, f = $$props.f);
+ if ('a' in $$props) $$invalidate(0, a = $$props.a);
+ if ('b' in $$props) $$invalidate(1, b = $$props.b);
+ if ('c' in $$props) $$invalidate(2, c = $$props.c);
+ if ('d' in $$props) $$invalidate(3, d = $$props.d);
+ if ('e' in $$props) $$invalidate(4, e = $$props.e);
+ if ('f' in $$props) $$invalidate(5, f = $$props.f);
};
return [a, b, c, d, e, f, Component];
diff --git a/test/js/samples/reactive-class-optimized/expected.js b/test/js/samples/reactive-class-optimized/expected.js
index b7c2c3a60b..1d0606ad60 100644
--- a/test/js/samples/reactive-class-optimized/expected.js
+++ b/test/js/samples/reactive-class-optimized/expected.js
@@ -13,7 +13,7 @@ import {
toggle_class
} from "svelte/internal";
-import { reactiveStoreVal, unreactiveExport } from "./store";
+import { reactiveStoreVal, unreactiveExport } from './store';
function create_fragment(ctx) {
let div0;
@@ -159,4 +159,4 @@ class Component extends SvelteComponent {
}
}
-export default Component;
+export default Component;
\ No newline at end of file
diff --git a/test/js/samples/reactive-values-non-topologically-ordered/expected.js b/test/js/samples/reactive-values-non-topologically-ordered/expected.js
index dbfd794dc7..82af20ee90 100644
--- a/test/js/samples/reactive-values-non-topologically-ordered/expected.js
+++ b/test/js/samples/reactive-values-non-topologically-ordered/expected.js
@@ -7,7 +7,7 @@ function instance($$self, $$props, $$invalidate) {
let b;
$$self.$$set = $$props => {
- if ("x" in $$props) $$invalidate(0, x = $$props.x);
+ if ('x' in $$props) $$invalidate(0, x = $$props.x);
};
$$self.$$.update = () => {
diff --git a/test/js/samples/reactive-values-non-writable-dependencies/expected.js b/test/js/samples/reactive-values-non-writable-dependencies/expected.js
index 5196a770d9..ca01bda65b 100644
--- a/test/js/samples/reactive-values-non-writable-dependencies/expected.js
+++ b/test/js/samples/reactive-values-non-writable-dependencies/expected.js
@@ -6,13 +6,13 @@ function instance($$self, $$props, $$invalidate) {
let { b = 2 } = $$props;
$$self.$$set = $$props => {
- if ("a" in $$props) $$invalidate(0, a = $$props.a);
- if ("b" in $$props) $$invalidate(1, b = $$props.b);
+ if ('a' in $$props) $$invalidate(0, a = $$props.a);
+ if ('b' in $$props) $$invalidate(1, b = $$props.b);
};
$$self.$$.update = () => {
if ($$self.$$.dirty & /*a, b*/ 3) {
- $: console.log("max", Math.max(a, b));
+ $: console.log('max', Math.max(a, b));
}
};
diff --git a/test/js/samples/select-dynamic-value/expected.js b/test/js/samples/select-dynamic-value/expected.js
index 8777cd2600..cd1ab1d812 100644
--- a/test/js/samples/select-dynamic-value/expected.js
+++ b/test/js/samples/select-dynamic-value/expected.js
@@ -51,7 +51,7 @@ function instance($$self, $$props, $$invalidate) {
let { current } = $$props;
$$self.$$set = $$props => {
- if ("current" in $$props) $$invalidate(0, current = $$props.current);
+ if ('current' in $$props) $$invalidate(0, current = $$props.current);
};
return [current];
diff --git a/test/js/samples/src-attribute-check-in-foreign/_config.js b/test/js/samples/src-attribute-check-in-foreign/_config.js
new file mode 100644
index 0000000000..af1bf11a52
--- /dev/null
+++ b/test/js/samples/src-attribute-check-in-foreign/_config.js
@@ -0,0 +1,5 @@
+export default {
+ options: {
+ hydratable: true
+ }
+};
diff --git a/test/js/samples/src-attribute-check-in-foreign/expected.js b/test/js/samples/src-attribute-check-in-foreign/expected.js
new file mode 100644
index 0000000000..3d781b72d4
--- /dev/null
+++ b/test/js/samples/src-attribute-check-in-foreign/expected.js
@@ -0,0 +1,70 @@
+/* generated by Svelte vX.Y.Z */
+import {
+ SvelteComponent,
+ append_hydration,
+ attr,
+ children,
+ claim_element,
+ detach,
+ init,
+ insert_hydration,
+ noop,
+ safe_not_equal
+} from "svelte/internal";
+
+function create_fragment(ctx) {
+ let svg;
+ let img;
+
+ return {
+ c() {
+ svg = document.createElementNS("https://svelte.dev/docs#svelte_options", "svg");
+ img = document.createElementNS("https://svelte.dev/docs#svelte_options", "img");
+ this.h();
+ },
+ l(nodes) {
+ svg = claim_element(nodes, "svg", {});
+ var svg_nodes = children(svg);
+ img = claim_element(svg_nodes, "img", { alt: true, src: true });
+ svg_nodes.forEach(detach);
+ this.h();
+ },
+ h() {
+ attr(img, "alt", "potato");
+ attr(img, "src", /*url*/ ctx[0]);
+ },
+ m(target, anchor) {
+ insert_hydration(target, svg, anchor);
+ append_hydration(svg, img);
+ },
+ p(ctx, [dirty]) {
+ if (dirty & /*url*/ 1) {
+ attr(img, "src", /*url*/ ctx[0]);
+ }
+ },
+ i: noop,
+ o: noop,
+ d(detaching) {
+ if (detaching) detach(svg);
+ }
+ };
+}
+
+function instance($$self, $$props, $$invalidate) {
+ let { url } = $$props;
+
+ $$self.$$set = $$props => {
+ if ('url' in $$props) $$invalidate(0, url = $$props.url);
+ };
+
+ return [url];
+}
+
+class Component extends SvelteComponent {
+ constructor(options) {
+ super();
+ init(this, options, instance, create_fragment, safe_not_equal, { url: 0 });
+ }
+}
+
+export default Component;
diff --git a/test/js/samples/src-attribute-check-in-foreign/input.svelte b/test/js/samples/src-attribute-check-in-foreign/input.svelte
new file mode 100644
index 0000000000..6d04f0fa55
--- /dev/null
+++ b/test/js/samples/src-attribute-check-in-foreign/input.svelte
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
diff --git a/test/js/samples/src-attribute-check-in-svg/_config.js b/test/js/samples/src-attribute-check-in-svg/_config.js
new file mode 100644
index 0000000000..af1bf11a52
--- /dev/null
+++ b/test/js/samples/src-attribute-check-in-svg/_config.js
@@ -0,0 +1,5 @@
+export default {
+ options: {
+ hydratable: true
+ }
+};
diff --git a/test/js/samples/src-attribute-check-in-svg/expected.js b/test/js/samples/src-attribute-check-in-svg/expected.js
new file mode 100644
index 0000000000..551a23e50e
--- /dev/null
+++ b/test/js/samples/src-attribute-check-in-svg/expected.js
@@ -0,0 +1,71 @@
+/* generated by Svelte vX.Y.Z */
+import {
+ SvelteComponent,
+ append_hydration,
+ attr,
+ children,
+ claim_svg_element,
+ detach,
+ init,
+ insert_hydration,
+ noop,
+ safe_not_equal,
+ svg_element
+} from "svelte/internal";
+
+function create_fragment(ctx) {
+ let svg;
+ let img;
+
+ return {
+ c() {
+ svg = svg_element("svg");
+ img = svg_element("img");
+ this.h();
+ },
+ l(nodes) {
+ svg = claim_svg_element(nodes, "svg", {});
+ var svg_nodes = children(svg);
+ img = claim_svg_element(svg_nodes, "img", { alt: true, src: true });
+ svg_nodes.forEach(detach);
+ this.h();
+ },
+ h() {
+ attr(img, "alt", "potato");
+ attr(img, "src", /*url*/ ctx[0]);
+ },
+ m(target, anchor) {
+ insert_hydration(target, svg, anchor);
+ append_hydration(svg, img);
+ },
+ p(ctx, [dirty]) {
+ if (dirty & /*url*/ 1) {
+ attr(img, "src", /*url*/ ctx[0]);
+ }
+ },
+ i: noop,
+ o: noop,
+ d(detaching) {
+ if (detaching) detach(svg);
+ }
+ };
+}
+
+function instance($$self, $$props, $$invalidate) {
+ let { url } = $$props;
+
+ $$self.$$set = $$props => {
+ if ('url' in $$props) $$invalidate(0, url = $$props.url);
+ };
+
+ return [url];
+}
+
+class Component extends SvelteComponent {
+ constructor(options) {
+ super();
+ init(this, options, instance, create_fragment, safe_not_equal, { url: 0 });
+ }
+}
+
+export default Component;
diff --git a/test/js/samples/src-attribute-check-in-svg/input.svelte b/test/js/samples/src-attribute-check-in-svg/input.svelte
new file mode 100644
index 0000000000..05dbc37608
--- /dev/null
+++ b/test/js/samples/src-attribute-check-in-svg/input.svelte
@@ -0,0 +1,7 @@
+
+
+
+
+
diff --git a/test/js/samples/src-attribute-check/expected.js b/test/js/samples/src-attribute-check/expected.js
index 93638edfb4..10ff49bb81 100644
--- a/test/js/samples/src-attribute-check/expected.js
+++ b/test/js/samples/src-attribute-check/expected.js
@@ -7,10 +7,11 @@ import {
detach,
element,
init,
- insert,
+ insert_hydration,
noop,
safe_not_equal,
- space
+ space,
+ src_url_equal
} from "svelte/internal";
function create_fragment(ctx) {
@@ -35,21 +36,21 @@ function create_fragment(ctx) {
},
h() {
attr(img0, "alt", "potato");
- if (img0.src !== (img0_src_value = /*url*/ ctx[0])) attr(img0, "src", img0_src_value);
+ if (!src_url_equal(img0.src, img0_src_value = /*url*/ ctx[0])) attr(img0, "src", img0_src_value);
attr(img1, "alt", "potato");
- if (img1.src !== (img1_src_value = "" + (/*slug*/ ctx[1] + ".jpg"))) attr(img1, "src", img1_src_value);
+ if (!src_url_equal(img1.src, img1_src_value = "" + (/*slug*/ ctx[1] + ".jpg"))) attr(img1, "src", img1_src_value);
},
m(target, anchor) {
- insert(target, img0, anchor);
- insert(target, t, anchor);
- insert(target, img1, anchor);
+ insert_hydration(target, img0, anchor);
+ insert_hydration(target, t, anchor);
+ insert_hydration(target, img1, anchor);
},
p(ctx, [dirty]) {
- if (dirty & /*url*/ 1 && img0.src !== (img0_src_value = /*url*/ ctx[0])) {
+ if (dirty & /*url*/ 1 && !src_url_equal(img0.src, img0_src_value = /*url*/ ctx[0])) {
attr(img0, "src", img0_src_value);
}
- if (dirty & /*slug*/ 2 && img1.src !== (img1_src_value = "" + (/*slug*/ ctx[1] + ".jpg"))) {
+ if (dirty & /*slug*/ 2 && !src_url_equal(img1.src, img1_src_value = "" + (/*slug*/ ctx[1] + ".jpg"))) {
attr(img1, "src", img1_src_value);
}
},
@@ -68,8 +69,8 @@ function instance($$self, $$props, $$invalidate) {
let { slug } = $$props;
$$self.$$set = $$props => {
- if ("url" in $$props) $$invalidate(0, url = $$props.url);
- if ("slug" in $$props) $$invalidate(1, slug = $$props.slug);
+ if ('url' in $$props) $$invalidate(0, url = $$props.url);
+ if ('slug' in $$props) $$invalidate(1, slug = $$props.slug);
};
return [url, slug];
@@ -82,4 +83,4 @@ class Component extends SvelteComponent {
}
}
-export default Component;
\ No newline at end of file
+export default Component;
diff --git a/test/js/samples/ssr-no-oncreate-etc/expected.js b/test/js/samples/ssr-no-oncreate-etc/expected.js
index b91deb3e97..09ae6fd4a6 100644
--- a/test/js/samples/ssr-no-oncreate-etc/expected.js
+++ b/test/js/samples/ssr-no-oncreate-etc/expected.js
@@ -1,14 +1,14 @@
/* generated by Svelte vX.Y.Z */
import { create_ssr_component } from "svelte/internal";
-import { onDestroy, onMount } from "svelte";
+import { onDestroy, onMount } from 'svelte';
function preload(input) {
return output;
}
function foo() {
- console.log("foo");
+ console.log('foo');
}
function swipe(node, callback) {
@@ -17,11 +17,11 @@ function swipe(node, callback) {
const Component = create_ssr_component(($$result, $$props, $$bindings, slots) => {
onMount(() => {
- console.log("onMount");
+ console.log('onMount');
});
onDestroy(() => {
- console.log("onDestroy");
+ console.log('onDestroy');
});
return ``;
diff --git a/test/js/samples/ssr-preserve-comments/expected.js b/test/js/samples/ssr-preserve-comments/expected.js
index de9fa7582e..4f3326cec5 100644
--- a/test/js/samples/ssr-preserve-comments/expected.js
+++ b/test/js/samples/ssr-preserve-comments/expected.js
@@ -3,8 +3,8 @@ import { create_ssr_component } from "svelte/internal";
const Component = create_ssr_component(($$result, $$props, $$bindings, slots) => {
return `content
-
+
more content
`;
});
-export default Component;
\ No newline at end of file
+export default Component;
diff --git a/test/js/samples/title/expected.js b/test/js/samples/title/expected.js
index b10f569759..6385f36acc 100644
--- a/test/js/samples/title/expected.js
+++ b/test/js/samples/title/expected.js
@@ -23,7 +23,7 @@ function instance($$self, $$props, $$invalidate) {
let { custom } = $$props;
$$self.$$set = $$props => {
- if ("custom" in $$props) $$invalidate(0, custom = $$props.custom);
+ if ('custom' in $$props) $$invalidate(0, custom = $$props.custom);
};
return [custom];
diff --git a/test/js/samples/transition-local/expected.js b/test/js/samples/transition-local/expected.js
index ea3d9db3d7..1824ccb066 100644
--- a/test/js/samples/transition-local/expected.js
+++ b/test/js/samples/transition-local/expected.js
@@ -125,8 +125,8 @@ function instance($$self, $$props, $$invalidate) {
let { y } = $$props;
$$self.$$set = $$props => {
- if ("x" in $$props) $$invalidate(0, x = $$props.x);
- if ("y" in $$props) $$invalidate(1, y = $$props.y);
+ if ('x' in $$props) $$invalidate(0, x = $$props.x);
+ if ('y' in $$props) $$invalidate(1, y = $$props.y);
};
return [x, y];
diff --git a/test/js/samples/transition-repeated-outro/expected.js b/test/js/samples/transition-repeated-outro/expected.js
index 12483ab91a..a2cbedffea 100644
--- a/test/js/samples/transition-repeated-outro/expected.js
+++ b/test/js/samples/transition-repeated-outro/expected.js
@@ -14,7 +14,7 @@ import {
transition_out
} from "svelte/internal";
-import { fade } from "svelte/transition";
+import { fade } from 'svelte/transition';
function create_if_block(ctx) {
let div;
@@ -103,7 +103,7 @@ function instance($$self, $$props, $$invalidate) {
let { num = 1 } = $$props;
$$self.$$set = $$props => {
- if ("num" in $$props) $$invalidate(0, num = $$props.num);
+ if ('num' in $$props) $$invalidate(0, num = $$props.num);
};
return [num];
diff --git a/test/js/samples/unchanged-expression/expected.js b/test/js/samples/unchanged-expression/expected.js
index 673d5b6abc..48ae8131ff 100644
--- a/test/js/samples/unchanged-expression/expected.js
+++ b/test/js/samples/unchanged-expression/expected.js
@@ -69,14 +69,14 @@ function create_fragment(ctx) {
};
}
-let world1 = "world";
-let world2 = "world";
+let world1 = 'world';
+let world2 = 'world';
function instance($$self, $$props, $$invalidate) {
- const world3 = "world";
+ const world3 = 'world';
function foo() {
- $$invalidate(0, world3 = "svelte");
+ $$invalidate(0, world3 = 'svelte');
}
return [world3];
diff --git a/test/js/samples/unreferenced-state-not-invalidated/expected.js b/test/js/samples/unreferenced-state-not-invalidated/expected.js
index 53044c7ed6..8c238a8397 100644
--- a/test/js/samples/unreferenced-state-not-invalidated/expected.js
+++ b/test/js/samples/unreferenced-state-not-invalidated/expected.js
@@ -12,7 +12,7 @@ import {
text
} from "svelte/internal";
-import { onMount } from "svelte";
+import { onMount } from 'svelte';
function create_fragment(ctx) {
let p;
diff --git a/test/js/samples/use-elements-as-anchors/expected.js b/test/js/samples/use-elements-as-anchors/expected.js
index d07411518e..8a45cb54c8 100644
--- a/test/js/samples/use-elements-as-anchors/expected.js
+++ b/test/js/samples/use-elements-as-anchors/expected.js
@@ -244,11 +244,11 @@ function instance($$self, $$props, $$invalidate) {
let { e } = $$props;
$$self.$$set = $$props => {
- if ("a" in $$props) $$invalidate(0, a = $$props.a);
- if ("b" in $$props) $$invalidate(1, b = $$props.b);
- if ("c" in $$props) $$invalidate(2, c = $$props.c);
- if ("d" in $$props) $$invalidate(3, d = $$props.d);
- if ("e" in $$props) $$invalidate(4, e = $$props.e);
+ if ('a' in $$props) $$invalidate(0, a = $$props.a);
+ if ('b' in $$props) $$invalidate(1, b = $$props.b);
+ if ('c' in $$props) $$invalidate(2, c = $$props.c);
+ if ('d' in $$props) $$invalidate(3, d = $$props.d);
+ if ('e' in $$props) $$invalidate(4, e = $$props.e);
};
return [a, b, c, d, e];
diff --git a/test/js/samples/video-bindings/expected.js b/test/js/samples/video-bindings/expected.js
index 8afa670bbb..020bab574c 100644
--- a/test/js/samples/video-bindings/expected.js
+++ b/test/js/samples/video-bindings/expected.js
@@ -94,10 +94,10 @@ function instance($$self, $$props, $$invalidate) {
}
$$self.$$set = $$props => {
- if ("currentTime" in $$props) $$invalidate(0, currentTime = $$props.currentTime);
- if ("videoHeight" in $$props) $$invalidate(1, videoHeight = $$props.videoHeight);
- if ("videoWidth" in $$props) $$invalidate(2, videoWidth = $$props.videoWidth);
- if ("offsetWidth" in $$props) $$invalidate(3, offsetWidth = $$props.offsetWidth);
+ if ('currentTime' in $$props) $$invalidate(0, currentTime = $$props.currentTime);
+ if ('videoHeight' in $$props) $$invalidate(1, videoHeight = $$props.videoHeight);
+ if ('videoWidth' in $$props) $$invalidate(2, videoWidth = $$props.videoWidth);
+ if ('offsetWidth' in $$props) $$invalidate(3, offsetWidth = $$props.offsetWidth);
};
return [
diff --git a/test/js/samples/window-binding-scroll/expected.js b/test/js/samples/window-binding-scroll/expected.js
index 09a4d3737d..ae155d42bf 100644
--- a/test/js/samples/window-binding-scroll/expected.js
+++ b/test/js/samples/window-binding-scroll/expected.js
@@ -79,7 +79,7 @@ function instance($$self, $$props, $$invalidate) {
}
$$self.$$set = $$props => {
- if ("y" in $$props) $$invalidate(0, y = $$props.y);
+ if ('y' in $$props) $$invalidate(0, y = $$props.y);
};
return [y, onwindowscroll];
diff --git a/test/parser/samples/attribute-curly-bracket/input.svelte b/test/parser/samples/attribute-curly-bracket/input.svelte
new file mode 100644
index 0000000000..4e40713771
--- /dev/null
+++ b/test/parser/samples/attribute-curly-bracket/input.svelte
@@ -0,0 +1 @@
+
diff --git a/test/parser/samples/attribute-curly-bracket/output.json b/test/parser/samples/attribute-curly-bracket/output.json
new file mode 100644
index 0000000000..7fa04859f3
--- /dev/null
+++ b/test/parser/samples/attribute-curly-bracket/output.json
@@ -0,0 +1,55 @@
+{
+ "html": {
+ "start": 0,
+ "end": 18,
+ "type": "Fragment",
+ "children": [
+ {
+ "start": 0,
+ "end": 18,
+ "type": "Element",
+ "name": "input",
+ "attributes": [
+ {
+ "start": 7,
+ "end": 15,
+ "type": "Attribute",
+ "name": "foo",
+ "value": [
+ {
+ "start": 11,
+ "end": 12,
+ "type": "Text",
+ "raw": "a",
+ "data": "a"
+ },
+ {
+ "start": 12,
+ "end": 15,
+ "type": "MustacheTag",
+ "expression": {
+ "type": "Literal",
+ "start": 13,
+ "end": 14,
+ "loc": {
+ "start": {
+ "line": 1,
+ "column": 13
+ },
+ "end": {
+ "line": 1,
+ "column": 14
+ }
+ },
+ "value": 1,
+ "raw": "1"
+ }
+ }
+ ]
+ }
+ ],
+ "children": []
+ }
+ ]
+ }
+}
diff --git a/test/parser/samples/attribute-dynamic/output.json b/test/parser/samples/attribute-dynamic/output.json
index 28b9da1dea..4926b645ab 100644
--- a/test/parser/samples/attribute-dynamic/output.json
+++ b/test/parser/samples/attribute-dynamic/output.json
@@ -18,7 +18,7 @@
"value": [
{
"start": 12,
- "end": 20,
+ "end": 19,
"type": "Text",
"raw": "color: ",
"data": "color: "
@@ -80,4 +80,4 @@
}
]
}
-}
\ No newline at end of file
+}
diff --git a/test/parser/samples/attribute-empty-error/error.json b/test/parser/samples/attribute-empty-error/error.json
new file mode 100644
index 0000000000..8c004d34ed
--- /dev/null
+++ b/test/parser/samples/attribute-empty-error/error.json
@@ -0,0 +1,10 @@
+{
+ "code": "missing-attribute-value",
+ "message": "Expected value for the attribute",
+ "pos": 12,
+ "start": {
+ "character": 12,
+ "column": 12,
+ "line": 1
+ }
+}
\ No newline at end of file
diff --git a/test/parser/samples/attribute-empty-error/input.svelte b/test/parser/samples/attribute-empty-error/input.svelte
new file mode 100644
index 0000000000..ee1b8935f1
--- /dev/null
+++ b/test/parser/samples/attribute-empty-error/input.svelte
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/parser/samples/attribute-empty/input.svelte b/test/parser/samples/attribute-empty/input.svelte
new file mode 100644
index 0000000000..d500678c37
--- /dev/null
+++ b/test/parser/samples/attribute-empty/input.svelte
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/parser/samples/attribute-empty/output.json b/test/parser/samples/attribute-empty/output.json
new file mode 100644
index 0000000000..22420b9fda
--- /dev/null
+++ b/test/parser/samples/attribute-empty/output.json
@@ -0,0 +1,108 @@
+{
+ "html": {
+ "start": 0,
+ "end": 38,
+ "type": "Fragment",
+ "children": [
+ {
+ "start": 0,
+ "end": 38,
+ "type": "Element",
+ "name": "div",
+ "attributes": [
+ {
+ "start": 5,
+ "end": 9,
+ "type": "Attribute",
+ "name": "a",
+ "value": [
+ {
+ "start": 8,
+ "end": 8,
+ "type": "Text",
+ "raw": "",
+ "data": ""
+ }
+ ]
+ },
+ {
+ "start": 10,
+ "end": 16,
+ "type": "Attribute",
+ "name": "b",
+ "value": [
+ {
+ "start": 12,
+ "end": 16,
+ "type": "MustacheTag",
+ "expression": {
+ "type": "Literal",
+ "start": 13,
+ "end": 15,
+ "loc": {
+ "start": {
+ "line": 1,
+ "column": 13
+ },
+ "end": {
+ "line": 1,
+ "column": 15
+ }
+ },
+ "value": "",
+ "raw": "''"
+ }
+ }
+ ]
+ },
+ {
+ "start": 17,
+ "end": 21,
+ "type": "Attribute",
+ "name": "c",
+ "value": [
+ {
+ "start": 20,
+ "end": 20,
+ "type": "Text",
+ "raw": "",
+ "data": ""
+ }
+ ]
+ },
+ {
+ "start": 22,
+ "end": 30,
+ "type": "Attribute",
+ "name": "d",
+ "value": [
+ {
+ "start": 25,
+ "end": 29,
+ "type": "MustacheTag",
+ "expression": {
+ "type": "Literal",
+ "start": 26,
+ "end": 28,
+ "loc": {
+ "start": {
+ "line": 1,
+ "column": 26
+ },
+ "end": {
+ "line": 1,
+ "column": 28
+ }
+ },
+ "value": "",
+ "raw": "''"
+ }
+ }
+ ]
+ }
+ ],
+ "children": []
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/test/parser/samples/comment-with-ignores/input.svelte b/test/parser/samples/comment-with-ignores/input.svelte
new file mode 100644
index 0000000000..c4fcec5e50
--- /dev/null
+++ b/test/parser/samples/comment-with-ignores/input.svelte
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/parser/samples/comment-with-ignores/output.json b/test/parser/samples/comment-with-ignores/output.json
new file mode 100644
index 0000000000..2705ec6658
--- /dev/null
+++ b/test/parser/samples/comment-with-ignores/output.json
@@ -0,0 +1,16 @@
+{
+ "html": {
+ "start": 0,
+ "end": 30,
+ "type": "Fragment",
+ "children": [
+ {
+ "start": 0,
+ "end": 30,
+ "type": "Comment",
+ "data": " svelte-ignore foo bar ",
+ "ignores": ["foo", "bar"]
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/test/parser/samples/comment/output.json b/test/parser/samples/comment/output.json
index 2a57c4fa5d..097fe994cf 100644
--- a/test/parser/samples/comment/output.json
+++ b/test/parser/samples/comment/output.json
@@ -8,7 +8,8 @@
"start": 0,
"end": 18,
"type": "Comment",
- "data": " a comment "
+ "data": " a comment ",
+ "ignores": []
}
]
}
diff --git a/test/parser/samples/element-with-attribute-empty-string/input.svelte b/test/parser/samples/element-with-attribute-empty-string/input.svelte
new file mode 100644
index 0000000000..685c0995d5
--- /dev/null
+++ b/test/parser/samples/element-with-attribute-empty-string/input.svelte
@@ -0,0 +1,2 @@
+
+
diff --git a/test/parser/samples/element-with-attribute-empty-string/output.json b/test/parser/samples/element-with-attribute-empty-string/output.json
new file mode 100644
index 0000000000..8e8768eb62
--- /dev/null
+++ b/test/parser/samples/element-with-attribute-empty-string/output.json
@@ -0,0 +1,64 @@
+{
+ "html": {
+ "start": 0,
+ "end": 43,
+ "type": "Fragment",
+ "children": [
+ {
+ "start": 0,
+ "end": 21,
+ "type": "Element",
+ "name": "span",
+ "attributes": [
+ {
+ "start": 6,
+ "end": 13,
+ "type": "Attribute",
+ "name": "attr",
+ "value": [
+ {
+ "start": 12,
+ "end": 12,
+ "type": "Text",
+ "raw": "",
+ "data": ""
+ }
+ ]
+ }
+ ],
+ "children": []
+ },
+ {
+ "start": 21,
+ "end": 22,
+ "type": "Text",
+ "raw": "\n",
+ "data": "\n"
+ },
+ {
+ "start": 22,
+ "end": 43,
+ "type": "Element",
+ "name": "span",
+ "attributes": [
+ {
+ "start": 28,
+ "end": 35,
+ "type": "Attribute",
+ "name": "attr",
+ "value": [
+ {
+ "start": 34,
+ "end": 34,
+ "type": "Text",
+ "raw": "",
+ "data": ""
+ }
+ ]
+ }
+ ],
+ "children": []
+ }
+ ]
+ }
+}
diff --git a/test/parser/samples/element-with-attribute/input.svelte b/test/parser/samples/element-with-attribute/input.svelte
new file mode 100644
index 0000000000..f564fd0541
--- /dev/null
+++ b/test/parser/samples/element-with-attribute/input.svelte
@@ -0,0 +1,2 @@
+
+
diff --git a/test/parser/samples/element-with-attribute/output.json b/test/parser/samples/element-with-attribute/output.json
new file mode 100644
index 0000000000..a80344101e
--- /dev/null
+++ b/test/parser/samples/element-with-attribute/output.json
@@ -0,0 +1,64 @@
+{
+ "html": {
+ "start": 0,
+ "end": 49,
+ "type": "Fragment",
+ "children": [
+ {
+ "start": 0,
+ "end": 24,
+ "type": "Element",
+ "name": "span",
+ "attributes": [
+ {
+ "start": 6,
+ "end": 16,
+ "type": "Attribute",
+ "name": "attr",
+ "value": [
+ {
+ "start": 12,
+ "end": 15,
+ "type": "Text",
+ "raw": "foo",
+ "data": "foo"
+ }
+ ]
+ }
+ ],
+ "children": []
+ },
+ {
+ "start": 24,
+ "end": 25,
+ "type": "Text",
+ "raw": "\n",
+ "data": "\n"
+ },
+ {
+ "start": 25,
+ "end": 49,
+ "type": "Element",
+ "name": "span",
+ "attributes": [
+ {
+ "start": 31,
+ "end": 41,
+ "type": "Attribute",
+ "name": "attr",
+ "value": [
+ {
+ "start": 37,
+ "end": 40,
+ "type": "Text",
+ "raw": "bar",
+ "data": "bar"
+ }
+ ]
+ }
+ ],
+ "children": []
+ }
+ ]
+ }
+}
diff --git a/test/parser/samples/error-comment-unclosed/error.json b/test/parser/samples/error-comment-unclosed/error.json
index 8e355fb821..95fa28c35a 100644
--- a/test/parser/samples/error-comment-unclosed/error.json
+++ b/test/parser/samples/error-comment-unclosed/error.json
@@ -1,5 +1,5 @@
{
- "code": "unexpected-eof",
+ "code": "unclosed-comment",
"message": "comment was left open, expected -->",
"start": {
"line": 1,
diff --git a/test/parser/samples/error-empty-attribute-shorthand/error.json b/test/parser/samples/error-empty-attribute-shorthand/error.json
new file mode 100644
index 0000000000..f465b3468a
--- /dev/null
+++ b/test/parser/samples/error-empty-attribute-shorthand/error.json
@@ -0,0 +1,10 @@
+{
+ "code": "empty-attribute-shorthand",
+ "message": "Attribute shorthand cannot be empty",
+ "start": {
+ "line": 1,
+ "column": 6,
+ "character": 6
+ },
+ "pos": 6
+}
\ No newline at end of file
diff --git a/test/parser/samples/error-empty-attribute-shorthand/input.svelte b/test/parser/samples/error-empty-attribute-shorthand/input.svelte
new file mode 100644
index 0000000000..2e137c8c6d
--- /dev/null
+++ b/test/parser/samples/error-empty-attribute-shorthand/input.svelte
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/parser/samples/error-empty-classname-binding/error.json b/test/parser/samples/error-empty-classname-binding/error.json
index edc09ff8e1..6ece5ff373 100644
--- a/test/parser/samples/error-empty-classname-binding/error.json
+++ b/test/parser/samples/error-empty-classname-binding/error.json
@@ -1,6 +1,6 @@
{
- "code": "invalid-class-directive",
- "message": "Class binding name cannot be empty",
+ "code": "empty-directive-name",
+ "message": "Class name cannot be empty",
"start": {
"line": 1,
"column": 10,
diff --git a/test/parser/samples/error-empty-directive-name/error.json b/test/parser/samples/error-empty-directive-name/error.json
new file mode 100644
index 0000000000..4fed0d8606
--- /dev/null
+++ b/test/parser/samples/error-empty-directive-name/error.json
@@ -0,0 +1,10 @@
+{
+ "code": "empty-directive-name",
+ "message": "Action name cannot be empty",
+ "start": {
+ "line": 1,
+ "column": 8,
+ "character": 8
+ },
+ "pos": 8
+}
diff --git a/test/parser/samples/error-empty-directive-name/input.svelte b/test/parser/samples/error-empty-directive-name/input.svelte
new file mode 100644
index 0000000000..b07875f398
--- /dev/null
+++ b/test/parser/samples/error-empty-directive-name/input.svelte
@@ -0,0 +1 @@
+Hello
diff --git a/test/parser/samples/error-script-unclosed-eof/error.json b/test/parser/samples/error-script-unclosed-eof/error.json
new file mode 100644
index 0000000000..277acd4196
--- /dev/null
+++ b/test/parser/samples/error-script-unclosed-eof/error.json
@@ -0,0 +1,10 @@
+{
+ "code": "unclosed-script",
+ "message": "
+
+Hello {name}!
\ No newline at end of file
diff --git a/test/parser/samples/whitespace-after-script-tag/output.json b/test/parser/samples/whitespace-after-script-tag/output.json
new file mode 100644
index 0000000000..903c392685
--- /dev/null
+++ b/test/parser/samples/whitespace-after-script-tag/output.json
@@ -0,0 +1,150 @@
+{
+ "html": {
+ "start": 51,
+ "end": 73,
+ "type": "Fragment",
+ "children": [
+ {
+ "start": 49,
+ "end": 51,
+ "type": "Text",
+ "raw": "\n\n",
+ "data": "\n\n"
+ },
+ {
+ "start": 51,
+ "end": 73,
+ "type": "Element",
+ "name": "h1",
+ "attributes": [],
+ "children": [
+ {
+ "start": 55,
+ "end": 61,
+ "type": "Text",
+ "raw": "Hello ",
+ "data": "Hello "
+ },
+ {
+ "start": 61,
+ "end": 67,
+ "type": "MustacheTag",
+ "expression": {
+ "type": "Identifier",
+ "start": 62,
+ "end": 66,
+ "loc": {
+ "start": {
+ "line": 10,
+ "column": 11
+ },
+ "end": {
+ "line": 10,
+ "column": 15
+ }
+ },
+ "name": "name"
+ }
+ },
+ {
+ "start": 67,
+ "end": 68,
+ "type": "Text",
+ "raw": "!",
+ "data": "!"
+ }
+ ]
+ }
+ ]
+ },
+ "instance": {
+ "type": "Script",
+ "start": 0,
+ "end": 49,
+ "context": "default",
+ "content": {
+ "type": "Program",
+ "start": 8,
+ "end": 30,
+ "loc": {
+ "start": {
+ "line": 1,
+ "column": 0
+ },
+ "end": {
+ "line": 3,
+ "column": 0
+ }
+ },
+ "body": [
+ {
+ "type": "VariableDeclaration",
+ "start": 10,
+ "end": 29,
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 1
+ },
+ "end": {
+ "line": 2,
+ "column": 20
+ }
+ },
+ "declarations": [
+ {
+ "type": "VariableDeclarator",
+ "start": 14,
+ "end": 28,
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 5
+ },
+ "end": {
+ "line": 2,
+ "column": 19
+ }
+ },
+ "id": {
+ "type": "Identifier",
+ "start": 14,
+ "end": 18,
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 5
+ },
+ "end": {
+ "line": 2,
+ "column": 9
+ }
+ },
+ "name": "name"
+ },
+ "init": {
+ "type": "Literal",
+ "start": 21,
+ "end": 28,
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 12
+ },
+ "end": {
+ "line": 2,
+ "column": 19
+ }
+ },
+ "value": "world",
+ "raw": "'world'"
+ }
+ }
+ ],
+ "kind": "let"
+ }
+ ],
+ "sourceType": "module"
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/parser/samples/whitespace-after-style-tag/input.svelte b/test/parser/samples/whitespace-after-style-tag/input.svelte
new file mode 100644
index 0000000000..ae4277b697
--- /dev/null
+++ b/test/parser/samples/whitespace-after-style-tag/input.svelte
@@ -0,0 +1,12 @@
+foo
+
+
\ No newline at end of file
diff --git a/test/parser/samples/whitespace-after-style-tag/output.json b/test/parser/samples/whitespace-after-style-tag/output.json
new file mode 100644
index 0000000000..5eee81f034
--- /dev/null
+++ b/test/parser/samples/whitespace-after-style-tag/output.json
@@ -0,0 +1,97 @@
+{
+ "html": {
+ "start": 0,
+ "end": 14,
+ "type": "Fragment",
+ "children": [
+ {
+ "start": 0,
+ "end": 14,
+ "type": "Element",
+ "name": "div",
+ "attributes": [],
+ "children": [
+ {
+ "start": 5,
+ "end": 8,
+ "type": "Text",
+ "raw": "foo",
+ "data": "foo"
+ }
+ ]
+ },
+ {
+ "start": 14,
+ "end": 16,
+ "type": "Text",
+ "raw": "\n\n",
+ "data": "\n\n"
+ }
+ ]
+ },
+ "css": {
+ "type": "Style",
+ "start": 16,
+ "end": 66,
+ "attributes": [],
+ "children": [
+ {
+ "type": "Rule",
+ "prelude": {
+ "type": "SelectorList",
+ "children": [
+ {
+ "type": "Selector",
+ "children": [
+ {
+ "type": "TypeSelector",
+ "name": "div",
+ "start": 25,
+ "end": 28
+ }
+ ],
+ "start": 25,
+ "end": 28
+ }
+ ],
+ "start": 25,
+ "end": 28
+ },
+ "block": {
+ "type": "Block",
+ "children": [
+ {
+ "type": "Declaration",
+ "important": false,
+ "property": "color",
+ "value": {
+ "type": "Value",
+ "children": [
+ {
+ "type": "Identifier",
+ "name": "red",
+ "start": 40,
+ "end": 43
+ }
+ ],
+ "start": 40,
+ "end": 43
+ },
+ "start": 33,
+ "end": 43
+ }
+ ],
+ "start": 29,
+ "end": 47
+ },
+ "start": 25,
+ "end": 47
+ }
+ ],
+ "content": {
+ "start": 23,
+ "end": 48,
+ "styles": "\n\tdiv {\n\t\tcolor: red;\n\t}\n"
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/preprocess/samples/empty-sourcemap/_config.js b/test/preprocess/samples/empty-sourcemap/_config.js
new file mode 100644
index 0000000000..941661ce01
--- /dev/null
+++ b/test/preprocess/samples/empty-sourcemap/_config.js
@@ -0,0 +1,7 @@
+export default {
+ preprocess: {
+ style: ({ content }) => {
+ return { code: content, map: { mappings: '' } };
+ }
+ }
+};
diff --git a/test/preprocess/samples/empty-sourcemap/input.svelte b/test/preprocess/samples/empty-sourcemap/input.svelte
new file mode 100644
index 0000000000..d2380c00cb
--- /dev/null
+++ b/test/preprocess/samples/empty-sourcemap/input.svelte
@@ -0,0 +1,7 @@
+bar
+
+
\ No newline at end of file
diff --git a/test/preprocess/samples/empty-sourcemap/output.svelte b/test/preprocess/samples/empty-sourcemap/output.svelte
new file mode 100644
index 0000000000..d2380c00cb
--- /dev/null
+++ b/test/preprocess/samples/empty-sourcemap/output.svelte
@@ -0,0 +1,7 @@
+bar
+
+
\ No newline at end of file
diff --git a/test/runtime-puppeteer/assert.js b/test/runtime-puppeteer/assert.js
new file mode 100644
index 0000000000..4ee8d9dda0
--- /dev/null
+++ b/test/runtime-puppeteer/assert.js
@@ -0,0 +1,54 @@
+export function deepEqual(a, b, message) {
+ if (!is_equal(a, b)) {
+ throw new Error(message || `Expected ${JSON.stringify(a)} to equal ${JSON.stringify(b)}`);
+ }
+}
+
+function is_equal(a, b) {
+ if (a && typeof a === 'object') {
+ const is_array = Array.isArray(a);
+ if (Array.isArray(b) !== is_array) return false;
+
+ if (is_array) {
+ if (a.length !== b.length) return false;
+ return a.every((value, i) => is_equal(value, b[i]));
+ }
+
+ const a_keys = Object.keys(a).sort();
+ const b_keys = Object.keys(b).sort();
+ if (a_keys.join(',') !== b_keys.join(',')) return false;
+
+ return a_keys.every(key => is_equal(a[key], b[key]));
+ }
+
+ return a === b;
+}
+
+export function equal(a, b, message) {
+ if (a != b) throw new Error(message || `Expected ${a} to equal ${b}`);
+}
+
+export function ok(condition, message) {
+ if (!condition) throw new Error(message || `Expected ${condition} to be truthy`);
+}
+
+export function htmlEqual(actual, expected, message) {
+ return deepEqual(
+ normalizeHtml(window, actual),
+ normalizeHtml(window, expected),
+ message
+ );
+}
+
+function normalizeHtml(window, html) {
+ try {
+ const node = window.document.createElement('div');
+ node.innerHTML = html
+ .replace(//g, '')
+ .replace(/>[\s\r\n]+<')
+ .trim();
+ return node.innerHTML.replace(/<\/?noscript\/?>/g, '');
+ } catch (err) {
+ throw new Error(`Failed to normalize HTML:\n${html}`);
+ }
+}
diff --git a/test/runtime-puppeteer/index.ts b/test/runtime-puppeteer/index.ts
new file mode 100644
index 0000000000..b700d47945
--- /dev/null
+++ b/test/runtime-puppeteer/index.ts
@@ -0,0 +1,250 @@
+import * as path from 'path';
+import * as fs from 'fs';
+import * as http from 'http';
+import { rollup } from 'rollup';
+import virtual from '@rollup/plugin-virtual';
+import puppeteer from 'puppeteer';
+
+import {
+ loadConfig,
+ loadSvelte,
+ mkdirp,
+ prettyPrintPuppeteerAssertionError
+} from '../helpers';
+import { deepEqual } from 'assert';
+
+const page = `
+
+
+
+
+`;
+
+let svelte;
+let server;
+let code;
+let browser;
+
+const internal = path.resolve('internal/index.mjs');
+const index = path.resolve('index.mjs');
+
+function create_server() {
+ return new Promise((fulfil, reject) => {
+ const server = http.createServer((req, res) => {
+ if (req.url === '/') {
+ res.end(page);
+ }
+
+ if (req.url === '/bundle.js') {
+ res.end(code);
+ }
+ });
+
+ server.on('error', reject);
+
+ server.listen('6789', () => {
+ fulfil(server);
+ });
+ });
+}
+
+const assert = fs.readFileSync(`${__dirname}/assert.js`, 'utf-8');
+
+describe('runtime (puppeteer)', () => {
+ before(async () => {
+ svelte = loadSvelte(false);
+ console.log('[runtime-puppeteer] Loaded Svelte');
+ server = await create_server();
+ console.log('[runtime-puppeteer] Started server');
+ browser = await puppeteer.launch();
+ console.log('[runtime-puppeteer] Launched puppeteer browser');
+ });
+
+ after(async () => {
+ if (server) server.close();
+ if (browser) await browser.close();
+ });
+
+ const failed = new Set();
+
+ function runTest(dir, hydrate) {
+ if (dir[0] === '.') return;
+
+ const config = loadConfig(`${__dirname}/samples/${dir}/_config.js`);
+ const solo = config.solo || /\.solo/.test(dir);
+ const skip = config.skip || /\.skip/.test(dir);
+
+ if (hydrate && config.skip_if_hydrate) return;
+
+ if (solo && process.env.CI) {
+ throw new Error('Forgot to remove `solo: true` from test');
+ }
+
+ (skip ? it.skip : solo ? it.only : it)(`${dir} ${hydrate ? '(with hydration)' : ''}`, async () => {
+ if (failed.has(dir)) {
+ // this makes debugging easier, by only printing compiled output once
+ throw new Error('skipping test, already failed');
+ }
+
+ const warnings = [];
+
+ const bundle = await rollup({
+ input: 'main',
+ plugins: [
+ {
+ name: 'testing-runtime-puppeteer',
+ resolveId(importee) {
+ if (importee === 'svelte/internal' || importee === './internal') {
+ return internal;
+ }
+
+ if (importee === 'svelte') {
+ return index;
+ }
+
+ if (importee === 'main') {
+ return 'main';
+ }
+ },
+ load(id) {
+ if (id === 'main') {
+ return `
+ import SvelteComponent from ${JSON.stringify(path.join(__dirname, 'samples', dir, 'main.svelte'))};
+ import config from ${JSON.stringify(path.join(__dirname, 'samples', dir, '_config.js'))};
+ import * as assert from 'assert';
+
+ export default async function (target) {
+ let unhandled_rejection = false;
+ function unhandled_rejection_handler(event) {
+ unhandled_rejection = event.reason;
+ }
+ window.addEventListener('unhandledrejection', unhandled_rejection_handler);
+
+ try {
+ if (config.before_test) config.before_test();
+
+ const options = Object.assign({}, {
+ target,
+ hydrate: ${String(!!hydrate)},
+ props: config.props,
+ intro: config.intro
+ }, config.options || {});
+
+ const component = new SvelteComponent(options);
+
+ if (config.html) {
+ assert.htmlEqual(target.innerHTML, config.html);
+ }
+
+ if (config.test) {
+ await config.test({
+ assert,
+ component,
+ target,
+ window,
+ });
+
+ component.$destroy();
+
+ if (unhandled_rejection) {
+ throw unhandled_rejection;
+ }
+ } else {
+ component.$destroy();
+ assert.htmlEqual(target.innerHTML, '');
+
+ if (unhandled_rejection) {
+ throw unhandled_rejection;
+ }
+ }
+
+ if (config.after_test) config.after_test();
+ } catch (error) {
+ if (config.error) {
+ assert.equal(err.message, config.error);
+ } else {
+ throw error;
+ }
+ } finally {
+ window.removeEventListener('unhandledrejection', unhandled_rejection_handler);
+ }
+ }
+ `;
+ }
+ return null;
+ },
+ transform(code, id) {
+ if (id.endsWith('.svelte')) {
+ const compiled = svelte.compile(code.replace(/\r/g, ''), {
+ ...config.compileOptions,
+ hydratable: hydrate,
+ immutable: config.immutable,
+ accessors: 'accessors' in config ? config.accessors : true
+ });
+
+ const out_dir = `${__dirname}/samples/${dir}/_output/${hydrate ? 'hydratable' : 'normal'}`;
+ const out = `${out_dir}/${path.basename(id).replace(/\.svelte$/, '.js')}`;
+
+ if (fs.existsSync(out)) {
+ fs.unlinkSync(out);
+ }
+
+ mkdirp(out_dir);
+ fs.writeFileSync(out, compiled.js.code, 'utf8');
+
+ compiled.warnings.forEach(w => warnings.push(w));
+
+ return compiled.js;
+ }
+ }
+ },
+ virtual({ assert })
+ ]
+ });
+
+ const result = await bundle.generate({ format: 'iife', name: 'test' });
+ code = result.output[0].code;
+
+ const page = await browser.newPage();
+
+ page.on('console', (type) => {
+ console[type._type](type._text);
+ });
+
+ page.on('error', error => {
+ console.log('>>> an error happened');
+ console.error(error);
+ });
+
+ try {
+ await page.goto('http://localhost:6789');
+
+ const result = await page.evaluate(() => test(document.querySelector('main')));
+ if (result) console.log(result);
+ } catch (err) {
+ failed.add(dir);
+ prettyPrintPuppeteerAssertionError(err.message);
+ throw err;
+ } finally {
+ if (config.warnings) {
+ deepEqual(warnings.map(w => ({
+ code: w.code,
+ message: w.message,
+ pos: w.pos,
+ start: w.start,
+ end: w.end
+ })), config.warnings);
+ } else if (warnings.length) {
+ failed.add(dir);
+ /* eslint-disable no-unsafe-finally */
+ throw new Error('Received unexpected warnings');
+ }
+ }
+ });
+ }
+
+ fs.readdirSync(`${__dirname}/samples`).forEach(dir => {
+ runTest(dir, false);
+ runTest(dir, true);
+ });
+});
diff --git a/test/runtime-puppeteer/samples/component-css-custom-properties-dynamic/Slider.svelte b/test/runtime-puppeteer/samples/component-css-custom-properties-dynamic/Slider.svelte
new file mode 100644
index 0000000000..4863966f85
--- /dev/null
+++ b/test/runtime-puppeteer/samples/component-css-custom-properties-dynamic/Slider.svelte
@@ -0,0 +1,17 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/test/runtime-puppeteer/samples/component-css-custom-properties-dynamic/_config.js b/test/runtime-puppeteer/samples/component-css-custom-properties-dynamic/_config.js
new file mode 100644
index 0000000000..96965c223b
--- /dev/null
+++ b/test/runtime-puppeteer/samples/component-css-custom-properties-dynamic/_config.js
@@ -0,0 +1,41 @@
+export default {
+ props: {
+ railColor1: 'black',
+ trackColor1: 'red',
+ railColor2: 'green',
+ trackColor2: 'blue'
+ },
+ html: `
+
+
+ `,
+ test({ component, assert, target }) {
+ component.railColor1 = 'yellow';
+ component.trackColor2 = 'orange';
+
+ assert.htmlEqual(target.innerHTML, `
+
+
+ `);
+ }
+};
diff --git a/test/runtime-puppeteer/samples/component-css-custom-properties-dynamic/main.svelte b/test/runtime-puppeteer/samples/component-css-custom-properties-dynamic/main.svelte
new file mode 100644
index 0000000000..94e68e38a2
--- /dev/null
+++ b/test/runtime-puppeteer/samples/component-css-custom-properties-dynamic/main.svelte
@@ -0,0 +1,23 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/test/runtime-puppeteer/samples/component-css-custom-properties/Slider.svelte b/test/runtime-puppeteer/samples/component-css-custom-properties/Slider.svelte
new file mode 100644
index 0000000000..4863966f85
--- /dev/null
+++ b/test/runtime-puppeteer/samples/component-css-custom-properties/Slider.svelte
@@ -0,0 +1,17 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/test/runtime-puppeteer/samples/component-css-custom-properties/_config.js b/test/runtime-puppeteer/samples/component-css-custom-properties/_config.js
new file mode 100644
index 0000000000..9c3b7cbdea
--- /dev/null
+++ b/test/runtime-puppeteer/samples/component-css-custom-properties/_config.js
@@ -0,0 +1,27 @@
+export default {
+ html: `
+
+
+ `,
+ test({ target, window, assert }) {
+ const railColor1 = target.querySelector('#slider-1 p');
+ const trackColor1 = target.querySelector('#slider-1 span');
+ const railColor2 = target.querySelector('#slider-2 p');
+ const trackColor2 = target.querySelector('#slider-2 span');
+
+ assert.htmlEqual(window.getComputedStyle(railColor1).color, 'rgb(0, 0, 0)');
+ assert.htmlEqual(window.getComputedStyle(trackColor1).color, 'rgb(255, 0, 0)');
+ assert.htmlEqual(window.getComputedStyle(railColor2).color, 'rgb(0, 255, 0)');
+ assert.htmlEqual(window.getComputedStyle(trackColor2).color, 'rgb(0, 0, 255)');
+ }
+};
diff --git a/test/runtime-puppeteer/samples/component-css-custom-properties/main.svelte b/test/runtime-puppeteer/samples/component-css-custom-properties/main.svelte
new file mode 100644
index 0000000000..0d92b7ae87
--- /dev/null
+++ b/test/runtime-puppeteer/samples/component-css-custom-properties/main.svelte
@@ -0,0 +1,15 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/test/runtime/index.ts b/test/runtime/index.ts
index 153ac9dbb8..ff6d1039d3 100644
--- a/test/runtime/index.ts
+++ b/test/runtime/index.ts
@@ -49,19 +49,21 @@ describe('runtime', () => {
const failed = new Set();
- function runTest(dir, hydrate) {
+ function runTest(dir, hydrate, from_ssr_html) {
if (dir[0] === '.') return;
const config = loadConfig(`${__dirname}/samples/${dir}/_config.js`);
const solo = config.solo || /\.solo/.test(dir);
if (hydrate && config.skip_if_hydrate) return;
+ if (hydrate && from_ssr_html && config.skip_if_hydrate_from_ssr) return;
if (solo && process.env.CI) {
throw new Error('Forgot to remove `solo: true` from test');
}
- (config.skip ? it.skip : solo ? it.only : it)(`${dir} ${hydrate ? '(with hydration)' : ''}`, () => {
+ const testName = `${dir} ${hydrate ? `(with hydration${from_ssr_html ? ' from ssr rendered html' : ''})` : ''}`;
+ (config.skip ? it.skip : solo ? it.only : it)(testName, () => {
if (failed.has(dir)) {
// this makes debugging easier, by only printing compiled output once
throw new Error('skipping test, already failed');
@@ -146,13 +148,25 @@ describe('runtime', () => {
throw err;
}
- if (config.before_test) config.before_test();
-
// Put things we need on window for testing
window.SvelteComponent = SvelteComponent;
const target = window.document.querySelector('main');
+ if (hydrate && from_ssr_html) {
+ // ssr into target
+ compileOptions.generate = 'ssr';
+ cleanRequireCache();
+ const SsrSvelteComponent = require(`./samples/${dir}/main.svelte`).default;
+ const { html } = SsrSvelteComponent.render(config.props);
+ target.innerHTML = html;
+ delete compileOptions.generate;
+ } else {
+ target.innerHTML = '';
+ }
+
+ if (config.before_test) config.before_test();
+
const warnings = [];
const warn = console.warn;
console.warn = warning => {
@@ -245,7 +259,8 @@ describe('runtime', () => {
fs.readdirSync(`${__dirname}/samples`).forEach(dir => {
runTest(dir, false);
- runTest(dir, true);
+ runTest(dir, true, false);
+ runTest(dir, true, true);
});
async function create_component(src = '
') {
diff --git a/test/runtime/samples/action-body/_config.js b/test/runtime/samples/action-body/_config.js
new file mode 100644
index 0000000000..c882499e0e
--- /dev/null
+++ b/test/runtime/samples/action-body/_config.js
@@ -0,0 +1,18 @@
+export default {
+ html: '
',
+
+ async test({ assert, target, window }) {
+ const enter = new window.MouseEvent('mouseenter');
+ const leave = new window.MouseEvent('mouseleave');
+
+ await window.document.body.dispatchEvent(enter);
+ assert.htmlEqual(target.innerHTML, `
+
+ `);
+
+ await window.document.body.dispatchEvent(leave);
+ assert.htmlEqual(target.innerHTML, '
');
+ }
+};
diff --git a/test/runtime/samples/action-body/main.svelte b/test/runtime/samples/action-body/main.svelte
new file mode 100644
index 0000000000..dd57116577
--- /dev/null
+++ b/test/runtime/samples/action-body/main.svelte
@@ -0,0 +1,32 @@
+
+
+
+
\ No newline at end of file
diff --git a/test/runtime/samples/apply-directives-in-order/_config.js b/test/runtime/samples/apply-directives-in-order/_config.js
index 7c8f87ef85..0c85c97f8b 100644
--- a/test/runtime/samples/apply-directives-in-order/_config.js
+++ b/test/runtime/samples/apply-directives-in-order/_config.js
@@ -9,7 +9,7 @@ export default {
`,
ssrHtml: `
-
+
`,
diff --git a/test/runtime/samples/attribute-boolean-indeterminate/_config.js b/test/runtime/samples/attribute-boolean-indeterminate/_config.js
index d16cb5f96b..d6e97ffc0e 100644
--- a/test/runtime/samples/attribute-boolean-indeterminate/_config.js
+++ b/test/runtime/samples/attribute-boolean-indeterminate/_config.js
@@ -7,9 +7,11 @@ export default {
indeterminate: true
},
- html: `
-
- `,
+ html: " ",
+
+ // somehow ssr will render indeterminate=""
+ // the hydrated html will still contain that attribute
+ ssrHtml: " ",
test({ assert, component, target }) {
const input = target.querySelector('input');
diff --git a/test/runtime/samples/attribute-casing-foreign-namespace-compiler-option/_config.js b/test/runtime/samples/attribute-casing-foreign-namespace-compiler-option/_config.js
index 1225c64fc2..9f8ee61c7a 100644
--- a/test/runtime/samples/attribute-casing-foreign-namespace-compiler-option/_config.js
+++ b/test/runtime/samples/attribute-casing-foreign-namespace-compiler-option/_config.js
@@ -1,14 +1,17 @@
-// Test support for the `foreign` namespace preserving attribute case.
+// Test support for the `foreign` namespace preserving attribute case,
+// including ensuring that SVG elements don't interfere.
export default {
html: `
-
+
+
`,
options: {
hydrate: false // Hydration test will fail as case sensitivity is only handled for svg elements.
},
+ skip_if_hydrate_from_ssr: true,
compileOptions: {
namespace: 'foreign'
},
@@ -16,5 +19,6 @@ export default {
const attr = sel => target.querySelector(sel).attributes[0].name;
assert.equal(attr('page'), 'horizontalAlignment');
assert.equal(attr('button'), 'textWrap');
+ assert.equal(attr('text'), 'wordWrap');
}
};
diff --git a/test/runtime/samples/attribute-casing-foreign-namespace-compiler-option/main.svelte b/test/runtime/samples/attribute-casing-foreign-namespace-compiler-option/main.svelte
index 6300ab3b63..52b3e646e1 100644
--- a/test/runtime/samples/attribute-casing-foreign-namespace-compiler-option/main.svelte
+++ b/test/runtime/samples/attribute-casing-foreign-namespace-compiler-option/main.svelte
@@ -1,3 +1,4 @@
-
-
\ No newline at end of file
+
+
+
diff --git a/test/runtime/samples/attribute-casing-foreign-namespace/_config.js b/test/runtime/samples/attribute-casing-foreign-namespace/_config.js
index d7eca6aba9..f74f622524 100644
--- a/test/runtime/samples/attribute-casing-foreign-namespace/_config.js
+++ b/test/runtime/samples/attribute-casing-foreign-namespace/_config.js
@@ -9,6 +9,7 @@ export default {
options: {
hydrate: false // Hydration test will fail as case sensitivity is only handled for svg elements.
},
+ skip_if_hydrate_from_ssr: true,
test({ assert, target }) {
const attr = sel => target.querySelector(sel).attributes[0].name;
diff --git a/test/runtime/samples/attribute-dynamic-type/_config.js b/test/runtime/samples/attribute-dynamic-type/_config.js
index 19aa33d65e..fa00cb6bc3 100644
--- a/test/runtime/samples/attribute-dynamic-type/_config.js
+++ b/test/runtime/samples/attribute-dynamic-type/_config.js
@@ -1,12 +1,11 @@
export default {
- skip_if_ssr: true,
-
props: {
inputType: 'text',
inputValue: 42
},
html: ' ',
+ ssrHtml: ' ',
test({ assert, component, target }) {
const input = target.querySelector('input');
diff --git a/test/runtime/samples/attribute-prefer-expression/_config.js b/test/runtime/samples/attribute-prefer-expression/_config.js
index 2388ff35df..22bed8a6bc 100644
--- a/test/runtime/samples/attribute-prefer-expression/_config.js
+++ b/test/runtime/samples/attribute-prefer-expression/_config.js
@@ -1,5 +1,4 @@
export default {
- skip_if_ssr: true,
props: {
foo: false
diff --git a/test/runtime/samples/autofocus/_config.js b/test/runtime/samples/autofocus/_config.js
index faf9cf9f48..b0131f8bfe 100644
--- a/test/runtime/samples/autofocus/_config.js
+++ b/test/runtime/samples/autofocus/_config.js
@@ -2,7 +2,23 @@ export default {
html: '',
test({ assert, component, target, window }) {
- component.visible = true;
- assert.equal(target.querySelector('input'), window.document.activeElement);
+ component.active = 'default';
+ assert.equal(target.querySelector('input[title="default"]'), window.document.activeElement);
+
+ component.active = 'dynamic-false';
+ assert.notEqual(target.querySelector('input[title="dynamic-false"]'), window.document.activeElement);
+
+ // when dynamically set autofocus to true, don't autofocus
+ component.autofocusFalse = true;
+ assert.notEqual(target.querySelector('input[title="dynamic-false"]'), window.document.activeElement);
+
+ component.active = 'dynamic-true';
+ assert.equal(target.querySelector('input[title="dynamic-true"]'), window.document.activeElement);
+
+ component.active = 'spread';
+ assert.equal(target.querySelector('input[title="spread"]'), window.document.activeElement);
+
+ component.active = 'spread-override';
+ assert.notEqual(target.querySelector('input[title="spread-override"]'), window.document.activeElement);
}
};
diff --git a/test/runtime/samples/autofocus/main.svelte b/test/runtime/samples/autofocus/main.svelte
index 561596e9cf..ecdb1beb5e 100644
--- a/test/runtime/samples/autofocus/main.svelte
+++ b/test/runtime/samples/autofocus/main.svelte
@@ -1,8 +1,18 @@
-{#if visible}
-
+{#if active === 'default'}
+
+{:else if active === 'dynamic-false'}
+
+{:else if active === 'dynamic-true'}
+
+{:else if active === 'spread'}
+
+{:else if active === 'spread-override'}
+
{/if}
\ No newline at end of file
diff --git a/test/runtime/samples/await-catch-no-expression/_config.js b/test/runtime/samples/await-catch-no-expression/_config.js
new file mode 100644
index 0000000000..5274e60e2d
--- /dev/null
+++ b/test/runtime/samples/await-catch-no-expression/_config.js
@@ -0,0 +1,47 @@
+let fulfil;
+
+let thePromise = new Promise(f => {
+ fulfil = f;
+});
+
+export default {
+ props: {
+ thePromise
+ },
+
+ html: `
+
+ the promise is pending
+ `,
+
+ async test({ assert, component, target }) {
+ fulfil(42);
+
+ await thePromise;
+
+ assert.htmlEqual(target.innerHTML, ' ');
+
+ let reject;
+
+ thePromise = new Promise((f, r) => {
+ reject = r;
+ });
+
+ component.thePromise = thePromise;
+
+ assert.htmlEqual(target.innerHTML, `
+
+ the promise is pending
+ `);
+
+ reject(new Error());
+
+ await thePromise.catch(() => {});
+
+ assert.htmlEqual(target.innerHTML, `
+ oh no! Something broke!
+
+ oh no! Something broke!
+ `);
+ }
+};
diff --git a/test/runtime/samples/await-catch-no-expression/main.svelte b/test/runtime/samples/await-catch-no-expression/main.svelte
new file mode 100644
index 0000000000..0da0d12092
--- /dev/null
+++ b/test/runtime/samples/await-catch-no-expression/main.svelte
@@ -0,0 +1,15 @@
+
+
+{#await thePromise catch}
+ oh no! Something broke!
+{/await}
+
+
+
+{#await thePromise}
+ the promise is pending
+{:catch}
+ oh no! Something broke!
+{/await}
diff --git a/test/runtime/samples/await-then-no-expression/_config.js b/test/runtime/samples/await-then-no-expression/_config.js
new file mode 100644
index 0000000000..f684da52ed
--- /dev/null
+++ b/test/runtime/samples/await-then-no-expression/_config.js
@@ -0,0 +1,55 @@
+let fulfil;
+
+let thePromise = new Promise(f => {
+ fulfil = f;
+});
+
+export default {
+ props: {
+ thePromise
+ },
+
+ html: `
+
+
+ the promise is pending
+ `,
+
+ async test({ assert, component, target }) {
+ fulfil();
+
+ await thePromise;
+
+ assert.htmlEqual(target.innerHTML, `
+ the promise is resolved
+
+ the promise is resolved
+
+ the promise is resolved
+ `);
+
+ let reject;
+
+ thePromise = new Promise((f, r) => {
+ reject = r;
+ });
+
+ component.thePromise = thePromise;
+
+ assert.htmlEqual(target.innerHTML, `
+
+
+ the promise is pending
+ `);
+
+ reject(new Error('something broke'));
+
+ await thePromise.catch(() => {});
+
+ assert.htmlEqual(target.innerHTML, `
+ oh no! something broke
+
+
+ `);
+ }
+};
diff --git a/test/runtime/samples/await-then-no-expression/main.svelte b/test/runtime/samples/await-then-no-expression/main.svelte
new file mode 100644
index 0000000000..fedc7cd2b7
--- /dev/null
+++ b/test/runtime/samples/await-then-no-expression/main.svelte
@@ -0,0 +1,23 @@
+
+
+{#await thePromise then}
+ the promise is resolved
+{:catch theError}
+ oh no! {theError.message}
+{/await}
+
+
+
+{#await thePromise then}
+ the promise is resolved
+{/await}
+
+
+
+{#await thePromise}
+ the promise is pending
+{:then}
+ the promise is resolved
+{/await}
\ No newline at end of file
diff --git a/test/runtime/samples/await-with-update-catch-scope/_config.js b/test/runtime/samples/await-with-update-catch-scope/_config.js
new file mode 100644
index 0000000000..4c60ef2150
--- /dev/null
+++ b/test/runtime/samples/await-with-update-catch-scope/_config.js
@@ -0,0 +1,51 @@
+export default {
+ props: {
+ thePromise: new Promise((_) => {})
+ },
+
+ html: `
+ error: undefined
+ `,
+
+ async test({ assert, component, target }) {
+ await (component.thePromise = Promise.resolve('abc'));
+
+ assert.htmlEqual(
+ target.innerHTML,
+ `
+
+ error: undefined
+ After Resolve: undefined
+
+ `
+ );
+
+ component.error = 'external error occurred';
+
+ assert.htmlEqual(
+ target.innerHTML,
+ `
+
+ error: ${component.error}
+ After Resolve: ${component.error}
+
+ `
+ );
+
+ try {
+ await (component.thePromise = Promise.reject('failure'));
+ } catch (error) {
+ // ignore
+ }
+
+ assert.htmlEqual(
+ target.innerHTML,
+ `
+
+ error: ${component.error}
+ Rejected: failure
+
+ `
+ );
+ }
+};
diff --git a/test/runtime/samples/await-with-update-catch-scope/main.svelte b/test/runtime/samples/await-with-update-catch-scope/main.svelte
new file mode 100644
index 0000000000..4d4eb53f0b
--- /dev/null
+++ b/test/runtime/samples/await-with-update-catch-scope/main.svelte
@@ -0,0 +1,13 @@
+
+
+
+ error: {error}
+ {#await thePromise then _}
+ After Resolve: {error}
+ {:catch error}
+ Rejected: {error}
+ {/await}
+
diff --git a/test/runtime/samples/binding-circular/_config.js b/test/runtime/samples/binding-circular/_config.js
index 505ed22beb..3e58ab2f98 100644
--- a/test/runtime/samples/binding-circular/_config.js
+++ b/test/runtime/samples/binding-circular/_config.js
@@ -3,11 +3,5 @@ export default {
wheeee
- `,
-
- ssrHtml: `
-
- wheeee
-
`
};
diff --git a/test/runtime/samples/binding-indirect-spread/_config.js b/test/runtime/samples/binding-indirect-spread/_config.js
index 1f24fcdbcb..b0701bdc7c 100644
--- a/test/runtime/samples/binding-indirect-spread/_config.js
+++ b/test/runtime/samples/binding-indirect-spread/_config.js
@@ -1,5 +1,13 @@
export default {
- skip_if_ssr: true,
+ ssrHtml: `
+
+
+
+
+
+
+
+ `,
async test({ assert, component, target, window }) {
const event = new window.MouseEvent('click');
diff --git a/test/runtime/samples/binding-input-checkbox-group-outside-each/_config.js b/test/runtime/samples/binding-input-checkbox-group-outside-each/_config.js
index ab89bc8daa..0948797865 100644
--- a/test/runtime/samples/binding-input-checkbox-group-outside-each/_config.js
+++ b/test/runtime/samples/binding-input-checkbox-group-outside-each/_config.js
@@ -25,6 +25,21 @@ export default {
Beta
`,
+ ssrHtml: `
+
+ Alpha
+
+
+
+ Beta
+
+
+
+ Gamma
+
+
+ Beta
`,
+
async test({ assert, component, target, window }) {
const inputs = target.querySelectorAll('input');
assert.equal(inputs[0].checked, false);
diff --git a/test/runtime/samples/binding-input-checkbox-group/_config.js b/test/runtime/samples/binding-input-checkbox-group/_config.js
index ab89bc8daa..0948797865 100644
--- a/test/runtime/samples/binding-input-checkbox-group/_config.js
+++ b/test/runtime/samples/binding-input-checkbox-group/_config.js
@@ -25,6 +25,21 @@ export default {
Beta
`,
+ ssrHtml: `
+
+ Alpha
+
+
+
+ Beta
+
+
+
+ Gamma
+
+
+ Beta
`,
+
async test({ assert, component, target, window }) {
const inputs = target.querySelectorAll('input');
assert.equal(inputs[0].checked, false);
diff --git a/test/runtime/samples/binding-input-group-each-1/_config.js b/test/runtime/samples/binding-input-group-each-1/_config.js
index 92010296dc..9bdf784f73 100644
--- a/test/runtime/samples/binding-input-group-each-1/_config.js
+++ b/test/runtime/samples/binding-input-group-each-1/_config.js
@@ -64,6 +64,54 @@ export default {
`,
+ ssrHtml: `
+
+
+
+ `,
+
async test({ assert, component, target, window }) {
const inputs = target.querySelectorAll('input');
assert.equal(inputs[0].checked, false);
diff --git a/test/runtime/samples/binding-input-group-each-2/_config.js b/test/runtime/samples/binding-input-group-each-2/_config.js
index 78d692d979..880b183f88 100644
--- a/test/runtime/samples/binding-input-group-each-2/_config.js
+++ b/test/runtime/samples/binding-input-group-each-2/_config.js
@@ -12,6 +12,19 @@ export default {
1, 2, 3
`,
+ ssrHtml: `
+
+ 1
+
+
+ 2
+
+
+ 3
+
+
+ 1, 2, 3
`,
+
async test({ assert, component, target, window }) {
const inputs = target.querySelectorAll('input');
assert.equal(inputs[0].checked, true);
diff --git a/test/runtime/samples/binding-input-group-each-3/_config.js b/test/runtime/samples/binding-input-group-each-3/_config.js
index 92010296dc..f4018295d7 100644
--- a/test/runtime/samples/binding-input-group-each-3/_config.js
+++ b/test/runtime/samples/binding-input-group-each-3/_config.js
@@ -63,7 +63,53 @@ export default {
Gamma
`,
+ ssrHtml: `
+
+
+
+ `,
async test({ assert, component, target, window }) {
const inputs = target.querySelectorAll('input');
assert.equal(inputs[0].checked, false);
diff --git a/test/runtime/samples/binding-input-group-each-4/_config.js b/test/runtime/samples/binding-input-group-each-4/_config.js
index f1168858b0..da5edf18bc 100644
--- a/test/runtime/samples/binding-input-group-each-4/_config.js
+++ b/test/runtime/samples/binding-input-group-each-4/_config.js
@@ -17,7 +17,24 @@ export default {
3
3
`,
-
+ ssrHtml: `
+ 1
+ 2
+ 3
+ 1
+ 1
+ 2
+ 3
+ 2
+ 1
+ 2
+ 3
+
+ 1
+ 2
+ 3
+ 3
+ `,
async test({ assert, component, target, window }) {
const inputs = target.querySelectorAll('input');
assert.equal(inputs[0].checked, true);
diff --git a/test/runtime/samples/binding-input-group-each-5/_config.js b/test/runtime/samples/binding-input-group-each-5/_config.js
index 579225c627..cdfe9308df 100644
--- a/test/runtime/samples/binding-input-group-each-5/_config.js
+++ b/test/runtime/samples/binding-input-group-each-5/_config.js
@@ -17,7 +17,24 @@ export default {
3
1
`,
-
+ ssrHtml: `
+ 1
+ 2
+ 3
+ 1
+ 1
+ 2
+ 3
+ 1, 2, 3
+ 1
+ 2
+ 3
+ 2
+ 1
+ 2
+ 3
+ 1
+ `,
async test({ assert, component, target, window }) {
const inputs = target.querySelectorAll('input');
assert.equal(inputs[0].checked, true);
diff --git a/test/runtime/samples/binding-input-group-each-6/_config.js b/test/runtime/samples/binding-input-group-each-6/_config.js
index 9eb251bf5d..4d280ed7ac 100644
--- a/test/runtime/samples/binding-input-group-each-6/_config.js
+++ b/test/runtime/samples/binding-input-group-each-6/_config.js
@@ -13,7 +13,6 @@ export default {
z
`,
-
async test({ assert, component, target, window }) {
const inputs = target.querySelectorAll('input');
assert.equal(inputs[0].checked, false);
diff --git a/test/runtime/samples/binding-input-radio-group/_config.js b/test/runtime/samples/binding-input-radio-group/_config.js
index e289d48597..9684f60fa6 100644
--- a/test/runtime/samples/binding-input-radio-group/_config.js
+++ b/test/runtime/samples/binding-input-radio-group/_config.js
@@ -25,6 +25,21 @@ export default {
Beta
`,
+ ssrHtml: `
+
+ Alpha
+
+
+
+ Beta
+
+
+
+ Gamma
+
+
+ Beta
`,
+
async test({ assert, component, target, window }) {
const inputs = target.querySelectorAll('input');
assert.equal(inputs[0].checked, false);
diff --git a/test/runtime/samples/binding-select-implicit-option-value/_config.js b/test/runtime/samples/binding-select-implicit-option-value/_config.js
index cce1172f6a..1266602a47 100644
--- a/test/runtime/samples/binding-select-implicit-option-value/_config.js
+++ b/test/runtime/samples/binding-select-implicit-option-value/_config.js
@@ -14,16 +14,6 @@ export default {
foo: 2
`,
- ssrHtml: `
-
- 1
- 2
- 3
-
-
- foo: 2
- `,
-
async test({ assert, component, target, window }) {
const select = target.querySelector('select');
const options = [...target.querySelectorAll('option')];
diff --git a/test/runtime/samples/binding-select-in-each-block/_config.js b/test/runtime/samples/binding-select-in-each-block/_config.js
index 89f40f8d48..80ea375b78 100644
--- a/test/runtime/samples/binding-select-in-each-block/_config.js
+++ b/test/runtime/samples/binding-select-in-each-block/_config.js
@@ -1,17 +1,4 @@
export default {
-
- ssrHtml: `
-
- Hullo
- World
-
-
-
- Hullo
- World
-
- `,
-
html: `
Hullo
diff --git a/test/runtime/samples/binding-select-initial-value-undefined/_config.js b/test/runtime/samples/binding-select-initial-value-undefined/_config.js
index 821a8a3c64..27bac7ef77 100644
--- a/test/runtime/samples/binding-select-initial-value-undefined/_config.js
+++ b/test/runtime/samples/binding-select-initial-value-undefined/_config.js
@@ -14,6 +14,7 @@ export default {
`,
test({ assert, component, target }) {
+ assert.equal(component.selected, 'a');
const select = target.querySelector('select');
const options = [...target.querySelectorAll('option')];
diff --git a/test/runtime/samples/binding-select-initial-value/_config.js b/test/runtime/samples/binding-select-initial-value/_config.js
index d34a987fa5..517107c4fb 100644
--- a/test/runtime/samples/binding-select-initial-value/_config.js
+++ b/test/runtime/samples/binding-select-initial-value/_config.js
@@ -11,18 +11,6 @@ export default {
selected: b
`,
- ssrHtml: `
- selected: b
-
-
- a
- b
- c
-
-
- selected: b
- `,
-
props: {
selected: 'b'
},
diff --git a/test/runtime/samples/binding-select-late-2/_config.js b/test/runtime/samples/binding-select-late-2/_config.js
index 42c45d1366..f4b0088fb9 100644
--- a/test/runtime/samples/binding-select-late-2/_config.js
+++ b/test/runtime/samples/binding-select-late-2/_config.js
@@ -9,11 +9,6 @@ export default {
selected: two
`,
- ssrHtml: `
-
- selected: two
- `,
-
test({ assert, component, target }) {
component.items = [ 'one', 'two', 'three' ];
diff --git a/test/runtime/samples/binding-select-multiple/_config.js b/test/runtime/samples/binding-select-multiple/_config.js
index b7d6c3589f..70a5620d05 100644
--- a/test/runtime/samples/binding-select-multiple/_config.js
+++ b/test/runtime/samples/binding-select-multiple/_config.js
@@ -4,16 +4,6 @@ export default {
selected: [ 'two', 'three' ]
},
- ssrHtml: `
-
- one
- two
- three
-
-
- selected: two, three
- `,
-
html: `
one
diff --git a/test/runtime/samples/binding-select-unmatched/_config.js b/test/runtime/samples/binding-select-unmatched/_config.js
new file mode 100644
index 0000000000..99e7d23927
--- /dev/null
+++ b/test/runtime/samples/binding-select-unmatched/_config.js
@@ -0,0 +1,60 @@
+export default {
+ html: `
+ selected: null
+
+
+ a
+ b
+ c
+
+
+ selected: null
+ `,
+
+ async test({ assert, component, target }) {
+ const select = target.querySelector('select');
+ const options = [...target.querySelectorAll('option')];
+
+ assert.equal(component.selected, null);
+
+ // no option should be selected since none of the options matches the bound value
+ assert.equal(select.value, '');
+ assert.equal(select.selectedIndex, -1);
+ assert.ok(!options[0].selected);
+
+ component.selected = 'a'; // first option should now be selected
+ assert.equal(select.value, 'a');
+ assert.ok(options[0].selected);
+
+ assert.htmlEqual(target.innerHTML, `
+ selected: a
+
+
+ a
+ b
+ c
+
+
+ selected: a
+ `);
+
+ component.selected = 'd'; // doesn't match an option
+
+ // now no option should be selected again
+ assert.equal(select.value, '');
+ assert.equal(select.selectedIndex, -1);
+ assert.ok(!options[0].selected);
+
+ assert.htmlEqual(target.innerHTML, `
+ selected: d
+
+
+ a
+ b
+ c
+
+
+ selected: d
+ `);
+ }
+};
diff --git a/test/runtime/samples/binding-select-unmatched/main.svelte b/test/runtime/samples/binding-select-unmatched/main.svelte
new file mode 100644
index 0000000000..20e13f4765
--- /dev/null
+++ b/test/runtime/samples/binding-select-unmatched/main.svelte
@@ -0,0 +1,14 @@
+
+
+selected: {selected}
+
+
+ a
+ b
+ c
+
+
+selected: {selected}
\ No newline at end of file
diff --git a/test/runtime/samples/binding-select/_config.js b/test/runtime/samples/binding-select/_config.js
index 310315176b..6cdef2651a 100644
--- a/test/runtime/samples/binding-select/_config.js
+++ b/test/runtime/samples/binding-select/_config.js
@@ -11,18 +11,6 @@ export default {
selected: one
`,
- ssrHtml: `
- selected: one
-
-
- one
- two
- three
-
-
- selected: one
- `,
-
props: {
selected: 'one'
},
diff --git a/test/runtime/samples/binding-this-each-block-property-2/_config.js b/test/runtime/samples/binding-this-each-block-property-2/_config.js
index b67d27050e..49131d6635 100644
--- a/test/runtime/samples/binding-this-each-block-property-2/_config.js
+++ b/test/runtime/samples/binding-this-each-block-property-2/_config.js
@@ -7,7 +7,7 @@ export default {
props: {
callback
},
- after_test() {
+ before_test() {
calls = [];
},
async test({ assert, component, target }) {
diff --git a/test/runtime/samples/bindings-global-dependency/_config.js b/test/runtime/samples/bindings-global-dependency/_config.js
index 1180424e81..907aa52e6e 100644
--- a/test/runtime/samples/bindings-global-dependency/_config.js
+++ b/test/runtime/samples/bindings-global-dependency/_config.js
@@ -1,3 +1,4 @@
export default {
- html: ' '
+ html: ' ',
+ ssrHtml: ' '
};
diff --git a/test/runtime/samples/bitmask-overflow-if-2/_config.js b/test/runtime/samples/bitmask-overflow-if-2/_config.js
new file mode 100644
index 0000000000..bdcf45abba
--- /dev/null
+++ b/test/runtime/samples/bitmask-overflow-if-2/_config.js
@@ -0,0 +1,23 @@
+// `bitmask-overflow-if` tests the case where the if condition is made of first 32 variables
+// this tests the case where the if condition is made of the next 32 variables
+export default {
+ html: `
+ 012345678910111213141516171819202122232425262728293031323334353637383940
+ expected: true
+ if: true
+ `,
+
+ async test({ assert, component, target }) {
+ component._40 = '-';
+
+ assert.htmlEqual(
+ target.innerHTML,
+ `
+ 0123456789101112131415161718192021222324252627282930313233343536373839-
+ expected: false
+ if: false
+
+ `
+ );
+ }
+};
diff --git a/test/runtime/samples/bitmask-overflow-if-2/main.svelte b/test/runtime/samples/bitmask-overflow-if-2/main.svelte
new file mode 100644
index 0000000000..f2a461b5b4
--- /dev/null
+++ b/test/runtime/samples/bitmask-overflow-if-2/main.svelte
@@ -0,0 +1,56 @@
+
+
+
+{_0}{_1}{_2}{_3}{_4}{_5}{_6}{_7}{_8}{_9}{_10}{_11}{_12}{_13}{_14}{_15}{_16}{_17}{_18}{_19}{_20}{_21}{_22}{_23}{_24}{_25}{_26}{_27}{_28}{_29}{_30}{_31}{_32}{_33}{_34}{_35}{_36}{_37}{_38}{_39}{_40}
+
+expected: {_a.indexOf(_40) > -1 && _40 === '40' && _39 === '39'}
+{#if _a.indexOf(_40) > -1 && _40 === '40' && _39 === '39'}
+if: true
+{:else}
+if: false
+
+{/if}
diff --git a/test/runtime/samples/component-binding-accessors/Nested.svelte b/test/runtime/samples/component-binding-accessors/Nested.svelte
new file mode 100644
index 0000000000..a3ce2afd9f
--- /dev/null
+++ b/test/runtime/samples/component-binding-accessors/Nested.svelte
@@ -0,0 +1,5 @@
+
+
+
\ No newline at end of file
diff --git a/test/runtime/samples/component-binding-accessors/_config.js b/test/runtime/samples/component-binding-accessors/_config.js
new file mode 100644
index 0000000000..0fb83df870
--- /dev/null
+++ b/test/runtime/samples/component-binding-accessors/_config.js
@@ -0,0 +1,18 @@
+export default {
+ async test({ assert, component, target, window }) {
+ const [input1, input2] = target.querySelectorAll('input');
+ assert.equal(input1.value, 'something');
+ assert.equal(input2.value, 'something');
+
+ input1.value = 'abc';
+
+ await input1.dispatchEvent(new window.Event('input'));
+ assert.equal(input1.value, 'abc');
+ assert.equal(input2.value, 'abc');
+
+ await target.querySelector('button').dispatchEvent(new window.MouseEvent('click'));
+
+ assert.equal(input1.value, 'Reset');
+ assert.equal(input2.value, 'Reset');
+ }
+};
diff --git a/test/runtime/samples/component-binding-accessors/main.svelte b/test/runtime/samples/component-binding-accessors/main.svelte
new file mode 100644
index 0000000000..1d8576643d
--- /dev/null
+++ b/test/runtime/samples/component-binding-accessors/main.svelte
@@ -0,0 +1,12 @@
+
+
+
+
+
+ {
+ c.value = 'Reset';
+}}>Reset
\ No newline at end of file
diff --git a/test/runtime/samples/component-binding-computed/_config.js b/test/runtime/samples/component-binding-computed/_config.js
index b287014065..f43a6834a8 100644
--- a/test/runtime/samples/component-binding-computed/_config.js
+++ b/test/runtime/samples/component-binding-computed/_config.js
@@ -3,6 +3,10 @@ export default {
firstname
lastname
`,
+ ssrHtml: `
+ firstname
+ lastname
+ `,
async test({ assert, component, target, window }) {
const input = new window.Event('input');
diff --git a/test/runtime/samples/component-binding-store/_config.js b/test/runtime/samples/component-binding-store/_config.js
index d17b9e2d80..8bbdab17ee 100644
--- a/test/runtime/samples/component-binding-store/_config.js
+++ b/test/runtime/samples/component-binding-store/_config.js
@@ -4,6 +4,11 @@ export default {
`,
+ ssrHtml: `
+
+
+
+ `,
async test({ assert, component, target, window }) {
let count = 0;
diff --git a/test/runtime/samples/component-events-this/Inner.svelte b/test/runtime/samples/component-events-this/Inner.svelte
new file mode 100644
index 0000000000..377aa17c43
--- /dev/null
+++ b/test/runtime/samples/component-events-this/Inner.svelte
@@ -0,0 +1,7 @@
+
+
+ dispatch('bar')} />
\ No newline at end of file
diff --git a/test/runtime/samples/component-events-this/Widget.svelte b/test/runtime/samples/component-events-this/Widget.svelte
new file mode 100644
index 0000000000..30b95e94f1
--- /dev/null
+++ b/test/runtime/samples/component-events-this/Widget.svelte
@@ -0,0 +1,6 @@
+
+
+click me
+
\ No newline at end of file
diff --git a/test/runtime/samples/component-events-this/_config.js b/test/runtime/samples/component-events-this/_config.js
new file mode 100644
index 0000000000..180ae7367d
--- /dev/null
+++ b/test/runtime/samples/component-events-this/_config.js
@@ -0,0 +1,11 @@
+export default {
+ test({ assert, component, target, window }) {
+ const [button1, button2] = target.querySelectorAll('button');
+
+ button1.dispatchEvent(new window.MouseEvent('click'));
+ button2.dispatchEvent(new window.MouseEvent('click'));
+
+ assert.strictEqual(component.logs[0], button1);
+ assert.ok(component.logs[1] instanceof component.Inner);
+ }
+};
diff --git a/test/runtime/samples/component-events-this/main.svelte b/test/runtime/samples/component-events-this/main.svelte
new file mode 100644
index 0000000000..328a524360
--- /dev/null
+++ b/test/runtime/samples/component-events-this/main.svelte
@@ -0,0 +1,16 @@
+
+
+
\ No newline at end of file
diff --git a/test/runtime/samples/component-namespaced/_config.js b/test/runtime/samples/component-namespaced/_config.js
index 35a5e46d47..7ec4a35c6d 100644
--- a/test/runtime/samples/component-namespaced/_config.js
+++ b/test/runtime/samples/component-namespaced/_config.js
@@ -1,5 +1,3 @@
-import * as path from 'path';
-
export default {
props: {
a: 1
@@ -9,10 +7,6 @@ export default {
foo 1
`,
- before_test() {
- delete require.cache[path.resolve(__dirname, 'components.js')];
- },
-
test({ assert, component, target }) {
component.a = 2;
assert.htmlEqual(target.innerHTML, `
diff --git a/test/runtime/samples/component-namespaced/components.js b/test/runtime/samples/component-namespaced/components.js
deleted file mode 100644
index 7dcfcf157c..0000000000
--- a/test/runtime/samples/component-namespaced/components.js
+++ /dev/null
@@ -1,3 +0,0 @@
-import Foo from './Foo.svelte';
-
-export default { Foo };
diff --git a/test/runtime/samples/component-namespaced/components.svelte b/test/runtime/samples/component-namespaced/components.svelte
new file mode 100644
index 0000000000..5b9a6c5167
--- /dev/null
+++ b/test/runtime/samples/component-namespaced/components.svelte
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/test/runtime/samples/component-namespaced/main.svelte b/test/runtime/samples/component-namespaced/main.svelte
index 541b68e47e..25862cf6f2 100644
--- a/test/runtime/samples/component-namespaced/main.svelte
+++ b/test/runtime/samples/component-namespaced/main.svelte
@@ -1,5 +1,5 @@
diff --git a/test/runtime/samples/component-slot-fallback-6/_config.js b/test/runtime/samples/component-slot-fallback-6/_config.js
index b32d96db2e..be47d31d03 100644
--- a/test/runtime/samples/component-slot-fallback-6/_config.js
+++ b/test/runtime/samples/component-slot-fallback-6/_config.js
@@ -4,6 +4,10 @@ export default {
{"value":""}
`,
+ ssrHtml: `
+
+ {"value":""}
+ `,
async test({ assert, target, window }) {
const input = target.querySelector('input');
diff --git a/test/runtime/samples/component-slot-spread-props/_config.js b/test/runtime/samples/component-slot-spread-props/_config.js
index 042bdca6ec..7beda8d3d5 100644
--- a/test/runtime/samples/component-slot-spread-props/_config.js
+++ b/test/runtime/samples/component-slot-spread-props/_config.js
@@ -5,6 +5,12 @@ export default {
`,
+ ssrHtml: `
+
+ `,
async test({ assert, component, target }) {
component.value = 'foo';
diff --git a/test/runtime/samples/constructor-prefer-passed-context/ChildComponent.svelte b/test/runtime/samples/constructor-prefer-passed-context/ChildComponent.svelte
new file mode 100644
index 0000000000..af77418a1f
--- /dev/null
+++ b/test/runtime/samples/constructor-prefer-passed-context/ChildComponent.svelte
@@ -0,0 +1,6 @@
+
+
+Value in child component: {value}
diff --git a/test/runtime/samples/constructor-prefer-passed-context/_config.js b/test/runtime/samples/constructor-prefer-passed-context/_config.js
new file mode 100644
index 0000000000..5d5cf9e44a
--- /dev/null
+++ b/test/runtime/samples/constructor-prefer-passed-context/_config.js
@@ -0,0 +1,6 @@
+export default {
+ skip_if_ssr: true,
+ html: `
+ Value in child component: undefined
+ `
+};
diff --git a/test/runtime/samples/constructor-prefer-passed-context/main.svelte b/test/runtime/samples/constructor-prefer-passed-context/main.svelte
new file mode 100644
index 0000000000..dd051a123a
--- /dev/null
+++ b/test/runtime/samples/constructor-prefer-passed-context/main.svelte
@@ -0,0 +1,15 @@
+
+
+
diff --git a/test/runtime/samples/context-api-d/Leaf.svelte b/test/runtime/samples/context-api-d/Leaf.svelte
new file mode 100644
index 0000000000..02b6b26e00
--- /dev/null
+++ b/test/runtime/samples/context-api-d/Leaf.svelte
@@ -0,0 +1,9 @@
+
+
+{#each [...context.keys()] as key}
+ {key}: {context.get(key)}
+{/each}
diff --git a/test/runtime/samples/context-api-d/Nested.svelte b/test/runtime/samples/context-api-d/Nested.svelte
new file mode 100644
index 0000000000..e8a7e083c3
--- /dev/null
+++ b/test/runtime/samples/context-api-d/Nested.svelte
@@ -0,0 +1,8 @@
+
+
+
\ No newline at end of file
diff --git a/test/runtime/samples/context-api-d/_config.js b/test/runtime/samples/context-api-d/_config.js
new file mode 100644
index 0000000000..a5b0769f8b
--- /dev/null
+++ b/test/runtime/samples/context-api-d/_config.js
@@ -0,0 +1,7 @@
+export default {
+ html: `
+ a: 1
+ b: 2
+ c: 3
+ `
+};
diff --git a/test/runtime/samples/context-api-d/main.svelte b/test/runtime/samples/context-api-d/main.svelte
new file mode 100644
index 0000000000..82d1021574
--- /dev/null
+++ b/test/runtime/samples/context-api-d/main.svelte
@@ -0,0 +1,8 @@
+
+
+
+
+
diff --git a/test/runtime/samples/deconflict-builtins-2/_config.js b/test/runtime/samples/deconflict-builtins-2/_config.js
index e136b0410d..fba811b880 100644
--- a/test/runtime/samples/deconflict-builtins-2/_config.js
+++ b/test/runtime/samples/deconflict-builtins-2/_config.js
@@ -1,4 +1,4 @@
export default {
- html: 'hello world ',
+ html: 'hello world ',
preserveIdentifiers: true
};
diff --git a/test/runtime/samples/deconflict-builtins-2/main.svelte b/test/runtime/samples/deconflict-builtins-2/main.svelte
index 82f9213045..db10a81c74 100644
--- a/test/runtime/samples/deconflict-builtins-2/main.svelte
+++ b/test/runtime/samples/deconflict-builtins-2/main.svelte
@@ -1,5 +1,6 @@
-
-{foo}
\ No newline at end of file
+
+ {foo}
+
\ No newline at end of file
diff --git a/test/runtime/samples/destructured-assignment-pattern-with-object-pattern/_config.js b/test/runtime/samples/destructured-assignment-pattern-with-object-pattern/_config.js
new file mode 100644
index 0000000000..75025e4614
--- /dev/null
+++ b/test/runtime/samples/destructured-assignment-pattern-with-object-pattern/_config.js
@@ -0,0 +1,6 @@
+export default {
+ html: `
+ hello undefined
+ hello bar2
+ `
+};
diff --git a/test/runtime/samples/destructured-assignment-pattern-with-object-pattern/main.svelte b/test/runtime/samples/destructured-assignment-pattern-with-object-pattern/main.svelte
new file mode 100644
index 0000000000..b71b25bd67
--- /dev/null
+++ b/test/runtime/samples/destructured-assignment-pattern-with-object-pattern/main.svelte
@@ -0,0 +1,11 @@
+
+
+hello {bar}
+hello {bar2}
diff --git a/test/runtime/samples/destructured-props-1/A.svelte b/test/runtime/samples/destructured-props-1/A.svelte
new file mode 100644
index 0000000000..d1b392ef34
--- /dev/null
+++ b/test/runtime/samples/destructured-props-1/A.svelte
@@ -0,0 +1,24 @@
+
+
+
+a: {a},
+b: {typeof b},
+c: {c},
+d_one: {d_one},
+d_three: {$d_three},
+f: {f},
+g: {g},
+e: {typeof e},
+e_one: {e_one},
+A: {A},
+C: {C}
+
+{JSON.stringify(THING)}
\ No newline at end of file
diff --git a/test/runtime/samples/destructured-props-1/_config.js b/test/runtime/samples/destructured-props-1/_config.js
new file mode 100644
index 0000000000..29feaaabab
--- /dev/null
+++ b/test/runtime/samples/destructured-props-1/_config.js
@@ -0,0 +1,9 @@
+export default {
+ html: `
+ a: 1, b: undefined, c: 2, d_one: 3, d_three: 5, f: undefined, g: 9, e: undefined, e_one: 6, A: 1, C: 2
+ {"a":1,"b":{"c":2,"d":[3,4,{}]},"e":[6],"h":8}
+
+ a: a, b: undefined, c: 2, d_one: d_one, d_three: 5, f: f, g: g, e: undefined, e_one: 6, A: 1, C: 2
+ {"a":1,"b":{"c":2,"d":[3,4,{}]},"e":[6],"h":8}
+ `
+};
diff --git a/test/runtime/samples/destructured-props-1/main.svelte b/test/runtime/samples/destructured-props-1/main.svelte
new file mode 100644
index 0000000000..dbe7c88d33
--- /dev/null
+++ b/test/runtime/samples/destructured-props-1/main.svelte
@@ -0,0 +1,7 @@
+
+
+
+
+
diff --git a/test/runtime/samples/destructured-props-2/A.svelte b/test/runtime/samples/destructured-props-2/A.svelte
new file mode 100644
index 0000000000..51167edbc4
--- /dev/null
+++ b/test/runtime/samples/destructured-props-2/A.svelte
@@ -0,0 +1,21 @@
+
+
+
+ x: {x},
+ list_two_a: {list_two_a},
+ list_two_b: {list_two_b},
+ y: {$y},
+ m: {m},
+ n: {n},
+ o: {o},
+ p: {p},
+ q: {$q}
+
+{JSON.stringify(LIST)}
\ No newline at end of file
diff --git a/test/runtime/samples/destructured-props-2/_config.js b/test/runtime/samples/destructured-props-2/_config.js
new file mode 100644
index 0000000000..c647f31be1
--- /dev/null
+++ b/test/runtime/samples/destructured-props-2/_config.js
@@ -0,0 +1,19 @@
+export default {
+ html: `
+ x: 1, list_two_a: 2, list_two_b: 5, y: 4, m: 1, n: 2, o: 5, p: 3, q: 4
+ [1,{"a":2},[3,{}]]
+ x: 1, list_two_a: 2, list_two_b: 5, y: 4, m: m, n: n, o: o, p: p, q: q
+ [1,{"a":2},[3,{}]]
+ `,
+
+ async test({ component, assert, target }) {
+ await component.update();
+
+ assert.htmlEqual(target.innerHTML, `
+ x: 1, list_two_a: 2, list_two_b: 5, y: 4, m: 1, n: 2, o: 5, p: 3, q: 4
+ [1,{"a":2},[3,{}]]
+ x: 1, list_two_a: 2, list_two_b: 5, y: 4, m: MM, n: NN, o: OO, p: PP, q: QQ
+ [1,{"a":2},[3,{}]]
+ `);
+ }
+};
diff --git a/test/runtime/samples/destructured-props-2/main.svelte b/test/runtime/samples/destructured-props-2/main.svelte
new file mode 100644
index 0000000000..f0044bb567
--- /dev/null
+++ b/test/runtime/samples/destructured-props-2/main.svelte
@@ -0,0 +1,30 @@
+
+
+
+
+
diff --git a/test/runtime/samples/destructured-props-3/A.svelte b/test/runtime/samples/destructured-props-3/A.svelte
new file mode 100644
index 0000000000..6c5aca05b0
--- /dev/null
+++ b/test/runtime/samples/destructured-props-3/A.svelte
@@ -0,0 +1,10 @@
+
+
+i: {i}, j: {j}, k: {$k}, l: {l}, m: {m}, n: {$n}, a: {a}, b: {b}, c: {$c}, d: {d}, e: {e}, f: {$f}
\ No newline at end of file
diff --git a/test/runtime/samples/destructured-props-3/_config.js b/test/runtime/samples/destructured-props-3/_config.js
new file mode 100644
index 0000000000..6d2e516e0e
--- /dev/null
+++ b/test/runtime/samples/destructured-props-3/_config.js
@@ -0,0 +1,15 @@
+export default {
+ html: `
+ i: 9, j: 10, k: 11, l: 12, m: 13, n: 14, a: 9, b: 10, c: 11, d: 12, e: 13, f: 14
+
+ i: 9, j: 10, k: 11, l: 12, m: 13, n: 14, a: a, b: 10, c: c, d: d, e: 13, f: f
+ `,
+ async test({ component, target, assert }) {
+ await component.update();
+ assert.htmlEqual(target.innerHTML, `
+ i: 9, j: 10, k: 11, l: 12, m: 13, n: 14, a: 9, b: 10, c: 11, d: 12, e: 13, f: 14
+
+ i: 9, j: 10, k: 11, l: 12, m: 13, n: 14, a: aa, b: 10, c: cc, d: dd, e: 13, f: ff
+ `);
+ }
+};
diff --git a/test/runtime/samples/destructured-props-3/main.svelte b/test/runtime/samples/destructured-props-3/main.svelte
new file mode 100644
index 0000000000..8152d61aab
--- /dev/null
+++ b/test/runtime/samples/destructured-props-3/main.svelte
@@ -0,0 +1,29 @@
+
+
+
+
+
diff --git a/test/runtime/samples/each-block-destructured-default-binding/_config.js b/test/runtime/samples/each-block-destructured-default-binding/_config.js
index 3697e37441..2ba27bff03 100644
--- a/test/runtime/samples/each-block-destructured-default-binding/_config.js
+++ b/test/runtime/samples/each-block-destructured-default-binding/_config.js
@@ -4,7 +4,7 @@ export default {
`,
ssrHtml: `
-
+
`,
diff --git a/test/runtime/samples/each-block-keyed-changed/_config.js b/test/runtime/samples/each-block-keyed-changed/_config.js
new file mode 100644
index 0000000000..afb3593b94
--- /dev/null
+++ b/test/runtime/samples/each-block-keyed-changed/_config.js
@@ -0,0 +1,13 @@
+export default {
+ props: {
+ titles: [{ name: 'a' }, { name: 'b' }, { name: 'c' }]
+ },
+
+ html: '',
+
+ test({ assert, component, target }) {
+ component.titles = [{ name: 'b' }, { name: 'c' }, { name: 'a' }];
+
+ assert.htmlEqual(target.innerHTML, '');
+ }
+};
diff --git a/test/runtime/samples/each-block-keyed-changed/main.svelte b/test/runtime/samples/each-block-keyed-changed/main.svelte
new file mode 100644
index 0000000000..1e1ef513a7
--- /dev/null
+++ b/test/runtime/samples/each-block-keyed-changed/main.svelte
@@ -0,0 +1,8 @@
+
+
+ {#each titles as title (title.name)}
+
{title.name}
+ {/each}
+
diff --git a/test/runtime/samples/each-block-keyed-dyanmic-key/_config.js b/test/runtime/samples/each-block-keyed-dyanmic-key/_config.js
index 0aed1b0e07..949235ee48 100644
--- a/test/runtime/samples/each-block-keyed-dyanmic-key/_config.js
+++ b/test/runtime/samples/each-block-keyed-dyanmic-key/_config.js
@@ -9,6 +9,10 @@ export default {
}
},
+ before_test() {
+ count = 0;
+ },
+
html: `
foo
foo
diff --git a/test/runtime/samples/event-handler-modifier-trusted/_config.js b/test/runtime/samples/event-handler-modifier-trusted/_config.js
new file mode 100644
index 0000000000..ac269e674a
--- /dev/null
+++ b/test/runtime/samples/event-handler-modifier-trusted/_config.js
@@ -0,0 +1,9 @@
+export default {
+ async test({ assert, component, target, window }) {
+ const button = target.querySelector('button');
+ const event = new window.MouseEvent('click');
+
+ await button.dispatchEvent(event);
+ assert.equal(component.trusted, true);
+ }
+};
diff --git a/test/runtime/samples/event-handler-modifier-trusted/main.svelte b/test/runtime/samples/event-handler-modifier-trusted/main.svelte
new file mode 100644
index 0000000000..504326a498
--- /dev/null
+++ b/test/runtime/samples/event-handler-modifier-trusted/main.svelte
@@ -0,0 +1,5 @@
+
+
+ trusted = false}">Only trusted events: {trusted?'true':'false'}
diff --git a/test/runtime/samples/export-from/A.svelte b/test/runtime/samples/export-from/A.svelte
new file mode 100644
index 0000000000..7773727704
--- /dev/null
+++ b/test/runtime/samples/export-from/A.svelte
@@ -0,0 +1,23 @@
+
+
+
+
+a: {typeof a}
+b: {typeof b}
+c: {typeof c}
+d: {typeof d}
+e: {typeof e}
+f: {typeof f}
+g: {typeof g}
\ No newline at end of file
diff --git a/test/runtime/samples/export-from/B.svelte b/test/runtime/samples/export-from/B.svelte
new file mode 100644
index 0000000000..0cc1070cb5
--- /dev/null
+++ b/test/runtime/samples/export-from/B.svelte
@@ -0,0 +1,8 @@
+
diff --git a/test/runtime/samples/export-from/_config.js b/test/runtime/samples/export-from/_config.js
new file mode 100644
index 0000000000..9e65b7501d
--- /dev/null
+++ b/test/runtime/samples/export-from/_config.js
@@ -0,0 +1,28 @@
+export default {
+ html: `
+ a,b,undefined,c
+
+ a: undefined
+ b: number
+ c: undefined
+ d: undefined
+ e: number
+ f: undefined
+ g: undefined
+
+ {"d":"d","e":"e","g":"f"}
+ `,
+ ssrHtml: `
+ a,b,undefined,c
+
+ a: undefined
+ b: number
+ c: undefined
+ d: undefined
+ e: number
+ f: undefined
+ g: undefined
+
+ {}
+ `
+};
diff --git a/test/runtime/samples/export-from/main.svelte b/test/runtime/samples/export-from/main.svelte
new file mode 100644
index 0000000000..18cc066c1f
--- /dev/null
+++ b/test/runtime/samples/export-from/main.svelte
@@ -0,0 +1,21 @@
+
+
+{a},{b},{c},{d}
+
+
+
+{JSON.stringify(props)}
\ No newline at end of file
diff --git a/test/runtime/samples/if-block-conservative-update/_config.js b/test/runtime/samples/if-block-conservative-update/_config.js
index f84ccb6b43..f7ba01a8fd 100644
--- a/test/runtime/samples/if-block-conservative-update/_config.js
+++ b/test/runtime/samples/if-block-conservative-update/_config.js
@@ -11,6 +11,9 @@ export default {
html: 'potato
',
+ before_test() {
+ count = 0;
+ },
test({ assert, component, target }) {
assert.equal(count, 1);
diff --git a/test/runtime/samples/if-block-else-conservative-update/_config.js b/test/runtime/samples/if-block-else-conservative-update/_config.js
index da83385dd5..b3db0bca54 100644
--- a/test/runtime/samples/if-block-else-conservative-update/_config.js
+++ b/test/runtime/samples/if-block-else-conservative-update/_config.js
@@ -17,6 +17,11 @@ export default {
html: 'potato
',
+ before_test() {
+ count_a = 0;
+ count_b = 0;
+ },
+
test({ assert, component, target }) {
assert.equal(count_a, 1);
assert.equal(count_b, 0);
diff --git a/test/runtime/samples/if-block-outro-computed-function/Foo.svelte b/test/runtime/samples/if-block-outro-computed-function/Foo.svelte
new file mode 100644
index 0000000000..1910281566
--- /dev/null
+++ b/test/runtime/samples/if-block-outro-computed-function/Foo.svelte
@@ -0,0 +1 @@
+foo
\ No newline at end of file
diff --git a/test/runtime/samples/if-block-outro-computed-function/_config.js b/test/runtime/samples/if-block-outro-computed-function/_config.js
new file mode 100644
index 0000000000..69fd95d008
--- /dev/null
+++ b/test/runtime/samples/if-block-outro-computed-function/_config.js
@@ -0,0 +1,12 @@
+export default {
+ props: {
+ foo: true
+ },
+
+ html: 'foo',
+
+ test({ assert, component, target }) {
+ component.foo = false;
+ assert.htmlEqual(target.innerHTML, 'bar');
+ }
+};
diff --git a/test/runtime/samples/if-block-outro-computed-function/main.svelte b/test/runtime/samples/if-block-outro-computed-function/main.svelte
new file mode 100644
index 0000000000..adf7cc3e0b
--- /dev/null
+++ b/test/runtime/samples/if-block-outro-computed-function/main.svelte
@@ -0,0 +1,13 @@
+
+
+{#if foo}
+
+{:else if bar()}
+ bar
+{:else}
+ else
+{/if}
diff --git a/test/runtime/samples/key-block-post-hydrate/_config.js b/test/runtime/samples/key-block-post-hydrate/_config.js
new file mode 100644
index 0000000000..e989d678e9
--- /dev/null
+++ b/test/runtime/samples/key-block-post-hydrate/_config.js
@@ -0,0 +1,19 @@
+export default {
+ html: `
+
+
item 1 something
+
item 2 something
+
item 3 something
+
+ `,
+ test({ assert, component, target }) {
+ component.sortById = false;
+ assert.htmlEqual( target.innerHTML, `
+
+
item 3 something
+
item 2 something
+
item 1 something
+
+ `);
+ }
+};
diff --git a/test/runtime/samples/key-block-post-hydrate/main.svelte b/test/runtime/samples/key-block-post-hydrate/main.svelte
new file mode 100644
index 0000000000..8ea316a0d7
--- /dev/null
+++ b/test/runtime/samples/key-block-post-hydrate/main.svelte
@@ -0,0 +1,23 @@
+
+
+
+ {#each items as item (item.id)}
+
+ {#if item.name}
+
+ {item.name}
+
+ {/if}
+ something
+
+ {/each}
+
diff --git a/test/runtime/samples/lifecycle-render-order-for-children/_config.js b/test/runtime/samples/lifecycle-render-order-for-children/_config.js
index d182d5a97e..b85c91d07f 100644
--- a/test/runtime/samples/lifecycle-render-order-for-children/_config.js
+++ b/test/runtime/samples/lifecycle-render-order-for-children/_config.js
@@ -2,7 +2,9 @@ import order from './order.js';
export default {
skip_if_ssr: true,
-
+ before_test() {
+ order.length = 0;
+ },
test({ assert, component, target, compileOptions }) {
if (compileOptions.hydratable) {
assert.deepEqual(order, [
@@ -43,7 +45,5 @@ export default {
'0: afterUpdate'
]);
}
-
- order.length = 0;
}
};
diff --git a/test/runtime/samples/lifecycle-render-order/_config.js b/test/runtime/samples/lifecycle-render-order/_config.js
index 5080973cef..2bbab7a838 100644
--- a/test/runtime/samples/lifecycle-render-order/_config.js
+++ b/test/runtime/samples/lifecycle-render-order/_config.js
@@ -3,6 +3,9 @@ import order from './order.js';
export default {
skip_if_ssr: true,
+ before_test() {
+ order.length = 0;
+ },
test({ assert }) {
assert.deepEqual(order, [
'beforeUpdate',
@@ -10,7 +13,5 @@ export default {
'onMount',
'afterUpdate'
]);
-
- order.length = 0;
}
};
diff --git a/test/runtime/samples/noscript-removal/_config.js b/test/runtime/samples/noscript-removal/_config.js
index 709792c14a..0fd03ea223 100644
--- a/test/runtime/samples/noscript-removal/_config.js
+++ b/test/runtime/samples/noscript-removal/_config.js
@@ -1,9 +1,33 @@
export default {
- skip_if_ssr: true,
+ ssrHtml: `
+ foo
- html: `
- foo
+ foofoo
-
-`
+
+ `,
+ test({ assert, target, compileOptions }) {
+ // if created on client side, should not build noscript
+ if (!compileOptions.hydratable) {
+ assert.equal(target.querySelectorAll('noscript').length, 0);
+ }
+
+ // it's okay not to remove the node during hydration
+ // will not be seen by user anyway
+ removeNoScript(target);
+
+ assert.htmlEqual(
+ target.innerHTML,
+ `
+ foo
+
+ `
+ );
+ }
};
+
+function removeNoScript(target) {
+ target.querySelectorAll('noscript').forEach(elem => {
+ elem.parentNode.removeChild(elem);
+ });
+}
diff --git a/test/runtime/samples/numeric-seperator/main.svelte b/test/runtime/samples/numeric-seperator/main.svelte
deleted file mode 100644
index e491b8a107..0000000000
--- a/test/runtime/samples/numeric-seperator/main.svelte
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-{num} {2_048}
\ No newline at end of file
diff --git a/test/runtime/samples/ondestroy-deep/_config.js b/test/runtime/samples/ondestroy-deep/_config.js
index 3f82e8b601..397d8c5684 100644
--- a/test/runtime/samples/ondestroy-deep/_config.js
+++ b/test/runtime/samples/ondestroy-deep/_config.js
@@ -2,6 +2,9 @@ import { destroyed, reset } from './destroyed.js';
export default {
test({ assert, component }) {
+ // for hydration, ssr may have pushed to `destroyed`
+ reset();
+
component.visible = false;
assert.deepEqual(destroyed, ['A', 'B', 'C']);
diff --git a/test/runtime/samples/raw-anchor-first-child/_config.js b/test/runtime/samples/raw-anchor-first-child/_config.js
index 02297675c5..f9e6b76626 100644
--- a/test/runtime/samples/raw-anchor-first-child/_config.js
+++ b/test/runtime/samples/raw-anchor-first-child/_config.js
@@ -8,5 +8,6 @@ export default {
assert.ok(!span.previousSibling);
component.raw = 'bar ';
+ assert.htmlEqual(target.innerHTML, 'bar
');
}
};
diff --git a/test/runtime/samples/raw-mustaches/_config.js b/test/runtime/samples/raw-mustaches/_config.js
index 9eda8289ce..a69b91d2d8 100644
--- a/test/runtime/samples/raw-mustaches/_config.js
+++ b/test/runtime/samples/raw-mustaches/_config.js
@@ -1,5 +1,4 @@
export default {
- skip_if_ssr: true,
props: {
raw: 'raw html!!!\\o/ '
diff --git a/test/runtime/samples/reactive-function-called-reassigned/_config.js b/test/runtime/samples/reactive-function-called-reassigned/_config.js
index 7b2a8b72fe..b4d50a3e84 100644
--- a/test/runtime/samples/reactive-function-called-reassigned/_config.js
+++ b/test/runtime/samples/reactive-function-called-reassigned/_config.js
@@ -9,6 +9,9 @@ export default {
props: {
callback
},
+ before_test() {
+ called = 0;
+ },
async test({ assert, component, target, window }) {
assert.equal(called, 1);
diff --git a/test/runtime/samples/spread-element-input-select/_config.js b/test/runtime/samples/spread-element-input-select/_config.js
new file mode 100644
index 0000000000..7361e6bb31
--- /dev/null
+++ b/test/runtime/samples/spread-element-input-select/_config.js
@@ -0,0 +1,25 @@
+export default {
+ async test({ assert, component, target, window }) {
+ const select = target.querySelector('select');
+ const [option1, option2] = select.childNodes;
+
+ let selections = Array.from(select.selectedOptions);
+ assert.equal(selections.length, 1);
+ assert.ok(!selections.includes(option1));
+ assert.ok(selections.includes(option2));
+
+ component.value = 'Hello';
+
+ selections = Array.from(select.selectedOptions);
+ assert.equal(selections.length, 1);
+ assert.ok(selections.includes(option1));
+ assert.ok(!selections.includes(option2));
+
+ component.spread = { value: 'World' };
+
+ selections = Array.from(select.selectedOptions);
+ assert.equal(selections.length, 1);
+ assert.ok(!selections.includes(option1));
+ assert.ok(selections.includes(option2));
+ }
+};
diff --git a/test/runtime/samples/spread-element-input-select/main.svelte b/test/runtime/samples/spread-element-input-select/main.svelte
new file mode 100644
index 0000000000..41554d794f
--- /dev/null
+++ b/test/runtime/samples/spread-element-input-select/main.svelte
@@ -0,0 +1,9 @@
+
+
+
+ Hello
+ World
+
diff --git a/test/runtime/samples/spread-element-select-value-undefined/Select.svelte b/test/runtime/samples/spread-element-select-value-undefined/Select.svelte
new file mode 100644
index 0000000000..6f5dadf001
--- /dev/null
+++ b/test/runtime/samples/spread-element-select-value-undefined/Select.svelte
@@ -0,0 +1,12 @@
+
+
+
+ {#each options as option}
+ {option}
+ {/each}
+
+{label}
diff --git a/test/runtime/samples/spread-element-select-value-undefined/_config.js b/test/runtime/samples/spread-element-select-value-undefined/_config.js
new file mode 100644
index 0000000000..59cf59d662
--- /dev/null
+++ b/test/runtime/samples/spread-element-select-value-undefined/_config.js
@@ -0,0 +1,11 @@
+export default {
+ async test({ assert, component, target, window }) {
+ const select = target.querySelector('select');
+
+ assert.equal(select.value, '1');
+
+ component.label = 'hoge';
+
+ assert.equal(select.value, '1');
+ }
+};
diff --git a/test/runtime/samples/spread-element-select-value-undefined/main.svelte b/test/runtime/samples/spread-element-select-value-undefined/main.svelte
new file mode 100644
index 0000000000..57a2e3cf3e
--- /dev/null
+++ b/test/runtime/samples/spread-element-select-value-undefined/main.svelte
@@ -0,0 +1,11 @@
+
+
+
diff --git a/test/runtime/samples/store-assignment-updates-destructure/_config.js b/test/runtime/samples/store-assignment-updates-destructure/_config.js
new file mode 100644
index 0000000000..7a1023614c
--- /dev/null
+++ b/test/runtime/samples/store-assignment-updates-destructure/_config.js
@@ -0,0 +1,11 @@
+export default {
+ html: `
+ $userName1: user1
+ $userName2: undefined
+ $userName3: undefined
+ $userName4: user4
+ $userName5: undefined
+ $userName6: user6
+ $userName7: undefined
+ `
+};
diff --git a/test/runtime/samples/store-assignment-updates-destructure/main.svelte b/test/runtime/samples/store-assignment-updates-destructure/main.svelte
new file mode 100644
index 0000000000..71e02fe16d
--- /dev/null
+++ b/test/runtime/samples/store-assignment-updates-destructure/main.svelte
@@ -0,0 +1,34 @@
+
+
+$userName1: {$userName1}
+$userName2: {$userName2}
+$userName3: {$userName3}
+$userName4: {$userName4}
+$userName5: {$userName5}
+$userName6: {$userName6}
+$userName7: {$userName7}
diff --git a/test/runtime/samples/store-auto-subscribe-in-reactive-declaration-2/App.svelte b/test/runtime/samples/store-auto-subscribe-in-reactive-declaration-2/App.svelte
new file mode 100644
index 0000000000..250305b62c
--- /dev/null
+++ b/test/runtime/samples/store-auto-subscribe-in-reactive-declaration-2/App.svelte
@@ -0,0 +1,8 @@
+
+{value}
+{$store}
diff --git a/test/runtime/samples/store-auto-subscribe-in-reactive-declaration-2/_config.js b/test/runtime/samples/store-auto-subscribe-in-reactive-declaration-2/_config.js
new file mode 100644
index 0000000000..27189d58d7
--- /dev/null
+++ b/test/runtime/samples/store-auto-subscribe-in-reactive-declaration-2/_config.js
@@ -0,0 +1,15 @@
+export default {
+ html: `
+ Hello World
+ Hello World
+ `,
+
+ async test({ assert, component, target, window }) {
+ await component.update_value('Hi Svelte');
+
+ assert.htmlEqual(target.innerHTML, `
+ Hi Svelte
+ Hi Svelte
+ `);
+ }
+};
diff --git a/test/runtime/samples/store-auto-subscribe-in-reactive-declaration-2/main.svelte b/test/runtime/samples/store-auto-subscribe-in-reactive-declaration-2/main.svelte
new file mode 100644
index 0000000000..4e771617bb
--- /dev/null
+++ b/test/runtime/samples/store-auto-subscribe-in-reactive-declaration-2/main.svelte
@@ -0,0 +1,12 @@
+
+
+
diff --git a/test/runtime/samples/store-invalidation-while-update-1/_config.js b/test/runtime/samples/store-invalidation-while-update-1/_config.js
index 6a931afeaf..0f8ff1809b 100644
--- a/test/runtime/samples/store-invalidation-while-update-1/_config.js
+++ b/test/runtime/samples/store-invalidation-while-update-1/_config.js
@@ -5,6 +5,12 @@ export default {
simple
click me
`,
+ ssrHtml: `
+
+
+ simple
+ click me
+ `,
async test({ assert, component, target, window }) {
const input = target.querySelector('input');
diff --git a/test/runtime/samples/store-invalidation-while-update-2/_config.js b/test/runtime/samples/store-invalidation-while-update-2/_config.js
index 6c2538e564..2465b7d444 100644
--- a/test/runtime/samples/store-invalidation-while-update-2/_config.js
+++ b/test/runtime/samples/store-invalidation-while-update-2/_config.js
@@ -5,6 +5,12 @@ export default {
click me
`,
+ ssrHtml: `
+
+ simple
+
+ click me
+ `,
async test({ assert, component, target, window }) {
const input = target.querySelector('input');
diff --git a/test/runtime/samples/store-unreferenced/_config.js b/test/runtime/samples/store-unreferenced/_config.js
index e15f202492..ce416bca5d 100644
--- a/test/runtime/samples/store-unreferenced/_config.js
+++ b/test/runtime/samples/store-unreferenced/_config.js
@@ -3,11 +3,13 @@ import { count } from './store.js';
export default {
html: 'count: 0
',
+ before_test() {
+ count.set(0);
+ },
+
async test({ assert, component, target }) {
await component.increment();
assert.htmlEqual(target.innerHTML, 'count: 1
');
-
- count.set(0);
}
};
diff --git a/test/runtime/samples/target-dom-detached/App.svelte b/test/runtime/samples/target-dom-detached/App.svelte
new file mode 100644
index 0000000000..251e480307
--- /dev/null
+++ b/test/runtime/samples/target-dom-detached/App.svelte
@@ -0,0 +1,11 @@
+
+
+Hello {name}
+
+
\ No newline at end of file
diff --git a/test/runtime/samples/target-dom-detached/_config.js b/test/runtime/samples/target-dom-detached/_config.js
new file mode 100644
index 0000000000..b63656530c
--- /dev/null
+++ b/test/runtime/samples/target-dom-detached/_config.js
@@ -0,0 +1,16 @@
+export default {
+ skip_if_ssr: true,
+ compileOptions: {
+ cssHash: () => 'svelte-xyz'
+ },
+ async test({ assert, component, target, window }) {
+ assert.htmlEqual(
+ window.document.head.innerHTML,
+ ''
+ );
+ assert.htmlEqual(
+ component.div.innerHTML,
+ 'Hello World
'
+ );
+ }
+};
diff --git a/test/runtime/samples/target-dom-detached/main.svelte b/test/runtime/samples/target-dom-detached/main.svelte
new file mode 100644
index 0000000000..42e7dffee9
--- /dev/null
+++ b/test/runtime/samples/target-dom-detached/main.svelte
@@ -0,0 +1,18 @@
+
diff --git a/test/runtime/samples/target-dom/App.svelte b/test/runtime/samples/target-dom/App.svelte
new file mode 100644
index 0000000000..251e480307
--- /dev/null
+++ b/test/runtime/samples/target-dom/App.svelte
@@ -0,0 +1,11 @@
+
+
+Hello {name}
+
+
\ No newline at end of file
diff --git a/test/runtime/samples/target-dom/_config.js b/test/runtime/samples/target-dom/_config.js
new file mode 100644
index 0000000000..b63656530c
--- /dev/null
+++ b/test/runtime/samples/target-dom/_config.js
@@ -0,0 +1,16 @@
+export default {
+ skip_if_ssr: true,
+ compileOptions: {
+ cssHash: () => 'svelte-xyz'
+ },
+ async test({ assert, component, target, window }) {
+ assert.htmlEqual(
+ window.document.head.innerHTML,
+ ''
+ );
+ assert.htmlEqual(
+ component.div.innerHTML,
+ 'Hello World
'
+ );
+ }
+};
diff --git a/test/runtime/samples/target-dom/main.svelte b/test/runtime/samples/target-dom/main.svelte
new file mode 100644
index 0000000000..68d2990552
--- /dev/null
+++ b/test/runtime/samples/target-dom/main.svelte
@@ -0,0 +1,18 @@
+
+
+
\ No newline at end of file
diff --git a/test/runtime/samples/target-shadow-dom/App.svelte b/test/runtime/samples/target-shadow-dom/App.svelte
new file mode 100644
index 0000000000..251e480307
--- /dev/null
+++ b/test/runtime/samples/target-shadow-dom/App.svelte
@@ -0,0 +1,11 @@
+
+
+Hello {name}
+
+
\ No newline at end of file
diff --git a/test/runtime/samples/target-shadow-dom/_config.js b/test/runtime/samples/target-shadow-dom/_config.js
new file mode 100644
index 0000000000..cec383afd0
--- /dev/null
+++ b/test/runtime/samples/target-shadow-dom/_config.js
@@ -0,0 +1,13 @@
+export default {
+ skip_if_ssr: true,
+ compileOptions: {
+ cssHash: () => 'svelte-xyz'
+ },
+ async test({ assert, component, target, window }) {
+ assert.htmlEqual(window.document.head.innerHTML, '');
+ assert.htmlEqual(component.div.shadowRoot.innerHTML, `
+
+ Hello World
+ `);
+ }
+};
diff --git a/test/runtime/samples/target-shadow-dom/main.svelte b/test/runtime/samples/target-shadow-dom/main.svelte
new file mode 100644
index 0000000000..cb47ad01f0
--- /dev/null
+++ b/test/runtime/samples/target-shadow-dom/main.svelte
@@ -0,0 +1,19 @@
+
+
+
\ No newline at end of file
diff --git a/test/runtime/samples/transition-css-in-out-in-with-param/_config.js b/test/runtime/samples/transition-css-in-out-in-with-param/_config.js
new file mode 100644
index 0000000000..c5dfb63225
--- /dev/null
+++ b/test/runtime/samples/transition-css-in-out-in-with-param/_config.js
@@ -0,0 +1,21 @@
+export default {
+ test({ assert, component, target, window, raf }) {
+ component.visible = true;
+ const div = target.querySelector('div');
+
+ // animation duration of `in` should be 10ms.
+ assert.equal(div.style.animation, '__svelte_1670736059_0 10ms linear 0ms 1 both');
+
+ // animation duration of `out` should be 5ms.
+ component.visible = false;
+ assert.equal(div.style.animation, '__svelte_1670736059_0 10ms linear 0ms 1 both, __svelte_1998461463_0 5ms linear 0ms 1 both');
+
+ // change param
+ raf.tick(1);
+ component.param = true;
+ component.visible = true;
+
+ // animation duration of `in` should be 20ms.
+ assert.equal(div.style.animation, '__svelte_722598827_0 20ms linear 0ms 1 both');
+ }
+};
diff --git a/test/runtime/samples/transition-css-in-out-in-with-param/main.svelte b/test/runtime/samples/transition-css-in-out-in-with-param/main.svelte
new file mode 100644
index 0000000000..616e2e0e8b
--- /dev/null
+++ b/test/runtime/samples/transition-css-in-out-in-with-param/main.svelte
@@ -0,0 +1,26 @@
+
+
+{#if visible}
+
+{/if}
\ No newline at end of file
diff --git a/test/runtime/samples/transition-css-in-out-in/_config.js b/test/runtime/samples/transition-css-in-out-in/_config.js
index cd7ae14ce8..6d93c0e8c3 100644
--- a/test/runtime/samples/transition-css-in-out-in/_config.js
+++ b/test/runtime/samples/transition-css-in-out-in/_config.js
@@ -15,6 +15,6 @@ export default {
component.visible = true;
// reset original styles
- assert.equal(div.style.animation, '__svelte_3809512021_1 100ms linear 0ms 1 both');
+ assert.equal(div.style.animation, '__svelte_3809512021_0 100ms linear 0ms 1 both');
}
};
diff --git a/test/runtime/samples/transition-js-slot-2/Nested.svelte b/test/runtime/samples/transition-js-slot-2/Nested.svelte
new file mode 100644
index 0000000000..4cd6a9b375
--- /dev/null
+++ b/test/runtime/samples/transition-js-slot-2/Nested.svelte
@@ -0,0 +1,18 @@
+
+
+{#if visible}
+
+
+
+{/if}
\ No newline at end of file
diff --git a/test/runtime/samples/transition-js-slot-2/_config.js b/test/runtime/samples/transition-js-slot-2/_config.js
new file mode 100644
index 0000000000..0f0cad5e41
--- /dev/null
+++ b/test/runtime/samples/transition-js-slot-2/_config.js
@@ -0,0 +1,24 @@
+// cancelled the transition halfway
+export default {
+ html: `
+ Foo
+ `,
+
+ async test({ assert, component, target, window, raf }) {
+ await component.hide();
+ const div = target.querySelector('div');
+
+ raf.tick(50);
+ assert.equal(div.foo, 0.5);
+
+ await component.show();
+
+ assert.htmlEqual(target.innerHTML, 'Bar
');
+
+ raf.tick(75);
+ assert.equal(div.foo, 0.75);
+
+ raf.tick(100);
+ assert.equal(div.foo, 1);
+ }
+};
diff --git a/test/runtime/samples/transition-js-slot-2/main.svelte b/test/runtime/samples/transition-js-slot-2/main.svelte
new file mode 100644
index 0000000000..2d45b5ca30
--- /dev/null
+++ b/test/runtime/samples/transition-js-slot-2/main.svelte
@@ -0,0 +1,18 @@
+
+
+
+ {name}
+
diff --git a/test/runtime/samples/transition-js-slot-3/Nested.svelte b/test/runtime/samples/transition-js-slot-3/Nested.svelte
new file mode 100644
index 0000000000..8a5b9ec2df
--- /dev/null
+++ b/test/runtime/samples/transition-js-slot-3/Nested.svelte
@@ -0,0 +1,27 @@
+
+
+{#if visible}
+
+
+
+{/if}
\ No newline at end of file
diff --git a/test/runtime/samples/transition-js-slot-3/_config.js b/test/runtime/samples/transition-js-slot-3/_config.js
new file mode 100644
index 0000000000..67cc0b46d2
--- /dev/null
+++ b/test/runtime/samples/transition-js-slot-3/_config.js
@@ -0,0 +1,23 @@
+export default {
+ html: `
+ Foo
+ `,
+
+ async test({ assert, component, target, window, raf }) {
+ await component.hide();
+ const div = target.querySelector('div');
+
+ raf.tick(50);
+ assert.equal(div.foo, 0.5);
+
+ await component.show();
+
+ assert.htmlEqual(target.innerHTML, 'Bar
');
+
+ raf.tick(75);
+ assert.equal(div.foo, 0.75);
+
+ raf.tick(100);
+ assert.equal(div.foo, 1);
+ }
+};
diff --git a/test/runtime/samples/transition-js-slot-3/main.svelte b/test/runtime/samples/transition-js-slot-3/main.svelte
new file mode 100644
index 0000000000..f10ad356e1
--- /dev/null
+++ b/test/runtime/samples/transition-js-slot-3/main.svelte
@@ -0,0 +1,16 @@
+
+
+
+ {data}
+
diff --git a/test/runtime/samples/transition-js-slot-4-cancelled/Nested.svelte b/test/runtime/samples/transition-js-slot-4-cancelled/Nested.svelte
new file mode 100644
index 0000000000..04eea750fd
--- /dev/null
+++ b/test/runtime/samples/transition-js-slot-4-cancelled/Nested.svelte
@@ -0,0 +1,19 @@
+
+
+{#if visible}
+
+
+
+{/if}
\ No newline at end of file
diff --git a/test/runtime/samples/transition-js-slot-4-cancelled/_config.js b/test/runtime/samples/transition-js-slot-4-cancelled/_config.js
new file mode 100644
index 0000000000..d6b7c31132
--- /dev/null
+++ b/test/runtime/samples/transition-js-slot-4-cancelled/_config.js
@@ -0,0 +1,35 @@
+// updated props in the middle of transitions
+// and cancelled the transition halfway
+export default {
+ html: `
+ outside Foo Foo Foo
+ inside Foo Foo Foo
+ `,
+ props: {
+ props: 'Foo'
+ },
+
+ async test({ assert, component, target, window, raf }) {
+ await component.hide();
+ const [, div] = target.querySelectorAll('div');
+
+ raf.tick(50);
+ assert.equal(div.foo, 0.5);
+
+ component.props = 'Bar';
+ assert.htmlEqual(target.innerHTML, `
+ outside Bar Bar Bar
+ inside Foo Foo Foo
+ `);
+
+ await component.show();
+
+ assert.htmlEqual(target.innerHTML, `
+ outside Bar Bar Bar
+ inside Bar Bar Bar
+ `);
+
+ raf.tick(100);
+ assert.equal(div.foo, 1);
+ }
+};
diff --git a/test/runtime/samples/transition-js-slot-4-cancelled/main.svelte b/test/runtime/samples/transition-js-slot-4-cancelled/main.svelte
new file mode 100644
index 0000000000..1003419244
--- /dev/null
+++ b/test/runtime/samples/transition-js-slot-4-cancelled/main.svelte
@@ -0,0 +1,22 @@
+
+
+outside {state} {props} {slotProps}
+
+ inside {state} {props} {slotProps}
+
diff --git a/test/runtime/samples/transition-js-slot-5-cancelled-overflow/Nested.svelte b/test/runtime/samples/transition-js-slot-5-cancelled-overflow/Nested.svelte
new file mode 100644
index 0000000000..10050b6a10
--- /dev/null
+++ b/test/runtime/samples/transition-js-slot-5-cancelled-overflow/Nested.svelte
@@ -0,0 +1,19 @@
+
+
+{#if visible}
+
+
+
+{/if}
diff --git a/test/runtime/samples/transition-js-slot-5-cancelled-overflow/_config.js b/test/runtime/samples/transition-js-slot-5-cancelled-overflow/_config.js
new file mode 100644
index 0000000000..aedc87f0b6
--- /dev/null
+++ b/test/runtime/samples/transition-js-slot-5-cancelled-overflow/_config.js
@@ -0,0 +1,40 @@
+// updated props in the middle of transitions
+// and cancelled the transition halfway
+// + spreaded props + overflow context
+
+export default {
+ html: `
+ outside Foo Foo Foo
+ inside Foo Foo Foo
+ 0
+ `,
+ props: {
+ props: 'Foo'
+ },
+
+ async test({ assert, component, target, window, raf }) {
+ await component.hide();
+ const [, div] = target.querySelectorAll('div');
+
+ raf.tick(50);
+ assert.equal(div.foo, 0.5);
+
+ component.props = 'Bar';
+ assert.htmlEqual(target.innerHTML, `
+ outside Bar Bar Bar
+ inside Foo Foo Foo
+ 0
+ `);
+
+ await component.show();
+
+ assert.htmlEqual(target.innerHTML, `
+ outside Bar Bar Bar
+ inside Bar Bar Bar
+ 0
+ `);
+
+ raf.tick(100);
+ assert.equal(div.foo, 1);
+ }
+};
diff --git a/test/runtime/samples/transition-js-slot-5-cancelled-overflow/main.svelte b/test/runtime/samples/transition-js-slot-5-cancelled-overflow/main.svelte
new file mode 100644
index 0000000000..9c46fd0521
--- /dev/null
+++ b/test/runtime/samples/transition-js-slot-5-cancelled-overflow/main.svelte
@@ -0,0 +1,27 @@
+
+
+outside {state} {props} {slotProps}
+
+
+ inside {state} {props} {slotProps}
+
+
+{a1+a2+a3+a4+a5+a6+a7+a8+a9+a10+a11+a12+a13+a14+a15+a16+a17+a18+a19+a20+a21+a22+a23+a24+a25+a26+a27+a28+a29+a30+a31+a32+a33}
\ No newline at end of file
diff --git a/test/runtime/samples/transition-js-slot-6-spread-cancelled/Nested.svelte b/test/runtime/samples/transition-js-slot-6-spread-cancelled/Nested.svelte
new file mode 100644
index 0000000000..b1853993d3
--- /dev/null
+++ b/test/runtime/samples/transition-js-slot-6-spread-cancelled/Nested.svelte
@@ -0,0 +1,19 @@
+
+
+{#if visible}
+
+
+
+{/if}
\ No newline at end of file
diff --git a/test/runtime/samples/transition-js-slot-6-spread-cancelled/Nested2.svelte b/test/runtime/samples/transition-js-slot-6-spread-cancelled/Nested2.svelte
new file mode 100644
index 0000000000..52f89858a0
--- /dev/null
+++ b/test/runtime/samples/transition-js-slot-6-spread-cancelled/Nested2.svelte
@@ -0,0 +1,19 @@
+
+
+{#if visible}
+
+
+
+{/if}
\ No newline at end of file
diff --git a/test/runtime/samples/transition-js-slot-6-spread-cancelled/_config.js b/test/runtime/samples/transition-js-slot-6-spread-cancelled/_config.js
new file mode 100644
index 0000000000..1d42c9cf71
--- /dev/null
+++ b/test/runtime/samples/transition-js-slot-6-spread-cancelled/_config.js
@@ -0,0 +1,40 @@
+// updated props in the middle of transitions
+// and cancelled the transition halfway
+// with spreaded props
+
+export default {
+ html: `
+ outside Foo Foo Foo
+ inside Foo Foo Foo
+ inside Foo Foo XXX
+ `,
+ props: {
+ props: 'Foo'
+ },
+
+ async test({ assert, component, target, window, raf }) {
+ await component.hide();
+ const [, div] = target.querySelectorAll('div');
+
+ raf.tick(50);
+ assert.equal(div.foo, 0.5);
+
+ component.props = 'Bar';
+ assert.htmlEqual(target.innerHTML, `
+ outside Bar Bar Bar
+ inside Foo Foo Foo
+ inside Foo Foo XXX
+ `);
+
+ await component.show();
+
+ assert.htmlEqual(target.innerHTML, `
+ outside Bar Bar Bar
+ inside Bar Bar Bar
+ inside Bar Bar XXX
+ `);
+
+ raf.tick(100);
+ assert.equal(div.foo, 1);
+ }
+};
diff --git a/test/runtime/samples/transition-js-slot-6-spread-cancelled/main.svelte b/test/runtime/samples/transition-js-slot-6-spread-cancelled/main.svelte
new file mode 100644
index 0000000000..5dd8ce348e
--- /dev/null
+++ b/test/runtime/samples/transition-js-slot-6-spread-cancelled/main.svelte
@@ -0,0 +1,26 @@
+
+
+outside {state} {props} {slotProps.slotProps}
+
+ inside {state} {props} {slotProps}
+
+
+ inside {state} {props} {slotProps}
+
diff --git a/test/runtime/samples/transition-js-slot-7-spread-cancelled-overflow/Nested.svelte b/test/runtime/samples/transition-js-slot-7-spread-cancelled-overflow/Nested.svelte
new file mode 100644
index 0000000000..b01200fd9f
--- /dev/null
+++ b/test/runtime/samples/transition-js-slot-7-spread-cancelled-overflow/Nested.svelte
@@ -0,0 +1,19 @@
+
+
+{#if visible}
+
+
+
+{/if}
diff --git a/test/runtime/samples/transition-js-slot-7-spread-cancelled-overflow/_config.js b/test/runtime/samples/transition-js-slot-7-spread-cancelled-overflow/_config.js
new file mode 100644
index 0000000000..aedc87f0b6
--- /dev/null
+++ b/test/runtime/samples/transition-js-slot-7-spread-cancelled-overflow/_config.js
@@ -0,0 +1,40 @@
+// updated props in the middle of transitions
+// and cancelled the transition halfway
+// + spreaded props + overflow context
+
+export default {
+ html: `
+ outside Foo Foo Foo
+ inside Foo Foo Foo
+ 0
+ `,
+ props: {
+ props: 'Foo'
+ },
+
+ async test({ assert, component, target, window, raf }) {
+ await component.hide();
+ const [, div] = target.querySelectorAll('div');
+
+ raf.tick(50);
+ assert.equal(div.foo, 0.5);
+
+ component.props = 'Bar';
+ assert.htmlEqual(target.innerHTML, `
+ outside Bar Bar Bar
+ inside Foo Foo Foo
+ 0
+ `);
+
+ await component.show();
+
+ assert.htmlEqual(target.innerHTML, `
+ outside Bar Bar Bar
+ inside Bar Bar Bar
+ 0
+ `);
+
+ raf.tick(100);
+ assert.equal(div.foo, 1);
+ }
+};
diff --git a/test/runtime/samples/transition-js-slot-7-spread-cancelled-overflow/main.svelte b/test/runtime/samples/transition-js-slot-7-spread-cancelled-overflow/main.svelte
new file mode 100644
index 0000000000..000b29ee7f
--- /dev/null
+++ b/test/runtime/samples/transition-js-slot-7-spread-cancelled-overflow/main.svelte
@@ -0,0 +1,27 @@
+
+
+outside {state} {props} {slotProps.slotProps}
+
+
+ inside {state} {props} {slotProps}
+
+
+{a1+a2+a3+a4+a5+a6+a7+a8+a9+a10+a11+a12+a13+a14+a15+a16+a17+a18+a19+a20+a21+a22+a23+a24+a25+a26+a27+a28+a29+a30+a31+a32+a33}
\ No newline at end of file
diff --git a/test/runtime/samples/transition-js-slot-fallback/_config.js b/test/runtime/samples/transition-js-slot-fallback/_config.js
new file mode 100644
index 0000000000..67cc0b46d2
--- /dev/null
+++ b/test/runtime/samples/transition-js-slot-fallback/_config.js
@@ -0,0 +1,23 @@
+export default {
+ html: `
+ Foo
+ `,
+
+ async test({ assert, component, target, window, raf }) {
+ await component.hide();
+ const div = target.querySelector('div');
+
+ raf.tick(50);
+ assert.equal(div.foo, 0.5);
+
+ await component.show();
+
+ assert.htmlEqual(target.innerHTML, 'Bar
');
+
+ raf.tick(75);
+ assert.equal(div.foo, 0.75);
+
+ raf.tick(100);
+ assert.equal(div.foo, 1);
+ }
+};
diff --git a/test/runtime/samples/transition-js-slot-fallback/main.svelte b/test/runtime/samples/transition-js-slot-fallback/main.svelte
new file mode 100644
index 0000000000..3392792043
--- /dev/null
+++ b/test/runtime/samples/transition-js-slot-fallback/main.svelte
@@ -0,0 +1,27 @@
+
+
+{#if visible}
+
+ {data}
+
+{/if}
\ No newline at end of file
diff --git a/test/server-side-rendering/index.ts b/test/server-side-rendering/index.ts
index e81058181d..cc3f20d637 100644
--- a/test/server-side-rendering/index.ts
+++ b/test/server-side-rendering/index.ts
@@ -81,7 +81,9 @@ describe('ssr', () => {
if (css.code) fs.writeFileSync(`${dir}/_actual.css`, css.code);
try {
- assert.htmlEqual(html, expectedHtml);
+ (compileOptions.preserveComments
+ ? assert.htmlEqualWithComments
+ : assert.htmlEqual)(html, expectedHtml);
} catch (error) {
if (shouldUpdateExpected()) {
fs.writeFileSync(`${dir}/_expected.html`, html);
@@ -135,100 +137,105 @@ describe('ssr', () => {
});
// duplicate client-side tests, as far as possible
- fs.readdirSync('test/runtime/samples').forEach(dir => {
- if (dir[0] === '.') return;
+ runRuntimeSamples('runtime');
+ runRuntimeSamples('runtime-puppeteer');
- const config = loadConfig(`./runtime/samples/${dir}/_config.js`);
- const solo = config.solo || /\.solo/.test(dir);
+ function runRuntimeSamples(suite) {
+ fs.readdirSync(`test/${suite}/samples`).forEach(dir => {
+ if (dir[0] === '.') return;
- if (solo && process.env.CI) {
- throw new Error('Forgot to remove `solo: true` from test');
- }
+ const config = loadConfig(`./${suite}/samples/${dir}/_config.js`);
+ const solo = config.solo || /\.solo/.test(dir);
- if (config.skip_if_ssr) return;
+ if (solo && process.env.CI) {
+ throw new Error('Forgot to remove `solo: true` from test');
+ }
- (config.skip ? it.skip : solo ? it.only : it)(dir, () => {
- const cwd = path.resolve('test/runtime/samples', dir);
+ if (config.skip_if_ssr) return;
- cleanRequireCache();
+ (config.skip ? it.skip : solo ? it.only : it)(dir, () => {
+ const cwd = path.resolve(`test/${suite}/samples`, dir);
- delete global.window;
+ cleanRequireCache();
- const compileOptions = {
- sveltePath,
- ...config.compileOptions,
- generate: 'ssr',
- format: 'cjs'
- };
-
- require('../../register')(compileOptions);
+ delete global.window;
- glob('**/*.svelte', { cwd }).forEach(file => {
- if (file[0] === '_') return;
+ const compileOptions = {
+ sveltePath,
+ ...config.compileOptions,
+ generate: 'ssr',
+ format: 'cjs'
+ };
- const dir = `${cwd}/_output/ssr`;
- const out = `${dir}/${file.replace(/\.svelte$/, '.js')}`;
+ require('../../register')(compileOptions);
- if (fs.existsSync(out)) {
- fs.unlinkSync(out);
- }
+ glob('**/*.svelte', { cwd }).forEach(file => {
+ if (file[0] === '_') return;
- mkdirp(dir);
+ const dir = `${cwd}/_output/ssr`;
+ const out = `${dir}/${file.replace(/\.svelte$/, '.js')}`;
- try {
- const { js } = compile(
- fs.readFileSync(`${cwd}/${file}`, 'utf-8'),
- {
- ...compileOptions,
- filename: file
- }
- );
+ if (fs.existsSync(out)) {
+ fs.unlinkSync(out);
+ }
- fs.writeFileSync(out, js.code);
- } catch (err) {
- // do nothing
- }
- });
+ mkdirp(dir);
- try {
- if (config.before_test) config.before_test();
+ try {
+ const { js } = compile(
+ fs.readFileSync(`${cwd}/${file}`, 'utf-8'),
+ {
+ ...compileOptions,
+ filename: file
+ }
+ );
- const Component = require(`../runtime/samples/${dir}/main.svelte`).default;
- const { html } = Component.render(config.props, {
- store: (config.store !== true) && config.store
+ fs.writeFileSync(out, js.code);
+ } catch (err) {
+ // do nothing
+ }
});
- if (config.ssrHtml) {
- assert.htmlEqual(html, config.ssrHtml);
- } else if (config.html) {
- assert.htmlEqual(html, config.html);
- }
+ try {
+ if (config.before_test) config.before_test();
- if (config.test_ssr) {
- config.test_ssr({ assert });
- }
+ const Component = require(`../${suite}/samples/${dir}/main.svelte`).default;
+ const { html } = Component.render(config.props, {
+ store: (config.store !== true) && config.store
+ });
- if (config.after_test) config.after_test();
+ if (config.ssrHtml) {
+ assert.htmlEqual(html, config.ssrHtml);
+ } else if (config.html) {
+ assert.htmlEqual(html, config.html);
+ }
- if (config.show) {
- showOutput(cwd, compileOptions);
- }
- } catch (err) {
- err.stack += `\n\ncmd-click: ${path.relative(process.cwd(), cwd)}/main.svelte`;
+ if (config.test_ssr) {
+ config.test_ssr({ assert });
+ }
+
+ if (config.after_test) config.after_test();
- if (config.error) {
- if (typeof config.error === 'function') {
- config.error(assert, err);
+ if (config.show) {
+ showOutput(cwd, compileOptions);
+ }
+ } catch (err) {
+ err.stack += `\n\ncmd-click: ${path.relative(process.cwd(), cwd)}/main.svelte`;
+
+ if (config.error) {
+ if (typeof config.error === 'function') {
+ config.error(assert, err);
+ } else {
+ assert.equal(err.message, config.error);
+ }
} else {
- assert.equal(err.message, config.error);
+ showOutput(cwd, compileOptions);
+ throw err;
}
- } else {
- showOutput(cwd, compileOptions);
- throw err;
+ } finally {
+ set_current_component(null);
}
- } finally {
- set_current_component(null);
- }
+ });
});
- });
+ }
});
diff --git a/test/server-side-rendering/samples/attribute-escape-quotes-spread-2/_expected.html b/test/server-side-rendering/samples/attribute-escape-quotes-spread-2/_expected.html
new file mode 100644
index 0000000000..b3970f88ba
--- /dev/null
+++ b/test/server-side-rendering/samples/attribute-escape-quotes-spread-2/_expected.html
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/test/server-side-rendering/samples/attribute-escape-quotes-spread-2/main.svelte b/test/server-side-rendering/samples/attribute-escape-quotes-spread-2/main.svelte
new file mode 100644
index 0000000000..22f5526f3e
--- /dev/null
+++ b/test/server-side-rendering/samples/attribute-escape-quotes-spread-2/main.svelte
@@ -0,0 +1,10 @@
+
+
+
\ No newline at end of file
diff --git a/test/server-side-rendering/samples/attribute-escaped-quotes-spread/_expected.html b/test/server-side-rendering/samples/attribute-escaped-quotes-spread/_expected.html
index bc31ce8bc3..b3970f88ba 100644
--- a/test/server-side-rendering/samples/attribute-escaped-quotes-spread/_expected.html
+++ b/test/server-side-rendering/samples/attribute-escaped-quotes-spread/_expected.html
@@ -1,4 +1,5 @@
\ No newline at end of file
diff --git a/test/server-side-rendering/samples/attribute-escaped-quotes-spread/main.svelte b/test/server-side-rendering/samples/attribute-escaped-quotes-spread/main.svelte
index ff6c15981d..66047eb09a 100644
--- a/test/server-side-rendering/samples/attribute-escaped-quotes-spread/main.svelte
+++ b/test/server-side-rendering/samples/attribute-escaped-quotes-spread/main.svelte
@@ -2,7 +2,8 @@
export let props = {
foo: '">
diff --git a/test/server-side-rendering/samples/attribute-spread-with-null/_expected.html b/test/server-side-rendering/samples/attribute-spread-with-null/_expected.html
new file mode 100644
index 0000000000..281c6866c3
--- /dev/null
+++ b/test/server-side-rendering/samples/attribute-spread-with-null/_expected.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/server-side-rendering/samples/attribute-spread-with-null/main.svelte b/test/server-side-rendering/samples/attribute-spread-with-null/main.svelte
new file mode 100644
index 0000000000..adfa9e6919
--- /dev/null
+++ b/test/server-side-rendering/samples/attribute-spread-with-null/main.svelte
@@ -0,0 +1,5 @@
+
+
+
\ No newline at end of file
diff --git a/test/server-side-rendering/samples/bindings-empty-string/_expected.html b/test/server-side-rendering/samples/bindings-empty-string/_expected.html
new file mode 100644
index 0000000000..8344e198fa
--- /dev/null
+++ b/test/server-side-rendering/samples/bindings-empty-string/_expected.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/server-side-rendering/samples/bindings-empty-string/main.svelte b/test/server-side-rendering/samples/bindings-empty-string/main.svelte
new file mode 100644
index 0000000000..7257d0f85e
--- /dev/null
+++ b/test/server-side-rendering/samples/bindings-empty-string/main.svelte
@@ -0,0 +1,5 @@
+
+
+
\ No newline at end of file
diff --git a/test/server-side-rendering/samples/bindings-group/_expected.html b/test/server-side-rendering/samples/bindings-group/_expected.html
new file mode 100644
index 0000000000..06d4242b07
--- /dev/null
+++ b/test/server-side-rendering/samples/bindings-group/_expected.html
@@ -0,0 +1,5 @@
+Cheese
+
+
+
+
diff --git a/test/server-side-rendering/samples/bindings-group/main.svelte b/test/server-side-rendering/samples/bindings-group/main.svelte
new file mode 100644
index 0000000000..a88d3fb200
--- /dev/null
+++ b/test/server-side-rendering/samples/bindings-group/main.svelte
@@ -0,0 +1,12 @@
+
+
+{fillings.toString()}
+
+
+
+
+
+
diff --git a/test/server-side-rendering/samples/bindings-zero/_expected.html b/test/server-side-rendering/samples/bindings-zero/_expected.html
new file mode 100644
index 0000000000..d634c4b80f
--- /dev/null
+++ b/test/server-side-rendering/samples/bindings-zero/_expected.html
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/test/server-side-rendering/samples/bindings-zero/main.svelte b/test/server-side-rendering/samples/bindings-zero/main.svelte
new file mode 100644
index 0000000000..5689bb8d9c
--- /dev/null
+++ b/test/server-side-rendering/samples/bindings-zero/main.svelte
@@ -0,0 +1,6 @@
+
+
+
+
\ No newline at end of file
diff --git a/test/server-side-rendering/samples/comment-preserve/_config.js b/test/server-side-rendering/samples/comment-preserve/_config.js
new file mode 100644
index 0000000000..f440f86013
--- /dev/null
+++ b/test/server-side-rendering/samples/comment-preserve/_config.js
@@ -0,0 +1,5 @@
+export default {
+ compileOptions: {
+ preserveComments: true
+ }
+};
diff --git a/test/server-side-rendering/samples/comment-preserve/_expected.html b/test/server-side-rendering/samples/comment-preserve/_expected.html
new file mode 100644
index 0000000000..8ecd344816
--- /dev/null
+++ b/test/server-side-rendering/samples/comment-preserve/_expected.html
@@ -0,0 +1,3 @@
+before
+
+after
diff --git a/test/server-side-rendering/samples/comment-preserve/main.svelte b/test/server-side-rendering/samples/comment-preserve/main.svelte
new file mode 100644
index 0000000000..8ecd344816
--- /dev/null
+++ b/test/server-side-rendering/samples/comment-preserve/main.svelte
@@ -0,0 +1,3 @@
+before
+
+after
diff --git a/test/server-side-rendering/samples/constructor-prefer-passed-context/ChildComponent.svelte b/test/server-side-rendering/samples/constructor-prefer-passed-context/ChildComponent.svelte
new file mode 100644
index 0000000000..af77418a1f
--- /dev/null
+++ b/test/server-side-rendering/samples/constructor-prefer-passed-context/ChildComponent.svelte
@@ -0,0 +1,6 @@
+
+
+Value in child component: {value}
diff --git a/test/server-side-rendering/samples/constructor-prefer-passed-context/_expected.html b/test/server-side-rendering/samples/constructor-prefer-passed-context/_expected.html
new file mode 100644
index 0000000000..d9a67c64e9
--- /dev/null
+++ b/test/server-side-rendering/samples/constructor-prefer-passed-context/_expected.html
@@ -0,0 +1 @@
+Value in child component: undefined
diff --git a/test/server-side-rendering/samples/constructor-prefer-passed-context/main.svelte b/test/server-side-rendering/samples/constructor-prefer-passed-context/main.svelte
new file mode 100644
index 0000000000..eaf89dd813
--- /dev/null
+++ b/test/server-side-rendering/samples/constructor-prefer-passed-context/main.svelte
@@ -0,0 +1,10 @@
+
+
+{@html content}
diff --git a/test/server-side-rendering/samples/spread-attributes-white-space/_expected.html b/test/server-side-rendering/samples/spread-attributes-white-space/_expected.html
index a73bb17e8c..24473a7b12 100644
--- a/test/server-side-rendering/samples/spread-attributes-white-space/_expected.html
+++ b/test/server-side-rendering/samples/spread-attributes-white-space/_expected.html
@@ -2,7 +2,4 @@
bar
">
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/test/sourcemaps/samples/attached-sourcemap/_config.js b/test/sourcemaps/samples/attached-sourcemap/_config.js
index 6d9786f6b0..86498caeba 100644
--- a/test/sourcemaps/samples/attached-sourcemap/_config.js
+++ b/test/sourcemaps/samples/attached-sourcemap/_config.js
@@ -14,7 +14,7 @@ function get_processor(tag_name, search, replace) {
// change line + column
const indent = Array.from({ length: indent_size }).join(' ');
- ms.prependLeft(idx, '\n'+indent);
+ ms.prependLeft(idx, '\n' + indent);
const map_opts = { source: filename, hires: true, includeContent: false };
const map = ms.generateMap(map_opts);
diff --git a/test/sourcemaps/samples/attached-sourcemap/test.js b/test/sourcemaps/samples/attached-sourcemap/test.js
index c5b4d7989d..ecb88ab11d 100644
--- a/test/sourcemaps/samples/attached-sourcemap/test.js
+++ b/test/sourcemaps/samples/attached-sourcemap/test.js
@@ -7,8 +7,8 @@ export function test({ input, css, js }) {
let out_obj, loc_output, actual, loc_input, expected;
out_obj = js;
- // we need the second occurence of 'done_replace_script_2' in output.js
- // the first occurence is mapped back to markup '{done_replace_script_2}'
+ // we need the second occurrence of 'done_replace_script_2' in output.js
+ // the first occurrence is mapped back to markup '{done_replace_script_2}'
loc_output = out_obj.locate_1('done_replace_script_2');
loc_output = out_obj.locate_1('done_replace_script_2', loc_output.character + 1);
actual = out_obj.mapConsumer.originalPositionFor(loc_output);
diff --git a/test/sourcemaps/samples/compile-option-dev/test.js b/test/sourcemaps/samples/compile-option-dev/test.js
index bf240a5a89..f169ab8832 100644
--- a/test/sourcemaps/samples/compile-option-dev/test.js
+++ b/test/sourcemaps/samples/compile-option-dev/test.js
@@ -4,8 +4,8 @@ const b64dec = s => Buffer.from(s, 'base64').toString();
export async function test({ assert, css, js }) {
- // We check that the css source map embedded in the js is accurate
- const match = js.code.match(/\tstyle\.textContent = "(.*?)(?:\\n\/\*# sourceMappingURL=data:(.*?);charset=(.*?);base64,(.*?) \*\/)?";\n/);
+ // We check that the css source map embedded in the js is accurate
+ const match = js.code.match(/\tappend_styles\(target, "svelte-.{6}", "(.*?)(?:\\n\/\*# sourceMappingURL=data:(.*?);charset=(.*?);base64,(.*?) \*\/)?"\);\n/);
assert.notEqual(match, null);
const [mimeType, encoding, cssMapBase64] = match.slice(2);
diff --git a/test/sourcemaps/samples/decoded-sourcemap/_config.js b/test/sourcemaps/samples/decoded-sourcemap/_config.js
index dd4eee9461..a0b2c82692 100644
--- a/test/sourcemaps/samples/decoded-sourcemap/_config.js
+++ b/test/sourcemaps/samples/decoded-sourcemap/_config.js
@@ -3,7 +3,7 @@ import { magic_string_preprocessor_result, magic_string_replace_all } from '../.
export default {
- js_map_sources: [], // test component has no scripts
+ js_map_sources: ['input.svelte'],
preprocess: {
markup: ({ content, filename }) => {
diff --git a/test/sourcemaps/samples/external/_config.js b/test/sourcemaps/samples/external/_config.js
index 400def20ac..07a0903482 100644
--- a/test/sourcemaps/samples/external/_config.js
+++ b/test/sourcemaps/samples/external/_config.js
@@ -10,7 +10,7 @@ export const STYLES = '.awesome { color: orange; }\n';
export default {
css_map_sources: ['common.scss', 'styles.scss'],
- js_map_sources: [],
+ js_map_sources: ['input.svelte'],
preprocess: [
{
style: () => {
diff --git a/test/sourcemaps/samples/markup/input.svelte b/test/sourcemaps/samples/markup/input.svelte
new file mode 100644
index 0000000000..d5baaac693
--- /dev/null
+++ b/test/sourcemaps/samples/markup/input.svelte
@@ -0,0 +1,2 @@
+decoded-sourcemap
+replace me
\ No newline at end of file
diff --git a/test/sourcemaps/samples/markup/test.js b/test/sourcemaps/samples/markup/test.js
new file mode 100644
index 0000000000..2c6abfdf41
--- /dev/null
+++ b/test/sourcemaps/samples/markup/test.js
@@ -0,0 +1,34 @@
+export function test({ assert, input, js }) {
+ let expected;
+
+ let start;
+ let actual;
+
+ start = js.locate('insert(target, h1');
+ expected = input.locate(' {
diff --git a/test/sourcemaps/samples/sourcemap-basename-without-outputname/_config.js b/test/sourcemaps/samples/sourcemap-basename-without-outputname/_config.js
new file mode 100644
index 0000000000..15c346bfb9
--- /dev/null
+++ b/test/sourcemaps/samples/sourcemap-basename-without-outputname/_config.js
@@ -0,0 +1,33 @@
+
+import {magic_string_bundle} from '../../helpers';
+
+export const component_filepath = 'src/some/deep/path/input.svelte';
+export const component_file_basename = 'input.svelte';
+export const css_file_basename = 'input.css';
+
+const input_css = ' h1 {color: blue;}';
+
+export default {
+ preprocess: [
+ {
+ style: ({ content, filename }) => {
+ const style_to_add = `/* Filename from preprocess: ${filename} */` + input_css;
+ return magic_string_bundle([
+ { code: content, filename: component_file_basename },
+ { code: style_to_add, filename: css_file_basename }
+ ],component_filepath);
+ }
+ }
+ ],
+ js_map_sources: [component_file_basename],
+ css_map_sources: [css_file_basename,component_file_basename],
+ options: {
+ filename: component_filepath
+ },
+ compile_options: {
+ filename: component_filepath,
+ // ../../index.ts initializes output filenames, reset to undefined for this test
+ outputFilename: undefined,
+ cssOutputFilename: undefined
+ }
+};
diff --git a/test/sourcemaps/samples/sourcemap-basename-without-outputname/input.svelte b/test/sourcemaps/samples/sourcemap-basename-without-outputname/input.svelte
new file mode 100644
index 0000000000..189f28c390
--- /dev/null
+++ b/test/sourcemaps/samples/sourcemap-basename-without-outputname/input.svelte
@@ -0,0 +1,2 @@
+sourcemap-basename-without-outputname
+
diff --git a/test/sourcemaps/samples/sourcemap-basename-without-outputname/test.js b/test/sourcemaps/samples/sourcemap-basename-without-outputname/test.js
new file mode 100644
index 0000000000..c5747713a7
--- /dev/null
+++ b/test/sourcemaps/samples/sourcemap-basename-without-outputname/test.js
@@ -0,0 +1,3 @@
+// no additional test needed, _config.js values and the js.map.sources assertion in ../../index.ts cover it
+export function test() {}
+
diff --git a/test/sourcemaps/samples/sourcemap-basename/_config.js b/test/sourcemaps/samples/sourcemap-basename/_config.js
index 33146af7e7..7692b7a6d9 100644
--- a/test/sourcemaps/samples/sourcemap-basename/_config.js
+++ b/test/sourcemaps/samples/sourcemap-basename/_config.js
@@ -15,7 +15,7 @@ span {
export default {
css_map_sources: [external_relative_filename],
- js_map_sources: [],
+ js_map_sources: ['input.svelte'],
preprocess: [
{
style: ({ content, filename }) => {
diff --git a/test/sourcemaps/samples/sourcemap-offsets/_config.js b/test/sourcemaps/samples/sourcemap-offsets/_config.js
index 392fb68a43..bbc24c3225 100644
--- a/test/sourcemaps/samples/sourcemap-offsets/_config.js
+++ b/test/sourcemaps/samples/sourcemap-offsets/_config.js
@@ -3,7 +3,7 @@ import { magic_string_bundle } from '../../helpers';
export const EXTERNAL = 'span { --external-var: 1px; }';
export default {
- js_map_sources: [],
+ js_map_sources: ['input.svelte'],
css_map_sources: ['input.svelte', 'external.css'],
preprocess: [
{
diff --git a/test/store/index.js b/test/store/index.ts
similarity index 90%
rename from test/store/index.js
rename to test/store/index.ts
index 2af4a6f35d..b6fc5940e1 100644
--- a/test/store/index.js
+++ b/test/store/index.ts
@@ -22,6 +22,19 @@ describe('store', () => {
assert.deepEqual(values, [0, 1, 2]);
});
+ it('creates an undefined writable store', () => {
+ const store = writable();
+ const values = [];
+
+ const unsubscribe = store.subscribe(value => {
+ values.push(value);
+ });
+
+ unsubscribe();
+
+ assert.deepEqual(values, [undefined]);
+ });
+
it('calls provided subscribe handler', () => {
let called = 0;
@@ -114,6 +127,32 @@ describe('store', () => {
assert.deepEqual(values, [0, 1, 2]);
});
+
+ it('creates an undefined readable store', () => {
+ const store = readable();
+ const values = [];
+
+ const unsubscribe = store.subscribe(value => {
+ values.push(value);
+ });
+
+ unsubscribe();
+
+ assert.deepEqual(values, [undefined]);
+ });
+
+ it('creates a readable store without updater', () => {
+ const store = readable(100);
+ const values = [];
+
+ const unsubscribe = store.subscribe(value => {
+ values.push(value);
+ });
+
+ unsubscribe();
+
+ assert.deepEqual(values, [100]);
+ });
});
const fake_observable = {
diff --git a/test/validator/samples/a11y-anchor-has-content/input.svelte b/test/validator/samples/a11y-anchor-has-content/input.svelte
index ca81f90ae8..e246a1e593 100644
--- a/test/validator/samples/a11y-anchor-has-content/input.svelte
+++ b/test/validator/samples/a11y-anchor-has-content/input.svelte
@@ -1 +1,2 @@
-
\ No newline at end of file
+
+bar
diff --git a/test/validator/samples/a11y-media-has-caption/input.svelte b/test/validator/samples/a11y-media-has-caption/input.svelte
index 105269cddb..6d98fd3734 100644
--- a/test/validator/samples/a11y-media-has-caption/input.svelte
+++ b/test/validator/samples/a11y-media-has-caption/input.svelte
@@ -1,4 +1,4 @@
-
+
diff --git a/test/validator/samples/a11y-media-has-caption/warnings.json b/test/validator/samples/a11y-media-has-caption/warnings.json
index a8c894b1d4..72c2caae53 100644
--- a/test/validator/samples/a11y-media-has-caption/warnings.json
+++ b/test/validator/samples/a11y-media-has-caption/warnings.json
@@ -6,7 +6,7 @@
"column": 15,
"line": 2
},
- "message": "A11y: Media elements must have a ",
+ "message": "A11y: elements must have a ",
"pos": 40,
"start": {
"character": 40,
@@ -21,7 +21,7 @@
"column": 24,
"line": 3
},
- "message": "A11y: Media elements must have a ",
+ "message": "A11y: elements must have a ",
"pos": 56,
"start": {
"character": 56,
diff --git a/test/validator/samples/a11y-mouse-events-have-key-events/input.svelte b/test/validator/samples/a11y-mouse-events-have-key-events/input.svelte
new file mode 100644
index 0000000000..22de04f38a
--- /dev/null
+++ b/test/validator/samples/a11y-mouse-events-have-key-events/input.svelte
@@ -0,0 +1,15 @@
+
+
+ void 0} />
+
void 0} on:focus={() => void 0} />
+
void 0} {...otherProps} />
+
void 0} />
+
void 0} on:blur={() => void 0} />
+
void 0} {...otherProps} />
diff --git a/test/validator/samples/a11y-mouse-events-have-key-events/warnings.json b/test/validator/samples/a11y-mouse-events-have-key-events/warnings.json
new file mode 100644
index 0000000000..b3fe15feee
--- /dev/null
+++ b/test/validator/samples/a11y-mouse-events-have-key-events/warnings.json
@@ -0,0 +1,62 @@
+[
+ {
+ "code": "a11y-mouse-events-have-key-events",
+ "end": {
+ "character": 272,
+ "column": 35,
+ "line": 10
+ },
+ "message": "A11y: on:mouseover must be accompanied by on:focus",
+ "pos": 237,
+ "start": {
+ "character": 237,
+ "column": 0,
+ "line": 10
+ }
+ },
+ {
+ "code": "a11y-mouse-events-have-key-events",
+ "end": {
+ "character": 384,
+ "column": 51,
+ "line": 12
+ },
+ "message": "A11y: on:mouseover must be accompanied by on:focus",
+ "pos": 333,
+ "start": {
+ "character": 333,
+ "column": 0,
+ "line": 12
+ }
+ },
+ {
+ "code": "a11y-mouse-events-have-key-events",
+ "end": {
+ "character": 419,
+ "column": 34,
+ "line": 13
+ },
+ "message": "A11y: on:mouseout must be accompanied by on:blur",
+ "pos": 385,
+ "start": {
+ "character": 385,
+ "column": 0,
+ "line": 13
+ }
+ },
+ {
+ "code": "a11y-mouse-events-have-key-events",
+ "end": {
+ "character": 528,
+ "column": 50,
+ "line": 15
+ },
+ "message": "A11y: on:mouseout must be accompanied by on:blur",
+ "pos": 478,
+ "start": {
+ "character": 478,
+ "column": 0,
+ "line": 15
+ }
+ }
+]
\ No newline at end of file
diff --git a/test/validator/samples/a11y-no-onchange/input.svelte b/test/validator/samples/a11y-no-onchange/input.svelte
deleted file mode 100644
index af2041f406..0000000000
--- a/test/validator/samples/a11y-no-onchange/input.svelte
+++ /dev/null
@@ -1,16 +0,0 @@
-
{}}>
- foo
- bar
-
-
{}} on:blur={e => {}}>
- foo
- bar
-
-
- {}}>foo
- bar
-
-
- {}} on:blur={e => {}}>foo
- bar
-
\ No newline at end of file
diff --git a/test/validator/samples/a11y-no-onchange/warnings.json b/test/validator/samples/a11y-no-onchange/warnings.json
deleted file mode 100644
index 461f546c0b..0000000000
--- a/test/validator/samples/a11y-no-onchange/warnings.json
+++ /dev/null
@@ -1,32 +0,0 @@
-[
- {
- "code": "a11y-no-onchange",
- "end": {
- "character": 88,
- "column": 9,
- "line": 4
- },
- "message": "A11y: on:blur must be used instead of on:change, unless absolutely necessary and it causes no negative consequences for keyboard only or screen reader users.",
- "pos": 0,
- "start": {
- "character": 0,
- "column": 0,
- "line": 1
- }
- },
- {
- "code": "a11y-no-onchange",
- "end": {
- "character": 249,
- "column": 44,
- "line": 10
- },
- "message": "A11y: on:blur must be used instead of on:change, unless absolutely necessary and it causes no negative consequences for keyboard only or screen reader users.",
- "pos": 209,
- "start": {
- "character": 209,
- "column": 4,
- "line": 10
- }
- }
-]
diff --git a/test/validator/samples/css-invalid-global-placement-2/errors.json b/test/validator/samples/css-invalid-global-placement-2/errors.json
new file mode 100644
index 0000000000..4594469cc2
--- /dev/null
+++ b/test/validator/samples/css-invalid-global-placement-2/errors.json
@@ -0,0 +1,15 @@
+[{
+ "code": "css-invalid-global",
+ "message": ":global(...) can be at the start or end of a selector sequence, but not in the middle",
+ "start": {
+ "line": 2,
+ "column": 6,
+ "character": 14
+ },
+ "end": {
+ "line": 2,
+ "column": 19,
+ "character": 27
+ },
+ "pos": 14
+}]
diff --git a/test/validator/samples/css-invalid-global-placement-2/input.svelte b/test/validator/samples/css-invalid-global-placement-2/input.svelte
new file mode 100644
index 0000000000..75bd7b66e1
--- /dev/null
+++ b/test/validator/samples/css-invalid-global-placement-2/input.svelte
@@ -0,0 +1,5 @@
+
diff --git a/test/validator/samples/css-invalid-global-placement-3/errors.json b/test/validator/samples/css-invalid-global-placement-3/errors.json
new file mode 100644
index 0000000000..dc9d605c2c
--- /dev/null
+++ b/test/validator/samples/css-invalid-global-placement-3/errors.json
@@ -0,0 +1,15 @@
+[{
+ "code": "css-invalid-global",
+ "message": ":global(...) can be at the start or end of a selector sequence, but not in the middle",
+ "start": {
+ "line": 5,
+ "column": 6,
+ "character": 60
+ },
+ "end": {
+ "line": 5,
+ "column": 19,
+ "character": 73
+ },
+ "pos": 60
+}]
diff --git a/test/validator/samples/css-invalid-global-placement-3/input.svelte b/test/validator/samples/css-invalid-global-placement-3/input.svelte
new file mode 100644
index 0000000000..2a15c1086a
--- /dev/null
+++ b/test/validator/samples/css-invalid-global-placement-3/input.svelte
@@ -0,0 +1,8 @@
+
diff --git a/test/validator/samples/css-invalid-global-selector-2/errors.json b/test/validator/samples/css-invalid-global-selector-2/errors.json
new file mode 100644
index 0000000000..3317925b00
--- /dev/null
+++ b/test/validator/samples/css-invalid-global-selector-2/errors.json
@@ -0,0 +1,17 @@
+[
+ {
+ "code": "css-invalid-global-selector",
+ "message": ":global(...) must contain a single selector",
+ "start": {
+ "line": 11,
+ "column": 5,
+ "character": 156
+ },
+ "end": {
+ "line": 11,
+ "column": 29,
+ "character": 180
+ },
+ "pos": 156
+ }
+]
diff --git a/test/validator/samples/css-invalid-global-selector-2/input.svelte b/test/validator/samples/css-invalid-global-selector-2/input.svelte
new file mode 100644
index 0000000000..6acbabd7da
--- /dev/null
+++ b/test/validator/samples/css-invalid-global-selector-2/input.svelte
@@ -0,0 +1,18 @@
+
+
+
+
hello world
+
\ No newline at end of file
diff --git a/test/validator/samples/css-invalid-global-selector-3/errors.json b/test/validator/samples/css-invalid-global-selector-3/errors.json
new file mode 100644
index 0000000000..abc516a504
--- /dev/null
+++ b/test/validator/samples/css-invalid-global-selector-3/errors.json
@@ -0,0 +1,17 @@
+[
+ {
+ "code": "css-invalid-global-selector",
+ "message": ":global(...) must contain a single selector",
+ "start": {
+ "line": 5,
+ "column": 5,
+ "character": 77
+ },
+ "end": {
+ "line": 5,
+ "column": 44,
+ "character": 116
+ },
+ "pos": 77
+ }
+]
diff --git a/test/validator/samples/css-invalid-global-selector-3/input.svelte b/test/validator/samples/css-invalid-global-selector-3/input.svelte
new file mode 100644
index 0000000000..dca0094a06
--- /dev/null
+++ b/test/validator/samples/css-invalid-global-selector-3/input.svelte
@@ -0,0 +1,12 @@
+
+
+
+
hello world
+
diff --git a/test/validator/samples/css-invalid-global-selector-4/errors.json b/test/validator/samples/css-invalid-global-selector-4/errors.json
new file mode 100644
index 0000000000..8d76cb63c0
--- /dev/null
+++ b/test/validator/samples/css-invalid-global-selector-4/errors.json
@@ -0,0 +1,17 @@
+[
+ {
+ "code": "css-invalid-global-selector",
+ "message": ":global(...) must contain a single selector",
+ "start": {
+ "line": 2,
+ "column": 5,
+ "character": 13
+ },
+ "end": {
+ "line": 2,
+ "column": 24,
+ "character": 32
+ },
+ "pos": 13
+ }
+]
diff --git a/test/validator/samples/css-invalid-global-selector-4/input.svelte b/test/validator/samples/css-invalid-global-selector-4/input.svelte
new file mode 100644
index 0000000000..ed33b6b385
--- /dev/null
+++ b/test/validator/samples/css-invalid-global-selector-4/input.svelte
@@ -0,0 +1,9 @@
+
+
+
+
hello world
+
diff --git a/test/validator/samples/css-invalid-global-selector-5/errors.json b/test/validator/samples/css-invalid-global-selector-5/errors.json
new file mode 100644
index 0000000000..8129b236e6
--- /dev/null
+++ b/test/validator/samples/css-invalid-global-selector-5/errors.json
@@ -0,0 +1,17 @@
+[
+ {
+ "code": "css-invalid-global-selector",
+ "message": ":global(...) must contain a single selector",
+ "start": {
+ "line": 5,
+ "column": 1,
+ "character": 54
+ },
+ "end": {
+ "line": 5,
+ "column": 20,
+ "character": 73
+ },
+ "pos": 54
+ }
+]
diff --git a/test/validator/samples/css-invalid-global-selector-5/input.svelte b/test/validator/samples/css-invalid-global-selector-5/input.svelte
new file mode 100644
index 0000000000..67d4b9928a
--- /dev/null
+++ b/test/validator/samples/css-invalid-global-selector-5/input.svelte
@@ -0,0 +1,12 @@
+
+
+
+
hello world
+
\ No newline at end of file
diff --git a/test/validator/samples/css-invalid-global-selector-6/errors.json b/test/validator/samples/css-invalid-global-selector-6/errors.json
new file mode 100644
index 0000000000..8129b236e6
--- /dev/null
+++ b/test/validator/samples/css-invalid-global-selector-6/errors.json
@@ -0,0 +1,17 @@
+[
+ {
+ "code": "css-invalid-global-selector",
+ "message": ":global(...) must contain a single selector",
+ "start": {
+ "line": 5,
+ "column": 1,
+ "character": 54
+ },
+ "end": {
+ "line": 5,
+ "column": 20,
+ "character": 73
+ },
+ "pos": 54
+ }
+]
diff --git a/test/validator/samples/css-invalid-global-selector-6/input.svelte b/test/validator/samples/css-invalid-global-selector-6/input.svelte
new file mode 100644
index 0000000000..e0b2ffd597
--- /dev/null
+++ b/test/validator/samples/css-invalid-global-selector-6/input.svelte
@@ -0,0 +1,12 @@
+
+
+
+
hello world
+
\ No newline at end of file
diff --git a/test/validator/samples/css-invalid-global-selector/errors.json b/test/validator/samples/css-invalid-global-selector/errors.json
new file mode 100644
index 0000000000..7b2d5123b0
--- /dev/null
+++ b/test/validator/samples/css-invalid-global-selector/errors.json
@@ -0,0 +1,17 @@
+[
+ {
+ "code": "css-invalid-global-selector",
+ "message": ":global(...) must contain a single selector",
+ "start": {
+ "line": 11,
+ "column": 5,
+ "character": 143
+ },
+ "end": {
+ "line": 11,
+ "column": 24,
+ "character": 162
+ },
+ "pos": 143
+ }
+]
diff --git a/test/validator/samples/css-invalid-global-selector/input.svelte b/test/validator/samples/css-invalid-global-selector/input.svelte
new file mode 100644
index 0000000000..0ec337edfb
--- /dev/null
+++ b/test/validator/samples/css-invalid-global-selector/input.svelte
@@ -0,0 +1,18 @@
+
+
+
+
hello world
+
\ No newline at end of file
diff --git a/test/validator/samples/css-invalid-global/errors.json b/test/validator/samples/css-invalid-global/errors.json
deleted file mode 100644
index 63ed908342..0000000000
--- a/test/validator/samples/css-invalid-global/errors.json
+++ /dev/null
@@ -1,15 +0,0 @@
-[{
- "code": "css-invalid-global",
- "message": ":global(...) must be the first element in a compound selector",
- "start": {
- "line": 2,
- "column": 5,
- "character": 13
- },
- "end": {
- "line": 2,
- "column": 18,
- "character": 26
- },
- "pos": 13
-}]
\ No newline at end of file
diff --git a/test/validator/samples/css-invalid-global/input.svelte b/test/validator/samples/css-invalid-global/input.svelte
deleted file mode 100644
index 518674424a..0000000000
--- a/test/validator/samples/css-invalid-global/input.svelte
+++ /dev/null
@@ -1,5 +0,0 @@
-
\ No newline at end of file
diff --git a/test/validator/samples/default-export-anonymous-class/errors.json b/test/validator/samples/default-export-anonymous-class/errors.json
new file mode 100644
index 0000000000..0a410e5eda
--- /dev/null
+++ b/test/validator/samples/default-export-anonymous-class/errors.json
@@ -0,0 +1,15 @@
+[{
+ "code": "default-export",
+ "message": "A component cannot have a default export",
+ "pos": 10,
+ "start": {
+ "line": 2,
+ "column": 1,
+ "character": 10
+ },
+ "end": {
+ "line": 2,
+ "column": 30,
+ "character": 39
+ }
+}]
diff --git a/test/validator/samples/default-export-anonymous-class/input.svelte b/test/validator/samples/default-export-anonymous-class/input.svelte
new file mode 100644
index 0000000000..d78759e113
--- /dev/null
+++ b/test/validator/samples/default-export-anonymous-class/input.svelte
@@ -0,0 +1,3 @@
+
diff --git a/test/validator/samples/default-export-anonymous-function/errors.json b/test/validator/samples/default-export-anonymous-function/errors.json
new file mode 100644
index 0000000000..1f144e8392
--- /dev/null
+++ b/test/validator/samples/default-export-anonymous-function/errors.json
@@ -0,0 +1,15 @@
+[{
+ "code": "default-export",
+ "message": "A component cannot have a default export",
+ "pos": 10,
+ "start": {
+ "line": 2,
+ "column": 1,
+ "character": 10
+ },
+ "end": {
+ "line": 2,
+ "column": 24,
+ "character": 33
+ }
+}]
diff --git a/test/validator/samples/default-export-anonymous-function/input.svelte b/test/validator/samples/default-export-anonymous-function/input.svelte
new file mode 100644
index 0000000000..5e98ca42ab
--- /dev/null
+++ b/test/validator/samples/default-export-anonymous-function/input.svelte
@@ -0,0 +1,3 @@
+
diff --git a/test/validator/samples/error-mode-warn/input.svelte b/test/validator/samples/error-mode-warn/input.svelte
new file mode 100644
index 0000000000..5304ef4c71
--- /dev/null
+++ b/test/validator/samples/error-mode-warn/input.svelte
@@ -0,0 +1,6 @@
+
+
+
+
diff --git a/test/validator/samples/error-mode-warn/options.json b/test/validator/samples/error-mode-warn/options.json
new file mode 100644
index 0000000000..8d48d2f34e
--- /dev/null
+++ b/test/validator/samples/error-mode-warn/options.json
@@ -0,0 +1,3 @@
+{
+ "errorMode": "warn"
+}
\ No newline at end of file
diff --git a/test/validator/samples/error-mode-warn/warnings.json b/test/validator/samples/error-mode-warn/warnings.json
new file mode 100644
index 0000000000..cce6324df5
--- /dev/null
+++ b/test/validator/samples/error-mode-warn/warnings.json
@@ -0,0 +1,47 @@
+[
+ {
+ "code": "invalid-binding",
+ "message": "Cannot bind to a variable which is not writable",
+ "pos": 61,
+ "start": {
+ "line": 5,
+ "column": 19,
+ "character": 61
+ },
+ "end": {
+ "line": 5,
+ "column": 24,
+ "character": 66
+ }
+ },
+ {
+ "code": "missing-declaration",
+ "message": "'undeclared' is not defined",
+ "pos": 88,
+ "start": {
+ "character": 88,
+ "column": 19,
+ "line": 6
+ },
+ "end": {
+ "character": 98,
+ "column": 29,
+ "line": 6
+ }
+ },
+ {
+ "code": "binding-undeclared",
+ "message": "undeclared is not declared",
+ "pos": 88,
+ "end": {
+ "character": 98,
+ "column": 29,
+ "line": 6
+ },
+ "start": {
+ "character": 88,
+ "column": 19,
+ "line": 6
+ }
+ }
+]
\ No newline at end of file
diff --git a/test/validator/samples/event-modifiers-invalid/errors.json b/test/validator/samples/event-modifiers-invalid/errors.json
index 59a142d632..ea6de4ce34 100644
--- a/test/validator/samples/event-modifiers-invalid/errors.json
+++ b/test/validator/samples/event-modifiers-invalid/errors.json
@@ -1,5 +1,5 @@
[{
- "message": "Valid event modifiers are preventDefault, stopPropagation, capture, once, passive, nonpassive or self",
+ "message": "Valid event modifiers are preventDefault, stopPropagation, capture, once, passive, nonpassive, self or trusted",
"code": "invalid-event-modifier",
"start": {
"line": 1,
diff --git a/test/validator/samples/reactive-module-const-variable/input.svelte b/test/validator/samples/reactive-module-const-variable/input.svelte
new file mode 100644
index 0000000000..c89cc1c1d0
--- /dev/null
+++ b/test/validator/samples/reactive-module-const-variable/input.svelte
@@ -0,0 +1,9 @@
+
+
+
diff --git a/test/validator/samples/reactive-module-const-variable/warnings.json b/test/validator/samples/reactive-module-const-variable/warnings.json
new file mode 100644
index 0000000000..0d4f101c7a
--- /dev/null
+++ b/test/validator/samples/reactive-module-const-variable/warnings.json
@@ -0,0 +1,2 @@
+[
+]
diff --git a/test/validator/samples/reactive-module-variable-2/input.svelte b/test/validator/samples/reactive-module-variable-2/input.svelte
new file mode 100644
index 0000000000..d36d9cf210
--- /dev/null
+++ b/test/validator/samples/reactive-module-variable-2/input.svelte
@@ -0,0 +1,7 @@
+
+
diff --git a/test/validator/samples/reactive-module-variable-2/warnings.json b/test/validator/samples/reactive-module-variable-2/warnings.json
new file mode 100644
index 0000000000..fe51488c70
--- /dev/null
+++ b/test/validator/samples/reactive-module-variable-2/warnings.json
@@ -0,0 +1 @@
+[]
diff --git a/test/validator/samples/reactive-module-variable/warnings.json b/test/validator/samples/reactive-module-variable/warnings.json
index c3c52cb479..d08fc1309f 100644
--- a/test/validator/samples/reactive-module-variable/warnings.json
+++ b/test/validator/samples/reactive-module-variable/warnings.json
@@ -2,15 +2,15 @@
{
"code": "module-script-reactive-declaration",
"message": "\"foo\" is declared in a module script and will not be reactive",
- "pos": 65,
+ "pos": 59,
"start": {
- "character": 65,
- "column": 10,
+ "character": 59,
+ "column": 4,
"line": 5
},
"end": {
- "character": 68,
- "column": 13,
+ "character": 69,
+ "column": 14,
"line": 5
}
}
diff --git a/test/validator/samples/silence-warnings-2/input.svelte b/test/validator/samples/silence-warnings-2/input.svelte
new file mode 100644
index 0000000000..81cb90b7be
--- /dev/null
+++ b/test/validator/samples/silence-warnings-2/input.svelte
@@ -0,0 +1,9 @@
+
+
+
+
diff --git a/test/validator/samples/silence-warnings-2/warnings.json b/test/validator/samples/silence-warnings-2/warnings.json
new file mode 100644
index 0000000000..fe51488c70
--- /dev/null
+++ b/test/validator/samples/silence-warnings-2/warnings.json
@@ -0,0 +1 @@
+[]
diff --git a/test/validator/samples/silence-warnings/input.svelte b/test/validator/samples/silence-warnings/input.svelte
new file mode 100644
index 0000000000..0e473f51db
--- /dev/null
+++ b/test/validator/samples/silence-warnings/input.svelte
@@ -0,0 +1,15 @@
+
+
+
+
+
+
diff --git a/test/validator/samples/silence-warnings/warnings.json b/test/validator/samples/silence-warnings/warnings.json
new file mode 100644
index 0000000000..fe51488c70
--- /dev/null
+++ b/test/validator/samples/silence-warnings/warnings.json
@@ -0,0 +1 @@
+[]
diff --git a/test/vars/samples/vars-report-false/_config.js b/test/vars/samples/vars-report-false/_config.js
new file mode 100644
index 0000000000..f4709f09c8
--- /dev/null
+++ b/test/vars/samples/vars-report-false/_config.js
@@ -0,0 +1,9 @@
+export default {
+ options: {
+ varsReport: false
+ },
+
+ test(assert, vars) {
+ assert.deepEqual(vars, []);
+ }
+};
diff --git a/test/vars/samples/vars-report-false/input.svelte b/test/vars/samples/vars-report-false/input.svelte
new file mode 100644
index 0000000000..7583c99845
--- /dev/null
+++ b/test/vars/samples/vars-report-false/input.svelte
@@ -0,0 +1,5 @@
+
+
+{foo}
\ No newline at end of file
diff --git a/test/vars/samples/vars-report-full-noscript/_config.js b/test/vars/samples/vars-report-full-noscript/_config.js
new file mode 100644
index 0000000000..9c39324518
--- /dev/null
+++ b/test/vars/samples/vars-report-full-noscript/_config.js
@@ -0,0 +1,19 @@
+export default {
+ options: {
+ varsReport: 'full'
+ },
+
+ test(assert, vars) {
+ assert.deepEqual(vars, [{
+ name: 'foo',
+ export_name: null,
+ injected: false,
+ module: false,
+ mutated: false,
+ reassigned: false,
+ referenced: true,
+ referenced_from_script: false,
+ writable: false
+ }]);
+ }
+};
diff --git a/test/vars/samples/vars-report-full-noscript/input.svelte b/test/vars/samples/vars-report-full-noscript/input.svelte
new file mode 100644
index 0000000000..e076ac55f8
--- /dev/null
+++ b/test/vars/samples/vars-report-full-noscript/input.svelte
@@ -0,0 +1 @@
+{foo}
\ No newline at end of file
diff --git a/test/vars/samples/vars-report-full-script/_config.js b/test/vars/samples/vars-report-full-script/_config.js
new file mode 100644
index 0000000000..2519dc5508
--- /dev/null
+++ b/test/vars/samples/vars-report-full-script/_config.js
@@ -0,0 +1,31 @@
+export default {
+ options: {
+ varsReport: 'full'
+ },
+
+ test(assert, vars) {
+ assert.deepEqual(vars, [
+ {
+ name: 'foo',
+ export_name: 'foo',
+ injected: false,
+ module: false,
+ mutated: false,
+ reassigned: false,
+ referenced: true,
+ referenced_from_script: false,
+ writable: true
+ }, {
+ name: 'bar',
+ export_name: null,
+ injected: false,
+ module: false,
+ mutated: false,
+ reassigned: false,
+ referenced: true,
+ referenced_from_script: false,
+ writable: false
+ }
+ ]);
+ }
+};
diff --git a/test/vars/samples/vars-report-full-script/input.svelte b/test/vars/samples/vars-report-full-script/input.svelte
new file mode 100644
index 0000000000..11870584a6
--- /dev/null
+++ b/test/vars/samples/vars-report-full-script/input.svelte
@@ -0,0 +1,5 @@
+
+
+{foo} {bar}
\ No newline at end of file
diff --git a/test/vars/samples/vars-report-full/_config.js b/test/vars/samples/vars-report-full/_config.js
new file mode 100644
index 0000000000..9c39324518
--- /dev/null
+++ b/test/vars/samples/vars-report-full/_config.js
@@ -0,0 +1,19 @@
+export default {
+ options: {
+ varsReport: 'full'
+ },
+
+ test(assert, vars) {
+ assert.deepEqual(vars, [{
+ name: 'foo',
+ export_name: null,
+ injected: false,
+ module: false,
+ mutated: false,
+ reassigned: false,
+ referenced: true,
+ referenced_from_script: false,
+ writable: false
+ }]);
+ }
+};
diff --git a/test/vars/samples/vars-report-full/input.svelte b/test/vars/samples/vars-report-full/input.svelte
new file mode 100644
index 0000000000..0178466fe3
--- /dev/null
+++ b/test/vars/samples/vars-report-full/input.svelte
@@ -0,0 +1,3 @@
+
+
+{foo}
\ No newline at end of file
diff --git a/tsconfig.json b/tsconfig.json
index 248e3b5e98..f2e055a2a9 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -21,6 +21,9 @@
"resolveJsonModule": true,
"allowSyntheticDefaultImports": true,
+ // Hides exports flagged with @internal from the d.ts output
+ "stripInternal": true,
+
// TODO: error all the things
//"strict": true,
"noImplicitThis": true,