From 3e8ea124eafa9e6685dbd9cf459814945c8a943c Mon Sep 17 00:00:00 2001 From: Richard Harris Date: Sun, 3 Mar 2019 17:40:17 -0500 Subject: [PATCH] document stores --- .../01-writable-stores/app-a/App.svelte | 18 ++++++ .../app-a/Decrementer.svelte | 11 ++++ .../app-a/Incrementer.svelte | 11 ++++ .../01-writable-stores/app-a/Resetter.svelte | 11 ++++ .../01-writable-stores/app-a/stores.js | 3 + .../01-writable-stores/app-b/App.svelte | 18 ++++++ .../app-b/Decrementer.svelte | 11 ++++ .../app-b/Incrementer.svelte | 11 ++++ .../01-writable-stores/app-b/Resetter.svelte | 11 ++++ .../01-writable-stores/app-b/stores.js | 3 + .../07-stores/01-writable-stores/text.md | 27 +++++++++ .../02-auto-subscriptions/app-a/App.svelte | 18 ++++++ .../app-a/Decrementer.svelte | 11 ++++ .../app-a/Incrementer.svelte | 11 ++++ .../app-a/Resetter.svelte | 11 ++++ .../02-auto-subscriptions/app-a/stores.js | 3 + .../02-auto-subscriptions/app-b/App.svelte | 12 ++++ .../app-b/Decrementer.svelte | 11 ++++ .../app-b/Incrementer.svelte | 11 ++++ .../app-b/Resetter.svelte | 11 ++++ .../02-auto-subscriptions/app-b/stores.js | 3 + .../07-stores/02-auto-subscriptions/text.md | 44 ++++++++++++++ .../03-readable-stores/app-a/App.svelte | 12 ++++ .../03-readable-stores/app-a/stores.js | 9 +++ .../03-readable-stores/app-b/App.svelte | 12 ++++ .../03-readable-stores/app-b/stores.js | 11 ++++ .../07-stores/03-readable-stores/text.md | 19 ++++++ .../04-derived-stores/app-a/App.svelte | 17 ++++++ .../04-derived-stores/app-a/stores.js | 18 ++++++ .../04-derived-stores/app-b/App.svelte | 17 ++++++ .../04-derived-stores/app-b/stores.js | 18 ++++++ .../07-stores/04-derived-stores/text.md | 14 +++++ .../05-custom-stores/app-a/App.svelte | 9 +++ .../05-custom-stores/app-a/stores.js | 14 +++++ .../05-custom-stores/app-b/App.svelte | 9 +++ .../05-custom-stores/app-b/stores.js | 14 +++++ .../07-stores/05-custom-stores/text.md | 21 +++++++ site/content/tutorial/07-stores/meta.json | 3 + site/content/tutorial/99-todo/99-todo/text.md | 16 +++-- site/src/routes/tutorial/[slug]/index.svelte | 6 +- site/src/routes/tutorial/index.json.js | 58 +++++++++++++------ 41 files changed, 554 insertions(+), 24 deletions(-) create mode 100644 site/content/tutorial/07-stores/01-writable-stores/app-a/App.svelte create mode 100644 site/content/tutorial/07-stores/01-writable-stores/app-a/Decrementer.svelte create mode 100644 site/content/tutorial/07-stores/01-writable-stores/app-a/Incrementer.svelte create mode 100644 site/content/tutorial/07-stores/01-writable-stores/app-a/Resetter.svelte create mode 100644 site/content/tutorial/07-stores/01-writable-stores/app-a/stores.js create mode 100644 site/content/tutorial/07-stores/01-writable-stores/app-b/App.svelte create mode 100644 site/content/tutorial/07-stores/01-writable-stores/app-b/Decrementer.svelte create mode 100644 site/content/tutorial/07-stores/01-writable-stores/app-b/Incrementer.svelte create mode 100644 site/content/tutorial/07-stores/01-writable-stores/app-b/Resetter.svelte create mode 100644 site/content/tutorial/07-stores/01-writable-stores/app-b/stores.js create mode 100644 site/content/tutorial/07-stores/01-writable-stores/text.md create mode 100644 site/content/tutorial/07-stores/02-auto-subscriptions/app-a/App.svelte create mode 100644 site/content/tutorial/07-stores/02-auto-subscriptions/app-a/Decrementer.svelte create mode 100644 site/content/tutorial/07-stores/02-auto-subscriptions/app-a/Incrementer.svelte create mode 100644 site/content/tutorial/07-stores/02-auto-subscriptions/app-a/Resetter.svelte create mode 100644 site/content/tutorial/07-stores/02-auto-subscriptions/app-a/stores.js create mode 100644 site/content/tutorial/07-stores/02-auto-subscriptions/app-b/App.svelte create mode 100644 site/content/tutorial/07-stores/02-auto-subscriptions/app-b/Decrementer.svelte create mode 100644 site/content/tutorial/07-stores/02-auto-subscriptions/app-b/Incrementer.svelte create mode 100644 site/content/tutorial/07-stores/02-auto-subscriptions/app-b/Resetter.svelte create mode 100644 site/content/tutorial/07-stores/02-auto-subscriptions/app-b/stores.js create mode 100644 site/content/tutorial/07-stores/02-auto-subscriptions/text.md create mode 100644 site/content/tutorial/07-stores/03-readable-stores/app-a/App.svelte create mode 100644 site/content/tutorial/07-stores/03-readable-stores/app-a/stores.js create mode 100644 site/content/tutorial/07-stores/03-readable-stores/app-b/App.svelte create mode 100644 site/content/tutorial/07-stores/03-readable-stores/app-b/stores.js create mode 100644 site/content/tutorial/07-stores/03-readable-stores/text.md create mode 100644 site/content/tutorial/07-stores/04-derived-stores/app-a/App.svelte create mode 100644 site/content/tutorial/07-stores/04-derived-stores/app-a/stores.js create mode 100644 site/content/tutorial/07-stores/04-derived-stores/app-b/App.svelte create mode 100644 site/content/tutorial/07-stores/04-derived-stores/app-b/stores.js create mode 100644 site/content/tutorial/07-stores/04-derived-stores/text.md create mode 100644 site/content/tutorial/07-stores/05-custom-stores/app-a/App.svelte create mode 100644 site/content/tutorial/07-stores/05-custom-stores/app-a/stores.js create mode 100644 site/content/tutorial/07-stores/05-custom-stores/app-b/App.svelte create mode 100644 site/content/tutorial/07-stores/05-custom-stores/app-b/stores.js create mode 100644 site/content/tutorial/07-stores/05-custom-stores/text.md create mode 100644 site/content/tutorial/07-stores/meta.json diff --git a/site/content/tutorial/07-stores/01-writable-stores/app-a/App.svelte b/site/content/tutorial/07-stores/01-writable-stores/app-a/App.svelte new file mode 100644 index 0000000000..ee542f789d --- /dev/null +++ b/site/content/tutorial/07-stores/01-writable-stores/app-a/App.svelte @@ -0,0 +1,18 @@ + + +

The count is {count_value}

+ + + + \ No newline at end of file diff --git a/site/content/tutorial/07-stores/01-writable-stores/app-a/Decrementer.svelte b/site/content/tutorial/07-stores/01-writable-stores/app-a/Decrementer.svelte new file mode 100644 index 0000000000..9bd4422f49 --- /dev/null +++ b/site/content/tutorial/07-stores/01-writable-stores/app-a/Decrementer.svelte @@ -0,0 +1,11 @@ + + + \ No newline at end of file diff --git a/site/content/tutorial/07-stores/01-writable-stores/app-a/Incrementer.svelte b/site/content/tutorial/07-stores/01-writable-stores/app-a/Incrementer.svelte new file mode 100644 index 0000000000..3581f243d8 --- /dev/null +++ b/site/content/tutorial/07-stores/01-writable-stores/app-a/Incrementer.svelte @@ -0,0 +1,11 @@ + + + \ No newline at end of file diff --git a/site/content/tutorial/07-stores/01-writable-stores/app-a/Resetter.svelte b/site/content/tutorial/07-stores/01-writable-stores/app-a/Resetter.svelte new file mode 100644 index 0000000000..b4a6b7559b --- /dev/null +++ b/site/content/tutorial/07-stores/01-writable-stores/app-a/Resetter.svelte @@ -0,0 +1,11 @@ + + + \ No newline at end of file diff --git a/site/content/tutorial/07-stores/01-writable-stores/app-a/stores.js b/site/content/tutorial/07-stores/01-writable-stores/app-a/stores.js new file mode 100644 index 0000000000..143e0c99f0 --- /dev/null +++ b/site/content/tutorial/07-stores/01-writable-stores/app-a/stores.js @@ -0,0 +1,3 @@ +import { writable } from 'svelte/store'; + +export const count = writable(0); \ No newline at end of file diff --git a/site/content/tutorial/07-stores/01-writable-stores/app-b/App.svelte b/site/content/tutorial/07-stores/01-writable-stores/app-b/App.svelte new file mode 100644 index 0000000000..ee542f789d --- /dev/null +++ b/site/content/tutorial/07-stores/01-writable-stores/app-b/App.svelte @@ -0,0 +1,18 @@ + + +

The count is {count_value}

+ + + + \ No newline at end of file diff --git a/site/content/tutorial/07-stores/01-writable-stores/app-b/Decrementer.svelte b/site/content/tutorial/07-stores/01-writable-stores/app-b/Decrementer.svelte new file mode 100644 index 0000000000..043b795047 --- /dev/null +++ b/site/content/tutorial/07-stores/01-writable-stores/app-b/Decrementer.svelte @@ -0,0 +1,11 @@ + + + \ No newline at end of file diff --git a/site/content/tutorial/07-stores/01-writable-stores/app-b/Incrementer.svelte b/site/content/tutorial/07-stores/01-writable-stores/app-b/Incrementer.svelte new file mode 100644 index 0000000000..2b5763012b --- /dev/null +++ b/site/content/tutorial/07-stores/01-writable-stores/app-b/Incrementer.svelte @@ -0,0 +1,11 @@ + + + \ No newline at end of file diff --git a/site/content/tutorial/07-stores/01-writable-stores/app-b/Resetter.svelte b/site/content/tutorial/07-stores/01-writable-stores/app-b/Resetter.svelte new file mode 100644 index 0000000000..4183421e51 --- /dev/null +++ b/site/content/tutorial/07-stores/01-writable-stores/app-b/Resetter.svelte @@ -0,0 +1,11 @@ + + + \ No newline at end of file diff --git a/site/content/tutorial/07-stores/01-writable-stores/app-b/stores.js b/site/content/tutorial/07-stores/01-writable-stores/app-b/stores.js new file mode 100644 index 0000000000..143e0c99f0 --- /dev/null +++ b/site/content/tutorial/07-stores/01-writable-stores/app-b/stores.js @@ -0,0 +1,3 @@ +import { writable } from 'svelte/store'; + +export const count = writable(0); \ No newline at end of file diff --git a/site/content/tutorial/07-stores/01-writable-stores/text.md b/site/content/tutorial/07-stores/01-writable-stores/text.md new file mode 100644 index 0000000000..57c27411ea --- /dev/null +++ b/site/content/tutorial/07-stores/01-writable-stores/text.md @@ -0,0 +1,27 @@ +--- +title: Writable stores +--- + +Not all application state belongs inside your application's component hierarchy. Sometimes, you'll have values that need to be accessed by multiple unrelated components, or by a regular JavaScript module. + +In Svelte, we do this with *stores*. A store is simply an object with a `subscribe` method that allows interested parties to be notified whenever the store value changes. In `App.svelte`, `count` is a store, and we're setting `count_value` in the `count.subscribe` callback. + +Click the `stores.js` tab to see the definition of `count`. It's a *writable* store, which means it has `set` and `update` methods in addition to `subscribe`. + +Now go to the `Incrementer.svelte` tab so that we can wire up the `+` button: + +```js +function increment() { + count.update(n => n + 1); +} +``` + +Clicking the `+` button should now update the count. Do the inverse for `Decrementer.svelte`. + +Finally, in `Resetter.svelte`, implement `reset`: + +```js +function reset() { + count.set(0); +} +``` \ No newline at end of file diff --git a/site/content/tutorial/07-stores/02-auto-subscriptions/app-a/App.svelte b/site/content/tutorial/07-stores/02-auto-subscriptions/app-a/App.svelte new file mode 100644 index 0000000000..ee542f789d --- /dev/null +++ b/site/content/tutorial/07-stores/02-auto-subscriptions/app-a/App.svelte @@ -0,0 +1,18 @@ + + +

The count is {count_value}

+ + + + \ No newline at end of file diff --git a/site/content/tutorial/07-stores/02-auto-subscriptions/app-a/Decrementer.svelte b/site/content/tutorial/07-stores/02-auto-subscriptions/app-a/Decrementer.svelte new file mode 100644 index 0000000000..043b795047 --- /dev/null +++ b/site/content/tutorial/07-stores/02-auto-subscriptions/app-a/Decrementer.svelte @@ -0,0 +1,11 @@ + + + \ No newline at end of file diff --git a/site/content/tutorial/07-stores/02-auto-subscriptions/app-a/Incrementer.svelte b/site/content/tutorial/07-stores/02-auto-subscriptions/app-a/Incrementer.svelte new file mode 100644 index 0000000000..2b5763012b --- /dev/null +++ b/site/content/tutorial/07-stores/02-auto-subscriptions/app-a/Incrementer.svelte @@ -0,0 +1,11 @@ + + + \ No newline at end of file diff --git a/site/content/tutorial/07-stores/02-auto-subscriptions/app-a/Resetter.svelte b/site/content/tutorial/07-stores/02-auto-subscriptions/app-a/Resetter.svelte new file mode 100644 index 0000000000..4183421e51 --- /dev/null +++ b/site/content/tutorial/07-stores/02-auto-subscriptions/app-a/Resetter.svelte @@ -0,0 +1,11 @@ + + + \ No newline at end of file diff --git a/site/content/tutorial/07-stores/02-auto-subscriptions/app-a/stores.js b/site/content/tutorial/07-stores/02-auto-subscriptions/app-a/stores.js new file mode 100644 index 0000000000..143e0c99f0 --- /dev/null +++ b/site/content/tutorial/07-stores/02-auto-subscriptions/app-a/stores.js @@ -0,0 +1,3 @@ +import { writable } from 'svelte/store'; + +export const count = writable(0); \ No newline at end of file diff --git a/site/content/tutorial/07-stores/02-auto-subscriptions/app-b/App.svelte b/site/content/tutorial/07-stores/02-auto-subscriptions/app-b/App.svelte new file mode 100644 index 0000000000..10ebfb65bb --- /dev/null +++ b/site/content/tutorial/07-stores/02-auto-subscriptions/app-b/App.svelte @@ -0,0 +1,12 @@ + + +

The count is {$count}

+ + + + \ No newline at end of file diff --git a/site/content/tutorial/07-stores/02-auto-subscriptions/app-b/Decrementer.svelte b/site/content/tutorial/07-stores/02-auto-subscriptions/app-b/Decrementer.svelte new file mode 100644 index 0000000000..043b795047 --- /dev/null +++ b/site/content/tutorial/07-stores/02-auto-subscriptions/app-b/Decrementer.svelte @@ -0,0 +1,11 @@ + + + \ No newline at end of file diff --git a/site/content/tutorial/07-stores/02-auto-subscriptions/app-b/Incrementer.svelte b/site/content/tutorial/07-stores/02-auto-subscriptions/app-b/Incrementer.svelte new file mode 100644 index 0000000000..2b5763012b --- /dev/null +++ b/site/content/tutorial/07-stores/02-auto-subscriptions/app-b/Incrementer.svelte @@ -0,0 +1,11 @@ + + + \ No newline at end of file diff --git a/site/content/tutorial/07-stores/02-auto-subscriptions/app-b/Resetter.svelte b/site/content/tutorial/07-stores/02-auto-subscriptions/app-b/Resetter.svelte new file mode 100644 index 0000000000..4183421e51 --- /dev/null +++ b/site/content/tutorial/07-stores/02-auto-subscriptions/app-b/Resetter.svelte @@ -0,0 +1,11 @@ + + + \ No newline at end of file diff --git a/site/content/tutorial/07-stores/02-auto-subscriptions/app-b/stores.js b/site/content/tutorial/07-stores/02-auto-subscriptions/app-b/stores.js new file mode 100644 index 0000000000..143e0c99f0 --- /dev/null +++ b/site/content/tutorial/07-stores/02-auto-subscriptions/app-b/stores.js @@ -0,0 +1,3 @@ +import { writable } from 'svelte/store'; + +export const count = writable(0); \ No newline at end of file diff --git a/site/content/tutorial/07-stores/02-auto-subscriptions/text.md b/site/content/tutorial/07-stores/02-auto-subscriptions/text.md new file mode 100644 index 0000000000..7c4a40fb25 --- /dev/null +++ b/site/content/tutorial/07-stores/02-auto-subscriptions/text.md @@ -0,0 +1,44 @@ +--- +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*. + +One way to fix it would be to use the `onDestroy` [lifecycle hook](tutorial/ondestroy): + +```html + + +

The count is {count_value}

+``` + +It starts to get a bit boilerplatey though, especially if your component subscribes to multiple stores. Instead, Svelte has a trick up its sleeve — you can reference a store value by prefixing the store name with `$`: + +```html + + +

The count is {$count}

+``` + +You're not limited to using `$count` inside the markup, either — you can use it anywhere in the ` + +

The time is {formatter.format($time)}

\ No newline at end of file diff --git a/site/content/tutorial/07-stores/03-readable-stores/app-a/stores.js b/site/content/tutorial/07-stores/03-readable-stores/app-a/stores.js new file mode 100644 index 0000000000..1e5d11e2d9 --- /dev/null +++ b/site/content/tutorial/07-stores/03-readable-stores/app-a/stores.js @@ -0,0 +1,9 @@ +import { readable } from 'svelte/store'; + +export const time = readable(function start(set) { + // implementation goes here + + return function stop() { + + }; +}); \ No newline at end of file diff --git a/site/content/tutorial/07-stores/03-readable-stores/app-b/App.svelte b/site/content/tutorial/07-stores/03-readable-stores/app-b/App.svelte new file mode 100644 index 0000000000..3ff0b0362f --- /dev/null +++ b/site/content/tutorial/07-stores/03-readable-stores/app-b/App.svelte @@ -0,0 +1,12 @@ + + +

The time is {formatter.format($time)}

\ No newline at end of file diff --git a/site/content/tutorial/07-stores/03-readable-stores/app-b/stores.js b/site/content/tutorial/07-stores/03-readable-stores/app-b/stores.js new file mode 100644 index 0000000000..015de5ad45 --- /dev/null +++ b/site/content/tutorial/07-stores/03-readable-stores/app-b/stores.js @@ -0,0 +1,11 @@ +import { readable } from 'svelte/store'; + +export const time = readable(function start(set) { + const interval = setInterval(() => { + set(new Date()); + }, 1000); + + return function stop() { + clearInterval(interval); + }; +}, new Date()); \ No newline at end of file diff --git a/site/content/tutorial/07-stores/03-readable-stores/text.md b/site/content/tutorial/07-stores/03-readable-stores/text.md new file mode 100644 index 0000000000..6ef989fffa --- /dev/null +++ b/site/content/tutorial/07-stores/03-readable-stores/text.md @@ -0,0 +1,19 @@ +--- +title: Readable stores +--- + +Not all stores should be writable by whoever has a reference to them. For example, you might have a store representing the mouse position or the user's geolocation, and it doesn't make sense to be able to set those values from 'outside'. For those cases, we have *readable* stores. + +Click over to the `stores.js` tab. The first argument to `readable` is a `start` function that takes a `set` callback and returns a `stop` function. The `start` function is called when the store gets its first subscriber; `stop` is called when the last subscriber unsubscribes. The second (optional) argument is the initial value. + +```js +export const time = readable(function start(set) { + const interval = setInterval(() => { + set(new Date()); + }, 1000); + + return function stop() { + clearInterval(interval); + }; +}, new Date()); +``` \ No newline at end of file diff --git a/site/content/tutorial/07-stores/04-derived-stores/app-a/App.svelte b/site/content/tutorial/07-stores/04-derived-stores/app-a/App.svelte new file mode 100644 index 0000000000..8182ecd671 --- /dev/null +++ b/site/content/tutorial/07-stores/04-derived-stores/app-a/App.svelte @@ -0,0 +1,17 @@ + + +

The time is {formatter.format($time)}

+ +

+ This page has been open for + {$elapsed} {$elapsed === 1 ? 'second' : 'seconds'} +

\ No newline at end of file diff --git a/site/content/tutorial/07-stores/04-derived-stores/app-a/stores.js b/site/content/tutorial/07-stores/04-derived-stores/app-a/stores.js new file mode 100644 index 0000000000..483d3094f0 --- /dev/null +++ b/site/content/tutorial/07-stores/04-derived-stores/app-a/stores.js @@ -0,0 +1,18 @@ +import { readable, derive } from 'svelte/store'; + +export const time = readable(function start(set) { + const interval = setInterval(() => { + set(new Date()); + }, 1000); + + return function stop() { + clearInterval(interval); + }; +}, new Date()); + +const start = new Date(); + +export const elapsed = derive( + time, + $time => {} +); \ No newline at end of file diff --git a/site/content/tutorial/07-stores/04-derived-stores/app-b/App.svelte b/site/content/tutorial/07-stores/04-derived-stores/app-b/App.svelte new file mode 100644 index 0000000000..8182ecd671 --- /dev/null +++ b/site/content/tutorial/07-stores/04-derived-stores/app-b/App.svelte @@ -0,0 +1,17 @@ + + +

The time is {formatter.format($time)}

+ +

+ This page has been open for + {$elapsed} {$elapsed === 1 ? 'second' : 'seconds'} +

\ No newline at end of file diff --git a/site/content/tutorial/07-stores/04-derived-stores/app-b/stores.js b/site/content/tutorial/07-stores/04-derived-stores/app-b/stores.js new file mode 100644 index 0000000000..2f3af1247a --- /dev/null +++ b/site/content/tutorial/07-stores/04-derived-stores/app-b/stores.js @@ -0,0 +1,18 @@ +import { readable, derive } from 'svelte/store'; + +export const time = readable(function start(set) { + const interval = setInterval(() => { + set(new Date()); + }, 1000); + + return function stop() { + clearInterval(interval); + }; +}, new Date()); + +const start = new Date(); + +export const elapsed = derive( + time, + $time => Math.round(($time - start) / 1000) +); \ No newline at end of file diff --git a/site/content/tutorial/07-stores/04-derived-stores/text.md b/site/content/tutorial/07-stores/04-derived-stores/text.md new file mode 100644 index 0000000000..9ee25b916c --- /dev/null +++ b/site/content/tutorial/07-stores/04-derived-stores/text.md @@ -0,0 +1,14 @@ +--- +title: Derived stores +--- + +You can create a store whose value is based on the value of one or more *other* stores with `derive`. Building on our previous example, we can create a store that derives the time the page has been open: + +```js +export const elapsed = derive( + time, + $time => Math.round(($time - start) / 1000) +); +``` + +> It's possible to derive a store from multiple inputs, and to explicitly `set` a value instead of returning it (which is useful for deriving values asynchronously). Consult the [API reference](docs/TK) for more information. \ No newline at end of file diff --git a/site/content/tutorial/07-stores/05-custom-stores/app-a/App.svelte b/site/content/tutorial/07-stores/05-custom-stores/app-a/App.svelte new file mode 100644 index 0000000000..a320cc052f --- /dev/null +++ b/site/content/tutorial/07-stores/05-custom-stores/app-a/App.svelte @@ -0,0 +1,9 @@ + + +

The count is {$count}

+ + + + \ No newline at end of file diff --git a/site/content/tutorial/07-stores/05-custom-stores/app-a/stores.js b/site/content/tutorial/07-stores/05-custom-stores/app-a/stores.js new file mode 100644 index 0000000000..ccb322652b --- /dev/null +++ b/site/content/tutorial/07-stores/05-custom-stores/app-a/stores.js @@ -0,0 +1,14 @@ +import { writable } from 'svelte/store'; + +function createCount() { + const { subscribe, set, update } = writable(0); + + return { + subscribe, + increment: () => {}, + decrement: () => {}, + reset: () => {} + }; +} + +export const count = createCount(); \ No newline at end of file diff --git a/site/content/tutorial/07-stores/05-custom-stores/app-b/App.svelte b/site/content/tutorial/07-stores/05-custom-stores/app-b/App.svelte new file mode 100644 index 0000000000..a320cc052f --- /dev/null +++ b/site/content/tutorial/07-stores/05-custom-stores/app-b/App.svelte @@ -0,0 +1,9 @@ + + +

The count is {$count}

+ + + + \ No newline at end of file diff --git a/site/content/tutorial/07-stores/05-custom-stores/app-b/stores.js b/site/content/tutorial/07-stores/05-custom-stores/app-b/stores.js new file mode 100644 index 0000000000..5a26025b03 --- /dev/null +++ b/site/content/tutorial/07-stores/05-custom-stores/app-b/stores.js @@ -0,0 +1,14 @@ +import { writable } from 'svelte/store'; + +function createCount() { + const { subscribe, set, update } = writable(0); + + return { + subscribe, + increment: () => update(n => n + 1), + decrement: () => update(n => n - 1), + reset: () => set(0) + }; +} + +export const count = createCount(); \ No newline at end of file diff --git a/site/content/tutorial/07-stores/05-custom-stores/text.md b/site/content/tutorial/07-stores/05-custom-stores/text.md new file mode 100644 index 0000000000..febd0ad7f7 --- /dev/null +++ b/site/content/tutorial/07-stores/05-custom-stores/text.md @@ -0,0 +1,21 @@ +--- +title: Custom stores +--- + +As long as an object correctly implements the `subscribe` method, it's a store. Beyond that, anything goes. It's very easy, therefore, to create custom stores with domain-specific logic. + +For example, the `count` store from our earlier example could include `increment`, `decrement` and `reset` methods and avoid exposing `set` and `update`: + +```js +function createCount() { + const { subscribe, set, update } = writable(0); + + return { + subscribe, + increment: () => update(n => n + 1), + decrement: () => update(n => n - 1), + reset: () => set(0) + }; +} +``` + diff --git a/site/content/tutorial/07-stores/meta.json b/site/content/tutorial/07-stores/meta.json new file mode 100644 index 0000000000..ad974de0d9 --- /dev/null +++ b/site/content/tutorial/07-stores/meta.json @@ -0,0 +1,3 @@ +{ + "title": "Stores" +} \ No newline at end of file diff --git a/site/content/tutorial/99-todo/99-todo/text.md b/site/content/tutorial/99-todo/99-todo/text.md index ba93a02266..11378cd651 100644 --- a/site/content/tutorial/99-todo/99-todo/text.md +++ b/site/content/tutorial/99-todo/99-todo/text.md @@ -78,13 +78,21 @@ Maybe lifecycle should go first, since we're using `onMount` in the `this` demo? ## Stores -* [ ] `writable` (and second argument?) -* [ ] `$foo` -* [ ] `readable` -* [ ] `derive` +* [x] `writable` (and second argument?) +* [x] `$foo` +* [x] `readable` +* [x] `derive` +* [ ] custom stores +* [ ] `bind:value={$foo}` * [ ] `$foo += 1` (if we implement it) +## Motion + +* [ ] `tweened` +* [ ] `spring` + + ## Lifecycle * [ ] `onMount` diff --git a/site/src/routes/tutorial/[slug]/index.svelte b/site/src/routes/tutorial/[slug]/index.svelte index 9a4b1e6bb3..082c9a98bc 100644 --- a/site/src/routes/tutorial/[slug]/index.svelte +++ b/site/src/routes/tutorial/[slug]/index.svelte @@ -26,6 +26,7 @@ let repl; let prev; + let scrollable; const lookup = new Map(); sections.forEach(section => { @@ -46,6 +47,9 @@ }); }); + // TODO is there a non-hacky way to trigger scroll when chapter changes? + $: if (scrollable) chapter, scrollable.scrollTo(0, 0); + // TODO: this will need to be changed to the master branch, and probably should be dynamic instead of included // here statically const tutorial_repo_link = 'https://github.com/sveltejs/svelte/tree/restructure-docs/site/content/tutorial'; @@ -226,7 +230,7 @@ -
+
{@html chapter.html}
diff --git a/site/src/routes/tutorial/index.json.js b/site/src/routes/tutorial/index.json.js index f51c82c842..52b9e8aa33 100644 --- a/site/src/routes/tutorial/index.json.js +++ b/site/src/routes/tutorial/index.json.js @@ -9,27 +9,37 @@ function get_sections() { const sections = fs.readdirSync(`content/tutorial`) .filter(dir => /^\d+/.test(dir)) .map(dir => { - const meta = JSON.parse(fs.readFileSync(`content/tutorial/${dir}/meta.json`, 'utf-8')); + let meta; + + try { + meta = JSON.parse(fs.readFileSync(`content/tutorial/${dir}/meta.json`, 'utf-8')); + } catch (err) { + throw new Error(`Error reading metadata for ${dir}`); + } return { title: meta.title, chapters: fs.readdirSync(`content/tutorial/${dir}`) .filter(dir => /^\d+/.test(dir)) .map(tutorial => { - const md = fs.readFileSync(`content/tutorial/${dir}/${tutorial}/text.md`, 'utf-8'); - const { metadata, content } = extract_frontmatter(md); + try { + const md = fs.readFileSync(`content/tutorial/${dir}/${tutorial}/text.md`, 'utf-8'); + const { metadata } = extract_frontmatter(md); - const slug = tutorial.replace(/^\d+-/, ''); + const slug = tutorial.replace(/^\d+-/, ''); - if (slugs.has(slug)) throw new Error(`Duplicate slug: ${slug}`); - slugs.add(slug); + if (slugs.has(slug)) throw new Error(`Duplicate slug: ${slug}`); + slugs.add(slug); - return { - slug, - title: metadata.title, - section_dir: dir, - chapter_dir: tutorial, - }; + return { + slug, + title: metadata.title, + section_dir: dir, + chapter_dir: tutorial, + }; + } catch (err) { + throw new Error(`Error building tutorial ${dir}/${tutorial}: ${err.message}`); + } }) } }); @@ -38,13 +48,23 @@ function get_sections() { } export function get(req, res) { - if (!json || process.env.NODE_ENV !== 'production') { - json = JSON.stringify(get_sections()); - } + try { + if (!json || process.env.NODE_ENV !== 'production') { + json = JSON.stringify(get_sections()); + } - res.set({ - 'Content-Type': 'application/json' - }); + res.set({ + 'Content-Type': 'application/json' + }); - res.end(json); + res.end(json); + } catch (err) { + res.writeHead(500, { + 'Content-Type': 'application/json' + }); + + res.end(JSON.stringify({ + message: err.message + })); + } }