diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml index 9acc6de3f..cb004fcf5 100644 --- a/.github/workflows/node.js.yml +++ b/.github/workflows/node.js.yml @@ -16,7 +16,7 @@ jobs: strategy: matrix: - node-version: [18.x] + node-version: [20.x] # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ steps: diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 000000000..0598ad131 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,9 @@ +MIT License + +Copyright (c) 2023 [these people](https://github.com/sveltejs/learn.svelte.dev/graphs/contributors) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md index d99fc947c..8866c4475 100644 --- a/README.md +++ b/README.md @@ -6,21 +6,21 @@ A soup-to-nuts interactive tutorial on how to build apps with Svelte. This repo uses [pnpm](https://pnpm.io/). -## Running the app +## Developing the app -First, run `node scripts/create-common-bundle`. This packages up everything that's needed to run a SvelteKit app (Vite, Esbuild, SvelteKit, Svelte compiler etc) which can subsequently be unpacked on a server to create and run and instance of a SvelteKit application (which powers the output window of the tutorial). +First, run `node scripts/create-common-bundle`. This packages up everything that's needed to run a SvelteKit app (Vite, esbuild, SvelteKit, Svelte compiler, etc.) which can subsequently be unpacked on a server to create and run an instance of a SvelteKit application (which powers the output window of the tutorial). Then, run `dev`: -The next steps depend on whether you want to run this locally in filesystem mode, or in WebContainer mode. For now, it works with filesystem mode only locally. In future, it will run both locally and on the web (using [WebContainers](https://blog.stackblitz.com/posts/introducing-webcontainers/)). +```bash +node scripts/create-common-bundle +pnpm dev +``` -### Local/filesystem mode +To build for production and run locally: -1. add an `.env` file with `PUBLIC_USE_FILESYSTEM=true` in it -2. Run the app locally with `pnpm dev` or `pnpm build && pnpm preview`. - -### WebContainer mode - -1. if an `.env` file exists, modify it so there's `PUBLIC_USE_FILESYSTEM=` in it -2. Run the app locally with `pnpm dev` or `pnpm build && pnpm preview`. +```bash +pnpm build +pnpm preview +``` ## Creating new tutorials @@ -28,4 +28,4 @@ Tutorials live inside `content`. Each tutorial consists of a `README.md`, which ## Bumping tutorial dependencies -Bump the dependency (for example Svelte) in both the root and the `content/common` `package.json`. In the root do `pnpm i` (to update `pnpm-lock.yaml`), in `content/common` do `npm i` (to update `package-lock.json`). After deployment things might be out of date because Vercel caches things, redeploy without cache in that case. +Bump the dependency (for example Svelte) in both the root and the `content/common` `package.json`. In the root do `pnpm i` (to update `pnpm-lock.yaml`), in `content/common` do `npm i` (to update `package-lock.json`). \ No newline at end of file diff --git a/backend/+server.js b/backend/+server.js deleted file mode 100644 index 951581de2..000000000 --- a/backend/+server.js +++ /dev/null @@ -1,14 +0,0 @@ -import { json } from '@sveltejs/kit'; -import { create } from './apps'; - -/** @type {import('./$types').RequestHandler} */ -export async function POST({ request }) { - return json( - await create({ - files: await request.json() - }), - { - status: 201 // should this be a 200? - } - ); -} diff --git a/backend/README.md b/backend/README.md deleted file mode 100644 index 39de3f70c..000000000 --- a/backend/README.md +++ /dev/null @@ -1 +0,0 @@ -This used to live in src/routes/backend, but it makes it impossible to use with edge functions. Keeping it here in case we need it in future. diff --git a/backend/[id]/+server.js b/backend/[id]/+server.js deleted file mode 100644 index 918ddfefd..000000000 --- a/backend/[id]/+server.js +++ /dev/null @@ -1,17 +0,0 @@ -import { clear, update } from '../apps'; - -/** @type {import('./$types').RequestHandler} */ -export async function PUT({ url, request, params }) { - const { id } = params; - const files = await request.json(); - - if (url.searchParams.has('reset')) { - clear({ id, files }); - } - - update({ id, files }); - - return new Response(undefined, { - status: 201 - }); -} diff --git a/backend/apps.js b/backend/apps.js deleted file mode 100644 index 80b0669d8..000000000 --- a/backend/apps.js +++ /dev/null @@ -1,208 +0,0 @@ -import fs from 'node:fs'; -import path from 'node:path'; -import { spawn } from 'node:child_process'; -import { createRequire } from 'node:module'; -import * as ports from 'port-authority'; -import { broadcast, ready } from './ws'; - -/** - * @typedef {{ - * process: import('child_process').ChildProcess, - * filenames: string[] - * }} App */ - -fs.rmSync('.apps', { recursive: true, force: true }); -fs.mkdirSync('.apps', { recursive: true }); - -// poor man's HMR, pending https://github.com/vitejs/vite/issues/7887 -// @ts-expect-error -if (globalThis.__apps) { - globalThis.__apps.forEach((app) => { - app.process.kill(); - }); -} - -const require = createRequire(import.meta.url); -const vite_pkg_file = require.resolve('vite/package.json'); -const vite_pkg = JSON.parse(fs.readFileSync(vite_pkg_file, 'utf-8')); -const vite = path.resolve(vite_pkg_file, '..', vite_pkg.bin['vite']); - -/** @type {Map} */ -const apps = new Map(); -globalThis.__apps = apps; - -const hooks_src = `/** @type {import('@sveltejs/kit').Handle} */ -export async function handle({ event, resolve }) { - const response = await resolve(event); - - response.headers.set('cross-origin-opener-policy', 'same-origin'); - response.headers.set('cross-origin-embedder-policy', 'require-corp'); - response.headers.set('cross-origin-resource-policy', 'cross-origin'); - - return response; -}`; - -/** - * @param {{ - * files: import('$lib/types').FileStub[] - * }} options - */ -export async function create({ files }) { - const id = String(Date.now()); - const filenames = write_files(id, files); - - // TODO this enables embedding on cross-origin sites, which is - // necessary for the JSNation talk, but will currently break if an app - // already has a src/hooks.server.js file (though it could be worked - // around easily enough if necessary) - if (!files.find((stub) => stub.name === '/src/hooks.server.js')) { - fs.writeFileSync(`.apps/${id}/src/hooks.server.js`, hooks_src); - } - - const port = await ports.find(3001); - - apps.set(id, { - process: launch(id, String(port)), - filenames - }); - - await ports.waitUntilBusy(port); - - await ready; - - return { - id, - port - }; -} - -/** - * @param {{ - * id: string; - * files: import('$lib/types').FileStub[] - * }} options - */ -export function clear({ id, files }) { - const app = apps.get(id); - - if (!app) { - throw new Error(`app ${id} does not exist`); - } - - const dir = `.apps/${id}`; - const old_filenames = new Set(app.filenames); - - /** @type {string[]} */ - const filenames = []; - - for (const file of files) { - if (file.type === 'file') { - filenames.push(file.name); - old_filenames.delete(file.name); - } - } - - for (const file of old_filenames) { - if (fs.existsSync(dir + file)) { - fs.unlinkSync(dir + file); - } - } - - app.filenames = filenames; -} - -/** - * @param {{ - * id: string; - * files: import('$lib/types').FileStub[] - * }} options - */ -export function update({ id, files }) { - if (!apps.has(id)) { - throw new Error(`app ${id} does not exist`); - } - - write_files(id, files); -} - -/** - * @param {{ id: string }} options - */ -export function destroy({ id }) { - const dir = `.apps/${id}`; - - fs.rmSync(dir, { recursive: true, force: true }); - - apps.get(id)?.process.kill(); - apps.delete(id); -} - -/** - * @param {string} id - * @param {string} port - */ -function launch(id, port) { - const cwd = `.apps/${id}`; - - const process = spawn('node', [vite, 'dev', '--port', port], { - cwd - }); - - process.stdout.on('data', (data) => { - broadcast({ id, data: data.toString(), type: 'stdout' }); - }); - - process.stderr.on('data', (data) => { - broadcast({ id, data: data.toString(), type: 'stderr' }); - }); - - return process; -} - -/** - * - * @param {string} file - * @param {string | Buffer} contents - */ -function write_if_changed(file, contents) { - if (typeof contents === 'string' && fs.existsSync(file)) { - const existing = fs.readFileSync(file, 'utf-8'); - if (contents === existing) return; - } - - fs.mkdirSync(path.dirname(file), { recursive: true }); - fs.writeFileSync(file, contents); -} - -/** - * - * @param {string} id - * @param {import('$lib/types').FileStub[]} files - */ -function write_files(id, files) { - const dir = `.apps/${id}`; - - /** @type {string[]} */ - const filenames = []; - - for (const file of files) { - if (file.type === 'file') { - filenames.push(file.name); - - const dest = `${dir}/${file.name}`; - let content = file.text ? file.contents : Buffer.from(file.contents, 'base64'); - - if (file.name === '/src/app.html' && typeof content === 'string') { - // TODO handle case where config.kit.files.template is different - content = content.replace( - '', - '' - ); - } - - write_if_changed(dest, content); - } - } - - return filenames; -} diff --git a/backend/destroy/+server.js b/backend/destroy/+server.js deleted file mode 100644 index ad9c89efd..000000000 --- a/backend/destroy/+server.js +++ /dev/null @@ -1,14 +0,0 @@ -import { destroy } from '../apps'; - -// this is implemented as a POST handler because it is -// triggered by `navigator.sendBeacon` rather than `fetch` - -/** @type {import('./$types').RequestHandler} */ -export function POST({ url }) { - const id = /** @type {string} */ (url.searchParams.get('id')); - destroy({ id }); - - return new Response(undefined, { - status: 204 - }); -} diff --git a/backend/ws.js b/backend/ws.js deleted file mode 100644 index e02317c0d..000000000 --- a/backend/ws.js +++ /dev/null @@ -1,33 +0,0 @@ -// import './websocket.js'; -import { WebSocketServer } from 'ws'; - -// poor man's HMR, pending https://github.com/vitejs/vite/issues/7887 -// @ts-expect-error -if (globalThis.__wss) globalThis.__wss.close(); - -const wss = new WebSocketServer({ port: 4567 }); -globalThis.__wss = wss; - -/** @type {Set} */ -const connections = new Set(); - -wss.on('connection', (ws) => { - connections.add(ws); - - ws.on('close', () => { - connections.delete(ws); - }); -}); - -export const ready = new Promise((fulfil) => { - wss.on('listening', () => { - fulfil(undefined); - }); -}); - -/** @param {any} data */ -export function broadcast(data) { - for (const connection of connections) { - connection.send(JSON.stringify(data)); - } -} diff --git a/content/tutorial/01-svelte/01-introduction/03-dynamic-attributes/README.md b/content/tutorial/01-svelte/01-introduction/03-dynamic-attributes/README.md index e03524b1a..6c325239f 100644 --- a/content/tutorial/01-svelte/01-introduction/03-dynamic-attributes/README.md +++ b/content/tutorial/01-svelte/01-introduction/03-dynamic-attributes/README.md @@ -32,5 +32,5 @@ It's not uncommon to have an attribute where the name and value are the same, li ```svelte /// file: App.svelte -A man dances. +{name} dances. ``` diff --git a/content/tutorial/01-svelte/01-introduction/06-html-tags/README.md b/content/tutorial/01-svelte/01-introduction/06-html-tags/README.md index 914e76bbf..801b22a1d 100644 --- a/content/tutorial/01-svelte/01-introduction/06-html-tags/README.md +++ b/content/tutorial/01-svelte/01-introduction/06-html-tags/README.md @@ -13,4 +13,4 @@ In Svelte, you do this with the special `{@html ...}` tag:

{+++@html+++ string}

``` -> **Warning!** Svelte doesn't perform any sanitization of the expression inside `{@html ...}` before it gets inserted into the DOM. In other words, if you use this feature it's critical that you manually escape HTML that comes from sources you don't trust, otherwise you risk exposing your users to Cross-Site Scripting (XSS) attacks. +> **Warning!** Svelte doesn't perform any sanitization of the expression inside `{@html ...}` before it gets inserted into the DOM. This isn't an issue if the content is something you trust like an article you wrote yourself. However if it's some untrusted user content, e.g. a comment on an article, then it's critical that you manually escape it, otherwise you risk exposing your users to Cross-Site Scripting (XSS) attacks. diff --git a/content/tutorial/01-svelte/02-reactivity/02-reactive-declarations/README.md b/content/tutorial/01-svelte/02-reactivity/02-reactive-declarations/README.md index 16fb5dfb1..0ef6f276f 100644 --- a/content/tutorial/01-svelte/02-reactivity/02-reactive-declarations/README.md +++ b/content/tutorial/01-svelte/02-reactivity/02-reactive-declarations/README.md @@ -12,6 +12,8 @@ let count = 0; +++$: doubled = count * 2;+++ ``` +If a reactive statement consists entirely of an assignment to an undeclared variable, Svelte will inject a `let` declaration on your behalf. + > Don't worry if this looks a little alien. It's [valid](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/label) (if unconventional) JavaScript, which Svelte interprets to mean 're-run this code whenever any of the referenced values change'. Once you get used to it, there's no going back. Let's use `doubled` in our markup: @@ -24,3 +26,5 @@ Let's use `doubled` in our markup: ``` Of course, you could just write `{count * 2}` in the markup instead — you don't have to use reactive values. Reactive values become particularly valuable (no pun intended) when you need to reference them multiple times, or you have values that depend on _other_ reactive values. + +> Note that reactive declarations and statements will run after other script code and before component markup is rendered. diff --git a/content/tutorial/01-svelte/02-reactivity/04-updating-arrays-and-objects/README.md b/content/tutorial/01-svelte/02-reactivity/04-updating-arrays-and-objects/README.md index 74e3a581f..49e0654ab 100644 --- a/content/tutorial/01-svelte/02-reactivity/04-updating-arrays-and-objects/README.md +++ b/content/tutorial/01-svelte/02-reactivity/04-updating-arrays-and-objects/README.md @@ -38,8 +38,9 @@ A simple rule of thumb: the name of the updated variable must appear on the left ```js /// no-file +const obj = { foo: { bar: 1 } }; const foo = obj.foo; -foo.bar = 'baz'; +foo.bar = 2; ``` ...won't trigger reactivity on `obj.foo.bar`, unless you follow it up with `obj = obj`. diff --git a/content/tutorial/01-svelte/02-reactivity/04-updating-arrays-and-objects/app-a/src/lib/App.svelte b/content/tutorial/01-svelte/02-reactivity/04-updating-arrays-and-objects/app-a/src/lib/App.svelte index 77d176923..ab6ef7074 100644 --- a/content/tutorial/01-svelte/02-reactivity/04-updating-arrays-and-objects/app-a/src/lib/App.svelte +++ b/content/tutorial/01-svelte/02-reactivity/04-updating-arrays-and-objects/app-a/src/lib/App.svelte @@ -5,7 +5,7 @@ numbers.push(numbers.length + 1); } - $: sum = numbers.reduce((t, n) => t + n, 0); + $: sum = numbers.reduce((total, currentNumber) => total + currentNumber, 0);

{numbers.join(' + ')} = {sum}

diff --git a/content/tutorial/01-svelte/02-reactivity/04-updating-arrays-and-objects/app-b/src/lib/App.svelte b/content/tutorial/01-svelte/02-reactivity/04-updating-arrays-and-objects/app-b/src/lib/App.svelte index d15f58c4d..730ae8cc7 100644 --- a/content/tutorial/01-svelte/02-reactivity/04-updating-arrays-and-objects/app-b/src/lib/App.svelte +++ b/content/tutorial/01-svelte/02-reactivity/04-updating-arrays-and-objects/app-b/src/lib/App.svelte @@ -5,7 +5,7 @@ numbers = [...numbers, numbers.length + 1]; } - $: sum = numbers.reduce((t, n) => t + n, 0); + $: sum = numbers.reduce((total, currentNumber) => total + currentNumber, 0);

{numbers.join(' + ')} = {sum}

diff --git a/content/tutorial/01-svelte/03-props/03-spread-props/app-a/src/lib/App.svelte b/content/tutorial/01-svelte/03-props/03-spread-props/app-a/src/lib/App.svelte index 4fb555240..2d5d7123b 100644 --- a/content/tutorial/01-svelte/03-props/03-spread-props/app-a/src/lib/App.svelte +++ b/content/tutorial/01-svelte/03-props/03-spread-props/app-a/src/lib/App.svelte @@ -4,7 +4,7 @@ const pkg = { name: 'svelte', speed: 'blazing', - version: 3, + version: 4, website: 'https://svelte.dev/' }; diff --git a/content/tutorial/01-svelte/03-props/03-spread-props/app-b/src/lib/App.svelte b/content/tutorial/01-svelte/03-props/03-spread-props/app-b/src/lib/App.svelte index 5934bdabf..3ded4fd56 100644 --- a/content/tutorial/01-svelte/03-props/03-spread-props/app-b/src/lib/App.svelte +++ b/content/tutorial/01-svelte/03-props/03-spread-props/app-b/src/lib/App.svelte @@ -4,7 +4,7 @@ const pkg = { name: 'svelte', speed: 'blazing', - version: 3, + version: 4, website: 'https://svelte.dev/' }; diff --git a/content/tutorial/01-svelte/04-logic/01-if-blocks/README.md b/content/tutorial/01-svelte/04-logic/01-if-blocks/README.md index 45d60b4bc..845b4ab99 100644 --- a/content/tutorial/01-svelte/04-logic/01-if-blocks/README.md +++ b/content/tutorial/01-svelte/04-logic/01-if-blocks/README.md @@ -18,4 +18,4 @@ To conditionally render some markup, we wrap it in an `if` block. Let's add some {/if}+++ ``` -Try it — update the component, and click on the buttons. +Try it — update the component, and click on the button. diff --git a/content/tutorial/01-svelte/04-logic/04-each-blocks/README.md b/content/tutorial/01-svelte/04-logic/04-each-blocks/README.md index 9c9e7ffc3..3011cbb8f 100644 --- a/content/tutorial/01-svelte/04-logic/04-each-blocks/README.md +++ b/content/tutorial/01-svelte/04-logic/04-each-blocks/README.md @@ -11,7 +11,7 @@ Instead of laboriously copying, pasting and editing, we can get rid of all but t
+++{#each colors as color}+++
``` diff --git a/content/tutorial/01-svelte/05-events/03-event-modifiers/README.md b/content/tutorial/01-svelte/05-events/03-event-modifiers/README.md index a47995a7c..5cccee218 100644 --- a/content/tutorial/01-svelte/05-events/03-event-modifiers/README.md +++ b/content/tutorial/01-svelte/05-events/03-event-modifiers/README.md @@ -17,7 +17,7 @@ The full list of modifiers: - `stopPropagation` — calls `event.stopPropagation()`, preventing the event reaching the next element - `passive` — improves scrolling performance on touch/wheel events (Svelte will add it automatically where it's safe to do so) - `nonpassive` — explicitly set `passive: false` -- `capture` — fires the handler during the _capture_ phase instead of the _bubbling_ phase ([MDN docs](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events#event_capture)) +- `capture` — fires the handler during the [_capture_](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events#event_capture) phase instead of the [_bubbling_](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events#event_bubbling) phase - `once` — remove the handler after the first time it runs - `self` — only trigger handler if event.target is the element itself - `trusted` — only trigger handler if `event.isTrusted` is `true`, meaning the event was triggered by a user action rather than because some JavaScript called `element.dispatchEvent(...)` diff --git a/content/tutorial/01-svelte/05-events/04-component-events/README.md b/content/tutorial/01-svelte/05-events/04-component-events/README.md index 71c34ee8f..12457f8ed 100644 --- a/content/tutorial/01-svelte/05-events/04-component-events/README.md +++ b/content/tutorial/01-svelte/05-events/04-component-events/README.md @@ -28,4 +28,4 @@ Then, add an `on:message` handler in `App.svelte`: ``` -> You can also try changing the event name to something else. For instance, change `dispatch('message')` to `dispatch('greet')` in `Inner.svelte` and change the attribute name from `on:message` to `on:greet` in `App.svelte`. +> You can also try changing the event name to something else. For instance, change `dispatch('message', {...})` to `dispatch('greet', {...})` in `Inner.svelte` and change the attribute name from `on:message` to `on:greet` in `App.svelte`. diff --git a/content/tutorial/01-svelte/05-events/06-dom-event-forwarding/app-a/src/lib/App.svelte b/content/tutorial/01-svelte/05-events/06-dom-event-forwarding/app-a/src/lib/App.svelte index b47a06f1e..33d318c91 100644 --- a/content/tutorial/01-svelte/05-events/06-dom-event-forwarding/app-a/src/lib/App.svelte +++ b/content/tutorial/01-svelte/05-events/06-dom-event-forwarding/app-a/src/lib/App.svelte @@ -6,6 +6,7 @@ audio.src = horn; function handleClick() { + audio.load(); audio.play(); } diff --git a/content/tutorial/01-svelte/06-bindings/03-checkbox-inputs/README.md b/content/tutorial/01-svelte/06-bindings/03-checkbox-inputs/README.md index 8df2be7c2..dc79573de 100644 --- a/content/tutorial/01-svelte/06-bindings/03-checkbox-inputs/README.md +++ b/content/tutorial/01-svelte/06-bindings/03-checkbox-inputs/README.md @@ -6,5 +6,5 @@ Checkboxes are used for toggling between states. Instead of binding to `input.va ```svelte /// file: App.svelte - + ``` diff --git a/content/tutorial/01-svelte/07-lifecycle/01-onmount/README.md b/content/tutorial/01-svelte/07-lifecycle/01-onmount/README.md index a996ca991..4195b5c69 100644 --- a/content/tutorial/01-svelte/07-lifecycle/01-onmount/README.md +++ b/content/tutorial/01-svelte/07-lifecycle/01-onmount/README.md @@ -4,7 +4,7 @@ title: onMount Every component has a _lifecycle_ that starts when it is created, and ends when it is destroyed. There are a handful of functions that allow you to run code at key moments during that lifecycle. The one you'll use most frequently is `onMount`, which runs after the component is first rendered to the DOM. -In this exercise, we have a `` that we'd like to animate, using the `paint` function in `gradient.js`. Begin by importing the function from `svelte`: +In this exercise, we have a `` that we'd like to animate, using the `paint` function in `gradient.js`. Begin by importing the `onMount` function from `svelte`: ```svelte /// file: App.svelte @@ -14,7 +14,7 @@ In this exercise, we have a `` that we'd like to animate, using the `pai ``` -Then, add a function that runs when the component mounts: +Then, add a callback that runs when the component mounts: ```svelte /// file: App.svelte @@ -41,7 +41,7 @@ So far so good — you should see gently undulating colours in the shape of the ```js /// file: App.svelte onMount(() => { - const canvas = document.querySelector('canvas') + const canvas = document.querySelector('canvas'); const context = canvas.getContext('2d'); +++let frame =+++ requestAnimationFrame(function loop(t) { @@ -49,10 +49,8 @@ onMount(() => { paint(context, t); }); - loop(); - +++ return () => { cancelAnimationFrame(frame); };+++ }); -``` \ No newline at end of file +``` diff --git a/content/tutorial/01-svelte/07-lifecycle/01-onmount/app-a/src/lib/App.svelte b/content/tutorial/01-svelte/07-lifecycle/01-onmount/app-a/src/lib/App.svelte index 39b42393d..b36b80ce0 100644 --- a/content/tutorial/01-svelte/07-lifecycle/01-onmount/app-a/src/lib/App.svelte +++ b/content/tutorial/01-svelte/07-lifecycle/01-onmount/app-a/src/lib/App.svelte @@ -5,7 +5,7 @@ +> - \ No newline at end of file + diff --git a/content/tutorial/02-advanced-svelte/05-bindings/03-media-elements/app-b/src/lib/AudioPlayer.svelte b/content/tutorial/02-advanced-svelte/05-bindings/03-media-elements/app-b/src/lib/AudioPlayer.svelte index eedbc07e5..fcfbc28ce 100644 --- a/content/tutorial/02-advanced-svelte/05-bindings/03-media-elements/app-b/src/lib/AudioPlayer.svelte +++ b/content/tutorial/02-advanced-svelte/05-bindings/03-media-elements/app-b/src/lib/AudioPlayer.svelte @@ -19,20 +19,21 @@
@@ -68,7 +69,7 @@ }); }} > -
+
{duration ? format(duration) : '--:--'}
diff --git a/content/tutorial/02-advanced-svelte/05-bindings/04-dimensions/README.md b/content/tutorial/02-advanced-svelte/05-bindings/04-dimensions/README.md index f92e77b03..bbc62bfb4 100644 --- a/content/tutorial/02-advanced-svelte/05-bindings/04-dimensions/README.md +++ b/content/tutorial/02-advanced-svelte/05-bindings/04-dimensions/README.md @@ -7,7 +7,8 @@ Every block-level element has `clientWidth`, `clientHeight`, `offsetWidth` and ` ```svelte /// file: App.svelte
- {text} + {text} + {w} x {h}px
``` diff --git a/content/tutorial/02-advanced-svelte/05-bindings/05-bind-this/app-a/src/lib/App.svelte b/content/tutorial/02-advanced-svelte/05-bindings/05-bind-this/app-a/src/lib/App.svelte index de10e6465..582abc630 100644 --- a/content/tutorial/02-advanced-svelte/05-bindings/05-bind-this/app-a/src/lib/App.svelte +++ b/content/tutorial/02-advanced-svelte/05-bindings/05-bind-this/app-a/src/lib/App.svelte @@ -20,7 +20,7 @@ +> diff --git a/content/tutorial/02-advanced-svelte/06-classes-and-styles/04-component-styles/README.md b/content/tutorial/02-advanced-svelte/06-classes-and-styles/04-component-styles/README.md new file mode 100644 index 000000000..c272846c3 --- /dev/null +++ b/content/tutorial/02-advanced-svelte/06-classes-and-styles/04-component-styles/README.md @@ -0,0 +1,58 @@ +--- +title: Component styles +--- + +Often, you need to influence the styles inside a child component. Perhaps we want to make these boxes red, green and blue. + +One way to do this is with the `:global` CSS modifier, which allows you to indiscriminately target elements inside other components: + +```svelte +/// file: App.svelte + +``` + +But there are lots of reasons _not_ to do that. For one thing, it's extremely verbose. For another, it's brittle — any changes to the implementation details of `Box.svelte` could break the selector. + +Most of all though, it's rude. Components should be able to decide for themselves which styles can be controlled from 'outside', in the same way they decide which variables are exposed as props. `:global` should be used as an escape hatch — a last resort. + +Inside `Box.svelte`, change `background-color` so that it is determined by a [CSS custom property](https://developer.mozilla.org/en-US/docs/Web/CSS/--*): + +```svelte +/// file: Box.svelte + +``` + +Any parent element (such as `
`) can set the value of `--color`, but we can also set it on individual components: + +```svelte +/// file: App.svelte +
+ + + +
+``` + +The values can be dynamic, like any other attribute. + +This feature works by wrapping each component in a `
`, where needed, and applying the custom properties to it. diff --git a/content/tutorial/02-advanced-svelte/06-classes-and-styles/04-component-styles/app-a/src/lib/App.svelte b/content/tutorial/02-advanced-svelte/06-classes-and-styles/04-component-styles/app-a/src/lib/App.svelte new file mode 100644 index 000000000..5e5f48c93 --- /dev/null +++ b/content/tutorial/02-advanced-svelte/06-classes-and-styles/04-component-styles/app-a/src/lib/App.svelte @@ -0,0 +1,9 @@ + + +
+ + + +
\ No newline at end of file diff --git a/content/tutorial/02-advanced-svelte/06-classes-and-styles/04-component-styles/app-a/src/lib/Box.svelte b/content/tutorial/02-advanced-svelte/06-classes-and-styles/04-component-styles/app-a/src/lib/Box.svelte new file mode 100644 index 000000000..87eee2f31 --- /dev/null +++ b/content/tutorial/02-advanced-svelte/06-classes-and-styles/04-component-styles/app-a/src/lib/Box.svelte @@ -0,0 +1,11 @@ +
+ + diff --git a/content/tutorial/02-advanced-svelte/06-classes-and-styles/04-component-styles/app-b/src/lib/App.svelte b/content/tutorial/02-advanced-svelte/06-classes-and-styles/04-component-styles/app-b/src/lib/App.svelte new file mode 100644 index 000000000..7de216df9 --- /dev/null +++ b/content/tutorial/02-advanced-svelte/06-classes-and-styles/04-component-styles/app-b/src/lib/App.svelte @@ -0,0 +1,9 @@ + + +
+ + + +
\ No newline at end of file diff --git a/content/tutorial/02-advanced-svelte/06-classes-and-styles/04-component-styles/app-b/src/lib/Box.svelte b/content/tutorial/02-advanced-svelte/06-classes-and-styles/04-component-styles/app-b/src/lib/Box.svelte new file mode 100644 index 000000000..c91e97bf7 --- /dev/null +++ b/content/tutorial/02-advanced-svelte/06-classes-and-styles/04-component-styles/app-b/src/lib/Box.svelte @@ -0,0 +1,11 @@ +
+ + diff --git a/content/tutorial/02-advanced-svelte/06-classes/meta.json b/content/tutorial/02-advanced-svelte/06-classes-and-styles/meta.json similarity index 74% rename from content/tutorial/02-advanced-svelte/06-classes/meta.json rename to content/tutorial/02-advanced-svelte/06-classes-and-styles/meta.json index ecad0ac09..35c1e5197 100644 --- a/content/tutorial/02-advanced-svelte/06-classes/meta.json +++ b/content/tutorial/02-advanced-svelte/06-classes-and-styles/meta.json @@ -1,5 +1,5 @@ { - "title": "Classes", + "title": "Classes and styles", "scope": { "prefix": "/src/lib/", "name": "src" diff --git a/content/tutorial/02-advanced-svelte/07-composition/01-slots/README.md b/content/tutorial/02-advanced-svelte/07-composition/01-slots/README.md index fbf7bb8ba..1f9fe948c 100644 --- a/content/tutorial/02-advanced-svelte/07-composition/01-slots/README.md +++ b/content/tutorial/02-advanced-svelte/07-composition/01-slots/README.md @@ -15,8 +15,8 @@ Just like elements can have children... ```svelte /// file: Card.svelte -
- ++++++ +
+ ++++++
``` diff --git a/content/tutorial/02-advanced-svelte/07-composition/01-slots/app-a/src/lib/paper.svg b/content/tutorial/02-advanced-svelte/07-composition/01-slots/app-a/src/lib/paper.svg index f8f704fdf..5dba50c15 100644 --- a/content/tutorial/02-advanced-svelte/07-composition/01-slots/app-a/src/lib/paper.svg +++ b/content/tutorial/02-advanced-svelte/07-composition/01-slots/app-a/src/lib/paper.svg @@ -6,5 +6,5 @@ - - \ No newline at end of file + + diff --git a/content/tutorial/02-advanced-svelte/07-composition/02-named-slots/README.md b/content/tutorial/02-advanced-svelte/07-composition/02-named-slots/README.md index 7918e0423..901e987ce 100644 --- a/content/tutorial/02-advanced-svelte/07-composition/02-named-slots/README.md +++ b/content/tutorial/02-advanced-svelte/07-composition/02-named-slots/README.md @@ -4,20 +4,20 @@ title: Named slots The previous example contained a _default slot_, which renders the direct children of a component. Sometimes you will need more control over placement. In those cases, we can use _named slots_. -Inside the `` component, we've got `` and others for `company` and `address`. Let's add the corresponding named slots in `Card.svelte`: +Inside `App.svelte`, we're rendering a `` component that contains `` and others for `company` and `address`. Let's add the corresponding named slots in `Card.svelte`: ```svelte /// file: Card.svelte
+++
- - + +
+++ - - + + +++
- +
+++
``` @@ -47,7 +47,7 @@ Alternatively, we could use the `:global` modifier inside `Card.svelte` to targe ```svelte /// file: Card.svelte -``` \ No newline at end of file +``` diff --git a/content/tutorial/02-advanced-svelte/07-composition/02-named-slots/app-a/src/lib/App.svelte b/content/tutorial/02-advanced-svelte/07-composition/02-named-slots/app-a/src/lib/App.svelte index 594151af4..a9bde36e5 100644 --- a/content/tutorial/02-advanced-svelte/07-composition/02-named-slots/app-a/src/lib/App.svelte +++ b/content/tutorial/02-advanced-svelte/07-composition/02-named-slots/app-a/src/lib/App.svelte @@ -14,7 +14,7 @@ Mergers and Aquisitions
- 358 Exchange Place, New York, N.Y. 100099 fax 212 555 6390 telex 10 4534 + 358 Exchange Place, New York, N.Y. 10099 fax 212 555 6390 telex 10 4534
diff --git a/content/tutorial/02-advanced-svelte/07-composition/02-named-slots/app-a/src/lib/paper.svg b/content/tutorial/02-advanced-svelte/07-composition/02-named-slots/app-a/src/lib/paper.svg index f8f704fdf..5dba50c15 100644 --- a/content/tutorial/02-advanced-svelte/07-composition/02-named-slots/app-a/src/lib/paper.svg +++ b/content/tutorial/02-advanced-svelte/07-composition/02-named-slots/app-a/src/lib/paper.svg @@ -6,5 +6,5 @@ - - \ No newline at end of file + + diff --git a/content/tutorial/02-advanced-svelte/07-composition/02-named-slots/app-b/src/lib/App.svelte b/content/tutorial/02-advanced-svelte/07-composition/02-named-slots/app-b/src/lib/App.svelte index 2613efd08..6ddf52dcc 100644 --- a/content/tutorial/02-advanced-svelte/07-composition/02-named-slots/app-b/src/lib/App.svelte +++ b/content/tutorial/02-advanced-svelte/07-composition/02-named-slots/app-b/src/lib/App.svelte @@ -14,7 +14,7 @@ Mergers and Aquisitions
- 358 Exchange Place, New York, N.Y. 100099 fax 212 555 6390 telex 10 4534 + 358 Exchange Place, New York, N.Y. 10099 fax 212 555 6390 telex 10 4534
diff --git a/content/tutorial/02-advanced-svelte/07-composition/03-slot-fallbacks/README.md b/content/tutorial/02-advanced-svelte/07-composition/03-slot-fallbacks/README.md index cb6169707..a65b270de 100644 --- a/content/tutorial/02-advanced-svelte/07-composition/03-slot-fallbacks/README.md +++ b/content/tutorial/02-advanced-svelte/07-composition/03-slot-fallbacks/README.md @@ -5,7 +5,7 @@ title: Slot fallbacks A component can specify _fallbacks_ for any slots that are left empty, by putting content inside the `` element: ```svelte -/// file: Box.svelte +/// file: Card.svelte
diff --git a/content/tutorial/02-advanced-svelte/07-composition/03-slot-fallbacks/app-a/src/lib/App.svelte b/content/tutorial/02-advanced-svelte/07-composition/03-slot-fallbacks/app-a/src/lib/App.svelte index 5bb5882ca..b7b99912f 100644 --- a/content/tutorial/02-advanced-svelte/07-composition/03-slot-fallbacks/app-a/src/lib/App.svelte +++ b/content/tutorial/02-advanced-svelte/07-composition/03-slot-fallbacks/app-a/src/lib/App.svelte @@ -14,7 +14,7 @@ Mergers and Aquisitions - 358 Exchange Place, New York, N.Y. 100099 fax 212 555 6390 telex 10 4534 + 358 Exchange Place, New York, N.Y. 10099 fax 212 555 6390 telex 10 4534 diff --git a/content/tutorial/02-advanced-svelte/07-composition/03-slot-fallbacks/app-a/src/lib/paper.svg b/content/tutorial/02-advanced-svelte/07-composition/03-slot-fallbacks/app-a/src/lib/paper.svg index f8f704fdf..5dba50c15 100644 --- a/content/tutorial/02-advanced-svelte/07-composition/03-slot-fallbacks/app-a/src/lib/paper.svg +++ b/content/tutorial/02-advanced-svelte/07-composition/03-slot-fallbacks/app-a/src/lib/paper.svg @@ -6,5 +6,5 @@ - - \ No newline at end of file + + diff --git a/content/tutorial/02-advanced-svelte/07-composition/04-slot-props/README.md b/content/tutorial/02-advanced-svelte/07-composition/04-slot-props/README.md index 896528c17..c8dbd89a4 100644 --- a/content/tutorial/02-advanced-svelte/07-composition/04-slot-props/README.md +++ b/content/tutorial/02-advanced-svelte/07-composition/04-slot-props/README.md @@ -12,7 +12,7 @@ Open `FilterableList.svelte`. The `` is being rendered for each filtered i /// file: FilterableList.svelte
{#each data.filter(matches) as item} - + {/each}
``` diff --git a/content/tutorial/02-advanced-svelte/07-composition/04-slot-props/app-a/src/lib/App.svelte b/content/tutorial/02-advanced-svelte/07-composition/04-slot-props/app-a/src/lib/App.svelte index 9757ff15d..1a7c9c9d5 100644 --- a/content/tutorial/02-advanced-svelte/07-composition/04-slot-props/app-a/src/lib/App.svelte +++ b/content/tutorial/02-advanced-svelte/07-composition/04-slot-props/app-a/src/lib/App.svelte @@ -10,7 +10,7 @@ field="name" >
- + name hex rgb @@ -18,7 +18,7 @@
- + {row.name} {row.hex} {row.rgb} diff --git a/content/tutorial/02-advanced-svelte/07-composition/04-slot-props/app-b/src/lib/App.svelte b/content/tutorial/02-advanced-svelte/07-composition/04-slot-props/app-b/src/lib/App.svelte index a21b37016..34c173fff 100644 --- a/content/tutorial/02-advanced-svelte/07-composition/04-slot-props/app-b/src/lib/App.svelte +++ b/content/tutorial/02-advanced-svelte/07-composition/04-slot-props/app-b/src/lib/App.svelte @@ -9,7 +9,7 @@ let:item={row} >
- + name hex rgb @@ -17,7 +17,7 @@
- + {row.name} {row.hex} {row.rgb} diff --git a/content/tutorial/02-advanced-svelte/07-composition/05-optional-slots/README.md b/content/tutorial/02-advanced-svelte/07-composition/05-optional-slots/README.md index 7f1d3d859..c9c219f69 100644 --- a/content/tutorial/02-advanced-svelte/07-composition/05-optional-slots/README.md +++ b/content/tutorial/02-advanced-svelte/07-composition/05-optional-slots/README.md @@ -7,7 +7,7 @@ In some cases, you may want to control parts of your component based on whether ```svelte /// file: App.svelte ---
- + name hex rgb @@ -31,7 +31,7 @@ We can fix that by using the special `$$slots` variable in `FilterableList.svelt /// file: FilterableList.svelte +++{#if $$slots.header}+++
- +
+++{/if}+++ ``` diff --git a/content/tutorial/02-advanced-svelte/07-composition/05-optional-slots/app-b/src/lib/App.svelte b/content/tutorial/02-advanced-svelte/07-composition/05-optional-slots/app-b/src/lib/App.svelte index de5be5138..0dde93327 100644 --- a/content/tutorial/02-advanced-svelte/07-composition/05-optional-slots/app-b/src/lib/App.svelte +++ b/content/tutorial/02-advanced-svelte/07-composition/05-optional-slots/app-b/src/lib/App.svelte @@ -9,7 +9,7 @@ let:item={row} >
- + {row.name} {row.hex} {row.rgb} diff --git a/content/tutorial/02-advanced-svelte/08-context/01-context-api/README.md b/content/tutorial/02-advanced-svelte/08-context/01-context-api/README.md index d88c5b015..208cf5798 100644 --- a/content/tutorial/02-advanced-svelte/08-context/01-context-api/README.md +++ b/content/tutorial/02-advanced-svelte/08-context/01-context-api/README.md @@ -86,5 +86,5 @@ import { getContext } from 'svelte'; const { count } = getContext('my-context'); -$: console.log({ count }); +$: console.log({ count: $count }); ``` diff --git a/content/tutorial/02-advanced-svelte/09-special-elements/01-svelte-self/README.md b/content/tutorial/02-advanced-svelte/09-special-elements/01-svelte-self/README.md index c117ad4ce..ea4e6a572 100644 --- a/content/tutorial/02-advanced-svelte/09-special-elements/01-svelte-self/README.md +++ b/content/tutorial/02-advanced-svelte/09-special-elements/01-svelte-self/README.md @@ -20,8 +20,8 @@ It's useful for things like this folder tree view, where folders can contain _ot ```svelte /// file: Folder.svelte {#if file.files} - ++++++ + ++++++ {:else} - + {/if} ``` diff --git a/content/tutorial/02-advanced-svelte/09-special-elements/02-svelte-component/README.md b/content/tutorial/02-advanced-svelte/09-special-elements/02-svelte-component/README.md index 0b31b2f81..bc16deb01 100644 --- a/content/tutorial/02-advanced-svelte/09-special-elements/02-svelte-component/README.md +++ b/content/tutorial/02-advanced-svelte/09-special-elements/02-svelte-component/README.md @@ -27,7 +27,7 @@ We _could_ do this with a sequence of `if` blocks... {/each} -++++++ +++++++ ``` The `this` value can be any component constructor, or a falsy value — if it's falsy, no component is rendered. diff --git a/content/tutorial/02-advanced-svelte/09-special-elements/09-svelte-options/README.md b/content/tutorial/02-advanced-svelte/09-special-elements/09-svelte-options/README.md index 145ed9407..6514e388c 100644 --- a/content/tutorial/02-advanced-svelte/09-special-elements/09-svelte-options/README.md +++ b/content/tutorial/02-advanced-svelte/09-special-elements/09-svelte-options/README.md @@ -26,6 +26,6 @@ The options that can be set here are: - `accessors={true}` — adds getters and setters for the component's props - `accessors={false}` — the default - `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 +- `customElement="..."` — the name to use when compiling this component as a custom element Consult the [API reference](https://svelte.dev/docs) for more information on these options. diff --git a/content/tutorial/02-advanced-svelte/09-special-elements/10-svelte-fragment/app-b/src/lib/App.svelte b/content/tutorial/02-advanced-svelte/09-special-elements/10-svelte-fragment/app-b/src/lib/App.svelte index 9ad2616ad..7b32fa007 100644 --- a/content/tutorial/02-advanced-svelte/09-special-elements/10-svelte-fragment/app-b/src/lib/App.svelte +++ b/content/tutorial/02-advanced-svelte/09-special-elements/10-svelte-fragment/app-b/src/lib/App.svelte @@ -1,10 +1,67 @@ - - -

All rights reserved.

-

Copyright (c) 2019 Svelte Industries

-
-
+
+ + + {#each squares as square, i} + + {/each} + + +
+ +
+
+
+ + diff --git a/content/tutorial/02-advanced-svelte/10-module-context/01-sharing-code/README.md b/content/tutorial/02-advanced-svelte/10-module-context/01-sharing-code/README.md index c726db3c2..bbf556be7 100644 --- a/content/tutorial/02-advanced-svelte/10-module-context/01-sharing-code/README.md +++ b/content/tutorial/02-advanced-svelte/10-module-context/01-sharing-code/README.md @@ -4,9 +4,9 @@ title: Sharing code In all the examples we've seen so far, the ` ``` diff --git a/content/tutorial/02-advanced-svelte/10-module-context/02-module-exports/app-b/src/lib/AudioPlayer.svelte b/content/tutorial/02-advanced-svelte/10-module-context/02-module-exports/app-b/src/lib/AudioPlayer.svelte index 0eaa4a16e..323286b79 100644 --- a/content/tutorial/02-advanced-svelte/10-module-context/02-module-exports/app-b/src/lib/AudioPlayer.svelte +++ b/content/tutorial/02-advanced-svelte/10-module-context/02-module-exports/app-b/src/lib/AudioPlayer.svelte @@ -42,13 +42,13 @@ on:ended={() => { time = 0; }} - /> + >
@@ -84,7 +84,7 @@ }); }} > -
+
{duration ? format(duration) : '--:--'}
diff --git a/content/tutorial/02-advanced-svelte/common/src/routes/+error.svelte b/content/tutorial/02-advanced-svelte/common/src/routes/+error.svelte index 930ccfd10..fb5551052 100644 --- a/content/tutorial/02-advanced-svelte/common/src/routes/+error.svelte +++ b/content/tutorial/02-advanced-svelte/common/src/routes/+error.svelte @@ -11,7 +11,7 @@ code {$page.status}

diff --git a/content/tutorial/03-sveltekit/01-concepts/01-introducing-sveltekit/README.md b/content/tutorial/03-sveltekit/01-concepts/01-introducing-sveltekit/README.md index 90592b276..d9b1e5311 100644 --- a/content/tutorial/03-sveltekit/01-concepts/01-introducing-sveltekit/README.md +++ b/content/tutorial/03-sveltekit/01-concepts/01-introducing-sveltekit/README.md @@ -2,7 +2,7 @@ title: What is SvelteKit? --- -SvelteKit is a framework for building extremely high-performance web apps. Whereas Svelte is a _component framework_, SvelteKit is an _app framework_ (or 'metaframework', depending on who you ask) that solves the tricky problems of building something production-ready: +Whereas Svelte is a _component framework_, SvelteKit is an _app framework_ (or 'metaframework', depending on who you ask) that solves the tricky problems of building something production-ready: - Routing - Server-side rendering @@ -18,4 +18,20 @@ SvelteKit is a framework for building extremely high-performance web apps. Where SvelteKit apps are server-rendered by default (like traditional 'multi-page apps' or MPAs) for excellent first load performance and SEO characteristics, but can then transition to client-side navigation (like modern 'single-page apps' or SPAs) to avoid jankily reloading everything (including things like third-party analytics code) when the user navigates. They can run anywhere JavaScript runs, though — as we'll see — your users may not need to run any JavaScript at all. -If that sounds complicated, worry not: SvelteKit is the framework that grows with you! Start simple and add new features as they come. This tutorial will go over the core concepts, while the [Advanced SvelteKit](/tutorial/handle) tutorial teaches you how to tackle more complex use cases. +If that sounds complicated, worry not: SvelteKit is the framework that grows with you! Start simple and add new features as you need them. + +## Project structure + +On the right, in the file tree viewer, you'll see a handful of files that SvelteKit expects to find in a project. + +`package.json` will be familiar if you've worked with Node.js before. It lists the project's dependencies — including `svelte` and `@sveltejs/kit` — and a variety of `scripts` for interacting with the SvelteKit CLI. (We're currently running `npm run dev` in the bottom window.) + +> Note that it also specifies `"type": "module"`, which means that `.js` files are treated as native JavaScript modules by default, rather than the legacy CommonJS format. + +`svelte.config.js` contains your project configuration. We don't need to worry about this file for now, but if you're curious, [visit the documentation](https://kit.svelte.dev/docs/configuration). + +`vite.config.js` contains the [Vite](https://vitejs.dev/) configuration. Because SvelteKit uses Vite, you can use [Vite features](https://vitejs.dev/guide/features.html) like hot module replacement, TypeScript support, static asset handling and so on. + +`src` is where your app's source code goes. `src/app.html` is your page template (SvelteKit replaces the `%sveltekit.head%` and `%sveltekit.body%` as appropriate), and `src/routes` defines the [routes](/tutorial/pages) of your app. + +Finally, `static` contains any assets (like a `favicon.png` or a `robots.txt`) that should be included when your app is deployed. \ No newline at end of file diff --git a/content/tutorial/03-sveltekit/01-concepts/02-project-structure/README.md b/content/tutorial/03-sveltekit/01-concepts/02-project-structure/README.md deleted file mode 100644 index 46a7c971a..000000000 --- a/content/tutorial/03-sveltekit/01-concepts/02-project-structure/README.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -title: Project structure ---- - -On the right, in the file tree viewer, you'll see a handful of files that SvelteKit expects to find in a project. - -`package.json` will be familiar if you've worked with Node.js before. It lists the project's dependencies — including `svelte` and `@sveltejs/kit` — and a variety of `scripts` for interacting with the SvelteKit CLI. (We're currently running `npm run dev` in the bottom window.) - -> Note that it also specifies `"type": "module"`, which means that `.js` files are treated as native JavaScript modules by default, rather than the legacy CommonJS format. - -`svelte.config.js` contains your project configuration. We don't need to worry about this file for now, but if you're curious, [visit the documentation](https://kit.svelte.dev/docs/configuration). - -`src` is where your app's source code goes. `src/app.html` is your page template (SvelteKit replaces the `%sveltekit.head%` and `%sveltekit.body%` as appropriate), and `src/routes` defines the [routes](/tutorial/pages) of your app. - -Finally, `static` contains any assets (like a `favicon.png` or a `robots.txt`) that should be included when your app is deployed. diff --git a/content/tutorial/03-sveltekit/01-concepts/03-server-and-client/README.md b/content/tutorial/03-sveltekit/01-concepts/03-server-and-client/README.md deleted file mode 100644 index e9b409b79..000000000 --- a/content/tutorial/03-sveltekit/01-concepts/03-server-and-client/README.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -title: Server and client ---- - -A SvelteKit app can be thought of as two distinct entities working in tandem — the _server_ and the _client_. - -'Server' is, perhaps, a confusing word since your app will often be running in a _serverless_ environment (cloud/edge functions) or might even be deployed as a set of completely static files. But it's the best we've got. The server's basic job is to turn a request into a response. - -'Client' refers to the JavaScript that loads in the browser. - -SvelteKit makes the two communicate with each other seamlessly. On the initial page load, the server renders the HTML, meaning content is visible as quickly as possible. The client then takes over in a process called 'hydration', so that subsequent navigations happen without full page reloads. It will request additional code and data from the server as needed. - -> You can [adjust this behavior](https://kit.svelte.dev/docs/page-options) as needed. SvelteKit is very versatile! diff --git a/content/tutorial/03-sveltekit/01-concepts/meta.json b/content/tutorial/03-sveltekit/01-concepts/meta.json index 75021ded3..fd70acd69 100644 --- a/content/tutorial/03-sveltekit/01-concepts/meta.json +++ b/content/tutorial/03-sveltekit/01-concepts/meta.json @@ -1,3 +1,3 @@ { - "title": "Concepts" + "title": "Introduction" } diff --git a/content/tutorial/03-sveltekit/02-routing/02-layouts/README.md b/content/tutorial/03-sveltekit/02-routing/02-layouts/README.md index e7812fead..79898d168 100644 --- a/content/tutorial/03-sveltekit/02-routing/02-layouts/README.md +++ b/content/tutorial/03-sveltekit/02-routing/02-layouts/README.md @@ -14,7 +14,7 @@ src/routes/ └ +page.svelte ``` -...and move the duplicated content from the `+page.svelte` files into the new `+layout.svelte` file. The `` element is where the page content will be rendered: +...and move the duplicated content from the `+page.svelte` files into the new `+layout.svelte` file. The `` element is where the page content will be rendered: ```svelte /// file: src/routes/+layout.svelte @@ -23,7 +23,7 @@ src/routes/ about - + ``` A `+layout.svelte` file applies to every child route, including the sibling `+page.svelte` (if it exists). You can nest layouts to arbitrary depth. diff --git a/content/tutorial/03-sveltekit/03-loading-data/01-page-data/README.md b/content/tutorial/03-sveltekit/03-loading-data/01-page-data/README.md index f23ff32c3..8d9b4049b 100644 --- a/content/tutorial/03-sveltekit/03-loading-data/01-page-data/README.md +++ b/content/tutorial/03-sveltekit/03-loading-data/01-page-data/README.md @@ -7,7 +7,7 @@ At its core, SvelteKit's job boils down to three things: 1. **Routing** — figure out which route matches an incoming request 2. **Loading** — get the data needed by the route -3. **Rendering** - generate some HTML (on the server) or update the DOM (in the browser) +3. **Rendering** — generate some HTML (on the server) or update the DOM (in the browser) We've seen how routing and rendering work. Let's talk about the middle part — loading. diff --git a/content/tutorial/03-sveltekit/03-loading-data/02-layout-data/README.md b/content/tutorial/03-sveltekit/03-loading-data/02-layout-data/README.md index 60e262c68..a96aab1ad 100644 --- a/content/tutorial/03-sveltekit/03-loading-data/02-layout-data/README.md +++ b/content/tutorial/03-sveltekit/03-loading-data/02-layout-data/README.md @@ -19,7 +19,7 @@ Now, add a sidebar in the layout for the post page:
- +
+++
+
diff --git a/src/routes/tutorial/[slug]/Output.svelte b/src/routes/tutorial/[slug]/Output.svelte index 59b94af4e..629a2cf5b 100644 --- a/src/routes/tutorial/[slug]/Output.svelte +++ b/src/routes/tutorial/[slug]/Output.svelte @@ -1,11 +1,11 @@ -
{ - if (sessionStorage[copy_enabled]) return; - - /** @type {HTMLElement | null} */ - let node = /** @type {HTMLElement} */ (e.target); - - while (node && node !== e.currentTarget) { - if (node.nodeName === 'PRE') { - show_modal = true; +
+
{ + if (sessionStorage[copy_enabled]) return; - e.preventDefault(); - return; - } + /** @type {HTMLElement | null} */ + let node = /** @type {HTMLElement} */ (e.target); - node = /** @type {HTMLElement | null} */ (node.parentNode); - } - }} -> - -
{ - const node = /** @type {HTMLElement} */ (e.target); + while (node && node !== e.currentTarget) { + if (node.nodeName === 'PRE') { + show_modal = true; - if (node.nodeName === 'CODE') { - const { file } = node.dataset; - if (file) { - dispatch('select', { file }); + e.preventDefault(); + return; } - } - if (node.nodeName === 'SPAN' && node.classList.contains('filename')) { - const file = exercise.scope.prefix + node.textContent; - dispatch('select', { file }); + node = /** @type {HTMLElement | null} */ (node.parentNode); } }} > - {@html exercise.html} + + +
{ + const node = /** @type {HTMLElement} */ (e.target); + + if (node.nodeName === 'CODE') { + const { file } = node.dataset; + if (file) { + dispatch('select', { file }); + } + } + + if (node.nodeName === 'SPAN' && node.classList.contains('filename')) { + const file = exercise.scope.prefix + node.textContent; + dispatch('select', { file }); + } + }} + > + {@html exercise.html} +
+ + {#if exercise.next} +

Next: {exercise.next.title}

+ {/if}
- {#if exercise.next} -

Next: {exercise.next.title}

- {/if} -
- - + +
{#if show_modal} (show_modal = false)}> @@ -113,9 +107,16 @@ {/if}