From 40f7923a44648649e13bd0ba98bfa01021eadabc Mon Sep 17 00:00:00 2001 From: Will Marquardt Date: Thu, 9 Mar 2023 15:44:07 +0100 Subject: [PATCH 001/303] Provide a link to the relevant docs until the tutorial is ready (#233) --- .../03-loading-data/03-universal-load-functions/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/content/tutorial/02-sveltekit/03-loading-data/03-universal-load-functions/README.md b/content/tutorial/02-sveltekit/03-loading-data/03-universal-load-functions/README.md index 38bdaa984..2c09853bb 100644 --- a/content/tutorial/02-sveltekit/03-loading-data/03-universal-load-functions/README.md +++ b/content/tutorial/02-sveltekit/03-loading-data/03-universal-load-functions/README.md @@ -4,6 +4,8 @@ title: Universal load functions > Coming soon +In the meantime, read the [documentation](https://kit.svelte.dev/docs/load#shared-vs-server) to learn more about the distinction between server `load` functions and universal `load` functions. + - { - if (!cancelling) return; - commit(e); - }} - on:keyup={(e) => { - if (e.key === 'Enter') { - commit(e); - } - - if (e.key === 'Escape') { - cancel(); - } - }} - /> -{:else} - - - {#if actions.length > 0} -
- {#each actions as action} -
+
  • + {#if renaming} + + { + if (!cancelling) { + commit(e); + } + }} + on:keyup={(e) => { + if (e.key === 'Enter') { + commit(e); + } + + if (e.key === 'Escape') { + cancel(); + } + }} + /> + {:else} + + + {#if actions.length > 0} +
    + {#each actions as action} +
    + {/if} {/if} -{/if} +
  • diff --git a/src/routes/tutorial/[slug]/state.js b/src/routes/tutorial/[slug]/state.js index fdd1c4267..1059950e8 100644 --- a/src/routes/tutorial/[slug]/state.js +++ b/src/routes/tutorial/[slug]/state.js @@ -12,6 +12,7 @@ import { derived, writable } from 'svelte/store'; * editing_constraints: import("$lib/types").EditingConstraints; * scope: import('$lib/types').Scope; * }; + * expanded: Record; * }} State */ @@ -29,8 +30,9 @@ const { subscribe, set, update } = writable({ create: [], remove: [] }, - scope: { depth: 0, name: '', prefix: '' } - } + scope: { name: '', prefix: '' } + }, + expanded: {} }); export const state = { @@ -69,6 +71,17 @@ export const state = { remove: exercise.editing_constraints.remove }; + /** @type {Record} */ + const expanded = { + '': true + }; + + for (const stub of Object.values(exercise.a)) { + if (stub.type === 'directory') { + expanded[stub.name] = true; + } + } + // TODO should exercise.a/b be an array in the first place? for (const stub of Object.values(exercise.b)) { if (stub.type === 'file' && stub.contents.startsWith('__delete')) { @@ -107,7 +120,8 @@ export const state = { scope: exercise.scope }, last_updated: undefined, - selected: exercise.focus + selected: exercise.focus, + expanded }); }, @@ -120,6 +134,20 @@ export const state = { })); }, + /** + * @param {string} name + * @param {boolean} [expanded] + */ + toggle_expanded: (name, expanded) => { + update((state) => ({ + ...state, + expanded: { + ...state.expanded, + [name]: expanded ?? !state.expanded[name] + } + })); + }, + /** @param {string | null} name */ select_file: (name) => { update((state) => ({ From bed4f26ea982aaf17879207f76a1c5ccffa02886 Mon Sep 17 00:00:00 2001 From: tomoam <29677552+tomoam@users.noreply.github.com> Date: Sat, 11 Mar 2023 00:07:25 +0900 Subject: [PATCH 011/303] fix: prevent iframe from reloading when a folder is clicked (#245) --- src/routes/tutorial/[slug]/state.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/routes/tutorial/[slug]/state.js b/src/routes/tutorial/[slug]/state.js index 1059950e8..575fd0b65 100644 --- a/src/routes/tutorial/[slug]/state.js +++ b/src/routes/tutorial/[slug]/state.js @@ -2,7 +2,7 @@ import { derived, writable } from 'svelte/store'; /** * @typedef {{ - * status: 'initial' | 'select' | 'set' | 'update' | 'switch'; + * status: 'initial' | 'select' | 'set' | 'update' | 'switch' | 'expand'; * stubs: import("$lib/types").Stub[]; * last_updated?: import("$lib/types").FileStub; * selected: string | null; @@ -141,6 +141,7 @@ export const state = { toggle_expanded: (name, expanded) => { update((state) => ({ ...state, + status: 'expand', expanded: { ...state.expanded, [name]: expanded ?? !state.expanded[name] From 457c40b6423e785a54288394768ced297ebeabd8 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Fri, 10 Mar 2023 10:51:20 -0500 Subject: [PATCH 012/303] Update deps (#246) * update deps * more updates --------- Co-authored-by: Rich Harris --- package.json | 10 +-- pnpm-lock.yaml | 177 +++++++++++++++++++++++++------------------------ 2 files changed, 97 insertions(+), 90 deletions(-) diff --git a/package.json b/package.json index 36c523483..efba89597 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ }, "devDependencies": { "@playwright/test": "^1.31.2", - "@sveltejs/adapter-vercel": "2.0.4", + "@sveltejs/adapter-vercel": "2.3.1", "@sveltejs/kit": "^1.11.0", "@sveltejs/site-kit": "^3.2.2", "@types/diff": "^5.0.2", @@ -24,10 +24,10 @@ "esbuild": "^0.17.11", "prettier": "^2.8.4", "prettier-plugin-svelte": "^2.9.0", - "svelte": "^3.55.1", - "svelte-check": "^2.10.3", + "svelte": "^3.56.0", + "svelte-check": "^3.1.1", "tiny-glob": "^0.2.9", - "typescript": "~4.6.4", + "typescript": "~4.9.5", "vite": "^4.1.4" }, "type": "module", @@ -38,7 +38,7 @@ "adm-zip": "^0.5.10", "base64-js": "^1.5.1", "marked": "^4.2.12", - "monaco-editor": "^0.33.0", + "monaco-editor": "^0.36.1", "port-authority": "^2.0.1", "prism-svelte": "^0.5.0", "prismjs": "^1.29.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a5dc16832..637ac5e9e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4,7 +4,7 @@ specifiers: '@fontsource/roboto-mono': ^4.5.10 '@playwright/test': ^1.31.2 '@rich_harris/svelte-split-pane': ^1.0.0 - '@sveltejs/adapter-vercel': 2.0.4 + '@sveltejs/adapter-vercel': 2.3.1 '@sveltejs/kit': ^1.11.0 '@sveltejs/site-kit': ^3.2.2 '@types/diff': ^5.0.2 @@ -17,27 +17,27 @@ specifiers: diff: ^5.1.0 esbuild: ^0.17.11 marked: ^4.2.12 - monaco-editor: ^0.33.0 + monaco-editor: ^0.36.1 port-authority: ^2.0.1 prettier: ^2.8.4 prettier-plugin-svelte: ^2.9.0 prism-svelte: ^0.5.0 prismjs: ^1.29.0 - svelte: ^3.55.1 - svelte-check: ^2.10.3 + svelte: ^3.56.0 + svelte-check: ^3.1.1 tiny-glob: ^0.2.9 - typescript: ~4.6.4 + typescript: ~4.9.5 vite: ^4.1.4 ws: ^8.12.1 dependencies: '@fontsource/roboto-mono': 4.5.10 - '@rich_harris/svelte-split-pane': 1.0.0_svelte@3.55.1 + '@rich_harris/svelte-split-pane': 1.0.0_svelte@3.56.0 '@webcontainer/api': 1.0.2 adm-zip: 0.5.10 base64-js: 1.5.1 marked: 4.2.12 - monaco-editor: 0.33.0 + monaco-editor: 0.36.1 port-authority: 2.0.1 prism-svelte: 0.5.0 prismjs: 1.29.0 @@ -45,8 +45,8 @@ dependencies: devDependencies: '@playwright/test': 1.31.2 - '@sveltejs/adapter-vercel': 2.0.4_@sveltejs+kit@1.11.0 - '@sveltejs/kit': 1.11.0_svelte@3.55.1+vite@4.1.4 + '@sveltejs/adapter-vercel': 2.3.1_@sveltejs+kit@1.11.0 + '@sveltejs/kit': 1.11.0_svelte@3.56.0+vite@4.1.4 '@sveltejs/site-kit': 3.2.2 '@types/diff': 5.0.2 '@types/marked': 4.0.8 @@ -55,11 +55,11 @@ devDependencies: diff: 5.1.0 esbuild: 0.17.11 prettier: 2.8.4 - prettier-plugin-svelte: 2.9.0_jrsxveqmsx2uadbqiuq74wlc4u - svelte: 3.55.1 - svelte-check: 2.10.3_svelte@3.55.1 + prettier-plugin-svelte: 2.9.0_gan2xfhhcbz3kbkivttwsjndea + svelte: 3.56.0 + svelte-check: 3.1.1_svelte@3.56.0 tiny-glob: 0.2.9 - typescript: 4.6.4 + typescript: 4.9.5 vite: 4.1.4 packages: @@ -524,7 +524,7 @@ packages: engines: {node: '>=14'} hasBin: true dependencies: - '@types/node': 18.14.0 + '@types/node': 18.15.0 playwright-core: 1.31.2 optionalDependencies: fsevents: 2.3.2 @@ -534,12 +534,12 @@ packages: resolution: {integrity: sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==} dev: true - /@rich_harris/svelte-split-pane/1.0.0_svelte@3.55.1: + /@rich_harris/svelte-split-pane/1.0.0_svelte@3.56.0: resolution: {integrity: sha512-nHc6DSIEoyiIAxfSBJkxJOvbUVhPA8HyWi6vzKGZcbQkCMuv6h29Qbotdzs12+zHDxWqECa0X9P0cYY4iDQimA==} peerDependencies: svelte: ^3.54.0 dependencies: - svelte: 3.55.1 + svelte: 3.56.0 dev: false /@rollup/pluginutils/4.2.1: @@ -550,12 +550,12 @@ packages: picomatch: 2.3.1 dev: true - /@sveltejs/adapter-vercel/2.0.4_@sveltejs+kit@1.11.0: - resolution: {integrity: sha512-5tN3sCMQtN/ZV7O26hEVpylIZMMPNkDaDmXxDdEyUZGYpO9x9FOa2CN1CbMQBBGAiCuMxgmtjlWFz4GkYXRU+Q==} + /@sveltejs/adapter-vercel/2.3.1_@sveltejs+kit@1.11.0: + resolution: {integrity: sha512-EanZoRgqaZw4EaT3yGbkUtswYW3cQFVL/7aRunbiZ86mmDEyn6liuYNpmMCiqhgnz6hwhfJErpR7p8l71zcKRA==} peerDependencies: '@sveltejs/kit': ^1.5.0 dependencies: - '@sveltejs/kit': 1.11.0_svelte@3.55.1+vite@4.1.4 + '@sveltejs/kit': 1.11.0_svelte@3.56.0+vite@4.1.4 '@vercel/nft': 0.22.6 esbuild: 0.16.17 transitivePeerDependencies: @@ -563,7 +563,7 @@ packages: - supports-color dev: true - /@sveltejs/kit/1.11.0_svelte@3.55.1+vite@4.1.4: + /@sveltejs/kit/1.11.0_svelte@3.56.0+vite@4.1.4: resolution: {integrity: sha512-PwViZcMoLgEU/jhLoSyjf5hSrHS67wvSm0ifBo4prP9irpGa5HuPOZeVDTL5tPDSBoKxtdYi1zlGdoiJfO86jA==} engines: {node: ^16.14 || >=18} hasBin: true @@ -572,7 +572,7 @@ packages: svelte: ^3.54.0 vite: ^4.0.0 dependencies: - '@sveltejs/vite-plugin-svelte': 2.0.2_svelte@3.55.1+vite@4.1.4 + '@sveltejs/vite-plugin-svelte': 2.0.3_svelte@3.56.0+vite@4.1.4 '@types/cookie': 0.5.1 cookie: 0.5.0 devalue: 4.3.0 @@ -583,7 +583,7 @@ packages: sade: 1.8.1 set-cookie-parser: 2.5.1 sirv: 2.0.2 - svelte: 3.55.1 + svelte: 3.56.0 tiny-glob: 0.2.9 undici: 5.20.0 vite: 4.1.4 @@ -595,8 +595,8 @@ packages: resolution: {integrity: sha512-HBLtfNdLr5Ykl8i8CvJcYjib7zMIJupg4T/omplp3ccpgpiUh26tk71vRG1+a6yMkfbfy0ShoPb9uwNril5cnw==} dev: true - /@sveltejs/vite-plugin-svelte/2.0.2_svelte@3.55.1+vite@4.1.4: - resolution: {integrity: sha512-xCEan0/NNpQuL0l5aS42FjwQ6wwskdxC3pW1OeFtEKNZwRg7Evro9lac9HesGP6TdFsTv2xMes5ASQVKbCacxg==} + /@sveltejs/vite-plugin-svelte/2.0.3_svelte@3.56.0+vite@4.1.4: + resolution: {integrity: sha512-o+cguBFdwIGtRbNkYOyqTM7KvRUffxh5bfK4oJsWKG2obu+v/cbpT03tJrGl58C7tRXo/aEC0/axN5FVHBj0nA==} engines: {node: ^14.18.0 || >= 16} peerDependencies: svelte: ^3.54.0 @@ -605,9 +605,9 @@ packages: debug: 4.3.4 deepmerge: 4.3.0 kleur: 4.1.5 - magic-string: 0.27.0 - svelte: 3.55.1 - svelte-hmr: 0.15.1_svelte@3.55.1 + magic-string: 0.29.0 + svelte: 3.56.0 + svelte-hmr: 0.15.1_svelte@3.56.0 vite: 4.1.4 vitefu: 0.2.4_vite@4.1.4 transitivePeerDependencies: @@ -626,8 +626,8 @@ packages: resolution: {integrity: sha512-HVNzMT5QlWCOdeuBsgXP8EZzKUf0+AXzN+sLmjvaB3ZlLqO+e4u0uXrdw9ub69wBKFs+c6/pA4r9sy6cCDvImw==} dev: true - /@types/node/18.14.0: - resolution: {integrity: sha512-5EWrvLmglK+imbCJY0+INViFWUHg1AHel1sq4ZVSfdcNqGy9Edv3UB9IIzzg+xPaUcAgZYcfVs2fBcwDeZzU0A==} + /@types/node/18.15.0: + resolution: {integrity: sha512-z6nr0TTEOBGkzLGmbypWOGnpSpSIBorEhC4L+4HeQ2iezKCi4f77kyslRwvHeNitymGQ+oFyIWGP96l/DPSV9w==} dev: true /@types/prismjs/1.26.0: @@ -638,16 +638,17 @@ packages: resolution: {integrity: sha512-SnHmG9wN1UVmagJOnyo/qkk0Z7gejYxOYYmaAwr5u2yFYfsupN3sg10kyzN8Hep/2zbHxCnsumxOoRIRMBwKCg==} dev: true - /@types/sass/1.43.1: - resolution: {integrity: sha512-BPdoIt1lfJ6B7rw35ncdwBZrAssjcwzI5LByIrYs+tpXlj/CAkuVdRsgZDdP4lq5EjyWzwxZCqAoFyHKFwp32g==} + /@types/sass/1.45.0: + resolution: {integrity: sha512-jn7qwGFmJHwUSphV8zZneO3GmtlgLsmhs/LQyVvQbIIa+fzGMUiHI4HXJZL3FT8MJmgXWbLGiVVY7ElvHq6vDA==} + deprecated: This is a stub types definition. sass provides its own type definitions, so you do not need this installed. dependencies: - '@types/node': 18.14.0 + sass: 1.58.3 dev: true /@types/ws/8.5.4: resolution: {integrity: sha512-zdQDHKUgcX/zBc4GrwsE/7dVdAD8JR4EuiAXiiUhhfyIJXXb2+PrGshFyeXWQPMmmZ2XxgaqclgpIC7eTXc1mg==} dependencies: - '@types/node': 18.14.0 + '@types/node': 18.15.0 dev: true /@vercel/nft/0.22.6: @@ -721,7 +722,7 @@ packages: engines: {node: '>=10'} dependencies: delegates: 1.0.0 - readable-stream: 3.6.0 + readable-stream: 3.6.2 dev: true /async-sema/3.1.1: @@ -803,7 +804,7 @@ packages: dev: true /concat-map/0.0.1: - resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=} + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} dev: true /console-control-strings/1.1.0: @@ -1048,6 +1049,10 @@ packages: - supports-color dev: true + /immutable/4.3.0: + resolution: {integrity: sha512-0AOCmOip+xgJwEVTQj1EfiDDOkPmuyllDuTuEX+DDXUgapLAsBIfkg3sxCYyCEA8mQqZrrxPUGjcOQ2JS3WLkg==} + dev: true + /import-fresh/3.3.0: resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} engines: {node: '>=6'} @@ -1114,14 +1119,15 @@ packages: yallist: 4.0.0 dev: true - /magic-string/0.25.9: - resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==} + /magic-string/0.27.0: + resolution: {integrity: sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==} + engines: {node: '>=12'} dependencies: - sourcemap-codec: 1.4.8 + '@jridgewell/sourcemap-codec': 1.4.14 dev: true - /magic-string/0.27.0: - resolution: {integrity: sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==} + /magic-string/0.29.0: + resolution: {integrity: sha512-WcfidHrDjMY+eLjlU+8OvwREqHwpgCeKVBUpQ3OhYYuvfaYCUgcbuBzappNzZvg/v8onU3oQj+BYpkOJe9Iw4Q==} engines: {node: '>=12'} dependencies: '@jridgewell/sourcemap-codec': 1.4.14 @@ -1188,8 +1194,8 @@ packages: yallist: 4.0.0 dev: true - /minipass/4.0.3: - resolution: {integrity: sha512-OW2r4sQ0sI+z5ckEt5c1Tri4xTgZwYDxpE54eqWlQloQRoWtXjqt9udJ5Z4dSv7wK+nfFI7FRXyCpBSft+gpFw==} + /minipass/4.2.4: + resolution: {integrity: sha512-lwycX3cBMTvcejsHITUgYj6Gy6A7Nh4Q6h9NP4sTHY1ccJlC7yKzDmiShEHsJ16Jf1nKGDEaiHxiltsJEvk0nQ==} engines: {node: '>=8'} dev: true @@ -1214,8 +1220,8 @@ packages: hasBin: true dev: true - /monaco-editor/0.33.0: - resolution: {integrity: sha512-VcRWPSLIUEgQJQIE0pVT8FcGBIgFoxz7jtqctE+IiCxWugD0DwgyQBcZBhdSrdMC84eumoqMZsGl2GTreOzwqw==} + /monaco-editor/0.36.1: + resolution: {integrity: sha512-/CaclMHKQ3A6rnzBzOADfwdSJ25BFoFT0Emxsc4zYVyav5SkK9iA6lEtIeuN/oRYbwPgviJT+t3l+sjFa28jYg==} dev: false /mri/1.2.0: @@ -1332,14 +1338,14 @@ packages: source-map-js: 1.0.2 dev: true - /prettier-plugin-svelte/2.9.0_jrsxveqmsx2uadbqiuq74wlc4u: + /prettier-plugin-svelte/2.9.0_gan2xfhhcbz3kbkivttwsjndea: resolution: {integrity: sha512-3doBi5NO4IVgaNPtwewvrgPpqAcvNv0NwJNflr76PIGgi9nf1oguQV1Hpdm9TI2ALIQVn/9iIwLpBO5UcD2Jiw==} peerDependencies: prettier: ^1.16.4 || ^2.0.0 svelte: ^3.2.0 dependencies: prettier: 2.8.4 - svelte: 3.55.1 + svelte: 3.56.0 dev: true /prettier/2.8.4: @@ -1361,8 +1367,8 @@ packages: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} dev: true - /readable-stream/3.6.0: - resolution: {integrity: sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==} + /readable-stream/3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} engines: {node: '>= 6'} dependencies: inherits: 2.0.4 @@ -1415,8 +1421,8 @@ packages: glob: 7.2.3 dev: true - /rollup/3.17.2: - resolution: {integrity: sha512-qMNZdlQPCkWodrAZ3qnJtvCAl4vpQ8q77uEujVCCbC/6CLB7Lcmvjq7HyiOSnf4fxTT9XgsE36oLHJBH49xjqA==} + /rollup/3.19.1: + resolution: {integrity: sha512-lAbrdN7neYCg/8WaoWn/ckzCtz+jr70GFfYdlf50OF7387HTg+wiuiqJRFYawwSPpqfqDNYqK7smY/ks2iAudg==} engines: {node: '>=14.18.0', npm: '>=8.0.0'} hasBin: true optionalDependencies: @@ -1449,6 +1455,16 @@ packages: rimraf: 2.7.1 dev: true + /sass/1.58.3: + resolution: {integrity: sha512-Q7RaEtYf6BflYrQ+buPudKR26/lH+10EmO9bBqbmPh/KeLqv8bjpTNqxe71ocONqXq+jYiCbpPUmQMS+JJPk4A==} + engines: {node: '>=12.0.0'} + hasBin: true + dependencies: + chokidar: 3.5.3 + immutable: 4.3.0 + source-map-js: 1.0.2 + dev: true + /semver/6.3.0: resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==} hasBin: true @@ -1483,14 +1499,14 @@ packages: totalist: 3.0.0 dev: true - /sorcery/0.10.0: - resolution: {integrity: sha512-R5ocFmKZQFfSTstfOtHjJuAwbpGyf9qjQa1egyhvXSbM7emjrtLXtGdZsDJDABC85YBfVvrOiGWKSYXPKdvP1g==} + /sorcery/0.11.0: + resolution: {integrity: sha512-J69LQ22xrQB1cIFJhPfgtLuI6BpWRiWu1Y3vSsIwK/eAScqJxd/+CJlUuHQRdX2C9NGFamq+KqNywGgaThwfHw==} hasBin: true dependencies: + '@jridgewell/sourcemap-codec': 1.4.14 buffer-crc32: 0.2.13 minimist: 1.2.8 sander: 0.5.1 - sourcemap-codec: 1.4.8 dev: true /source-map-js/1.0.2: @@ -1498,11 +1514,6 @@ packages: engines: {node: '>=0.10.0'} dev: true - /sourcemap-codec/1.4.8: - resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==} - deprecated: Please use @jridgewell/sourcemap-codec instead - dev: true - /streamsearch/1.1.0: resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==} engines: {node: '>=10.0.0'} @@ -1542,11 +1553,11 @@ packages: engines: {node: '>= 0.4'} dev: true - /svelte-check/2.10.3_svelte@3.55.1: - resolution: {integrity: sha512-Nt1aWHTOKFReBpmJ1vPug0aGysqPwJh2seM1OvICfM2oeyaA62mOiy5EvkXhltGfhCcIQcq2LoE0l1CwcWPjlw==} + /svelte-check/3.1.1_svelte@3.56.0: + resolution: {integrity: sha512-gupWK2sYXRAXg0mtuLOh7LvvuP7RaNH1qYe1dTM+7NyKs9+f1lf3ruxQKO0d6aAT5jWzWzgzGDXhh0xosEY4Zw==} hasBin: true peerDependencies: - svelte: ^3.24.0 + svelte: ^3.55.0 dependencies: '@jridgewell/trace-mapping': 0.3.17 chokidar: 3.5.3 @@ -1554,14 +1565,13 @@ packages: import-fresh: 3.3.0 picocolors: 1.0.0 sade: 1.8.1 - svelte: 3.55.1 - svelte-preprocess: 4.10.7_2k2jvcfvwmfbmgqn6isucmjpty - typescript: 4.6.4 + svelte: 3.56.0 + svelte-preprocess: 5.0.1_rx3ssngbibhj4vpczagsdyy47u + typescript: 4.9.5 transitivePeerDependencies: - '@babel/core' - coffeescript - less - - node-sass - postcss - postcss-load-config - pug @@ -1570,30 +1580,29 @@ packages: - sugarss dev: true - /svelte-hmr/0.15.1_svelte@3.55.1: + /svelte-hmr/0.15.1_svelte@3.56.0: resolution: {integrity: sha512-BiKB4RZ8YSwRKCNVdNxK/GfY+r4Kjgp9jCLEy0DuqAKfmQtpL38cQK3afdpjw4sqSs4PLi3jIPJIFp259NkZtA==} engines: {node: ^12.20 || ^14.13.1 || >= 16} peerDependencies: svelte: '>=3.19.0' dependencies: - svelte: 3.55.1 + svelte: 3.56.0 dev: true - /svelte-preprocess/4.10.7_2k2jvcfvwmfbmgqn6isucmjpty: - resolution: {integrity: sha512-sNPBnqYD6FnmdBrUmBCaqS00RyCsCpj2BG58A1JBswNF7b0OKviwxqVrOL/CKyJrLSClrSeqQv5BXNg2RUbPOw==} - engines: {node: '>= 9.11.2'} + /svelte-preprocess/5.0.1_rx3ssngbibhj4vpczagsdyy47u: + resolution: {integrity: sha512-0HXyhCoc9rsW4zGOgtInylC6qj259E1hpFnJMJWTf+aIfeqh4O/QHT31KT2hvPEqQfdjmqBR/kO2JDkkciBLrQ==} + engines: {node: '>= 14.10.0'} requiresBuild: true peerDependencies: '@babel/core': ^7.10.2 coffeescript: ^2.5.1 less: ^3.11.3 || ^4.0.0 - node-sass: '*' postcss: ^7 || ^8 postcss-load-config: ^2.1.0 || ^3.0.0 || ^4.0.0 pug: ^3.0.0 sass: ^1.26.8 stylus: ^0.55.0 - sugarss: ^2.0.0 + sugarss: ^2.0.0 || ^3.0.0 || ^4.0.0 svelte: ^3.23.0 typescript: ^3.9.5 || ^4.0.0 peerDependenciesMeta: @@ -1603,8 +1612,6 @@ packages: optional: true less: optional: true - node-sass: - optional: true postcss: optional: true postcss-load-config: @@ -1621,17 +1628,17 @@ packages: optional: true dependencies: '@types/pug': 2.0.6 - '@types/sass': 1.43.1 + '@types/sass': 1.45.0 detect-indent: 6.1.0 - magic-string: 0.25.9 - sorcery: 0.10.0 + magic-string: 0.27.0 + sorcery: 0.11.0 strip-indent: 3.0.0 - svelte: 3.55.1 - typescript: 4.6.4 + svelte: 3.56.0 + typescript: 4.9.5 dev: true - /svelte/3.55.1: - resolution: {integrity: sha512-S+87/P0Ve67HxKkEV23iCdAh/SX1xiSfjF1HOglno/YTbSTW7RniICMCofWGdJJbdjw3S+0PfFb1JtGfTXE0oQ==} + /svelte/3.56.0: + resolution: {integrity: sha512-LvXiJbjdvJKwB/0CQyYpDX0q+hFqCyWmybzC2G6eK1tJJA/RSRCytTfNmjHv+RHlLuA70vWG7nXp6gbeErYvRA==} engines: {node: '>= 8'} /tar/6.1.13: @@ -1640,7 +1647,7 @@ packages: dependencies: chownr: 2.0.0 fs-minipass: 2.1.0 - minipass: 4.0.3 + minipass: 4.2.4 minizlib: 2.1.2 mkdirp: 1.0.4 yallist: 4.0.0 @@ -1669,8 +1676,8 @@ packages: resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} dev: true - /typescript/4.6.4: - resolution: {integrity: sha512-9ia/jWHIEbo49HfjrLGfKbZSuWo9iTMwXO+Ca3pRsSpbsMbc7/IU8NKdCZVRRBafVPGnoJeFL76ZOAA84I9fEg==} + /typescript/4.9.5: + resolution: {integrity: sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==} engines: {node: '>=4.2.0'} hasBin: true dev: true @@ -1714,7 +1721,7 @@ packages: esbuild: 0.16.17 postcss: 8.4.21 resolve: 1.22.1 - rollup: 3.17.2 + rollup: 3.19.1 optionalDependencies: fsevents: 2.3.2 dev: true From 457da8a1dd5cb8187790fc56a07a4e249aba288d Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Fri, 10 Mar 2023 11:20:21 -0500 Subject: [PATCH 013/303] remove type annotations (#247) Co-authored-by: Rich Harris --- src/hooks.server.js | 1 - src/routes/+page.js | 1 - src/routes/assets/media/[...path]/+server.js | 1 - src/routes/tutorial/[slug]/+page.server.js | 1 - src/routes/tutorial/[slug]/+page.svelte | 1 - 5 files changed, 5 deletions(-) diff --git a/src/hooks.server.js b/src/hooks.server.js index 0d50447a0..ae29b46cf 100644 --- a/src/hooks.server.js +++ b/src/hooks.server.js @@ -1,4 +1,3 @@ -/** @type {import('@sveltejs/kit').Handle} */ export async function handle({ event, resolve }) { const response = await resolve(event); diff --git a/src/routes/+page.js b/src/routes/+page.js index 6506626ed..de2936142 100644 --- a/src/routes/+page.js +++ b/src/routes/+page.js @@ -1,6 +1,5 @@ import { redirect } from '@sveltejs/kit'; -/** @type {import('./$types').PageLoad} */ export function load() { throw redirect(307, '/tutorial/welcome-to-svelte'); } diff --git a/src/routes/assets/media/[...path]/+server.js b/src/routes/assets/media/[...path]/+server.js index dfe1d56c6..e867cbaf0 100644 --- a/src/routes/assets/media/[...path]/+server.js +++ b/src/routes/assets/media/[...path]/+server.js @@ -1,4 +1,3 @@ -/** @type {import('./$types').RequestHandler} */ export async function GET({ request, params, fetch }) { const request_headers = new Headers(); diff --git a/src/routes/tutorial/[slug]/+page.server.js b/src/routes/tutorial/[slug]/+page.server.js index f9df0e782..4ea9a924e 100644 --- a/src/routes/tutorial/[slug]/+page.server.js +++ b/src/routes/tutorial/[slug]/+page.server.js @@ -1,7 +1,6 @@ import { get_exercise } from '$lib/server/content'; import { error } from '@sveltejs/kit'; -/** @type {import('./$types').PageServerLoad} */ export function load({ params }) { const exercise = get_exercise(params.slug); diff --git a/src/routes/tutorial/[slug]/+page.svelte b/src/routes/tutorial/[slug]/+page.svelte index 5c2f19ed6..355e1cff3 100644 --- a/src/routes/tutorial/[slug]/+page.svelte +++ b/src/routes/tutorial/[slug]/+page.svelte @@ -13,7 +13,6 @@ import Sidebar from './Sidebar.svelte'; import { state, selected, completed } from './state.js'; - /** @type {import('./$types').PageData} */ export let data; let width = browser ? window.innerWidth : 1000; From 0aea74129bde3d86cb81835de05d9b42e7da9f38 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Mon, 13 Mar 2023 12:14:31 -0400 Subject: [PATCH 014/303] overhaul adapter code (#249) * tidy up * restart process immediately when it dies * create adapter in onMount * make adapter a singleton * WIP refactor * add an event mechanism for reloading iframe * call adapter methods directly * separate state from events * add some HMR support * unify types, remove destroy method * preserve loading screen until page is ready * expand new folders by default * remove unnecessary pagehide stuff * make update(...) take a single file * fix hella weird bug with process not exiting if vite and svelte configs are both written simultaneously * minor tweak * simplify * move collapsed state to the filetree * remove some more indirection * unused import * use sets for editing constraints * move logic to the server * move editing_constraints out of state * fix * create multiple independent stores so we can e.g. SSR the filetree * tweak * consistency * use correct path, prevent some errors --------- Co-authored-by: Rich Harris --- .../tutorial/common/src/routes/+page.svelte | 0 src/lib/client/adapters/filesystem/index.js | 6 +- src/lib/client/adapters/webcontainer/index.js | 163 +++++++------ src/lib/server/content.js | 41 +++- src/lib/types/index.d.ts | 21 +- src/routes/tutorial/[slug]/+page.svelte | 88 ++++++- src/routes/tutorial/[slug]/Editor.svelte | 18 +- src/routes/tutorial/[slug]/Output.svelte | 142 ++--------- src/routes/tutorial/[slug]/adapter.js | 149 ++++++------ .../tutorial/[slug]/filetree/File.svelte | 6 +- .../tutorial/[slug]/filetree/Filetree.svelte | 82 ++++--- .../tutorial/[slug]/filetree/Folder.svelte | 40 ++-- .../tutorial/[slug]/filetree/context.js | 1 + src/routes/tutorial/[slug]/state.js | 224 +++--------------- 14 files changed, 417 insertions(+), 564 deletions(-) create mode 100644 content/tutorial/common/src/routes/+page.svelte diff --git a/content/tutorial/common/src/routes/+page.svelte b/content/tutorial/common/src/routes/+page.svelte new file mode 100644 index 000000000..e69de29bb diff --git a/src/lib/client/adapters/filesystem/index.js b/src/lib/client/adapters/filesystem/index.js index e9d11f0fa..d3bd0e6ba 100644 --- a/src/lib/client/adapters/filesystem/index.js +++ b/src/lib/client/adapters/filesystem/index.js @@ -1,7 +1,7 @@ /** * @param {import('$lib/types').Stub[]} stubs * @param {(progress: number, status: string) => void} cb - * @returns {Promise} + * @returns {Promise} */ export async function create(stubs, cb) { const res = await fetch('http://github.com/backend', { @@ -56,10 +56,6 @@ export async function create(stubs, cb) { await new Promise((f) => setTimeout(f, 100)); // wait for chokidar return will_restart_vite_dev_server(stubs); - }, - - async destroy() { - navigator.sendBeacon(`/backend/destroy?id=${id}`); } }; } diff --git a/src/lib/client/adapters/webcontainer/index.js b/src/lib/client/adapters/webcontainer/index.js index 0ef49a1d4..125cc0e7e 100644 --- a/src/lib/client/adapters/webcontainer/index.js +++ b/src/lib/client/adapters/webcontainer/index.js @@ -16,16 +16,17 @@ function console_stream(label) { } /** - * @param {import('$lib/types').Stub[]} stubs - * @param {(progress: number, status: string) => void} callback - * @returns {Promise} + * @param {import('svelte/store').Writable} base + * @param {import('svelte/store').Writable} error + * @param {import('svelte/store').Writable<{ value: number, text: string }>} progress + * @returns {Promise} */ -export async function create(stubs, callback) { +export async function create(base, error, progress) { if (/safari/i.test(navigator.userAgent) && !/chrome/i.test(navigator.userAgent)) { throw new Error('WebContainers are not supported by Safari'); } - callback(0, 'loading files'); + progress.set({ value: 0, text: 'loading files' }); /** * Keeps track of the latest create/reset to ensure things are not processed in parallel. @@ -35,15 +36,15 @@ export async function create(stubs, callback) { let running; /** Paths and contents of the currently loaded file stubs */ - let current_stubs = stubs_to_map(stubs); + let current_stubs = stubs_to_map([]); /** @type {boolean} Track whether there was an error from vite dev server */ let vite_error = false; - callback(1 / 5, 'booting webcontainer'); + progress.set({ value: 1 / 5, text: 'booting webcontainer' }); vm = await WebContainer.boot(); - callback(2 / 5, 'writing virtual files'); + progress.set({ value: 2 / 5, text: 'writing virtual files' }); const common = await ready; await vm.mount({ 'common.zip': { @@ -51,11 +52,10 @@ export async function create(stubs, callback) { }, 'unzip.cjs': { file: { contents: common.unzip } - }, - ...convert_stubs_to_tree(stubs) + } }); - callback(3 / 5, 'unzipping files'); + progress.set({ value: 3 / 5, text: 'unzipping files' }); const unzip = await vm.spawn('node', ['unzip.cjs']); unzip.output.pipeTo(console_stream('unzip')); const code = await unzip.exit; @@ -66,41 +66,51 @@ export async function create(stubs, callback) { await vm.spawn('chmod', ['a+x', 'node_modules/vite/bin/vite.js']); - callback(4 / 5, 'starting dev server'); - const base = await new Promise(async (fulfil, reject) => { - const error_unsub = vm.on('error', (error) => { - error_unsub(); - reject(new Error(error.message)); - }); + vm.on('server-ready', (_port, url) => { + base.set(url); + }); - const ready_unsub = vm.on('server-ready', (_port, base) => { - ready_unsub(); - callback(5 / 5, 'ready'); - fulfil(base); // this will be the last thing that happens if everything goes well - }); + vm.on('error', ({ message }) => { + error.set(new Error(message)); + }); - await run_dev(); + let launched = false; - async function run_dev() { - const process = await vm.spawn('turbo', ['run', 'dev']); + async function launch() { + if (launched) return; + launched = true; - // TODO differentiate between stdout and stderr (sets `vite_error` to `true`) - // https://github.com/stackblitz/webcontainer-core/issues/971 - process.output.pipeTo(console_stream('dev')); + progress.set({ value: 4 / 5, text: 'starting dev server' }); - // keep restarting dev server (can crash in case of illegal +files for example) - process.exit.then((code) => { - if (code !== 0) { - setTimeout(() => { - run_dev(); - }, 2000); - } + await new Promise(async (fulfil, reject) => { + const error_unsub = vm.on('error', (error) => { + error_unsub(); + reject(new Error(error.message)); }); - } - }); + + const ready_unsub = vm.on('server-ready', (_port, base) => { + ready_unsub(); + progress.set({ value: 5 / 5, text: 'ready' }); + fulfil(base); // this will be the last thing that happens if everything goes well + }); + + await run_dev(); + + async function run_dev() { + const process = await vm.spawn('turbo', ['run', 'dev']); + + // TODO differentiate between stdout and stderr (sets `vite_error` to `true`) + // https://github.com/stackblitz/webcontainer-core/issues/971 + process.output.pipeTo(console_stream('dev')); + + // keep restarting dev server (can crash in case of illegal +files for example) + await process.exit; + run_dev(); + } + }); + } return { - base, reset: async (stubs) => { await running; /** @type {Function} */ @@ -146,7 +156,7 @@ export async function create(stubs, callback) { // For some reason, server-ready is fired again when the vite dev server is restarted. // We need to wait for it to finish before we can continue, else we might // request files from Vite before it's ready, leading to a timeout. - const will_restart = will_restart_vite_dev_server(to_write); + const will_restart = launched && to_write.some(will_restart_vite_dev_server); const promise = will_restart ? new Promise((fulfil, reject) => { const error_unsub = vm.on('error', (error) => { @@ -190,60 +200,57 @@ export async function create(stubs, callback) { // Also trigger a reload of the iframe in case new files were added / old ones deleted, // because that can result in a broken UI state - return will_restart || vite_error || to_delete.length > 0 || added_new_file; + const should_reload = !launched || will_restart || vite_error || to_delete.length > 0; + // `|| added_new_file`, but I don't actually think that's necessary? + + await launch(); + + return should_reload; }, - update: async (stubs) => { + update: async (file) => { await running; /** @type {import('@webcontainer/api').FileSystemTree} */ const root = {}; - for (const stub of stubs) { - let tree = root; - - const path = stub.name.split('/').slice(1); - const basename = /** @type {string} */ (path.pop()); + let tree = root; - for (const part of path) { - if (!tree[part]) { - /** @type {import('@webcontainer/api').FileSystemTree} */ - const directory = {}; + const path = file.name.split('/').slice(1); + const basename = /** @type {string} */ (path.pop()); - tree[part] = { - directory - }; - } + for (const part of path) { + if (!tree[part]) { + /** @type {import('@webcontainer/api').FileSystemTree} */ + const directory = {}; - tree = /** @type {import('@webcontainer/api').DirectoryNode} */ (tree[part]).directory; + tree[part] = { + directory + }; } - tree[basename] = to_file(stub); + tree = /** @type {import('@webcontainer/api').DirectoryNode} */ (tree[part]).directory; } + tree[basename] = to_file(file); + await vm.mount(root); - stubs_to_map(stubs, current_stubs); + current_stubs.set(file.name, file); await new Promise((f) => setTimeout(f, 200)); // wait for chokidar - return will_restart_vite_dev_server(stubs); - }, - destroy: async () => { - vm.teardown(); + return will_restart_vite_dev_server(file); } }; } /** - * @param {import('$lib/types').Stub[]} stubs + * @param {import('$lib/types').Stub} file */ -function will_restart_vite_dev_server(stubs) { - return stubs.some( - (stub) => - stub.type === 'file' && - (stub.name === '/vite.config.js' || - stub.name === '/svelte.config.js' || - stub.name === '/.env') +function will_restart_vite_dev_server(file) { + return ( + file.type === 'file' && + (file.name === '/vite.config.js' || file.name === '/svelte.config.js' || file.name === '/.env') ); } @@ -272,11 +279,11 @@ function convert_stubs_to_tree(stubs, depth = 1) { return tree; } -/** @param {import('$lib/types').FileStub} stub */ -function to_file(stub) { +/** @param {import('$lib/types').FileStub} file */ +function to_file(file) { // special case - if (stub.name === '/src/app.html') { - const contents = stub.contents.replace( + if (file.name === '/src/app.html') { + const contents = file.contents.replace( '', '' ); @@ -286,7 +293,7 @@ function to_file(stub) { }; } - const contents = stub.text ? stub.contents : base64.toByteArray(stub.contents); + const contents = file.text ? file.contents : base64.toByteArray(file.contents); return { file: { contents } @@ -294,12 +301,12 @@ function to_file(stub) { } /** - * @param {import('$lib/types').Stub[]} stubs + * @param {import('$lib/types').Stub[]} files * @returns {Map} */ -function stubs_to_map(stubs, map = new Map()) { - for (const stub of stubs) { - map.set(stub.name, stub); +function stubs_to_map(files, map = new Map()) { + for (const file of files) { + map.set(file.name, file); } return map; } diff --git a/src/lib/server/content.js b/src/lib/server/content.js index d10024d05..cfdd1bac5 100644 --- a/src/lib/server/content.js +++ b/src/lib/server/content.js @@ -101,6 +101,7 @@ export function get_exercise(slug) { } const b = walk(`${dir}/app-b`); + const has_solution = Object.keys(b).length > 0; const part_meta = json(`content/tutorial/${part_dir}/meta.json`); const chapter_meta = json(`content/tutorial/${part_dir}/${chapter_dir}/meta.json`); @@ -152,6 +153,36 @@ export function get_exercise(slug) { }; } + const editing_constraints = { + create: new Set(exercise_meta.editing_constraints?.create ?? []), + remove: new Set(exercise_meta.editing_constraints?.remove ?? []) + }; + + const solution = { ...a }; + + for (const stub of Object.values(b)) { + if (stub.type === 'file' && stub.contents.startsWith('__delete')) { + // remove file + editing_constraints.remove.add(stub.name); + delete solution[stub.name]; + } else if (stub.name.endsWith('/__delete')) { + // remove directory + const parent = stub.name.slice(0, stub.name.lastIndexOf('/')); + editing_constraints.remove.add(parent); + delete solution[parent]; + for (const k in solution) { + if (k.startsWith(parent + '/')) { + delete solution[k]; + } + } + } else { + if (!solution[stub.name]) { + editing_constraints.create.add(stub.name); + } + solution[stub.name] = stub; + } + } + return { part: { slug: part_dir, @@ -169,10 +200,7 @@ export function get_exercise(slug) { prev, next, dir, - editing_constraints: { - create: exercise_meta.editing_constraints?.create ?? [], - remove: exercise_meta.editing_constraints?.remove ?? [] - }, + editing_constraints, html: transform(markdown, { codespan: (text) => filenames.size > 1 && filenames.has(text) @@ -180,7 +208,8 @@ export function get_exercise(slug) { : `${text}` }), a, - b + b: solution, + has_solution }; } @@ -218,7 +247,7 @@ function extract_frontmatter(markdown, dir) { * exclude?: string[] * }} options */ -export function walk(cwd, options = {}) { +function walk(cwd, options = {}) { /** @type {Record} */ const result = {}; diff --git a/src/lib/types/index.d.ts b/src/lib/types/index.d.ts index 394f858be..f0779b4a8 100644 --- a/src/lib/types/index.d.ts +++ b/src/lib/types/index.d.ts @@ -16,18 +16,10 @@ export interface DirectoryStub { export type Stub = FileStub | DirectoryStub; -export interface AdapterInternal { - base: string; +export interface Adapter { /** Returns `false` if the reset was in such a way that a reload of the iframe isn't needed */ reset(files: Array): Promise; - update(file: Array): Promise; - destroy(): Promise; -} - -export interface Adapter extends AdapterInternal { - reset(files: Array): Promise; - update(file: Array): Promise; - init: Promise; + update(file: FileStub): Promise; } export interface Scope { @@ -55,11 +47,12 @@ export interface Exercise { html: string; dir: string; editing_constraints: { - create: string[]; - remove: string[]; + create: Set; + remove: Set; }; a: Record; b: Record; + has_solution: boolean; } export interface ExerciseStub { @@ -80,6 +73,6 @@ export interface PartStub { } export interface EditingConstraints { - create: string[]; - remove: string[]; + create: Set; + remove: Set; } diff --git a/src/routes/tutorial/[slug]/+page.svelte b/src/routes/tutorial/[slug]/+page.svelte index 355e1cff3..39d7baa27 100644 --- a/src/routes/tutorial/[slug]/+page.svelte +++ b/src/routes/tutorial/[slug]/+page.svelte @@ -1,7 +1,7 @@ @@ -57,7 +119,7 @@ index={data.index} exercise={data.exercise} on:select={(e) => { - state.select_file(e.detail.file); + select_file(e.detail.file); }} /> @@ -72,16 +134,16 @@
    - +
    diff --git a/src/routes/tutorial/[slug]/Editor.svelte b/src/routes/tutorial/[slug]/Editor.svelte index d755bbf03..387644008 100644 --- a/src/routes/tutorial/[slug]/Editor.svelte +++ b/src/routes/tutorial/[slug]/Editor.svelte @@ -1,7 +1,7 @@ { if (preserve_editor_focus && e.data.type === 'iframe_took_focus') { - instance?.editor.focus(); + editor_view.focus(); } }} /> -
    -
    { - if (e.key === 'Tab') { - preserve_editor_focus = false; +
    { + if (e.key === 'Tab') { + preserve_editor_focus = false; - setTimeout(() => { - preserve_editor_focus = true; - }, 200); - } - }} - on:focusin={() => { - clearTimeout(remove_focus_timeout); - preserve_editor_focus = true; - }} - on:focusout={() => { - // Heuristic: user did refocus themmselves if iframe_took_focus - // doesn't happen in the next few miliseconds. Needed - // because else navigations inside the iframe refocus the editor. - remove_focus_timeout = setTimeout(() => { - preserve_editor_focus = false; + setTimeout(() => { + preserve_editor_focus = true; }, 200); - }} - /> + } + }} + on:focusin={() => { + clearTimeout(remove_focus_timeout); + preserve_editor_focus = true; + }} + on:focusout={() => { + // Heuristic: user did refocus themmselves if iframe_took_focus + // doesn't happen in the next few miliseconds. Needed + // because else navigations inside the iframe refocus the editor. + remove_focus_timeout = setTimeout(() => { + preserve_editor_focus = false; + }, 200); + }} +> + {#if !browser && $selected_file} +
    +
    + {#each $selected_file.contents.split('\n') as _, i} +
    {i + 1}
    + {/each} +
    +
    + {#each $selected_file.contents.split('\n') as line} +
    {line || ' '}
    + {/each} +
    +
    + {/if}
    diff --git a/src/routes/tutorial/[slug]/Output.svelte b/src/routes/tutorial/[slug]/Output.svelte index 4d1ef46b5..59f907648 100644 --- a/src/routes/tutorial/[slug]/Output.svelte +++ b/src/routes/tutorial/[slug]/Output.svelte @@ -69,7 +69,7 @@ // removing the iframe from the document allows us to // change the src without adding a history entry, which // would make back/forward traversal very annoying - const parentNode = /** @type {HTMLElement} */ (iframe.parentNode); + const parentNode = /** @type {HTMLElement} */ (iframe?.parentNode); parentNode?.removeChild(iframe); iframe.src = src; parentNode?.appendChild(iframe); diff --git a/src/routes/tutorial/[slug]/codemirror.css b/src/routes/tutorial/[slug]/codemirror.css new file mode 100644 index 000000000..63d9a3360 --- /dev/null +++ b/src/routes/tutorial/[slug]/codemirror.css @@ -0,0 +1,60 @@ +.codemirror-wrapper { + height: 100%; +} + +.cm-editor { + height: 100%; +} + +.cm-editor .cm-scroller { + font-family: var(--font-mono); + font-size: 1.3rem; + line-height: 2rem; +} + +.cm-editor .cm-gutters { + background: var(--sk-back-3); + border-right: none; + padding: 0; + width: 5rem; +} + +.cm-editor .cm-activeLineGutter { + background-color: var(--sk-back-3); +} + +.cm-editor .cm-lineNumbers { + flex: 1; + color: #237893; +} + +.cm-editor .cm-foldGutter { + width: 1rem; +} + +.cm-editor .cm-content { + padding: 1rem 0; +} + +.cm-editor .cm-line { + padding: 0 1rem; +} + +.cm-editor .cm-selectionBackground { + border-radius: 2px; +} + +.cm-editor .cm-selectionMatch { + background: rgba(0,0,0,0.2); + color: var(--sk-text-2); +} + +@media (prefers-color-scheme: dark) { + .cm-editor .cm-activeLineGutter { + background-color: var(--sk-back-3); + } + + .cm-editor .cm-activeLine { + background-color: var(--sk-back-2); + } +} \ No newline at end of file diff --git a/tests/env_file.spec.ts b/tests/env_file.spec.ts index 1c5bc39cc..7177e40cf 100644 --- a/tests/env_file.spec.ts +++ b/tests/env_file.spec.ts @@ -2,6 +2,8 @@ import { expect, test } from '@playwright/test'; const iframe_selector = 'iframe[src*="webcontainer.io/"]'; +test.describe.configure({ mode: 'parallel' }); + test('.env file: no timeout error occurs when switching a tutorials without a .env file to one with it', async ({ page }) => { diff --git a/tests/focus_management.spec.ts b/tests/focus_management.spec.ts index 3ca821761..7b180d214 100644 --- a/tests/focus_management.spec.ts +++ b/tests/focus_management.spec.ts @@ -1,9 +1,11 @@ import { expect, test } from '@playwright/test'; -const editor_selector = 'div.monaco-scrollable-element.editor-scrollable'; -const editor_focus_selector = 'textarea.inputarea.monaco-mouse-cursor-text'; +const editor_selector = '.cm-content'; +const editor_focus_selector = '.cm-content'; const iframe_selector = 'iframe[src*="webcontainer.io/"]'; +test.describe.configure({ mode: 'parallel' }); + test('focus management: the editor keeps focus when iframe is loaded', async ({ page }) => { await page.bringToFront(); @@ -108,7 +110,7 @@ test('focus management: The editor keeps focus while typing', async ({ page }) = // get code from DOM, then replace nbsp with normal space const received = (await page.locator(editor_selector).innerText()).replace(/\u00a0/g, ' '); - const expected = '\n

    Hello world!

    '; + const expected = '\n\n'; expect(received).toBe(expected); }); From cc3cd3072ebcab41d3526f9b46c1df9236280971 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Mon, 13 Mar 2023 21:28:40 -0400 Subject: [PATCH 018/303] preload --- src/app.html | 2 +- src/routes/tutorial/[slug]/Menu.svelte | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/app.html b/src/app.html index 8b1aa7c88..7ea18c7cc 100644 --- a/src/app.html +++ b/src/app.html @@ -7,7 +7,7 @@ %sveltekit.head% - +
    %sveltekit.body%
    diff --git a/src/routes/tutorial/[slug]/Menu.svelte b/src/routes/tutorial/[slug]/Menu.svelte index ffaca2faf..3c682c727 100644 --- a/src/routes/tutorial/[slug]/Menu.svelte +++ b/src/routes/tutorial/[slug]/Menu.svelte @@ -135,11 +135,7 @@ ? 'page' : undefined} > - (is_open = false)} - > + (is_open = false)}> {exercise.title} From c1e1e58a4251826917db4ff94e0bed7836658a95 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Tue, 14 Mar 2023 09:08:43 -0400 Subject: [PATCH 019/303] mobile layout (#254) * partial fix for #12 * use dynamic viewport units --------- Co-authored-by: Rich Harris --- package.json | 2 +- pnpm-lock.yaml | 8 ++++---- src/routes/+layout.svelte | 4 ++-- src/routes/tutorial/[slug]/Editor.svelte | 4 +++- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index b23cf28f7..ea2158932 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "@lezer/javascript": "^1.4.1", "@lezer/lr": "^1.3.3", "@replit/codemirror-lang-svelte": "^6.0.0", - "@rich_harris/svelte-split-pane": "^1.0.0", + "@rich_harris/svelte-split-pane": "^1.0.1", "@webcontainer/api": "^1.0.2", "adm-zip": "^0.5.10", "ansi-to-html": "^0.7.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1a8fc2ab3..60bac2584 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -16,7 +16,7 @@ specifiers: '@lezer/lr': ^1.3.3 '@playwright/test': ^1.31.2 '@replit/codemirror-lang-svelte': ^6.0.0 - '@rich_harris/svelte-split-pane': ^1.0.0 + '@rich_harris/svelte-split-pane': ^1.0.1 '@sveltejs/adapter-vercel': 2.3.1 '@sveltejs/kit': ^1.11.0 '@sveltejs/site-kit': ^3.2.2 @@ -59,7 +59,7 @@ dependencies: '@lezer/javascript': 1.4.1 '@lezer/lr': 1.3.3 '@replit/codemirror-lang-svelte': 6.0.0_ybny7xhlf2ysg4majw54z4nkly - '@rich_harris/svelte-split-pane': 1.0.0_svelte@3.56.0 + '@rich_harris/svelte-split-pane': 1.0.1_svelte@3.56.0 '@webcontainer/api': 1.0.2 adm-zip: 0.5.10 ansi-to-html: 0.7.2 @@ -728,8 +728,8 @@ packages: '@lezer/lr': 1.3.3 dev: false - /@rich_harris/svelte-split-pane/1.0.0_svelte@3.56.0: - resolution: {integrity: sha512-nHc6DSIEoyiIAxfSBJkxJOvbUVhPA8HyWi6vzKGZcbQkCMuv6h29Qbotdzs12+zHDxWqECa0X9P0cYY4iDQimA==} + /@rich_harris/svelte-split-pane/1.0.1_svelte@3.56.0: + resolution: {integrity: sha512-/11fp3792qh4pXxO3XtVmIQf6SCDFKcQyyQvVOAKr8U5tG0Z4QaLEXsyOKOpeAkngqWT1dbBfjVynUXa7kb1EA==} peerDependencies: svelte: ^3.54.0 dependencies: diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index 22f5c25e5..9cdff2f85 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -50,7 +50,7 @@ :global(body) { margin: 0; width: 100%; - min-height: 100vh; + min-height: 100dvh; } /* TODO when we remove the launch banner, we can remove this override */ @@ -60,7 +60,7 @@ main { width: 100%; - height: calc(100vh - var(--nav-h)); + height: calc(100dvh - var(--nav-h)); position: relative; top: var(--nav-h); } diff --git a/src/routes/tutorial/[slug]/Editor.svelte b/src/routes/tutorial/[slug]/Editor.svelte index cbc0784c0..058fff696 100644 --- a/src/routes/tutorial/[slug]/Editor.svelte +++ b/src/routes/tutorial/[slug]/Editor.svelte @@ -75,7 +75,9 @@ editor_states.set(file.name, state); } - editor_view.setState(state); + if (editor_view) { + editor_view.setState(state); + } } onMount(() => { From 8ab615a2edaba2511151fe172054fb00e9a431a6 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Tue, 14 Mar 2023 11:23:43 -0400 Subject: [PATCH 020/303] fix solve button (#258) * style tweak * fix solve button - closes #256 --------- Co-authored-by: Rich Harris --- src/routes/tutorial/[slug]/Editor.svelte | 125 ++++++++++++++++------- src/routes/tutorial/[slug]/state.js | 6 ++ 2 files changed, 96 insertions(+), 35 deletions(-) diff --git a/src/routes/tutorial/[slug]/Editor.svelte b/src/routes/tutorial/[slug]/Editor.svelte index 058fff696..ff8589197 100644 --- a/src/routes/tutorial/[slug]/Editor.svelte +++ b/src/routes/tutorial/[slug]/Editor.svelte @@ -1,6 +1,6 @@ @@ -214,4 +263,10 @@ .fake-content { padding: 0 1rem; } + + @media (prefers-color-scheme: dark) { + .fake * { + color: #666; + } + } diff --git a/src/routes/tutorial/[slug]/state.js b/src/routes/tutorial/[slug]/state.js index 800c21db3..9932b214c 100644 --- a/src/routes/tutorial/[slug]/state.js +++ b/src/routes/tutorial/[slug]/state.js @@ -34,6 +34,12 @@ export function update_file(file) { /** @param {import('$lib/types').Stub[]} new_files */ export function reset_files(new_files) { + // if the selected file no longer exists, clear it + selected_name.update(($selected_name) => { + const file = new_files.find((file) => file.name === $selected_name); + return file?.name ?? null; + }); + files.set(new_files); adapter.reset(new_files); } From 4bda38b70f7caa76fa96a8d526bbe21b9decaff2 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Tue, 14 Mar 2023 11:32:57 -0400 Subject: [PATCH 021/303] show inline diagnostics (#17) (#257) Co-authored-by: Rich Harris --- content/tutorial/common/src/__client.js | 10 +++++++ content/tutorial/common/svelte.config.js | 6 +++++ package.json | 1 + pnpm-lock.yaml | 2 ++ src/routes/tutorial/[slug]/Editor.svelte | 32 +++++++++++++++++++++-- src/routes/tutorial/[slug]/Output.svelte | 6 +++++ src/routes/tutorial/[slug]/codemirror.css | 26 ++++++++++++++++++ src/routes/tutorial/[slug]/state.js | 27 ++++++++++++++++--- 8 files changed, 105 insertions(+), 5 deletions(-) diff --git a/content/tutorial/common/src/__client.js b/content/tutorial/common/src/__client.js index a6765fb35..4f4ffee9b 100644 --- a/content/tutorial/common/src/__client.js +++ b/content/tutorial/common/src/__client.js @@ -118,4 +118,14 @@ if (import.meta.hot) { '*' ); }); + + import.meta.hot.on('svelte:warnings', (data) => { + parent.postMessage( + { + type: 'warnings', + data + }, + '*' + ); + }); } diff --git a/content/tutorial/common/svelte.config.js b/content/tutorial/common/svelte.config.js index 29ce35b4b..66ff56f30 100644 --- a/content/tutorial/common/svelte.config.js +++ b/content/tutorial/common/svelte.config.js @@ -5,6 +5,12 @@ const config = { // Don't do this in your own apps unless you know what you're doing! // See https://kit.svelte.dev/docs/configuration#csrf for more info. csrf: false + }, + + vitePlugin: { + experimental: { + sendWarningsToBrowser: true + } } }; diff --git a/package.json b/package.json index ea2158932..4d3bc7fdc 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ "@codemirror/lang-html": "^6.4.2", "@codemirror/lang-javascript": "^6.1.4", "@codemirror/language": "^6.6.0", + "@codemirror/lint": "^6.2.0", "@codemirror/state": "^6.2.0", "@codemirror/view": "^6.9.2", "@fontsource/roboto-mono": "^4.5.10", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 60bac2584..7b5b7c8b2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -7,6 +7,7 @@ specifiers: '@codemirror/lang-html': ^6.4.2 '@codemirror/lang-javascript': ^6.1.4 '@codemirror/language': ^6.6.0 + '@codemirror/lint': ^6.2.0 '@codemirror/state': ^6.2.0 '@codemirror/view': ^6.9.2 '@fontsource/roboto-mono': ^4.5.10 @@ -51,6 +52,7 @@ dependencies: '@codemirror/lang-html': 6.4.2 '@codemirror/lang-javascript': 6.1.4 '@codemirror/language': 6.6.0 + '@codemirror/lint': 6.2.0 '@codemirror/state': 6.2.0 '@codemirror/view': 6.9.2 '@fontsource/roboto-mono': 4.5.10 diff --git a/src/routes/tutorial/[slug]/Editor.svelte b/src/routes/tutorial/[slug]/Editor.svelte index ff8589197..b4ce4390e 100644 --- a/src/routes/tutorial/[slug]/Editor.svelte +++ b/src/routes/tutorial/[slug]/Editor.svelte @@ -6,6 +6,7 @@ import { EditorState } from '@codemirror/state'; import { indentWithTab } from '@codemirror/commands'; import { indentUnit } from '@codemirror/language'; + import { setDiagnostics } from '@codemirror/lint'; import { javascript } from '@codemirror/lang-javascript'; import { html } from '@codemirror/lang-html'; import { svelte } from '@replit/codemirror-lang-svelte'; @@ -13,7 +14,7 @@ import { HighlightStyle } from '@codemirror/language'; import { syntaxHighlighting } from '@codemirror/language'; import { afterNavigate, beforeNavigate } from '$app/navigation'; - import { files, selected_file, selected_name, update_file } from './state.js'; + import { files, selected_file, selected_name, update_file, warnings } from './state.js'; import './codemirror.css'; // TODO add more styles (selection ranges, etc) @@ -49,7 +50,31 @@ theme ]; - $: if (editor_view) select_state($selected_name); + $: if (editor_view) { + select_state($selected_name); + + if ($selected_name) { + const current_warnings = $warnings[$selected_name]; + + if (current_warnings) { + const diagnostics = current_warnings.map((warning) => { + /** @type {import('@codemirror/lint').Diagnostic} */ + const diagnostic = { + from: warning.start.character, + to: warning.end.character, + severity: 'warning', + message: warning.message + }; + + return diagnostic; + }); + + const transaction = setDiagnostics(editor_view.state, diagnostics); + + editor_view.dispatch(transaction); + } + } + } $: reset($files); @@ -178,6 +203,9 @@ reset($files); select_state($selected_name); + + // clear warnings + warnings.set({}); }); diff --git a/src/routes/tutorial/[slug]/Output.svelte b/src/routes/tutorial/[slug]/Output.svelte index 59f907648..a84a295fe 100644 --- a/src/routes/tutorial/[slug]/Output.svelte +++ b/src/routes/tutorial/[slug]/Output.svelte @@ -5,6 +5,7 @@ import Chrome from './Chrome.svelte'; import Loading from './Loading.svelte'; import { base, error, logs, progress, subscribe } from './adapter'; + import { warnings } from './state'; /** @type {import('$lib/types').Exercise} */ export let exercise; @@ -61,6 +62,11 @@ }, 1000); } else if (e.data.type === 'ping-pause') { clearTimeout(timeout); + } else if (e.data.type === 'warnings') { + warnings.update(($warnings) => ({ + ...$warnings, + [e.data.data.normalizedFilename]: e.data.data.allWarnings + })); } } diff --git a/src/routes/tutorial/[slug]/codemirror.css b/src/routes/tutorial/[slug]/codemirror.css index 63d9a3360..416da525a 100644 --- a/src/routes/tutorial/[slug]/codemirror.css +++ b/src/routes/tutorial/[slug]/codemirror.css @@ -49,6 +49,28 @@ color: var(--sk-text-2); } +.cm-editor .cm-tooltip { + border: none; + border-radius: 2px; + overflow: hidden; + margin: 0.4rem 0; + filter: drop-shadow(1px 2px 5px rgba(0,0,0,0.1)); +} +.cm-editor .cm-tooltip-hover {} +.cm-editor .cm-tooltip-below {} +.cm-editor .cm-tooltip-lint {} +.cm-editor .cm-tooltip-section {} +.cm-editor .cm-diagnostic { + border: none; + padding: 0.2rem 0.8rem; +} +.cm-editor .cm-diagnostic-warning { + /* background: hsl(36, 100%, 32%); */ + background: hsl(39, 100%, 10%); +} +.cm-editor .cm-diagnosticText {} + + @media (prefers-color-scheme: dark) { .cm-editor .cm-activeLineGutter { background-color: var(--sk-back-3); @@ -57,4 +79,8 @@ .cm-editor .cm-activeLine { background-color: var(--sk-back-2); } + + .cm-editor .cm-diagnostic-warning { + background: hsl(39, 100%, 20%); + } } \ No newline at end of file diff --git a/src/routes/tutorial/[slug]/state.js b/src/routes/tutorial/[slug]/state.js index 9932b214c..b9290b678 100644 --- a/src/routes/tutorial/[slug]/state.js +++ b/src/routes/tutorial/[slug]/state.js @@ -1,13 +1,34 @@ import { derived, writable } from 'svelte/store'; import * as adapter from './adapter.js'; -/** @type {import('svelte/store').Writable} */ +/** + * @template T + * @typedef {import('svelte/store').Writable} Writable + */ + +// TODO would be nice if svelte exported this type (maybe it does already?) +/** + * @typedef {{ + * code: string; + * start: { line: number, column: number, character: number }; + * end: { line: number, column: number, character: number }; + * pos: number; + * filename: string; + * frame: string; + * message: string; + * }} CompilerWarning + */ + +/** @type {Writable} */ export const files = writable([]); -/** @type {import('svelte/store').Writable>} */ +/** @type {Writable>} */ export const solution = writable({}); -/** @type {import('svelte/store').Writable} */ +/** @type {Writable>} */ +export const warnings = writable({}); + +/** @type {Writable} */ export const selected_name = writable(null); export const selected_file = derived([files, selected_name], ([$files, $selected_name]) => { From 2b1610c560712b565a6745e33baba7fecabd1bd2 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Tue, 14 Mar 2023 21:09:16 -0400 Subject: [PATCH 022/303] better mobile layout (#259) * mobile toggle * a11y * update lockfile * fix * fix tooltip positions * mobile filetree * debugging * wtf * throw CSS at the problem * remove debugging stuff * make view history-driven --------- Co-authored-by: Rich Harris --- package.json | 2 +- pnpm-lock.yaml | 8 +- src/routes/tutorial/[slug]/+page.svelte | 266 ++++++++++++------ src/routes/tutorial/[slug]/Editor.svelte | 5 +- src/routes/tutorial/[slug]/Output.svelte | 6 +- .../tutorial/[slug]/ScreenToggle.svelte | 74 +++-- .../tutorial/[slug]/ToggleButton.svelte | 83 ++++++ .../tutorial/[slug]/filetree/File.svelte | 8 +- .../tutorial/[slug]/filetree/Filetree.svelte | 24 +- .../tutorial/[slug]/filetree/Folder.svelte | 40 ++- .../tutorial/[slug]/filetree/Item.svelte | 3 +- .../tutorial/[slug]/filetree/context.js | 2 +- 12 files changed, 368 insertions(+), 153 deletions(-) create mode 100644 src/routes/tutorial/[slug]/ToggleButton.svelte diff --git a/package.json b/package.json index 4d3bc7fdc..ca5c1cca4 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "@lezer/javascript": "^1.4.1", "@lezer/lr": "^1.3.3", "@replit/codemirror-lang-svelte": "^6.0.0", - "@rich_harris/svelte-split-pane": "^1.0.1", + "@rich_harris/svelte-split-pane": "^1.0.2", "@webcontainer/api": "^1.0.2", "adm-zip": "^0.5.10", "ansi-to-html": "^0.7.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7b5b7c8b2..32c554354 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -17,7 +17,7 @@ specifiers: '@lezer/lr': ^1.3.3 '@playwright/test': ^1.31.2 '@replit/codemirror-lang-svelte': ^6.0.0 - '@rich_harris/svelte-split-pane': ^1.0.1 + '@rich_harris/svelte-split-pane': ^1.0.2 '@sveltejs/adapter-vercel': 2.3.1 '@sveltejs/kit': ^1.11.0 '@sveltejs/site-kit': ^3.2.2 @@ -61,7 +61,7 @@ dependencies: '@lezer/javascript': 1.4.1 '@lezer/lr': 1.3.3 '@replit/codemirror-lang-svelte': 6.0.0_ybny7xhlf2ysg4majw54z4nkly - '@rich_harris/svelte-split-pane': 1.0.1_svelte@3.56.0 + '@rich_harris/svelte-split-pane': 1.0.2_svelte@3.56.0 '@webcontainer/api': 1.0.2 adm-zip: 0.5.10 ansi-to-html: 0.7.2 @@ -730,8 +730,8 @@ packages: '@lezer/lr': 1.3.3 dev: false - /@rich_harris/svelte-split-pane/1.0.1_svelte@3.56.0: - resolution: {integrity: sha512-/11fp3792qh4pXxO3XtVmIQf6SCDFKcQyyQvVOAKr8U5tG0Z4QaLEXsyOKOpeAkngqWT1dbBfjVynUXa7kb1EA==} + /@rich_harris/svelte-split-pane/1.0.2_svelte@3.56.0: + resolution: {integrity: sha512-8Qhno4kshsBFWC3MnM0++TIbyAvbiuCWXxiCA38VhCr/ZFKQcS8k9mjzWt9eynQjgkyZHejXN0j0V7ws7LV1KA==} peerDependencies: svelte: ^3.54.0 dependencies: diff --git a/src/routes/tutorial/[slug]/+page.svelte b/src/routes/tutorial/[slug]/+page.svelte index 6bb3bee4e..600a097bf 100644 --- a/src/routes/tutorial/[slug]/+page.svelte +++ b/src/routes/tutorial/[slug]/+page.svelte @@ -1,12 +1,10 @@ -
    - {#each labels as label, index} - - {/each} +
    + + +
    diff --git a/src/routes/tutorial/[slug]/ToggleButton.svelte b/src/routes/tutorial/[slug]/ToggleButton.svelte new file mode 100644 index 000000000..f16e49a69 --- /dev/null +++ b/src/routes/tutorial/[slug]/ToggleButton.svelte @@ -0,0 +1,83 @@ + + + + + + diff --git a/src/routes/tutorial/[slug]/filetree/File.svelte b/src/routes/tutorial/[slug]/filetree/File.svelte index e762a51cb..6b65bf25b 100644 --- a/src/routes/tutorial/[slug]/filetree/File.svelte +++ b/src/routes/tutorial/[slug]/filetree/File.svelte @@ -2,7 +2,7 @@ import * as context from './context.js'; import Item from './Item.svelte'; import file_icon from '$lib/icons/file.svg'; - import { selected_name, select_file, solution } from '../state.js'; + import { selected_name, solution } from '../state.js'; /** @type {import('$lib/types').FileStub} */ export let file; @@ -10,11 +10,11 @@ /** @type {number} */ export let depth; - const { rename, remove, readonly } = context.get(); + const { rename, remove, select } = context.get(); let renaming = false; - $: can_remove = !$readonly && !$solution[file.name]; + $: can_remove = !$solution[file.name]; /** @type {import('./ContextMenu.svelte').MenuItems} */ $: actions = can_remove @@ -45,7 +45,7 @@ icon={file_icon} selected={file.name === $selected_name} {actions} - on:click={() => select_file(file.name)} + on:click={() => select(file.name)} on:edit={() => { renaming = true; }} diff --git a/src/routes/tutorial/[slug]/filetree/Filetree.svelte b/src/routes/tutorial/[slug]/filetree/Filetree.svelte index 64252c98f..e23abd1a1 100644 --- a/src/routes/tutorial/[slug]/filetree/Filetree.svelte +++ b/src/routes/tutorial/[slug]/filetree/Filetree.svelte @@ -1,4 +1,5 @@ \n'; - await page.locator(editor_focus_selector).fill(code); + await page.locator(editor_selector).fill(code); // move the cursor into the script tag - await page.keyboard.press('PageUp', { delay: 500 }); - await page.keyboard.press('ArrowDown', { delay: 500 }); + await page.waitForTimeout(500); + await page.keyboard.press('PageUp'); + await page.waitForTimeout(500); + await page.keyboard.press('ArrowDown'); // wait a little because the above operation is flaky await page.waitForTimeout(500); From ec0fa015771f1d127397569eafaa8702fbb64253 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Wed, 15 Mar 2023 12:29:02 -0400 Subject: [PATCH 025/303] fix cursor styles - closes #262 (#264) Co-authored-by: Rich Harris --- src/routes/tutorial/[slug]/codemirror.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/routes/tutorial/[slug]/codemirror.css b/src/routes/tutorial/[slug]/codemirror.css index 416da525a..3a0f001be 100644 --- a/src/routes/tutorial/[slug]/codemirror.css +++ b/src/routes/tutorial/[slug]/codemirror.css @@ -32,6 +32,10 @@ width: 1rem; } +.cm-focused .cm-cursor { + border-left-color: var(--sk-text-3); +} + .cm-editor .cm-content { padding: 1rem 0; } From d5b80c55346779a43b15e162b3f4efc488f6d0ce Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Wed, 15 Mar 2023 14:04:38 -0400 Subject: [PATCH 026/303] Tweaks (#265) * better highlight * fix light mode diagnostic styling * always open external URLs in a new tab * tweak each block exercise * more * tidy up await block exercise * more --------- Co-authored-by: Rich Harris --- .../04-logic/04-each-blocks/README.md | 22 +++++---- .../04-each-blocks/app-a/src/lib/App.svelte | 13 +++--- .../04-each-blocks/app-b/src/lib/App.svelte | 5 +-- .../04-logic/05-keyed-each-blocks/README.md | 4 +- .../app-a/src/lib/Thing.svelte | 10 +---- .../app-b/src/lib/Thing.svelte | 45 ------------------- .../06-await-blocks/app-a/src/lib/App.svelte | 16 ++++--- .../app-a/src/routes/random-number/+server.js | 23 ++++++++++ .../06-await-blocks/app-b/src/lib/App.svelte | 16 ++++--- .../05-events/01-dom-events/README.md | 2 +- .../05-events/02-inline-handlers/README.md | 17 +++++-- .../05-events/03-event-modifiers/README.md | 4 +- .../app-a/src/lib/App.svelte | 4 +- content/tutorial/common/src/__client.js | 16 +++++++ src/routes/tutorial/[slug]/Sidebar.svelte | 2 +- src/routes/tutorial/[slug]/codemirror.css | 7 ++- 16 files changed, 106 insertions(+), 100 deletions(-) delete mode 100644 content/tutorial/01-svelte/04-logic/05-keyed-each-blocks/app-b/src/lib/Thing.svelte create mode 100644 content/tutorial/01-svelte/04-logic/06-await-blocks/app-a/src/routes/random-number/+server.js 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 f277503ce..f345bca34 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 @@ -6,11 +6,13 @@ If you need to loop over lists of data, use an `each` block: ```svelte ``` @@ -19,10 +21,12 @@ If you need to loop over lists of data, use an `each` block: You can get the current _index_ as a second argument, like so: ```svelte -{#each cats as cat, i} -
  • - {i + 1}: {cat.name} -
  • +{#each cats as cat+++, i}+++ +
  • + + +++{i + 1}:+++ {cat.name} + +
  • {/each} ``` diff --git a/content/tutorial/01-svelte/04-logic/04-each-blocks/app-a/src/lib/App.svelte b/content/tutorial/01-svelte/04-logic/04-each-blocks/app-a/src/lib/App.svelte index 490c5f6c3..501254eb1 100644 --- a/content/tutorial/01-svelte/04-logic/04-each-blocks/app-a/src/lib/App.svelte +++ b/content/tutorial/01-svelte/04-logic/04-each-blocks/app-a/src/lib/App.svelte @@ -19,13 +19,10 @@ diff --git a/content/tutorial/01-svelte/04-logic/04-each-blocks/app-b/src/lib/App.svelte b/content/tutorial/01-svelte/04-logic/04-each-blocks/app-b/src/lib/App.svelte index 5676c3c59..7d5d7187a 100644 --- a/content/tutorial/01-svelte/04-logic/04-each-blocks/app-b/src/lib/App.svelte +++ b/content/tutorial/01-svelte/04-logic/04-each-blocks/app-b/src/lib/App.svelte @@ -20,10 +20,7 @@
      {#each cats as { id, name }, i}
    • - + {i + 1}: {name}
    • diff --git a/content/tutorial/01-svelte/04-logic/05-keyed-each-blocks/README.md b/content/tutorial/01-svelte/04-logic/05-keyed-each-blocks/README.md index d6c0aa3c2..77bf35720 100644 --- a/content/tutorial/01-svelte/04-logic/05-keyed-each-blocks/README.md +++ b/content/tutorial/01-svelte/04-logic/05-keyed-each-blocks/README.md @@ -4,14 +4,14 @@ title: Keyed each blocks By default, when you modify the value of an `each` block, it will add and remove items at the _end_ of the block, and update any values that have changed. That might not be what you want. -It's easier to show why than to explain. Click the 'Remove first thing' button a few times, and notice what happens: It removes the first `` component, but the _last_ DOM node. Then it updates the `name` value in the remaining DOM nodes, but not the emoji. +It's easier to show why than to explain. Click the 'Remove first thing' button a few times, and notice what happens: It removes the first `` component, but the _last_ DOM node. Then it updates the `name` value in the remaining DOM nodes, but not the emoji, which in `Thing.svelte` is fixed when the component is created. Instead, we'd like to remove only the first `` component and its DOM node, and leave the others unaffected. To do that, we specify a unique identifier (or "key") for the `each` block: ```svelte -{#each things as thing (thing.id)} +{#each things as thing (+++thing.id+++)} {/each} ``` diff --git a/content/tutorial/01-svelte/04-logic/05-keyed-each-blocks/app-a/src/lib/Thing.svelte b/content/tutorial/01-svelte/04-logic/05-keyed-each-blocks/app-a/src/lib/Thing.svelte index 3eb272b93..f5284f746 100644 --- a/content/tutorial/01-svelte/04-logic/05-keyed-each-blocks/app-a/src/lib/Thing.svelte +++ b/content/tutorial/01-svelte/04-logic/05-keyed-each-blocks/app-a/src/lib/Thing.svelte @@ -1,6 +1,4 @@

      diff --git a/content/tutorial/01-svelte/04-logic/05-keyed-each-blocks/app-b/src/lib/Thing.svelte b/content/tutorial/01-svelte/04-logic/05-keyed-each-blocks/app-b/src/lib/Thing.svelte deleted file mode 100644 index 9ca6b8b17..000000000 --- a/content/tutorial/01-svelte/04-logic/05-keyed-each-blocks/app-b/src/lib/Thing.svelte +++ /dev/null @@ -1,45 +0,0 @@ - - -

      - The emoji for {name} is {emoji} -

      - - diff --git a/content/tutorial/01-svelte/04-logic/06-await-blocks/app-a/src/lib/App.svelte b/content/tutorial/01-svelte/04-logic/06-await-blocks/app-a/src/lib/App.svelte index 524f9bfa0..7af6f29b5 100644 --- a/content/tutorial/01-svelte/04-logic/06-await-blocks/app-a/src/lib/App.svelte +++ b/content/tutorial/01-svelte/04-logic/06-await-blocks/app-a/src/lib/App.svelte @@ -1,14 +1,14 @@ - +

      {promise}

      diff --git a/content/tutorial/01-svelte/04-logic/06-await-blocks/app-a/src/routes/random-number/+server.js b/content/tutorial/01-svelte/04-logic/06-await-blocks/app-a/src/routes/random-number/+server.js new file mode 100644 index 000000000..e051d80bd --- /dev/null +++ b/content/tutorial/01-svelte/04-logic/06-await-blocks/app-a/src/routes/random-number/+server.js @@ -0,0 +1,23 @@ +export async function GET(req) { + const query = req.url.searchParams; + let min = query.get('min') || '0'; + let max = query.get('max') || '100'; + min = +min; + max = +max; + + // simulate a long delay + await new Promise((res) => setTimeout(res, 1000)); + + // fail sometimes + if (Math.random() < 0.333) { + return new Response(`Failed to generate random number. Please try again`, { + status: 400, + headers: { 'Access-Control-Allow-Origin': '*' } + }); + } + + const num = min + Math.round(Math.random() * (max - min)); + return new Response(String(num), { + headers: { 'Access-Control-Allow-Origin': '*' } + }); +} \ No newline at end of file diff --git a/content/tutorial/01-svelte/04-logic/06-await-blocks/app-b/src/lib/App.svelte b/content/tutorial/01-svelte/04-logic/06-await-blocks/app-b/src/lib/App.svelte index 7a0cd07fd..73b7d3f19 100644 --- a/content/tutorial/01-svelte/04-logic/06-await-blocks/app-b/src/lib/App.svelte +++ b/content/tutorial/01-svelte/04-logic/06-await-blocks/app-b/src/lib/App.svelte @@ -1,14 +1,14 @@ - + {#await promise}

      ...waiting

      diff --git a/content/tutorial/01-svelte/05-events/01-dom-events/README.md b/content/tutorial/01-svelte/05-events/01-dom-events/README.md index 64cfa3217..a0dfceef7 100644 --- a/content/tutorial/01-svelte/05-events/01-dom-events/README.md +++ b/content/tutorial/01-svelte/05-events/01-dom-events/README.md @@ -5,7 +5,7 @@ title: DOM events As we've briefly seen already, you can listen to any event on an element with the `on:` directive: ```svelte -
      +
      The mouse position is {m.x} x {m.y}
      ``` diff --git a/content/tutorial/01-svelte/05-events/02-inline-handlers/README.md b/content/tutorial/01-svelte/05-events/02-inline-handlers/README.md index 40585909f..8d59e4dba 100644 --- a/content/tutorial/01-svelte/05-events/02-inline-handlers/README.md +++ b/content/tutorial/01-svelte/05-events/02-inline-handlers/README.md @@ -5,11 +5,22 @@ title: Inline handlers You can also declare event handlers inline: ```svelte -
      + + +
      { + m = { x: e.clientX, y: e.clientY }; + }}+++ +> The mouse position is {m.x} x {m.y}
      ``` -The quote marks are optional, but they're helpful for syntax highlighting in some environments. - > In some frameworks you may see recommendations to avoid inline event handlers for performance reasons, particularly inside loops. That advice doesn't apply to Svelte — the compiler will always do the right thing, whichever form you choose. 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 71954b2fc..4661d8de4 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 @@ -7,11 +7,11 @@ DOM event handlers can have _modifiers_ that alter their behaviour. For example, ```svelte - ``` diff --git a/content/tutorial/01-svelte/05-events/03-event-modifiers/app-a/src/lib/App.svelte b/content/tutorial/01-svelte/05-events/03-event-modifiers/app-a/src/lib/App.svelte index 0a000c832..c56713d01 100644 --- a/content/tutorial/01-svelte/05-events/03-event-modifiers/app-a/src/lib/App.svelte +++ b/content/tutorial/01-svelte/05-events/03-event-modifiers/app-a/src/lib/App.svelte @@ -4,4 +4,6 @@ } - + diff --git a/content/tutorial/common/src/__client.js b/content/tutorial/common/src/__client.js index 4f4ffee9b..e735c3a65 100644 --- a/content/tutorial/common/src/__client.js +++ b/content/tutorial/common/src/__client.js @@ -93,6 +93,22 @@ window.addEventListener('focusin', (e) => { } }); +window.addEventListener('click', (e) => { + let node = e.target; + while (node) { + if (node.nodeName === 'A') { + const href = node.href; + const url = new URL(href); + + if (url.origin !== location.origin) { + e.preventDefault(); + window.open(url, '_blank'); + } + } + node = node.parent; + } +}); + function ping() { parent.postMessage( { diff --git a/src/routes/tutorial/[slug]/Sidebar.svelte b/src/routes/tutorial/[slug]/Sidebar.svelte index 541e0bc96..42f5dabd7 100644 --- a/src/routes/tutorial/[slug]/Sidebar.svelte +++ b/src/routes/tutorial/[slug]/Sidebar.svelte @@ -130,7 +130,7 @@ } .text :global(pre) :global(.highlight.add) { - --color: rgba(0, 255, 0, 0.1); + --color: rgba(0, 255, 0, 0.18); } .text :global(pre) :global(.highlight.remove) { diff --git a/src/routes/tutorial/[slug]/codemirror.css b/src/routes/tutorial/[slug]/codemirror.css index 3a0f001be..26526680b 100644 --- a/src/routes/tutorial/[slug]/codemirror.css +++ b/src/routes/tutorial/[slug]/codemirror.css @@ -69,8 +69,7 @@ padding: 0.2rem 0.8rem; } .cm-editor .cm-diagnostic-warning { - /* background: hsl(36, 100%, 32%); */ - background: hsl(39, 100%, 10%); + background: hsl(39, 100%, 70%); } .cm-editor .cm-diagnosticText {} @@ -87,4 +86,8 @@ .cm-editor .cm-diagnostic-warning { background: hsl(39, 100%, 20%); } + + .cm-editor .cm-diagnostic-warning { + background: hsl(39, 100%, 10%); + } } \ No newline at end of file From 8fac2beac2d2c41b42d71e2d88cacd66c5078ef5 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Thu, 16 Mar 2023 14:21:06 -0400 Subject: [PATCH 027/303] tweak --- .../tutorial/01-svelte/05-events/05-event-forwarding/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/tutorial/01-svelte/05-events/05-event-forwarding/README.md b/content/tutorial/01-svelte/05-events/05-event-forwarding/README.md index 3daff332a..41467fd4f 100644 --- a/content/tutorial/01-svelte/05-events/05-event-forwarding/README.md +++ b/content/tutorial/01-svelte/05-events/05-event-forwarding/README.md @@ -30,5 +30,5 @@ But that's a lot of code to write, so Svelte gives us an equivalent shorthand import Inner from './Inner.svelte'; - + ``` From 843014076a34accae136ba1241c37ed8e51078ea Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Thu, 16 Mar 2023 15:44:29 -0400 Subject: [PATCH 028/303] escape html in terminal (#267) Co-authored-by: Rich Harris --- src/lib/client/adapters/webcontainer/index.js | 4 ++-- src/lib/server/markdown.js | 17 +++-------------- src/lib/utils.js | 12 ++++++++++++ 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/src/lib/client/adapters/webcontainer/index.js b/src/lib/client/adapters/webcontainer/index.js index 5e977162f..922643f99 100644 --- a/src/lib/client/adapters/webcontainer/index.js +++ b/src/lib/client/adapters/webcontainer/index.js @@ -1,7 +1,7 @@ import { WebContainer } from '@webcontainer/api'; import base64 from 'base64-js'; import AnsiToHtml from 'ansi-to-html'; -import { get_depth } from '../../../utils.js'; +import { escape_html, get_depth } from '../../../utils.js'; import { ready } from '../common/index.js'; const converter = new AnsiToHtml({ @@ -59,7 +59,7 @@ export async function create(base, error, progress, logs) { // clear screen logs.set([]); } else { - const log = converter.toHtml(chunk); + const log = converter.toHtml(escape_html(chunk)); logs.update(($logs) => [...$logs, log]); } } diff --git a/src/lib/server/markdown.js b/src/lib/server/markdown.js index eaadb73d3..d92d71c28 100644 --- a/src/lib/server/markdown.js +++ b/src/lib/server/markdown.js @@ -4,6 +4,7 @@ import 'prismjs/components/prism-diff.js'; import 'prismjs/components/prism-typescript.js'; import 'prism-svelte'; import { marked } from 'marked'; +import { escape_html } from '$lib/utils'; const languages = { bash: 'bash', @@ -17,18 +18,6 @@ const languages = { '': '' }; -/** @type {Record} */ -const chars = { - '&': '&', - '<': '<', - '>': '>' -}; - -/** @param {string} html */ -function escape(html) { - return html.replace(/[&<>]/g, (c) => chars[c]); -} - const delimiter_substitutes = { '+++': ' ', '---': ' ', @@ -84,7 +73,7 @@ const default_renderer = { return { type, - content: escape(content) + content: escape_html(content) }; }); @@ -99,7 +88,7 @@ const default_renderer = { const plang = languages[lang]; const highlighted = plang ? PrismJS.highlight(source, PrismJS.languages[plang], language) - : escape(source); + : escape_html(source); html = `
      ${ options.file ? `${options.file}` : '' diff --git a/src/lib/utils.js b/src/lib/utils.js index 07bb5146e..b4c4ea460 100644 --- a/src/lib/utils.js +++ b/src/lib/utils.js @@ -2,3 +2,15 @@ export function get_depth(name) { return name.split('/').length - 1; } + +/** @type {Record} */ +const chars = { + '&': '&', + '<': '<', + '>': '>' +}; + +/** @param {string} html */ +export function escape_html(html) { + return html.replace(/[&<>]/g, (c) => chars[c]); +} \ No newline at end of file From bf5fda6053ff856231aaba5206ae43995b98364e Mon Sep 17 00:00:00 2001 From: Simon H <5968653+dummdidumm@users.noreply.github.com> Date: Fri, 17 Mar 2023 18:08:02 +0100 Subject: [PATCH 029/303] docs: add svelte:element/document chapters (#270) from old tutorial - also updates some existing content --- .../app-a/src/lib/Folder.svelte | 11 +-- .../01-svelte-self/app-b/src/lib/File.svelte | 17 ---- .../app-b/src/lib/Folder.svelte | 11 +-- .../03-svelte-element/README.md | 23 +++++ .../app-a/src/lib/App.svelte | 18 ++++ .../app-b/src/lib/App.svelte | 12 +++ .../README.md | 0 .../app-a/src/lib/App.svelte | 0 .../app-b/src/lib/App.svelte | 0 .../README.md | 0 .../app-a/src/lib/App.svelte | 0 .../app-b/src/lib/App.svelte | 0 .../06-svelte-document/README.md | 13 +++ .../app-a/src/lib/App.svelte | 10 ++ .../app-b/src/lib/App.svelte | 10 ++ .../README.md | 0 .../app-a/src/lib/App.svelte | 0 .../app-a/static/kitten.png | Bin .../app-b/src/lib/App.svelte | 0 .../07-svelte-options/app-b/src/lib/flash.js | 13 --- .../README.md | 0 .../app-a/src/lib/App.svelte | 0 .../app-b/src/lib/App.svelte | 0 .../README.md | 0 .../app-a/src/lib/App.svelte | 0 .../app-a/src/lib/Todo.svelte | 12 ++- .../app-a/src/lib/flash.js | 0 .../app-b/src/lib/App.svelte | 0 .../app-b/src/lib/Todo.svelte | 12 ++- .../README.md | 0 .../app-a/src/lib/App.svelte | 0 .../app-a/src/lib/Box.svelte | 0 .../app-b/src/lib/App.svelte | 0 .../app-b/src/lib/Box.svelte | 0 content/tutorial/common/package-lock.json | 14 +-- content/tutorial/common/package.json | 2 +- package.json | 2 +- pnpm-lock.yaml | 88 ++++++++---------- 38 files changed, 158 insertions(+), 110 deletions(-) delete mode 100644 content/tutorial/03-advanced-svelte/09-special-elements/01-svelte-self/app-b/src/lib/File.svelte create mode 100644 content/tutorial/03-advanced-svelte/09-special-elements/03-svelte-element/README.md create mode 100644 content/tutorial/03-advanced-svelte/09-special-elements/03-svelte-element/app-a/src/lib/App.svelte create mode 100644 content/tutorial/03-advanced-svelte/09-special-elements/03-svelte-element/app-b/src/lib/App.svelte rename content/tutorial/03-advanced-svelte/09-special-elements/{03-svelte-window => 04-svelte-window}/README.md (100%) rename content/tutorial/03-advanced-svelte/09-special-elements/{03-svelte-window => 04-svelte-window}/app-a/src/lib/App.svelte (100%) rename content/tutorial/03-advanced-svelte/09-special-elements/{03-svelte-window => 04-svelte-window}/app-b/src/lib/App.svelte (100%) rename content/tutorial/03-advanced-svelte/09-special-elements/{04-svelte-window-bindings => 05-svelte-window-bindings}/README.md (100%) rename content/tutorial/03-advanced-svelte/09-special-elements/{04-svelte-window-bindings => 05-svelte-window-bindings}/app-a/src/lib/App.svelte (100%) rename content/tutorial/03-advanced-svelte/09-special-elements/{04-svelte-window-bindings => 05-svelte-window-bindings}/app-b/src/lib/App.svelte (100%) create mode 100644 content/tutorial/03-advanced-svelte/09-special-elements/06-svelte-document/README.md create mode 100644 content/tutorial/03-advanced-svelte/09-special-elements/06-svelte-document/app-a/src/lib/App.svelte create mode 100644 content/tutorial/03-advanced-svelte/09-special-elements/06-svelte-document/app-b/src/lib/App.svelte rename content/tutorial/03-advanced-svelte/09-special-elements/{05-svelte-body => 07-svelte-body}/README.md (100%) rename content/tutorial/03-advanced-svelte/09-special-elements/{05-svelte-body => 07-svelte-body}/app-a/src/lib/App.svelte (100%) rename content/tutorial/03-advanced-svelte/09-special-elements/{05-svelte-body => 07-svelte-body}/app-a/static/kitten.png (100%) rename content/tutorial/03-advanced-svelte/09-special-elements/{05-svelte-body => 07-svelte-body}/app-b/src/lib/App.svelte (100%) delete mode 100644 content/tutorial/03-advanced-svelte/09-special-elements/07-svelte-options/app-b/src/lib/flash.js rename content/tutorial/03-advanced-svelte/09-special-elements/{06-svelte-head => 08-svelte-head}/README.md (100%) rename content/tutorial/03-advanced-svelte/09-special-elements/{06-svelte-head => 08-svelte-head}/app-a/src/lib/App.svelte (100%) rename content/tutorial/03-advanced-svelte/09-special-elements/{06-svelte-head => 08-svelte-head}/app-b/src/lib/App.svelte (100%) rename content/tutorial/03-advanced-svelte/09-special-elements/{07-svelte-options => 09-svelte-options}/README.md (100%) rename content/tutorial/03-advanced-svelte/09-special-elements/{07-svelte-options => 09-svelte-options}/app-a/src/lib/App.svelte (100%) rename content/tutorial/03-advanced-svelte/09-special-elements/{07-svelte-options => 09-svelte-options}/app-a/src/lib/Todo.svelte (70%) rename content/tutorial/03-advanced-svelte/09-special-elements/{07-svelte-options => 09-svelte-options}/app-a/src/lib/flash.js (100%) rename content/tutorial/03-advanced-svelte/09-special-elements/{07-svelte-options => 09-svelte-options}/app-b/src/lib/App.svelte (100%) rename content/tutorial/03-advanced-svelte/09-special-elements/{07-svelte-options => 09-svelte-options}/app-b/src/lib/Todo.svelte (72%) rename content/tutorial/03-advanced-svelte/09-special-elements/{08-svelte-fragment => 10-svelte-fragment}/README.md (100%) rename content/tutorial/03-advanced-svelte/09-special-elements/{08-svelte-fragment => 10-svelte-fragment}/app-a/src/lib/App.svelte (100%) rename content/tutorial/03-advanced-svelte/09-special-elements/{08-svelte-fragment => 10-svelte-fragment}/app-a/src/lib/Box.svelte (100%) rename content/tutorial/03-advanced-svelte/09-special-elements/{08-svelte-fragment => 10-svelte-fragment}/app-b/src/lib/App.svelte (100%) rename content/tutorial/03-advanced-svelte/09-special-elements/{08-svelte-fragment => 10-svelte-fragment}/app-b/src/lib/Box.svelte (100%) diff --git a/content/tutorial/03-advanced-svelte/09-special-elements/01-svelte-self/app-a/src/lib/Folder.svelte b/content/tutorial/03-advanced-svelte/09-special-elements/01-svelte-self/app-a/src/lib/Folder.svelte index 770339c77..cf49668e9 100644 --- a/content/tutorial/03-advanced-svelte/09-special-elements/01-svelte-self/app-a/src/lib/Folder.svelte +++ b/content/tutorial/03-advanced-svelte/09-special-elements/01-svelte-self/app-a/src/lib/Folder.svelte @@ -10,9 +10,7 @@ } -{name} + {#if expanded}
        @@ -29,13 +27,14 @@ {/if} diff --git a/content/tutorial/03-advanced-svelte/09-special-elements/01-svelte-self/app-b/src/lib/Folder.svelte b/content/tutorial/03-advanced-svelte/09-special-elements/01-svelte-self/app-b/src/lib/Folder.svelte index 213a3b598..dcf80e364 100644 --- a/content/tutorial/03-advanced-svelte/09-special-elements/01-svelte-self/app-b/src/lib/Folder.svelte +++ b/content/tutorial/03-advanced-svelte/09-special-elements/01-svelte-self/app-b/src/lib/Folder.svelte @@ -10,9 +10,7 @@ } -{name} + {#if expanded}
          @@ -29,13 +27,14 @@ {/if} diff --git a/content/tutorial/01-svelte/08-stores/01-writable-stores/app-b/src/lib/App.svelte b/content/tutorial/01-svelte/08-stores/01-writable-stores/app-b/src/lib/App.svelte deleted file mode 100644 index a4d9b16dc..000000000 --- a/content/tutorial/01-svelte/08-stores/01-writable-stores/app-b/src/lib/App.svelte +++ /dev/null @@ -1,18 +0,0 @@ - - -

          The count is {count_value}

          - - - - diff --git a/content/tutorial/01-svelte/08-stores/01-writable-stores/app-b/src/lib/stores.js b/content/tutorial/01-svelte/08-stores/01-writable-stores/app-b/src/lib/stores.js deleted file mode 100644 index d432d339e..000000000 --- a/content/tutorial/01-svelte/08-stores/01-writable-stores/app-b/src/lib/stores.js +++ /dev/null @@ -1,3 +0,0 @@ -import { writable } from 'svelte/store'; - -export const count = writable(0); diff --git a/content/tutorial/01-svelte/08-stores/02-auto-subscriptions/app-b/src/lib/Decrementer.svelte b/content/tutorial/01-svelte/08-stores/02-auto-subscriptions/app-b/src/lib/Decrementer.svelte deleted file mode 100644 index 596ba4bba..000000000 --- a/content/tutorial/01-svelte/08-stores/02-auto-subscriptions/app-b/src/lib/Decrementer.svelte +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/content/tutorial/01-svelte/08-stores/02-auto-subscriptions/app-b/src/lib/Incrementer.svelte b/content/tutorial/01-svelte/08-stores/02-auto-subscriptions/app-b/src/lib/Incrementer.svelte deleted file mode 100644 index 1fb7dea3c..000000000 --- a/content/tutorial/01-svelte/08-stores/02-auto-subscriptions/app-b/src/lib/Incrementer.svelte +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/content/tutorial/01-svelte/08-stores/02-auto-subscriptions/app-b/src/lib/Resetter.svelte b/content/tutorial/01-svelte/08-stores/02-auto-subscriptions/app-b/src/lib/Resetter.svelte deleted file mode 100644 index 9c8809961..000000000 --- a/content/tutorial/01-svelte/08-stores/02-auto-subscriptions/app-b/src/lib/Resetter.svelte +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/content/tutorial/01-svelte/08-stores/02-auto-subscriptions/app-b/src/lib/stores.js b/content/tutorial/01-svelte/08-stores/02-auto-subscriptions/app-b/src/lib/stores.js deleted file mode 100644 index d432d339e..000000000 --- a/content/tutorial/01-svelte/08-stores/02-auto-subscriptions/app-b/src/lib/stores.js +++ /dev/null @@ -1,3 +0,0 @@ -import { writable } from 'svelte/store'; - -export const count = writable(0); diff --git a/content/tutorial/01-svelte/08-stores/03-readable-stores/app-b/src/lib/App.svelte b/content/tutorial/01-svelte/08-stores/03-readable-stores/app-b/src/lib/App.svelte deleted file mode 100644 index 463523a03..000000000 --- a/content/tutorial/01-svelte/08-stores/03-readable-stores/app-b/src/lib/App.svelte +++ /dev/null @@ -1,15 +0,0 @@ - - -

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

          diff --git a/content/tutorial/01-svelte/08-stores/04-derived-stores/app-b/src/lib/App.svelte b/content/tutorial/01-svelte/08-stores/04-derived-stores/app-b/src/lib/App.svelte deleted file mode 100644 index 782ff95d3..000000000 --- a/content/tutorial/01-svelte/08-stores/04-derived-stores/app-b/src/lib/App.svelte +++ /dev/null @@ -1,21 +0,0 @@ - - -

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

          - -

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

          diff --git a/content/tutorial/01-svelte/08-stores/05-custom-stores/app-b/src/lib/App.svelte b/content/tutorial/01-svelte/08-stores/05-custom-stores/app-b/src/lib/App.svelte deleted file mode 100644 index dbdd299d6..000000000 --- a/content/tutorial/01-svelte/08-stores/05-custom-stores/app-b/src/lib/App.svelte +++ /dev/null @@ -1,9 +0,0 @@ - - -

          The count is {$count}

          - - - - diff --git a/content/tutorial/01-svelte/08-stores/06-store-bindings/app-b/src/lib/stores.js b/content/tutorial/01-svelte/08-stores/06-store-bindings/app-b/src/lib/stores.js deleted file mode 100644 index 58f25475c..000000000 --- a/content/tutorial/01-svelte/08-stores/06-store-bindings/app-b/src/lib/stores.js +++ /dev/null @@ -1,5 +0,0 @@ -import { writable, derived } from 'svelte/store'; - -export const name = writable('world'); - -export const greeting = derived(name, ($name) => `Hello ${$name}!`); diff --git a/content/tutorial/02-sveltekit/05-api-routes/01-get-handlers/app-b/src/routes/+page.svelte b/content/tutorial/02-sveltekit/05-api-routes/01-get-handlers/app-b/src/routes/+page.svelte deleted file mode 100644 index 99955f2ed..000000000 --- a/content/tutorial/02-sveltekit/05-api-routes/01-get-handlers/app-b/src/routes/+page.svelte +++ /dev/null @@ -1,15 +0,0 @@ - - - - -{#if number !== undefined} -

          You rolled a {number}

          -{/if} diff --git a/content/tutorial/02-sveltekit/05-api-routes/02-post-put-patch-delete/app-b/src/routes/+page.svelte b/content/tutorial/02-sveltekit/05-api-routes/02-post-put-patch-delete/app-b/src/routes/+page.svelte deleted file mode 100644 index 1333ed77b..000000000 --- a/content/tutorial/02-sveltekit/05-api-routes/02-post-put-patch-delete/app-b/src/routes/+page.svelte +++ /dev/null @@ -1 +0,0 @@ -TODO diff --git a/content/tutorial/03-advanced-svelte/05-bindings/06-component-bindings/app-b/src/lib/Keypad.svelte b/content/tutorial/03-advanced-svelte/05-bindings/06-component-bindings/app-b/src/lib/Keypad.svelte deleted file mode 100644 index b94e94453..000000000 --- a/content/tutorial/03-advanced-svelte/05-bindings/06-component-bindings/app-b/src/lib/Keypad.svelte +++ /dev/null @@ -1,44 +0,0 @@ - - -
          - - - - - - - - - - - - - -
          - - diff --git a/content/tutorial/03-advanced-svelte/05-bindings/07-component-this/app-b/src/lib/InputField.svelte b/content/tutorial/03-advanced-svelte/05-bindings/07-component-this/app-b/src/lib/InputField.svelte deleted file mode 100644 index caf9c2c9e..000000000 --- a/content/tutorial/03-advanced-svelte/05-bindings/07-component-this/app-b/src/lib/InputField.svelte +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/content/tutorial/03-advanced-svelte/07-composition/04-optional-slots/app-b/src/lib/App.svelte b/content/tutorial/03-advanced-svelte/07-composition/04-optional-slots/app-b/src/lib/App.svelte deleted file mode 100755 index eed35a30e..000000000 --- a/content/tutorial/03-advanced-svelte/07-composition/04-optional-slots/app-b/src/lib/App.svelte +++ /dev/null @@ -1,62 +0,0 @@ - - -

          Projects

          - -
            -
          • - -
            - -

            - Those interface tests are now passing. -

            -
            -
            -
            -
          • -
          • - -
          • -
          - - diff --git a/content/tutorial/03-advanced-svelte/07-composition/04-optional-slots/app-b/src/lib/Comment.svelte b/content/tutorial/03-advanced-svelte/07-composition/04-optional-slots/app-b/src/lib/Comment.svelte deleted file mode 100755 index a14ddebef..000000000 --- a/content/tutorial/03-advanced-svelte/07-composition/04-optional-slots/app-b/src/lib/Comment.svelte +++ /dev/null @@ -1,66 +0,0 @@ - - -
          -
          - -
          -

          {name}

          - -
          -
          -
          - -
          -
          - - diff --git a/content/tutorial/03-advanced-svelte/08-context/01-context-api/app-b/src/lib/App.svelte b/content/tutorial/03-advanced-svelte/08-context/01-context-api/app-b/src/lib/App.svelte deleted file mode 100644 index a5bcd9c09..000000000 --- a/content/tutorial/03-advanced-svelte/08-context/01-context-api/app-b/src/lib/App.svelte +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - diff --git a/content/tutorial/03-advanced-svelte/08-context/01-context-api/app-b/src/lib/mapbox.js b/content/tutorial/03-advanced-svelte/08-context/01-context-api/app-b/src/lib/mapbox.js deleted file mode 100644 index 42660d35a..000000000 --- a/content/tutorial/03-advanced-svelte/08-context/01-context-api/app-b/src/lib/mapbox.js +++ /dev/null @@ -1,8 +0,0 @@ -import mapbox from 'mapbox-gl'; - -// https://docs.mapbox.com/help/glossary/access-token/ -mapbox.accessToken = MAPBOX_ACCESS_TOKEN; - -const key = {}; - -export { mapbox, key }; diff --git a/content/tutorial/03-advanced-svelte/09-special-elements/01-svelte-self/app-b/src/lib/App.svelte b/content/tutorial/03-advanced-svelte/09-special-elements/01-svelte-self/app-b/src/lib/App.svelte deleted file mode 100644 index 6046e6ced..000000000 --- a/content/tutorial/03-advanced-svelte/09-special-elements/01-svelte-self/app-b/src/lib/App.svelte +++ /dev/null @@ -1,35 +0,0 @@ - - - diff --git a/content/tutorial/03-advanced-svelte/09-special-elements/02-svelte-component/app-b/src/lib/BlueThing.svelte b/content/tutorial/03-advanced-svelte/09-special-elements/02-svelte-component/app-b/src/lib/BlueThing.svelte deleted file mode 100644 index 551f1afbb..000000000 --- a/content/tutorial/03-advanced-svelte/09-special-elements/02-svelte-component/app-b/src/lib/BlueThing.svelte +++ /dev/null @@ -1,7 +0,0 @@ -Blue thing - - diff --git a/content/tutorial/03-advanced-svelte/09-special-elements/02-svelte-component/app-b/src/lib/GreenThing.svelte b/content/tutorial/03-advanced-svelte/09-special-elements/02-svelte-component/app-b/src/lib/GreenThing.svelte deleted file mode 100644 index a224720e6..000000000 --- a/content/tutorial/03-advanced-svelte/09-special-elements/02-svelte-component/app-b/src/lib/GreenThing.svelte +++ /dev/null @@ -1,7 +0,0 @@ -Green thing - - diff --git a/content/tutorial/03-advanced-svelte/09-special-elements/02-svelte-component/app-b/src/lib/RedThing.svelte b/content/tutorial/03-advanced-svelte/09-special-elements/02-svelte-component/app-b/src/lib/RedThing.svelte deleted file mode 100644 index 9774363c1..000000000 --- a/content/tutorial/03-advanced-svelte/09-special-elements/02-svelte-component/app-b/src/lib/RedThing.svelte +++ /dev/null @@ -1,7 +0,0 @@ -Red thing - - diff --git a/content/tutorial/03-advanced-svelte/09-special-elements/09-svelte-options/app-b/src/lib/App.svelte b/content/tutorial/03-advanced-svelte/09-special-elements/09-svelte-options/app-b/src/lib/App.svelte deleted file mode 100644 index 5be861d9c..000000000 --- a/content/tutorial/03-advanced-svelte/09-special-elements/09-svelte-options/app-b/src/lib/App.svelte +++ /dev/null @@ -1,34 +0,0 @@ - - -

          Todos

          -{#each todos as todo} - toggle(todo)} /> -{/each} diff --git a/content/tutorial/03-advanced-svelte/09-special-elements/10-svelte-fragment/app-b/src/lib/Box.svelte b/content/tutorial/03-advanced-svelte/09-special-elements/10-svelte-fragment/app-b/src/lib/Box.svelte deleted file mode 100644 index bd9bc6c7f..000000000 --- a/content/tutorial/03-advanced-svelte/09-special-elements/10-svelte-fragment/app-b/src/lib/Box.svelte +++ /dev/null @@ -1,21 +0,0 @@ -
          - No header was provided -

          Some content between header and footer

          - -
          - - diff --git a/content/tutorial/03-advanced-svelte/10-module-context/01-sharing-code/app-b/src/lib/App.svelte b/content/tutorial/03-advanced-svelte/10-module-context/01-sharing-code/app-b/src/lib/App.svelte deleted file mode 100644 index 9c127ce0d..000000000 --- a/content/tutorial/03-advanced-svelte/10-module-context/01-sharing-code/app-b/src/lib/App.svelte +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/src/lib/server/content.js b/src/lib/server/content.js index cfdd1bac5..c827e3149 100644 --- a/src/lib/server/content.js +++ b/src/lib/server/content.js @@ -103,6 +103,19 @@ export function get_exercise(slug) { const b = walk(`${dir}/app-b`); const has_solution = Object.keys(b).length > 0; + // ensure no duplicate content + for (const key in b) { + if (!a[key]) continue; + if (b[key].type !== 'file') continue; + + const a_ = /** @type {import('$lib/types').FileStub} */ (a[key]); + const b_ = /** @type {import('$lib/types').FileStub} */ (b[key]); + + if (a_.contents === b_.contents) { + throw new Error(`duplicate file: ${exercise_slug} ${key}`) + } + } + const part_meta = json(`content/tutorial/${part_dir}/meta.json`); const chapter_meta = json(`content/tutorial/${part_dir}/${chapter_dir}/meta.json`); From 1bf38b7a904f058f1e63e2dfd7621c62cde58458 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Mon, 20 Mar 2023 23:13:11 -0400 Subject: [PATCH 037/303] Tighten up styles (#278) * update styles * update exercise * remove duplicate file * more styles * nicer styles * more tweaks --------- Co-authored-by: Rich Harris --- .../app-a/src/lib/PackageInfo.svelte | 8 - .../app-a/src/lib/Thing.svelte | 24 +-- .../01-dom-events/app-a/src/lib/App.svelte | 4 + .../01-dom-events/app-b/src/lib/App.svelte | 4 + .../app-a/src/lib/App.svelte | 19 -- .../app-b/src/lib/App.svelte | 4 + .../06-dom-event-forwarding/README.md | 4 +- .../app-a/src/lib/App.svelte | 10 +- .../app-a/src/lib/BigRedButton.svelte | 25 +++ .../app-a/src/lib/CustomButton.svelte | 24 --- .../app-a/src/lib/horn.mp3 | Bin 0 -> 30948 bytes .../app-b/src/lib/BigRedButton.svelte | 25 +++ .../app-b/src/lib/CustomButton.svelte | 24 --- .../app-a/src/lib/App.svelte | 11 -- .../app-b/src/lib/App.svelte | 11 -- .../app-a/src/lib/App.svelte | 10 +- .../app-b/src/lib/App.svelte | 8 - .../02-ondestroy/app-a/src/lib/Timer.svelte | 7 +- .../common/src/routes/+layout.svelte | 26 --- .../app-a/src/lib/App.svelte | 4 +- .../01-animate/app-a/src/lib/App.svelte | 5 +- .../05-bind-this/app-a/src/lib/App.svelte | 11 +- .../05-bind-this/app-b/src/lib/App.svelte | 11 +- .../01-classes/app-a/src/lib/App.svelte | 4 - .../01-classes/app-b/src/lib/App.svelte | 4 - .../app-a/src/lib/Folder.svelte | 1 + .../app-b/src/lib/Folder.svelte | 1 + .../app-a/src/lib/BlueThing.svelte | 4 +- .../app-a/src/lib/GreenThing.svelte | 4 +- .../app-a/src/lib/RedThing.svelte | 4 +- .../app-a/src/lib/App.svelte | 6 +- .../app-b/src/lib/App.svelte | 4 +- .../11-special-tags/meta.json | 2 +- .../common/src/routes/+layout.svelte | 26 --- .../app-a/src/routes/+layout.svelte | 2 +- content/tutorial/common/src/app.html | 171 +++++++++++++++--- 36 files changed, 250 insertions(+), 262 deletions(-) delete mode 100644 content/tutorial/01-svelte/05-events/02-inline-handlers/app-a/src/lib/App.svelte create mode 100644 content/tutorial/01-svelte/05-events/06-dom-event-forwarding/app-a/src/lib/BigRedButton.svelte delete mode 100644 content/tutorial/01-svelte/05-events/06-dom-event-forwarding/app-a/src/lib/CustomButton.svelte create mode 100644 content/tutorial/01-svelte/05-events/06-dom-event-forwarding/app-a/src/lib/horn.mp3 create mode 100644 content/tutorial/01-svelte/05-events/06-dom-event-forwarding/app-b/src/lib/BigRedButton.svelte delete mode 100644 content/tutorial/01-svelte/05-events/06-dom-event-forwarding/app-b/src/lib/CustomButton.svelte delete mode 100644 content/tutorial/01-svelte/common/src/routes/+layout.svelte delete mode 100644 content/tutorial/03-advanced-svelte/common/src/routes/+layout.svelte diff --git a/content/tutorial/01-svelte/03-props/03-spread-props/app-a/src/lib/PackageInfo.svelte b/content/tutorial/01-svelte/03-props/03-spread-props/app-a/src/lib/PackageInfo.svelte index a879f76ca..7148fffd9 100644 --- a/content/tutorial/01-svelte/03-props/03-spread-props/app-a/src/lib/PackageInfo.svelte +++ b/content/tutorial/01-svelte/03-props/03-spread-props/app-a/src/lib/PackageInfo.svelte @@ -13,11 +13,3 @@ npm and learn more here

          - - diff --git a/content/tutorial/01-svelte/04-logic/05-keyed-each-blocks/app-a/src/lib/Thing.svelte b/content/tutorial/01-svelte/04-logic/05-keyed-each-blocks/app-a/src/lib/Thing.svelte index f5284f746..96f48a8d2 100644 --- a/content/tutorial/01-svelte/04-logic/05-keyed-each-blocks/app-a/src/lib/Thing.svelte +++ b/content/tutorial/01-svelte/04-logic/05-keyed-each-blocks/app-a/src/lib/Thing.svelte @@ -15,26 +15,4 @@ const emoji = emojis[name]; -

          - The emoji for {name} is {emoji} -

          - - +

          {emoji} = {name}

          \ No newline at end of file diff --git a/content/tutorial/01-svelte/05-events/01-dom-events/app-a/src/lib/App.svelte b/content/tutorial/01-svelte/05-events/01-dom-events/app-a/src/lib/App.svelte index 5a020e0ea..ca3f7bd76 100644 --- a/content/tutorial/01-svelte/05-events/01-dom-events/app-a/src/lib/App.svelte +++ b/content/tutorial/01-svelte/05-events/01-dom-events/app-a/src/lib/App.svelte @@ -13,7 +13,11 @@ diff --git a/content/tutorial/01-svelte/05-events/01-dom-events/app-b/src/lib/App.svelte b/content/tutorial/01-svelte/05-events/01-dom-events/app-b/src/lib/App.svelte index 54470a9a5..e08a73976 100644 --- a/content/tutorial/01-svelte/05-events/01-dom-events/app-b/src/lib/App.svelte +++ b/content/tutorial/01-svelte/05-events/01-dom-events/app-b/src/lib/App.svelte @@ -13,7 +13,11 @@ diff --git a/content/tutorial/01-svelte/05-events/02-inline-handlers/app-a/src/lib/App.svelte b/content/tutorial/01-svelte/05-events/02-inline-handlers/app-a/src/lib/App.svelte deleted file mode 100644 index 54470a9a5..000000000 --- a/content/tutorial/01-svelte/05-events/02-inline-handlers/app-a/src/lib/App.svelte +++ /dev/null @@ -1,19 +0,0 @@ - - -
          - The mouse position is {m.x} x {m.y} -
          - - diff --git a/content/tutorial/01-svelte/05-events/02-inline-handlers/app-b/src/lib/App.svelte b/content/tutorial/01-svelte/05-events/02-inline-handlers/app-b/src/lib/App.svelte index 4c9fd299f..6dadbb296 100644 --- a/content/tutorial/01-svelte/05-events/02-inline-handlers/app-b/src/lib/App.svelte +++ b/content/tutorial/01-svelte/05-events/02-inline-handlers/app-b/src/lib/App.svelte @@ -12,7 +12,11 @@ diff --git a/content/tutorial/01-svelte/05-events/06-dom-event-forwarding/README.md b/content/tutorial/01-svelte/05-events/06-dom-event-forwarding/README.md index 7be654ecd..9232f0b7b 100644 --- a/content/tutorial/01-svelte/05-events/06-dom-event-forwarding/README.md +++ b/content/tutorial/01-svelte/05-events/06-dom-event-forwarding/README.md @@ -4,10 +4,10 @@ title: DOM event forwarding Event forwarding works for DOM events too. -We want to get notified of clicks on our `` — to do that, we just need to forward `click` events on the ` ``` 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 f7dc6576b..b47a06f1e 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 @@ -1,9 +1,13 @@ - + diff --git a/content/tutorial/01-svelte/05-events/06-dom-event-forwarding/app-a/src/lib/BigRedButton.svelte b/content/tutorial/01-svelte/05-events/06-dom-event-forwarding/app-a/src/lib/BigRedButton.svelte new file mode 100644 index 000000000..471695245 --- /dev/null +++ b/content/tutorial/01-svelte/05-events/06-dom-event-forwarding/app-a/src/lib/BigRedButton.svelte @@ -0,0 +1,25 @@ + + + diff --git a/content/tutorial/01-svelte/05-events/06-dom-event-forwarding/app-a/src/lib/CustomButton.svelte b/content/tutorial/01-svelte/05-events/06-dom-event-forwarding/app-a/src/lib/CustomButton.svelte deleted file mode 100644 index fe3b417be..000000000 --- a/content/tutorial/01-svelte/05-events/06-dom-event-forwarding/app-a/src/lib/CustomButton.svelte +++ /dev/null @@ -1,24 +0,0 @@ - - - diff --git a/content/tutorial/01-svelte/05-events/06-dom-event-forwarding/app-a/src/lib/horn.mp3 b/content/tutorial/01-svelte/05-events/06-dom-event-forwarding/app-a/src/lib/horn.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..3399767ac6d33d20dee4a6210d8093bcecfe579a GIT binary patch literal 30948 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 + Push + + + diff --git a/content/tutorial/01-svelte/05-events/06-dom-event-forwarding/app-b/src/lib/CustomButton.svelte b/content/tutorial/01-svelte/05-events/06-dom-event-forwarding/app-b/src/lib/CustomButton.svelte deleted file mode 100644 index ff5278619..000000000 --- a/content/tutorial/01-svelte/05-events/06-dom-event-forwarding/app-b/src/lib/CustomButton.svelte +++ /dev/null @@ -1,24 +0,0 @@ - - - diff --git a/content/tutorial/01-svelte/06-bindings/02-numeric-inputs/app-a/src/lib/App.svelte b/content/tutorial/01-svelte/06-bindings/02-numeric-inputs/app-a/src/lib/App.svelte index 3b790cfee..f4d3b4feb 100644 --- a/content/tutorial/01-svelte/06-bindings/02-numeric-inputs/app-a/src/lib/App.svelte +++ b/content/tutorial/01-svelte/06-bindings/02-numeric-inputs/app-a/src/lib/App.svelte @@ -36,14 +36,3 @@

          {a} + {b} = {a + b}

          - - diff --git a/content/tutorial/01-svelte/06-bindings/02-numeric-inputs/app-b/src/lib/App.svelte b/content/tutorial/01-svelte/06-bindings/02-numeric-inputs/app-b/src/lib/App.svelte index e24a9c1a9..d0016b0be 100644 --- a/content/tutorial/01-svelte/06-bindings/02-numeric-inputs/app-b/src/lib/App.svelte +++ b/content/tutorial/01-svelte/06-bindings/02-numeric-inputs/app-b/src/lib/App.svelte @@ -36,14 +36,3 @@

          {a} + {b} = {a + b}

          - - diff --git a/content/tutorial/01-svelte/06-bindings/06-select-bindings/app-a/src/lib/App.svelte b/content/tutorial/01-svelte/06-bindings/06-select-bindings/app-a/src/lib/App.svelte index ccc7b3a6d..95e34d897 100644 --- a/content/tutorial/01-svelte/06-bindings/06-select-bindings/app-a/src/lib/App.svelte +++ b/content/tutorial/01-svelte/06-bindings/06-select-bindings/app-a/src/lib/App.svelte @@ -50,12 +50,4 @@ selected question {selected ? selected.id : '[waiting...]'} -

          - - +

          \ No newline at end of file diff --git a/content/tutorial/01-svelte/06-bindings/06-select-bindings/app-b/src/lib/App.svelte b/content/tutorial/01-svelte/06-bindings/06-select-bindings/app-b/src/lib/App.svelte index 92e63e920..e771b95c9 100644 --- a/content/tutorial/01-svelte/06-bindings/06-select-bindings/app-b/src/lib/App.svelte +++ b/content/tutorial/01-svelte/06-bindings/06-select-bindings/app-b/src/lib/App.svelte @@ -51,11 +51,3 @@ ? selected.id : '[waiting...]'}

          - - diff --git a/content/tutorial/01-svelte/07-lifecycle/02-ondestroy/app-a/src/lib/Timer.svelte b/content/tutorial/01-svelte/07-lifecycle/02-ondestroy/app-a/src/lib/Timer.svelte index cf2dcf055..1e745e6aa 100644 --- a/content/tutorial/01-svelte/07-lifecycle/02-ondestroy/app-a/src/lib/Timer.svelte +++ b/content/tutorial/01-svelte/07-lifecycle/02-ondestroy/app-a/src/lib/Timer.svelte @@ -7,12 +7,7 @@ onInterval(callback, interval); -

          - This component executes a callback every - {interval} millisecond{interval === 1 - ? '' - : 's'} -

          +

          This component executes a callback every {interval}ms

          diff --git a/content/tutorial/03-advanced-svelte/02-transitions/09-deferred-transitions/app-a/src/lib/App.svelte b/content/tutorial/03-advanced-svelte/02-transitions/09-deferred-transitions/app-a/src/lib/App.svelte index b57ef3e5a..4e3e11139 100644 --- a/content/tutorial/03-advanced-svelte/02-transitions/09-deferred-transitions/app-a/src/lib/App.svelte +++ b/content/tutorial/03-advanced-svelte/02-transitions/09-deferred-transitions/app-a/src/lib/App.svelte @@ -46,10 +46,8 @@ .board > input { font-size: 1.4em; grid-column: 1/3; - border-radius: 5px; - background: #f4f4f4; padding: 0.5em; - border: none; + margin: 0 0 1rem 0; } h2 { diff --git a/content/tutorial/03-advanced-svelte/03-animations/01-animate/app-a/src/lib/App.svelte b/content/tutorial/03-advanced-svelte/03-animations/01-animate/app-a/src/lib/App.svelte index 4813193e8..4e3e11139 100644 --- a/content/tutorial/03-advanced-svelte/03-animations/01-animate/app-a/src/lib/App.svelte +++ b/content/tutorial/03-advanced-svelte/03-animations/01-animate/app-a/src/lib/App.svelte @@ -46,11 +46,8 @@ .board > input { font-size: 1.4em; grid-column: 1/3; - border-radius: 5px; - background: #f4f4f4; padding: 0.5em; - border: none; - color: black; + margin: 0 0 1rem 0; } h2 { diff --git a/content/tutorial/03-advanced-svelte/05-bindings/05-bind-this/app-a/src/lib/App.svelte b/content/tutorial/03-advanced-svelte/05-bindings/05-bind-this/app-a/src/lib/App.svelte index 25a95e906..a7c9acd92 100644 --- a/content/tutorial/03-advanced-svelte/05-bindings/05-bind-this/app-a/src/lib/App.svelte +++ b/content/tutorial/03-advanced-svelte/05-bindings/05-bind-this/app-a/src/lib/App.svelte @@ -55,12 +55,15 @@ diff --git a/content/tutorial/03-advanced-svelte/05-bindings/05-bind-this/app-b/src/lib/App.svelte b/content/tutorial/03-advanced-svelte/05-bindings/05-bind-this/app-b/src/lib/App.svelte index 4fd2b39db..bc1d207e5 100644 --- a/content/tutorial/03-advanced-svelte/05-bindings/05-bind-this/app-b/src/lib/App.svelte +++ b/content/tutorial/03-advanced-svelte/05-bindings/05-bind-this/app-b/src/lib/App.svelte @@ -59,12 +59,15 @@ diff --git a/content/tutorial/03-advanced-svelte/06-classes/01-classes/app-a/src/lib/App.svelte b/content/tutorial/03-advanced-svelte/06-classes/01-classes/app-a/src/lib/App.svelte index a960bb26e..3ce5493cd 100644 --- a/content/tutorial/03-advanced-svelte/06-classes/01-classes/app-a/src/lib/App.svelte +++ b/content/tutorial/03-advanced-svelte/06-classes/01-classes/app-a/src/lib/App.svelte @@ -18,10 +18,6 @@ > diff --git a/content/tutorial/03-advanced-svelte/09-special-elements/02-svelte-component/app-a/src/lib/GreenThing.svelte b/content/tutorial/03-advanced-svelte/09-special-elements/02-svelte-component/app-a/src/lib/GreenThing.svelte index a224720e6..302da2bdc 100644 --- a/content/tutorial/03-advanced-svelte/09-special-elements/02-svelte-component/app-a/src/lib/GreenThing.svelte +++ b/content/tutorial/03-advanced-svelte/09-special-elements/02-svelte-component/app-a/src/lib/GreenThing.svelte @@ -1,7 +1,7 @@ -Green thing +

          Green thing

          diff --git a/content/tutorial/03-advanced-svelte/09-special-elements/02-svelte-component/app-a/src/lib/RedThing.svelte b/content/tutorial/03-advanced-svelte/09-special-elements/02-svelte-component/app-a/src/lib/RedThing.svelte index 9774363c1..6fd2a61b4 100644 --- a/content/tutorial/03-advanced-svelte/09-special-elements/02-svelte-component/app-a/src/lib/RedThing.svelte +++ b/content/tutorial/03-advanced-svelte/09-special-elements/02-svelte-component/app-a/src/lib/RedThing.svelte @@ -1,7 +1,7 @@ -Red thing +

          Red thing

          diff --git a/content/tutorial/03-advanced-svelte/09-special-elements/03-svelte-element/app-a/src/lib/App.svelte b/content/tutorial/03-advanced-svelte/09-special-elements/03-svelte-element/app-a/src/lib/App.svelte index 0718efd94..8e16ba761 100644 --- a/content/tutorial/03-advanced-svelte/09-special-elements/03-svelte-element/app-a/src/lib/App.svelte +++ b/content/tutorial/03-advanced-svelte/09-special-elements/03-svelte-element/app-a/src/lib/App.svelte @@ -10,9 +10,9 @@ {#if selected === 'h1'} -

          I'm a h1 tag

          +

          I'm a <h1>

          {:else if selected === 'h3'} -

          I'm a h3 tag

          +

          I'm a <h3>

          {:else if selected === 'p'} -

          I'm a p tag

          +

          I'm a <p>

          {/if} diff --git a/content/tutorial/03-advanced-svelte/09-special-elements/03-svelte-element/app-b/src/lib/App.svelte b/content/tutorial/03-advanced-svelte/09-special-elements/03-svelte-element/app-b/src/lib/App.svelte index 068f7b3c4..f41011cc9 100644 --- a/content/tutorial/03-advanced-svelte/09-special-elements/03-svelte-element/app-b/src/lib/App.svelte +++ b/content/tutorial/03-advanced-svelte/09-special-elements/03-svelte-element/app-b/src/lib/App.svelte @@ -9,4 +9,6 @@ {/each} -I'm a {selected} tag + + I'm a <{selected}> + diff --git a/content/tutorial/03-advanced-svelte/11-special-tags/meta.json b/content/tutorial/03-advanced-svelte/11-special-tags/meta.json index fb2938580..b82c92d5b 100644 --- a/content/tutorial/03-advanced-svelte/11-special-tags/meta.json +++ b/content/tutorial/03-advanced-svelte/11-special-tags/meta.json @@ -1,5 +1,5 @@ { - "title": "Debugging", + "title": "Special tags", "scope": { "prefix": "/src/lib/", "name": "src" diff --git a/content/tutorial/03-advanced-svelte/common/src/routes/+layout.svelte b/content/tutorial/03-advanced-svelte/common/src/routes/+layout.svelte deleted file mode 100644 index 1b7e69566..000000000 --- a/content/tutorial/03-advanced-svelte/common/src/routes/+layout.svelte +++ /dev/null @@ -1,26 +0,0 @@ -
          - -
          - - diff --git a/content/tutorial/04-advanced-sveltekit/03-advanced-routing/05-breaking-out-of-layouts/app-a/src/routes/+layout.svelte b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/05-breaking-out-of-layouts/app-a/src/routes/+layout.svelte index a1836f323..a3716f875 100644 --- a/content/tutorial/04-advanced-sveltekit/03-advanced-routing/05-breaking-out-of-layouts/app-a/src/routes/+layout.svelte +++ b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/05-breaking-out-of-layouts/app-a/src/routes/+layout.svelte @@ -15,7 +15,7 @@ border: 1px solid #999; padding: 1em; margin: 1em 0 0 0; - border-radius: 2px; + border-radius: 4px; } :global(.layout::before) { diff --git a/content/tutorial/common/src/app.html b/content/tutorial/common/src/app.html index b24ae5c3a..4b820f1a8 100644 --- a/content/tutorial/common/src/app.html +++ b/content/tutorial/common/src/app.html @@ -9,9 +9,20 @@ From d30e5a04278d4e404204139827e721c8af9a2098 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Tue, 21 Mar 2023 17:44:56 -0400 Subject: [PATCH 038/303] Add `/// file` annotations (#285) * add clickable file annotations to code blocks * add more file annotations * add no-file * toggle mobile view when clicking annotations * create files from annotations * make all inline file annotations interactive * dont exempt exercises with only one file, its weird --------- Co-authored-by: Rich Harris --- .../02-your-first-component/README.md | 3 + .../03-dynamic-attributes/README.md | 3 + .../01-introduction/04-styling/README.md | 1 + .../05-nested-components/README.md | 2 + .../01-reactive-assignments/README.md | 2 + .../02-reactive-declarations/README.md | 2 + .../03-reactive-statements/README.md | 3 + .../04-updating-arrays-and-objects/README.md | 4 + .../03-props/01-declaring-props/README.md | 1 + .../03-props/02-default-values/README.md | 2 + .../03-props/03-spread-props/README.md | 1 + .../01-svelte/04-logic/01-if-blocks/README.md | 1 + .../04-logic/02-else-blocks/README.md | 1 + .../04-logic/03-else-if-blocks/README.md | 1 + .../04-logic/04-each-blocks/README.md | 2 + .../04-logic/05-keyed-each-blocks/README.md | 1 + .../04-logic/06-await-blocks/README.md | 2 + .../05-events/01-dom-events/README.md | 1 + .../05-events/02-inline-handlers/README.md | 1 + .../05-events/03-event-modifiers/README.md | 1 + .../05-events/04-component-events/README.md | 2 + .../05-events/05-event-forwarding/README.md | 2 + .../06-dom-event-forwarding/README.md | 1 + .../06-bindings/01-text-inputs/README.md | 1 + .../06-bindings/02-numeric-inputs/README.md | 1 + .../06-bindings/03-checkbox-inputs/README.md | 1 + .../06-bindings/04-group-inputs/README.md | 3 + .../06-bindings/05-textarea-inputs/README.md | 2 + .../06-bindings/06-select-bindings/README.md | 1 + .../07-multiple-select-bindings/README.md | 1 + .../07-lifecycle/01-onmount/README.md | 1 + .../07-lifecycle/02-ondestroy/README.md | 3 + .../07-lifecycle/03-update/README.md | 1 + .../01-svelte/07-lifecycle/04-tick/README.md | 2 + .../08-stores/01-writable-stores/README.md | 6 +- .../08-stores/02-auto-subscriptions/README.md | 20 ++++- .../08-stores/03-readable-stores/README.md | 3 +- .../08-stores/04-derived-stores/README.md | 6 +- .../04-derived-stores/app-a/src/lib/stores.js | 5 +- .../04-derived-stores/app-b/src/lib/stores.js | 5 +- .../08-stores/05-custom-stores/README.md | 7 +- .../08-stores/06-store-bindings/README.md | 8 +- .../02-routing/02-layouts/README.md | 4 +- .../03-loading-data/01-page-data/README.md | 1 + .../04-forms/03-form-validation/README.md | 1 + .../04-progressive-enhancement/README.md | 3 + .../05-customizing-use-enhance/README.md | 2 + .../01-motion/01-tweens/README.md | 2 + .../01-motion/02-springs/README.md | 2 + .../02-transitions/01-transition/README.md | 2 + .../README.md | 2 + .../02-transitions/03-in-and-out/README.md | 2 + .../04-custom-css-transitions/README.md | 3 + .../05-custom-js-transitions/README.md | 1 + .../06-transition-events/README.md | 1 + .../07-local-transitions/README.md | 1 + .../02-transitions/08-key-blocks/README.md | 1 + .../09-deferred-transitions/README.md | 4 +- .../03-animations/01-animate/README.md | 3 + .../04-actions/01-actions/README.md | 19 ++++- .../01-actions/app-a/src/lib/App.svelte | 7 +- .../src/lib/{click_outside.js => actions.js} | 0 .../01-actions/app-b/src/lib/App.svelte | 9 ++- .../src/lib/{click_outside.js => actions.js} | 0 .../02-adding-parameters-to-actions/README.md | 17 +++- .../app-a/src/lib/App.svelte | 3 +- .../app-a/src/lib/longpress.js | 2 +- .../app-b/src/lib/App.svelte | 3 +- .../01-contenteditable-bindings/README.md | 1 + .../02-each-block-bindings/README.md | 1 + .../05-bindings/03-media-elements/README.md | 1 + .../05-bindings/04-dimensions/README.md | 1 + .../05-bindings/05-bind-this/README.md | 1 + .../06-component-bindings/README.md | 1 + .../app-a/src/lib/App.svelte | 6 +- .../app-b/src/lib/App.svelte | 2 +- .../05-bindings/07-component-this/README.md | 12 ++- .../app-a/src/lib/App.svelte | 5 ++ .../app-b/src/lib/App.svelte | 6 +- .../06-classes/01-classes/README.md | 10 ++- .../06-classes/02-class-shorthand/README.md | 2 + .../07-composition/01-slots/README.md | 5 +- .../02-slot-fallbacks/README.md | 6 +- .../app-a/src/lib/Box.svelte | 2 +- .../07-composition/03-named-slots/README.md | 2 + .../04-optional-slots/README.md | 8 +- .../07-composition/05-slot-props/README.md | 3 + .../08-context/01-context-api/README.md | 4 + .../01-svelte-self/README.md | 4 +- .../02-svelte-component/README.md | 2 + .../03-svelte-element/README.md | 6 +- .../04-svelte-window/README.md | 1 + .../05-svelte-window-bindings/README.md | 1 + .../06-svelte-document/README.md | 3 +- .../07-svelte-body/README.md | 1 + .../08-svelte-head/README.md | 1 + .../09-svelte-options/README.md | 1 + .../10-svelte-fragment/README.md | 7 +- .../app-a/src/lib/Box.svelte | 3 +- .../01-sharing-code/README.md | 2 + .../02-module-exports/README.md | 11 ++- .../app-a/src/lib/App.svelte | 4 +- .../app-b/src/lib/App.svelte | 4 +- .../11-special-tags/01-debug/README.md | 1 + .../11-special-tags/02-html-tags/README.md | 1 + .../01-env-static-private/README.md | 1 + .../03-env-static-public/README.md | 1 + .../04-env-dynamic-public/README.md | 1 + src/lib/server/content.js | 26 +++++-- src/lib/server/markdown.js | 2 +- src/routes/tutorial/[slug]/+page.svelte | 77 +++++++++++++++++-- src/routes/tutorial/[slug]/Editor.svelte | 4 +- src/routes/tutorial/[slug]/Sidebar.svelte | 18 ++++- .../tutorial/[slug]/filetree/Filetree.svelte | 63 +++------------ .../tutorial/[slug]/filetree/Folder.svelte | 31 ++++---- src/routes/tutorial/[slug]/state.js | 41 +++++++++- 116 files changed, 448 insertions(+), 161 deletions(-) rename content/tutorial/03-advanced-svelte/04-actions/01-actions/app-a/src/lib/{click_outside.js => actions.js} (100%) rename content/tutorial/03-advanced-svelte/04-actions/01-actions/app-b/src/lib/{click_outside.js => actions.js} (100%) diff --git a/content/tutorial/01-svelte/01-introduction/02-your-first-component/README.md b/content/tutorial/01-svelte/01-introduction/02-your-first-component/README.md index 45117749f..ac4bb6c52 100644 --- a/content/tutorial/01-svelte/01-introduction/02-your-first-component/README.md +++ b/content/tutorial/01-svelte/01-introduction/02-your-first-component/README.md @@ -11,6 +11,7 @@ A component that just renders some static markup isn't very interesting. Let's a First, add a script tag to your component and declare a `name` variable: ```svelte +/// file: App.svelte ++++++ @@ -21,11 +22,13 @@ First, add a script tag to your component and declare a `name` variable: Then, we can refer to `name` in the markup: ```svelte +/// file: App.svelte

          Hello +++{name}+++!

          ``` Inside the curly braces, we can put any JavaScript we want. Try changing `name` to `name.toUpperCase()` for a shoutier greeting. ```svelte +/// file: App.svelte

          Hello {name+++.toUpperCase()+++}!

          ``` 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 b17bb93be..2f049885b 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 @@ -7,6 +7,7 @@ Just like you can use curly braces to control text, you can use them to control Our image is missing a `src` — let's add one: ```svelte +/// file: App.svelte ``` @@ -19,6 +20,7 @@ When building web apps, it's important to make sure that they're _accessible_ to In this case, we're missing the `alt` attribute that describes the image for people using screenreaders, or people with slow or flaky internet connections that can't download the image. Let's add one: ```svelte +/// file: App.svelte ``` @@ -29,5 +31,6 @@ We can use curly braces _inside_ attributes. Try changing it to `"{name} dances. It's not uncommon to have an attribute where the name and value are the same, like `src={src}`. Svelte gives us a convenient shorthand for these cases: ```svelte +/// file: App.svelte A man dances. ``` diff --git a/content/tutorial/01-svelte/01-introduction/04-styling/README.md b/content/tutorial/01-svelte/01-introduction/04-styling/README.md index 9b2adbcfb..71099a820 100644 --- a/content/tutorial/01-svelte/01-introduction/04-styling/README.md +++ b/content/tutorial/01-svelte/01-introduction/04-styling/README.md @@ -5,6 +5,7 @@ title: Styling Just like in HTML, you can add a ` \ No newline at end of file diff --git a/content/tutorial/01-svelte/04-logic/04-each-blocks/app-b/src/lib/App.svelte b/content/tutorial/01-svelte/04-logic/04-each-blocks/app-b/src/lib/App.svelte index 7d5d7187a..a4c929d7f 100644 --- a/content/tutorial/01-svelte/04-logic/04-each-blocks/app-b/src/lib/App.svelte +++ b/content/tutorial/01-svelte/04-logic/04-each-blocks/app-b/src/lib/App.svelte @@ -1,28 +1,45 @@ -

          The Famous Cats of YouTube

          +

          Pick a colour

          -
            - {#each cats as { id, name }, i} -
          • - - {i + 1}: {name} - -
          • +
            + {#each colors as color, i} + {/each} -
          +
      + + \ No newline at end of file From b2a590a58ed2b8c7371c93b4403475c72a3a762a Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Wed, 22 Mar 2023 13:20:43 -0400 Subject: [PATCH 046/303] tidy up await block example --- .../01-svelte/04-logic/06-await-blocks/README.md | 8 ++++---- .../06-await-blocks/app-a/src/lib/App.svelte | 16 ++-------------- .../06-await-blocks/app-a/src/lib/utils.js | 12 ++++++++++++ .../06-await-blocks/app-b/src/lib/App.svelte | 13 +------------ 4 files changed, 19 insertions(+), 30 deletions(-) create mode 100644 content/tutorial/01-svelte/04-logic/06-await-blocks/app-a/src/lib/utils.js diff --git a/content/tutorial/01-svelte/04-logic/06-await-blocks/README.md b/content/tutorial/01-svelte/04-logic/06-await-blocks/README.md index 4cd0b0ee1..37f5871b8 100644 --- a/content/tutorial/01-svelte/04-logic/06-await-blocks/README.md +++ b/content/tutorial/01-svelte/04-logic/06-await-blocks/README.md @@ -6,13 +6,13 @@ Most web applications have to deal with asynchronous data at some point. Svelte ```svelte /// file: App.svelte -{#await promise} ++++{#await promise}+++

      ...waiting

      -{:then number} ++++{:then number}

      The number is {number}

      {:catch error}

      {error.message}

      -{/await} +{/await}+++ ``` > Only the most recent `promise` is considered, meaning you don't need to worry about race conditions. @@ -20,7 +20,7 @@ Most web applications have to deal with asynchronous data at some point. Svelte If you know that your promise can't reject, you can omit the `catch` block. You can also omit the first block if you don't want to show anything until the promise resolves: ```svelte -/// file: App.svelte +/// no-file {#await promise then number}

      The number is {number}

      {/await} diff --git a/content/tutorial/01-svelte/04-logic/06-await-blocks/app-a/src/lib/App.svelte b/content/tutorial/01-svelte/04-logic/06-await-blocks/app-a/src/lib/App.svelte index 7af6f29b5..a3030a8b3 100644 --- a/content/tutorial/01-svelte/04-logic/06-await-blocks/app-a/src/lib/App.svelte +++ b/content/tutorial/01-svelte/04-logic/06-await-blocks/app-a/src/lib/App.svelte @@ -1,16 +1,5 @@
      - The mouse position is {m.x} x {m.y} + The pointer is at {m.x} x {m.y}
      diff --git a/content/tutorial/01-svelte/06-bindings/05-textarea-inputs/app-b/src/lib/App.svelte b/content/tutorial/01-svelte/06-bindings/05-textarea-inputs/app-b/src/lib/App.svelte index 057dafd2a..27e2ef0fe 100644 --- a/content/tutorial/01-svelte/06-bindings/05-textarea-inputs/app-b/src/lib/App.svelte +++ b/content/tutorial/01-svelte/06-bindings/05-textarea-inputs/app-b/src/lib/App.svelte @@ -1,15 +1,27 @@ -{@html marked(value)} +
      + input + - + output +
      {@html marked(value)}
      +
      diff --git a/content/tutorial/common/src/app.html b/content/tutorial/common/src/app.html index 4b820f1a8..c090e1a9f 100644 --- a/content/tutorial/common/src/app.html +++ b/content/tutorial/common/src/app.html @@ -23,6 +23,7 @@ font-family: var(--font); line-height: 1.5; margin: 1rem; + height: calc(100vh - 2rem); } h1, From c65a55f0b407a34200523922a9ef2ea48efa92fc Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Thu, 23 Mar 2023 12:45:53 -0400 Subject: [PATCH 056/303] reorder examples --- .../{06-select-bindings => 04-select-bindings}/README.md | 7 +++++-- .../app-a/src/lib/App.svelte | 0 .../app-b/src/lib/App.svelte | 0 .../{04-group-inputs => 05-group-inputs}/README.md | 0 .../app-a/src/lib/App.svelte | 0 .../app-b/src/lib/App.svelte | 0 .../README.md | 0 .../app-a/src/lib/App.svelte | 0 .../app-b/src/lib/App.svelte | 0 .../{05-textarea-inputs => 07-textarea-inputs}/README.md | 0 .../app-a/node_modules/.bin/marked | 0 .../app-a/node_modules/marked/LICENSE.md | 0 .../app-a/node_modules/marked/README.md | 0 .../app-a/node_modules/marked/bin/marked.js | 0 .../app-a/node_modules/marked/lib/marked.cjs | 0 .../app-a/node_modules/marked/lib/marked.esm.js | 0 .../app-a/node_modules/marked/lib/marked.umd.js | 0 .../app-a/node_modules/marked/man/marked.1 | 0 .../app-a/node_modules/marked/man/marked.1.txt | 0 .../app-a/node_modules/marked/marked.min.js | 0 .../app-a/node_modules/marked/package.json | 0 .../app-a/node_modules/marked/src/Lexer.js | 0 .../app-a/node_modules/marked/src/Parser.js | 0 .../app-a/node_modules/marked/src/Renderer.js | 0 .../app-a/node_modules/marked/src/Slugger.js | 0 .../app-a/node_modules/marked/src/TextRenderer.js | 0 .../app-a/node_modules/marked/src/Tokenizer.js | 0 .../app-a/node_modules/marked/src/defaults.js | 0 .../app-a/node_modules/marked/src/helpers.js | 0 .../app-a/node_modules/marked/src/marked.js | 0 .../app-a/node_modules/marked/src/rules.js | 0 .../app-a/package.json | 0 .../app-a/src/lib/App.svelte | 0 .../app-b/src/lib/App.svelte | 0 34 files changed, 5 insertions(+), 2 deletions(-) rename content/tutorial/01-svelte/06-bindings/{06-select-bindings => 04-select-bindings}/README.md (77%) rename content/tutorial/01-svelte/06-bindings/{06-select-bindings => 04-select-bindings}/app-a/src/lib/App.svelte (100%) rename content/tutorial/01-svelte/06-bindings/{06-select-bindings => 04-select-bindings}/app-b/src/lib/App.svelte (100%) rename content/tutorial/01-svelte/06-bindings/{04-group-inputs => 05-group-inputs}/README.md (100%) rename content/tutorial/01-svelte/06-bindings/{04-group-inputs => 05-group-inputs}/app-a/src/lib/App.svelte (100%) rename content/tutorial/01-svelte/06-bindings/{04-group-inputs => 05-group-inputs}/app-b/src/lib/App.svelte (100%) rename content/tutorial/01-svelte/06-bindings/{07-multiple-select-bindings => 06-multiple-select-bindings}/README.md (100%) rename content/tutorial/01-svelte/06-bindings/{07-multiple-select-bindings => 06-multiple-select-bindings}/app-a/src/lib/App.svelte (100%) rename content/tutorial/01-svelte/06-bindings/{07-multiple-select-bindings => 06-multiple-select-bindings}/app-b/src/lib/App.svelte (100%) rename content/tutorial/01-svelte/06-bindings/{05-textarea-inputs => 07-textarea-inputs}/README.md (100%) rename content/tutorial/01-svelte/06-bindings/{05-textarea-inputs => 07-textarea-inputs}/app-a/node_modules/.bin/marked (100%) rename content/tutorial/01-svelte/06-bindings/{05-textarea-inputs => 07-textarea-inputs}/app-a/node_modules/marked/LICENSE.md (100%) rename content/tutorial/01-svelte/06-bindings/{05-textarea-inputs => 07-textarea-inputs}/app-a/node_modules/marked/README.md (100%) rename content/tutorial/01-svelte/06-bindings/{05-textarea-inputs => 07-textarea-inputs}/app-a/node_modules/marked/bin/marked.js (100%) rename content/tutorial/01-svelte/06-bindings/{05-textarea-inputs => 07-textarea-inputs}/app-a/node_modules/marked/lib/marked.cjs (100%) rename content/tutorial/01-svelte/06-bindings/{05-textarea-inputs => 07-textarea-inputs}/app-a/node_modules/marked/lib/marked.esm.js (100%) rename content/tutorial/01-svelte/06-bindings/{05-textarea-inputs => 07-textarea-inputs}/app-a/node_modules/marked/lib/marked.umd.js (100%) rename content/tutorial/01-svelte/06-bindings/{05-textarea-inputs => 07-textarea-inputs}/app-a/node_modules/marked/man/marked.1 (100%) rename content/tutorial/01-svelte/06-bindings/{05-textarea-inputs => 07-textarea-inputs}/app-a/node_modules/marked/man/marked.1.txt (100%) rename content/tutorial/01-svelte/06-bindings/{05-textarea-inputs => 07-textarea-inputs}/app-a/node_modules/marked/marked.min.js (100%) rename content/tutorial/01-svelte/06-bindings/{05-textarea-inputs => 07-textarea-inputs}/app-a/node_modules/marked/package.json (100%) rename content/tutorial/01-svelte/06-bindings/{05-textarea-inputs => 07-textarea-inputs}/app-a/node_modules/marked/src/Lexer.js (100%) rename content/tutorial/01-svelte/06-bindings/{05-textarea-inputs => 07-textarea-inputs}/app-a/node_modules/marked/src/Parser.js (100%) rename content/tutorial/01-svelte/06-bindings/{05-textarea-inputs => 07-textarea-inputs}/app-a/node_modules/marked/src/Renderer.js (100%) rename content/tutorial/01-svelte/06-bindings/{05-textarea-inputs => 07-textarea-inputs}/app-a/node_modules/marked/src/Slugger.js (100%) rename content/tutorial/01-svelte/06-bindings/{05-textarea-inputs => 07-textarea-inputs}/app-a/node_modules/marked/src/TextRenderer.js (100%) rename content/tutorial/01-svelte/06-bindings/{05-textarea-inputs => 07-textarea-inputs}/app-a/node_modules/marked/src/Tokenizer.js (100%) rename content/tutorial/01-svelte/06-bindings/{05-textarea-inputs => 07-textarea-inputs}/app-a/node_modules/marked/src/defaults.js (100%) rename content/tutorial/01-svelte/06-bindings/{05-textarea-inputs => 07-textarea-inputs}/app-a/node_modules/marked/src/helpers.js (100%) rename content/tutorial/01-svelte/06-bindings/{05-textarea-inputs => 07-textarea-inputs}/app-a/node_modules/marked/src/marked.js (100%) rename content/tutorial/01-svelte/06-bindings/{05-textarea-inputs => 07-textarea-inputs}/app-a/node_modules/marked/src/rules.js (100%) rename content/tutorial/01-svelte/06-bindings/{05-textarea-inputs => 07-textarea-inputs}/app-a/package.json (100%) rename content/tutorial/01-svelte/06-bindings/{05-textarea-inputs => 07-textarea-inputs}/app-a/src/lib/App.svelte (100%) rename content/tutorial/01-svelte/06-bindings/{05-textarea-inputs => 07-textarea-inputs}/app-b/src/lib/App.svelte (100%) diff --git a/content/tutorial/01-svelte/06-bindings/06-select-bindings/README.md b/content/tutorial/01-svelte/06-bindings/04-select-bindings/README.md similarity index 77% rename from content/tutorial/01-svelte/06-bindings/06-select-bindings/README.md rename to content/tutorial/01-svelte/06-bindings/04-select-bindings/README.md index c1ce601c9..d6c22c998 100644 --- a/content/tutorial/01-svelte/06-bindings/06-select-bindings/README.md +++ b/content/tutorial/01-svelte/06-bindings/04-select-bindings/README.md @@ -2,11 +2,14 @@ title: Select bindings --- -We can also use `bind:value` with `` elements: ```svelte /// file: App.svelte - answer = ''} +> ``` Note that the `
      ``` -...so can components. Before a component can accept children, though, it needs to know where to put them. We do this with the `` element. Put this inside `Box.svelte`: +...so can components. Before a component can accept children, though, it needs to know where to put them. We do this with the `` element. Put this inside `Card.svelte`: ```svelte -/// file: Box.svelte -
      +/// file: Card.svelte +
      ++++++
      ``` -You can now put things in the box: +You can now put things on the card: ```svelte /// file: App.svelte - - +++

      Hello!

      +++ - +++

      This is a box. It can contain anything.

      +++ -
      + + +++Patrick BATEMAN+++ + +++Vice President+++ + ``` diff --git a/content/tutorial/03-advanced-svelte/07-composition/01-slots/app-a/src/lib/App.svelte b/content/tutorial/03-advanced-svelte/07-composition/01-slots/app-a/src/lib/App.svelte index 7f7b5d443..d17baea61 100644 --- a/content/tutorial/03-advanced-svelte/07-composition/01-slots/app-a/src/lib/App.svelte +++ b/content/tutorial/03-advanced-svelte/07-composition/01-slots/app-a/src/lib/App.svelte @@ -1,7 +1,18 @@ - - - +
      + + + +
      + + \ No newline at end of file diff --git a/content/tutorial/03-advanced-svelte/07-composition/01-slots/app-a/src/lib/Box.svelte b/content/tutorial/03-advanced-svelte/07-composition/01-slots/app-a/src/lib/Box.svelte deleted file mode 100644 index 36e57ccd8..000000000 --- a/content/tutorial/03-advanced-svelte/07-composition/01-slots/app-a/src/lib/Box.svelte +++ /dev/null @@ -1,14 +0,0 @@ -
      - -
      - - diff --git a/content/tutorial/03-advanced-svelte/07-composition/01-slots/app-a/src/lib/Card.svelte b/content/tutorial/03-advanced-svelte/07-composition/01-slots/app-a/src/lib/Card.svelte new file mode 100644 index 000000000..74d0e02d6 --- /dev/null +++ b/content/tutorial/03-advanced-svelte/07-composition/01-slots/app-a/src/lib/Card.svelte @@ -0,0 +1,47 @@ +
      + +
      + + diff --git a/content/tutorial/03-advanced-svelte/07-composition/01-slots/app-a/src/lib/paper.svg b/content/tutorial/03-advanced-svelte/07-composition/01-slots/app-a/src/lib/paper.svg new file mode 100644 index 000000000..f8f704fdf --- /dev/null +++ b/content/tutorial/03-advanced-svelte/07-composition/01-slots/app-a/src/lib/paper.svg @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/content/tutorial/03-advanced-svelte/07-composition/01-slots/app-a/src/lib/wood.svg b/content/tutorial/03-advanced-svelte/07-composition/01-slots/app-a/src/lib/wood.svg new file mode 100644 index 000000000..5157ea83b --- /dev/null +++ b/content/tutorial/03-advanced-svelte/07-composition/01-slots/app-a/src/lib/wood.svg @@ -0,0 +1,10 @@ + + + + + + + \ No newline at end of file diff --git a/content/tutorial/03-advanced-svelte/07-composition/01-slots/app-a/static/Garamond Classico SC Regular.woff2 b/content/tutorial/03-advanced-svelte/07-composition/01-slots/app-a/static/Garamond Classico SC Regular.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..1a7d49f92bbbf3257327d287368121a07c481154 GIT binary patch literal 31424 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�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 literal 0 HcmV?d00001 diff --git a/content/tutorial/03-advanced-svelte/07-composition/01-slots/app-b/src/lib/App.svelte b/content/tutorial/03-advanced-svelte/07-composition/01-slots/app-b/src/lib/App.svelte index 986bdc01c..377be5167 100644 --- a/content/tutorial/03-advanced-svelte/07-composition/01-slots/app-b/src/lib/App.svelte +++ b/content/tutorial/03-advanced-svelte/07-composition/01-slots/app-b/src/lib/App.svelte @@ -1,8 +1,19 @@ - -

      Hello!

      -

      This is a box. It can contain anything.

      -
      +
      + + Patrick BATEMAN + Vice President + +
      + + \ No newline at end of file diff --git a/content/tutorial/03-advanced-svelte/07-composition/01-slots/app-b/src/lib/Box.svelte b/content/tutorial/03-advanced-svelte/07-composition/01-slots/app-b/src/lib/Box.svelte deleted file mode 100644 index 2d0a378d2..000000000 --- a/content/tutorial/03-advanced-svelte/07-composition/01-slots/app-b/src/lib/Box.svelte +++ /dev/null @@ -1,14 +0,0 @@ -
      - -
      - - diff --git a/content/tutorial/03-advanced-svelte/07-composition/01-slots/app-b/src/lib/Card.svelte b/content/tutorial/03-advanced-svelte/07-composition/01-slots/app-b/src/lib/Card.svelte new file mode 100644 index 000000000..31dda2a77 --- /dev/null +++ b/content/tutorial/03-advanced-svelte/07-composition/01-slots/app-b/src/lib/Card.svelte @@ -0,0 +1,47 @@ +
      + +
      + + diff --git a/content/tutorial/03-advanced-svelte/07-composition/02-named-slots/README.md b/content/tutorial/03-advanced-svelte/07-composition/02-named-slots/README.md new file mode 100644 index 000000000..34ecc5250 --- /dev/null +++ b/content/tutorial/03-advanced-svelte/07-composition/02-named-slots/README.md @@ -0,0 +1,58 @@ +--- +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 `` element, we've got `` and others for `company` and `address`. Let's add the corresponding named slots in `Card.svelte`: + +```svelte +/// file: Card.svelte +
      ++++
      + + +
      +++ + + + ++++
      + +
      +++ +
      +``` + +We need to add some styles to the `` element so that it occupies its own line. The contents of `` inherit styles from `Card.svelte`, such as `font-family` (the lettering is something called ['Silian Rail'](https://www.youtube.com/watch?v=aZVkW9p-cCU)), but normal scoping rules apply — we need to add the styles to `App.svelte` because that's where the element is: + +```svelte +/// file: App.svelte + +``` + +Alternatively, we could use the `:global` modifier inside `Card.svelte` to target all `small` elements inside `.card`: + +```svelte +/// file: Card.svelte + +``` \ No newline at end of file diff --git a/content/tutorial/03-advanced-svelte/07-composition/02-named-slots/app-a/src/lib/App.svelte b/content/tutorial/03-advanced-svelte/07-composition/02-named-slots/app-a/src/lib/App.svelte new file mode 100644 index 000000000..987f6452c --- /dev/null +++ b/content/tutorial/03-advanced-svelte/07-composition/02-named-slots/app-a/src/lib/App.svelte @@ -0,0 +1,28 @@ + + +
      + + Patrick BATEMAN + Vice President + + 212 555 6342 + + + Pierce & Pierce + Mergers and Acquisitions + + + 358 Exchange Place, New York, N.Y. 100099 fax 212 555 6390 telex 10 4534 + +
      + + \ No newline at end of file diff --git a/content/tutorial/03-advanced-svelte/07-composition/02-named-slots/app-a/src/lib/Card.svelte b/content/tutorial/03-advanced-svelte/07-composition/02-named-slots/app-a/src/lib/Card.svelte new file mode 100644 index 000000000..31dda2a77 --- /dev/null +++ b/content/tutorial/03-advanced-svelte/07-composition/02-named-slots/app-a/src/lib/Card.svelte @@ -0,0 +1,47 @@ +
      + +
      + + diff --git a/content/tutorial/03-advanced-svelte/07-composition/02-named-slots/app-a/src/lib/paper.svg b/content/tutorial/03-advanced-svelte/07-composition/02-named-slots/app-a/src/lib/paper.svg new file mode 100644 index 000000000..f8f704fdf --- /dev/null +++ b/content/tutorial/03-advanced-svelte/07-composition/02-named-slots/app-a/src/lib/paper.svg @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/content/tutorial/03-advanced-svelte/07-composition/02-named-slots/app-a/src/lib/wood.svg b/content/tutorial/03-advanced-svelte/07-composition/02-named-slots/app-a/src/lib/wood.svg new file mode 100644 index 000000000..5157ea83b --- /dev/null +++ b/content/tutorial/03-advanced-svelte/07-composition/02-named-slots/app-a/src/lib/wood.svg @@ -0,0 +1,10 @@ + + + + + + + \ No newline at end of file diff --git a/content/tutorial/03-advanced-svelte/07-composition/02-named-slots/app-b/src/lib/App.svelte b/content/tutorial/03-advanced-svelte/07-composition/02-named-slots/app-b/src/lib/App.svelte new file mode 100644 index 000000000..c66e6e624 --- /dev/null +++ b/content/tutorial/03-advanced-svelte/07-composition/02-named-slots/app-b/src/lib/App.svelte @@ -0,0 +1,34 @@ + + +
      + + Patrick BATEMAN + Vice President + + 212 555 6342 + + + Pierce & Pierce + Mergers and Acquisitions + + + 358 Exchange Place, New York, N.Y. 100099 fax 212 555 6390 telex 10 4534 + +
      + + \ No newline at end of file diff --git a/content/tutorial/03-advanced-svelte/07-composition/02-named-slots/app-b/src/lib/Card.svelte b/content/tutorial/03-advanced-svelte/07-composition/02-named-slots/app-b/src/lib/Card.svelte new file mode 100644 index 000000000..b7f4b3a6d --- /dev/null +++ b/content/tutorial/03-advanced-svelte/07-composition/02-named-slots/app-b/src/lib/Card.svelte @@ -0,0 +1,56 @@ +
      +
      + + +
      + + + +
      + +
      +
      + + diff --git a/content/tutorial/03-advanced-svelte/07-composition/02-slot-fallbacks/README.md b/content/tutorial/03-advanced-svelte/07-composition/02-slot-fallbacks/README.md deleted file mode 100644 index 3735b8547..000000000 --- a/content/tutorial/03-advanced-svelte/07-composition/02-slot-fallbacks/README.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -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 -
      - - +++no content was provided+++ - -
      -``` - -We can now create instances of `` without any children: - -```svelte -/// file: App.svelte - -

      Hello!

      -

      This is a box. It can contain anything.

      -
      - -++++++ -``` diff --git a/content/tutorial/03-advanced-svelte/07-composition/02-slot-fallbacks/app-b/src/lib/App.svelte b/content/tutorial/03-advanced-svelte/07-composition/02-slot-fallbacks/app-b/src/lib/App.svelte deleted file mode 100644 index 708428d4d..000000000 --- a/content/tutorial/03-advanced-svelte/07-composition/02-slot-fallbacks/app-b/src/lib/App.svelte +++ /dev/null @@ -1,10 +0,0 @@ - - - -

      Hello!

      -

      This is a box. It can contain anything.

      -
      - - diff --git a/content/tutorial/03-advanced-svelte/07-composition/02-slot-fallbacks/app-b/src/lib/Box.svelte b/content/tutorial/03-advanced-svelte/07-composition/02-slot-fallbacks/app-b/src/lib/Box.svelte deleted file mode 100644 index 8cb8128b3..000000000 --- a/content/tutorial/03-advanced-svelte/07-composition/02-slot-fallbacks/app-b/src/lib/Box.svelte +++ /dev/null @@ -1,16 +0,0 @@ -
      - - no content was provided - -
      - - diff --git a/content/tutorial/03-advanced-svelte/07-composition/03-named-slots/README.md b/content/tutorial/03-advanced-svelte/07-composition/03-named-slots/README.md deleted file mode 100644 index 63fb33830..000000000 --- a/content/tutorial/03-advanced-svelte/07-composition/03-named-slots/README.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -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, such as with this ``. In those cases, we can use _named slots_. - -In `ContactCard.svelte`, add a `name` attribute to each slot: - -```svelte -/// file: ContactCard.svelte -
      -

      - - Unknown name - -

      - -
      - - Unknown address - -
      - - -
      -``` - -Then, add elements with corresponding `slot="..."` attributes inside the `` component: - -```svelte -/// file: App.svelte - - - P. Sherman - - - - 42 Wallaby Way
      - Sydney -
      -
      -``` diff --git a/content/tutorial/03-advanced-svelte/07-composition/03-named-slots/app-a/src/lib/App.svelte b/content/tutorial/03-advanced-svelte/07-composition/03-named-slots/app-a/src/lib/App.svelte deleted file mode 100644 index f3143305c..000000000 --- a/content/tutorial/03-advanced-svelte/07-composition/03-named-slots/app-a/src/lib/App.svelte +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/content/tutorial/03-advanced-svelte/07-composition/03-named-slots/app-a/src/lib/ContactCard.svelte b/content/tutorial/03-advanced-svelte/07-composition/03-named-slots/app-a/src/lib/ContactCard.svelte deleted file mode 100644 index a3174a921..000000000 --- a/content/tutorial/03-advanced-svelte/07-composition/03-named-slots/app-a/src/lib/ContactCard.svelte +++ /dev/null @@ -1,54 +0,0 @@ -
      -

      - - Unknown name - -

      - -
      - - Unknown address - -
      - - -
      - - diff --git a/content/tutorial/03-advanced-svelte/07-composition/03-named-slots/app-b/src/lib/App.svelte b/content/tutorial/03-advanced-svelte/07-composition/03-named-slots/app-b/src/lib/App.svelte deleted file mode 100644 index ea27d75ed..000000000 --- a/content/tutorial/03-advanced-svelte/07-composition/03-named-slots/app-b/src/lib/App.svelte +++ /dev/null @@ -1,12 +0,0 @@ - - - - P. Sherman - - - 42 Wallaby Way
      - Sydney -
      -
      diff --git a/content/tutorial/03-advanced-svelte/07-composition/03-named-slots/app-b/src/lib/ContactCard.svelte b/content/tutorial/03-advanced-svelte/07-composition/03-named-slots/app-b/src/lib/ContactCard.svelte deleted file mode 100644 index d72da2ad4..000000000 --- a/content/tutorial/03-advanced-svelte/07-composition/03-named-slots/app-b/src/lib/ContactCard.svelte +++ /dev/null @@ -1,54 +0,0 @@ -
      -

      - - Unknown name - -

      - -
      - - Unknown address - -
      - - -
      - - diff --git a/content/tutorial/03-advanced-svelte/07-composition/03-slot-fallbacks/README.md b/content/tutorial/03-advanced-svelte/07-composition/03-slot-fallbacks/README.md new file mode 100644 index 000000000..cb6169707 --- /dev/null +++ b/content/tutorial/03-advanced-svelte/07-composition/03-slot-fallbacks/README.md @@ -0,0 +1,30 @@ +--- +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 +
      +
      + + +++(telephone)+++ + + + + +++(company name)+++ + +
      + + + +++(name)+++ + + +
      + + +++(address)+++ + +
      +
      +``` \ No newline at end of file diff --git a/content/tutorial/03-advanced-svelte/07-composition/03-slot-fallbacks/app-a/src/lib/App.svelte b/content/tutorial/03-advanced-svelte/07-composition/03-slot-fallbacks/app-a/src/lib/App.svelte new file mode 100644 index 000000000..fe769fff2 --- /dev/null +++ b/content/tutorial/03-advanced-svelte/07-composition/03-slot-fallbacks/app-a/src/lib/App.svelte @@ -0,0 +1,46 @@ + + +
      + + Patrick BATEMAN + Vice President + + 212 555 6342 + + + Pierce & Pierce + Mergers and Acquisitions + + + 358 Exchange Place, New York, N.Y. 100099 fax 212 555 6390 telex 10 4534 + + + +
      + + \ No newline at end of file diff --git a/content/tutorial/03-advanced-svelte/07-composition/03-slot-fallbacks/app-a/src/lib/Card.svelte b/content/tutorial/03-advanced-svelte/07-composition/03-slot-fallbacks/app-a/src/lib/Card.svelte new file mode 100644 index 000000000..b7f4b3a6d --- /dev/null +++ b/content/tutorial/03-advanced-svelte/07-composition/03-slot-fallbacks/app-a/src/lib/Card.svelte @@ -0,0 +1,56 @@ +
      +
      + + +
      + + + +
      + +
      +
      + + diff --git a/content/tutorial/03-advanced-svelte/07-composition/03-slot-fallbacks/app-a/src/lib/paper.svg b/content/tutorial/03-advanced-svelte/07-composition/03-slot-fallbacks/app-a/src/lib/paper.svg new file mode 100644 index 000000000..f8f704fdf --- /dev/null +++ b/content/tutorial/03-advanced-svelte/07-composition/03-slot-fallbacks/app-a/src/lib/paper.svg @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/content/tutorial/03-advanced-svelte/07-composition/03-slot-fallbacks/app-a/src/lib/wood.svg b/content/tutorial/03-advanced-svelte/07-composition/03-slot-fallbacks/app-a/src/lib/wood.svg new file mode 100644 index 000000000..5157ea83b --- /dev/null +++ b/content/tutorial/03-advanced-svelte/07-composition/03-slot-fallbacks/app-a/src/lib/wood.svg @@ -0,0 +1,10 @@ + + + + + + + \ No newline at end of file diff --git a/content/tutorial/03-advanced-svelte/07-composition/03-slot-fallbacks/app-b/src/lib/Card.svelte b/content/tutorial/03-advanced-svelte/07-composition/03-slot-fallbacks/app-b/src/lib/Card.svelte new file mode 100644 index 000000000..94d36a66b --- /dev/null +++ b/content/tutorial/03-advanced-svelte/07-composition/03-slot-fallbacks/app-b/src/lib/Card.svelte @@ -0,0 +1,65 @@ +
      +
      + + (telephone) + + + + (company name) + +
      + + + (name) + + +
      + + (address) + +
      +
      + + From 9aa5e284b91e6c2a4eade6d0e76130d2077c6a52 Mon Sep 17 00:00:00 2001 From: tomoam <29677552+tomoam@users.noreply.github.com> Date: Wed, 5 Apr 2023 20:40:40 +0900 Subject: [PATCH 122/303] fix: refresh URL (#319) --- content/tutorial/common/src/__client.js | 9 +++++++++ src/routes/tutorial/[slug]/Output.svelte | 1 + 2 files changed, 10 insertions(+) diff --git a/content/tutorial/common/src/__client.js b/content/tutorial/common/src/__client.js index 6f5fba340..d60514ebe 100644 --- a/content/tutorial/common/src/__client.js +++ b/content/tutorial/common/src/__client.js @@ -105,6 +105,15 @@ function ping() { ); } +let pre_url = location.href; +const url_observer = new MutationObserver(() => { + if (location.href !== pre_url) { + pre_url = location.href; + ping(); + } +}); +url_observer.observe(document, { subtree: true, childList: true, attributes: true }); + ping(); if (import.meta.hot) { diff --git a/src/routes/tutorial/[slug]/Output.svelte b/src/routes/tutorial/[slug]/Output.svelte index 5052231f2..8b511495d 100644 --- a/src/routes/tutorial/[slug]/Output.svelte +++ b/src/routes/tutorial/[slug]/Output.svelte @@ -41,6 +41,7 @@ if (paused) return; if (e.data.type === 'ping') { + path = e.data.data.path ?? path; loading = false; } else if (e.data.type === 'warnings') { warnings.update(($warnings) => ({ From 330512310a7053af1532f696d1f28b8edcfbdbe4 Mon Sep 17 00:00:00 2001 From: Stephen Lewis Date: Wed, 5 Apr 2023 12:41:59 +0100 Subject: [PATCH 123/303] Fix user comment bug (#320) Set the user comment string before clearing the input value. --- .../01-svelte/07-lifecycle/02-update/app-a/src/lib/App.svelte | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/content/tutorial/01-svelte/07-lifecycle/02-update/app-a/src/lib/App.svelte b/content/tutorial/01-svelte/07-lifecycle/02-update/app-a/src/lib/App.svelte index d0ca382fc..93001c412 100644 --- a/content/tutorial/01-svelte/07-lifecycle/02-update/app-a/src/lib/App.svelte +++ b/content/tutorial/01-svelte/07-lifecycle/02-update/app-a/src/lib/App.svelte @@ -27,8 +27,6 @@ async function handleKeydown(event) { if (event.key === 'Enter' && event.target.value) { - event.target.value = ''; - const comment = { author: 'user', text: event.target.value @@ -39,6 +37,7 @@ text: eliza.transform(comment.text) }; + event.target.value = ''; comments = [...comments, comment]; await pause(200 * (1 + Math.random())); From c3b36ea4dfa2c8545b86fd104963089899d0fe11 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Wed, 5 Apr 2023 07:52:03 -0400 Subject: [PATCH 124/303] typo --- .../03-advanced-svelte/07-composition/02-named-slots/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/tutorial/03-advanced-svelte/07-composition/02-named-slots/README.md b/content/tutorial/03-advanced-svelte/07-composition/02-named-slots/README.md index 34ecc5250..3a19f5136 100644 --- a/content/tutorial/03-advanced-svelte/07-composition/02-named-slots/README.md +++ b/content/tutorial/03-advanced-svelte/07-composition/02-named-slots/README.md @@ -4,7 +4,7 @@ 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 `` element, we've got `` and others for `company` and `address`. Let's add the corresponding named slots in `Card.svelte`: +Inside the `` component, we've got `` and others for `company` and `address`. Let's add the corresponding named slots in `Card.svelte`: ```svelte /// file: Card.svelte From 138680aee77d1a571e4ecc39ce5d5ef0554e94bd Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Wed, 5 Apr 2023 07:54:57 -0400 Subject: [PATCH 125/303] they spell it wrong in the movie --- .../07-composition/02-named-slots/app-a/src/lib/App.svelte | 2 +- .../07-composition/02-named-slots/app-b/src/lib/App.svelte | 2 +- .../07-composition/03-slot-fallbacks/app-a/src/lib/App.svelte | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/content/tutorial/03-advanced-svelte/07-composition/02-named-slots/app-a/src/lib/App.svelte b/content/tutorial/03-advanced-svelte/07-composition/02-named-slots/app-a/src/lib/App.svelte index 987f6452c..594151af4 100644 --- a/content/tutorial/03-advanced-svelte/07-composition/02-named-slots/app-a/src/lib/App.svelte +++ b/content/tutorial/03-advanced-svelte/07-composition/02-named-slots/app-a/src/lib/App.svelte @@ -11,7 +11,7 @@ Pierce & Pierce - Mergers and Acquisitions + Mergers and Aquisitions 358 Exchange Place, New York, N.Y. 100099 fax 212 555 6390 telex 10 4534 diff --git a/content/tutorial/03-advanced-svelte/07-composition/02-named-slots/app-b/src/lib/App.svelte b/content/tutorial/03-advanced-svelte/07-composition/02-named-slots/app-b/src/lib/App.svelte index c66e6e624..2613efd08 100644 --- a/content/tutorial/03-advanced-svelte/07-composition/02-named-slots/app-b/src/lib/App.svelte +++ b/content/tutorial/03-advanced-svelte/07-composition/02-named-slots/app-b/src/lib/App.svelte @@ -11,7 +11,7 @@ Pierce & Pierce - Mergers and Acquisitions + Mergers and Aquisitions 358 Exchange Place, New York, N.Y. 100099 fax 212 555 6390 telex 10 4534 diff --git a/content/tutorial/03-advanced-svelte/07-composition/03-slot-fallbacks/app-a/src/lib/App.svelte b/content/tutorial/03-advanced-svelte/07-composition/03-slot-fallbacks/app-a/src/lib/App.svelte index fe769fff2..5bb5882ca 100644 --- a/content/tutorial/03-advanced-svelte/07-composition/03-slot-fallbacks/app-a/src/lib/App.svelte +++ b/content/tutorial/03-advanced-svelte/07-composition/03-slot-fallbacks/app-a/src/lib/App.svelte @@ -11,7 +11,7 @@ Pierce & Pierce - Mergers and Acquisitions + Mergers and Aquisitions 358 Exchange Place, New York, N.Y. 100099 fax 212 555 6390 telex 10 4534 From 13e685368aa084131973c57651aaa6ae71e3bd3b Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Wed, 5 Apr 2023 14:11:45 -0400 Subject: [PATCH 126/303] better eliza --- .../07-lifecycle/02-update/README.md | 5 +- .../02-update/app-a/src/lib/App.svelte | 104 ++++++++++++---- .../02-update/app-b/src/lib/App.svelte | 112 ++++++++++++++---- 3 files changed, 177 insertions(+), 44 deletions(-) diff --git a/content/tutorial/01-svelte/07-lifecycle/02-update/README.md b/content/tutorial/01-svelte/07-lifecycle/02-update/README.md index 0c587f497..b126e5beb 100644 --- a/content/tutorial/01-svelte/07-lifecycle/02-update/README.md +++ b/content/tutorial/01-svelte/07-lifecycle/02-update/README.md @@ -14,7 +14,10 @@ let div; +++let autoscroll = false;+++ beforeUpdate(() => { - +++autoscroll = div && div.offsetHeight + div.scrollTop > div.scrollHeight - 20;+++ ++++ if (div) { + const scrollableDistance = div.scrollHeight - div.offsetHeight; + autoscroll = div.scrollTop > scrollableDistance - 20; + }+++ }); afterUpdate(() => { diff --git a/content/tutorial/01-svelte/07-lifecycle/02-update/app-a/src/lib/App.svelte b/content/tutorial/01-svelte/07-lifecycle/02-update/app-a/src/lib/App.svelte index 93001c412..b6f8a5f29 100644 --- a/content/tutorial/01-svelte/07-lifecycle/02-update/app-a/src/lib/App.svelte +++ b/content/tutorial/01-svelte/07-lifecycle/02-update/app-a/src/lib/App.svelte @@ -21,9 +21,7 @@ const typing = { author: 'eliza', text: '...' }; - let comments = [ - { author: 'eliza', text: eliza.getInitial() } - ]; + let comments = []; async function handleKeydown(event) { if (event.key === 'Enter' && event.target.value) { @@ -49,37 +47,67 @@ } -
      -

      Eliza

      - -
      - {#each comments as comment} -
      - {comment.text} -
      - {/each} +
      +
      +
      +
      +

      Eliza

      + +
      + {eliza.getInitial()} +
      +
      + + {#each comments as comment} +
      + {comment.text} +
      + {/each} +
      + +
      - -
      diff --git a/content/tutorial/01-svelte/07-lifecycle/02-update/app-b/src/lib/App.svelte b/content/tutorial/01-svelte/07-lifecycle/02-update/app-b/src/lib/App.svelte index 58eb97852..3f0285387 100644 --- a/content/tutorial/01-svelte/07-lifecycle/02-update/app-b/src/lib/App.svelte +++ b/content/tutorial/01-svelte/07-lifecycle/02-update/app-b/src/lib/App.svelte @@ -9,7 +9,10 @@ let autoscroll = false; beforeUpdate(() => { - autoscroll = div && div.offsetHeight + div.scrollTop > div.scrollHeight - 20; + if (div) { + const scrollableDistance = div.scrollHeight - div.offsetHeight; + autoscroll = div.scrollTop > scrollableDistance - 20; + } }); afterUpdate(() => { @@ -23,14 +26,10 @@ const typing = { author: 'eliza', text: '...' }; - let comments = [ - { author: 'eliza', text: eliza.getInitial() } - ]; + let comments = []; async function handleKeydown(event) { if (event.key === 'Enter' && event.target.value) { - event.target.value = ''; - const comment = { author: 'user', text: event.target.value @@ -41,6 +40,7 @@ text: eliza.transform(comment.text) }; + event.target.value = ''; comments = [...comments, comment]; await pause(200 * (1 + Math.random())); @@ -52,37 +52,67 @@ } -
      -

      Eliza

      - -
      - {#each comments as comment} -
      - {comment.text} -
      - {/each} +
      +
      +
      +
      +

      Eliza

      + +
      + {eliza.getInitial()} +
      +
      + + {#each comments as comment} +
      + {comment.text} +
      + {/each} +
      + +
      - -
      From d1a397fc3f170aa6a0dfa430b2dbec1e5dd946f1 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Wed, 5 Apr 2023 14:24:22 -0400 Subject: [PATCH 127/303] dark mode fixes --- .../07-lifecycle/02-update/app-a/src/lib/App.svelte | 9 ++++----- .../07-lifecycle/02-update/app-b/src/lib/App.svelte | 9 ++++----- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/content/tutorial/01-svelte/07-lifecycle/02-update/app-a/src/lib/App.svelte b/content/tutorial/01-svelte/07-lifecycle/02-update/app-a/src/lib/App.svelte index b6f8a5f29..03d237aca 100644 --- a/content/tutorial/01-svelte/07-lifecycle/02-update/app-a/src/lib/App.svelte +++ b/content/tutorial/01-svelte/07-lifecycle/02-update/app-a/src/lib/App.svelte @@ -95,7 +95,6 @@ flex: 1; font-size: 1.4em; text-align: center; - border-bottom: 1px solid var(--bg-1); } .chat { @@ -120,9 +119,9 @@ } .eliza span { - background-color: #eee; + background-color: var(--bg-1); border-radius: 1em 1em 1em 0; - color: black; + color: var(--fg-1); } .user span { @@ -138,7 +137,7 @@ @media (min-width: 400px) { .phone { - background: var(--bg-1); + background: var(--bg-2); position: relative; font-size: min(2.5vh, 1rem); width: auto; @@ -147,7 +146,7 @@ border: 0.2em solid #222; border-radius: 1em; box-sizing: border-box; - filter: drop-shadow(1px 1px 0px var(--fg-1)) drop-shadow(2px 2px 0px var(--fg-1)) drop-shadow(3px 3px 0px var(--fg-1)) + filter: drop-shadow(1px 1px 0px #222) drop-shadow(2px 2px 0px #222) drop-shadow(3px 3px 0px #222) } .phone::after { diff --git a/content/tutorial/01-svelte/07-lifecycle/02-update/app-b/src/lib/App.svelte b/content/tutorial/01-svelte/07-lifecycle/02-update/app-b/src/lib/App.svelte index 3f0285387..c80a29b93 100644 --- a/content/tutorial/01-svelte/07-lifecycle/02-update/app-b/src/lib/App.svelte +++ b/content/tutorial/01-svelte/07-lifecycle/02-update/app-b/src/lib/App.svelte @@ -100,7 +100,6 @@ flex: 1; font-size: 1.4em; text-align: center; - border-bottom: 1px solid var(--bg-1); } .chat { @@ -125,9 +124,9 @@ } .eliza span { - background-color: #eee; + background-color: var(--bg-1); border-radius: 1em 1em 1em 0; - color: black; + color: var(--fg-1); } .user span { @@ -143,7 +142,7 @@ @media (min-width: 400px) { .phone { - background: var(--bg-1); + background: var(--bg-2); position: relative; font-size: min(2.5vh, 1rem); width: auto; @@ -152,7 +151,7 @@ border: 0.2em solid #222; border-radius: 1em; box-sizing: border-box; - filter: drop-shadow(1px 1px 0px var(--fg-1)) drop-shadow(2px 2px 0px var(--fg-1)) drop-shadow(3px 3px 0px var(--fg-1)) + filter: drop-shadow(1px 1px 0px #222) drop-shadow(2px 2px 0px #222) drop-shadow(3px 3px 0px #222) } .phone::after { From c35016d5c1fa14881896bb763c223a920c44d4cf Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Wed, 5 Apr 2023 16:27:14 -0400 Subject: [PATCH 128/303] make form exercises nicer --- .../04-forms/01-the-form-element/README.md | 5 +- .../app-a/src/lib/server/database.js | 12 +- .../app-a/src/routes/+page.svelte | 58 +++++-- .../app-a/src/routes/remove.svg | 3 + .../app-b/src/routes/+page.svelte | 75 +++++++-- .../04-forms/02-named-form-actions/README.md | 15 +- .../app-b/src/routes/+page.svelte | 84 +++++++--- .../04-forms/03-form-validation/README.md | 8 +- .../app-b/src/lib/server/database.js | 12 +- .../app-b/src/routes/+page.svelte | 98 ++++++++---- .../04-progressive-enhancement/README.md | 2 +- .../app-b/src/routes/+page.svelte | 98 ++++++++---- .../05-customizing-use-enhance/README.md | 20 ++- .../app-b/src/routes/+page.svelte | 146 ++++++++++++------ content/tutorial/common/src/app.html | 23 +++ 15 files changed, 480 insertions(+), 179 deletions(-) create mode 100644 content/tutorial/02-sveltekit/04-forms/01-the-form-element/app-a/src/routes/remove.svg diff --git a/content/tutorial/02-sveltekit/04-forms/01-the-form-element/README.md b/content/tutorial/02-sveltekit/04-forms/01-the-form-element/README.md index 76fdbc6f9..6f5269092 100644 --- a/content/tutorial/02-sveltekit/04-forms/01-the-form-element/README.md +++ b/content/tutorial/02-sveltekit/04-forms/01-the-form-element/README.md @@ -13,7 +13,10 @@ Let's build a todo app. We've already got an in-memory database set up in `src/l +++
      +++ diff --git a/content/tutorial/02-sveltekit/04-forms/01-the-form-element/app-a/src/lib/server/database.js b/content/tutorial/02-sveltekit/04-forms/01-the-form-element/app-a/src/lib/server/database.js index 06afbf801..785df854a 100644 --- a/content/tutorial/02-sveltekit/04-forms/01-the-form-element/app-a/src/lib/server/database.js +++ b/content/tutorial/02-sveltekit/04-forms/01-the-form-element/app-a/src/lib/server/database.js @@ -3,14 +3,18 @@ const db = new Map(); export function getTodos(userid) { + if (!db.get(userid)) { + db.set(userid, [{ + id: crypto.randomUUID(), + description: 'Learn SvelteKit', + done: false + }]); + } + return db.get(userid); } export function createTodo(userid, description) { - if (!db.has(userid)) { - db.set(userid, []); - } - const todos = db.get(userid); todos.push({ diff --git a/content/tutorial/02-sveltekit/04-forms/01-the-form-element/app-a/src/routes/+page.svelte b/content/tutorial/02-sveltekit/04-forms/01-the-form-element/app-a/src/routes/+page.svelte index 0c2fd19d2..8295cb33f 100644 --- a/content/tutorial/02-sveltekit/04-forms/01-the-form-element/app-a/src/routes/+page.svelte +++ b/content/tutorial/02-sveltekit/04-forms/01-the-form-element/app-a/src/routes/+page.svelte @@ -2,12 +2,52 @@ export let data; -

      todos

      - -
        - {#each data.todos as todo (todo.id)} -
      • - {todo.description} -
      • - {/each} -
      +
      +

      todos

      + +
        + {#each data.todos as todo (todo.id)} +
      • + {todo.description} +
      • + {/each} +
      +
      + + diff --git a/content/tutorial/02-sveltekit/04-forms/01-the-form-element/app-a/src/routes/remove.svg b/content/tutorial/02-sveltekit/04-forms/01-the-form-element/app-a/src/routes/remove.svg new file mode 100644 index 000000000..d338b3349 --- /dev/null +++ b/content/tutorial/02-sveltekit/04-forms/01-the-form-element/app-a/src/routes/remove.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/content/tutorial/02-sveltekit/04-forms/01-the-form-element/app-b/src/routes/+page.svelte b/content/tutorial/02-sveltekit/04-forms/01-the-form-element/app-b/src/routes/+page.svelte index 23d07eb27..e1d5603ec 100644 --- a/content/tutorial/02-sveltekit/04-forms/01-the-form-element/app-b/src/routes/+page.svelte +++ b/content/tutorial/02-sveltekit/04-forms/01-the-form-element/app-b/src/routes/+page.svelte @@ -2,19 +2,62 @@ export let data; -

      todos

      - -
      - -
      - -
        - {#each data.todos as todo (todo.id)} -
      • - {todo.description} -
      • - {/each} -
      +
      +

      todos

      + +
      + +
      + +
        + {#each data.todos as todo (todo.id)} +
      • + {todo.description} +
      • + {/each} +
      +
      + + diff --git a/content/tutorial/02-sveltekit/04-forms/02-named-form-actions/README.md b/content/tutorial/02-sveltekit/04-forms/02-named-form-actions/README.md index d76bfc221..83a3048cb 100644 --- a/content/tutorial/02-sveltekit/04-forms/02-named-form-actions/README.md +++ b/content/tutorial/02-sveltekit/04-forms/02-named-form-actions/README.md @@ -30,7 +30,10 @@ The `
      ` element has an optional `action` attribute, which is similar to an
      ``` @@ -41,14 +44,14 @@ Next, we want to create a form for each todo, complete with a hidden `` t ```svelte /// file: src/routes/+page.svelte -
        +
          {#each data.todos as todo (todo.id)} -
        • +
        • +++
          - +++ - {todo.description} -+++
          +++ + {todo.description} +
        • {/each}
        diff --git a/content/tutorial/02-sveltekit/04-forms/02-named-form-actions/app-b/src/routes/+page.svelte b/content/tutorial/02-sveltekit/04-forms/02-named-form-actions/app-b/src/routes/+page.svelte index 9c1809b36..7896e68b9 100644 --- a/content/tutorial/02-sveltekit/04-forms/02-named-form-actions/app-b/src/routes/+page.svelte +++ b/content/tutorial/02-sveltekit/04-forms/02-named-form-actions/app-b/src/routes/+page.svelte @@ -2,24 +2,66 @@ export let data; -

        todos

        - -
        - -
        - -
          - {#each data.todos as todo (todo.id)} -
        • -
          - - - - {todo.description} -
          -
        • - {/each} -
        +
        +

        todos

        + +
        + +
        + +
          + {#each data.todos as todo (todo.id)} +
        • +
          + + {todo.description} +
        • + {/each} +
        +
        + + diff --git a/content/tutorial/02-sveltekit/04-forms/03-form-validation/README.md b/content/tutorial/02-sveltekit/04-forms/03-form-validation/README.md index 6c7799b46..1b6130282 100644 --- a/content/tutorial/02-sveltekit/04-forms/03-form-validation/README.md +++ b/content/tutorial/02-sveltekit/04-forms/03-form-validation/README.md @@ -10,9 +10,10 @@ The first line of defense is the browser's [built-in form validation](https://de /// file: src/routes/+page.svelte
        @@ -32,10 +33,6 @@ export function createTodo(userid, description) { throw new Error('todo must have a description'); }+++ - if (!db.has(userid)) { - db.set(userid, []); - } - const todos = db.get(userid); +++ if (todos.find((todo) => todo.description === description)) { @@ -97,6 +94,7 @@ In `src/routes/+page.svelte`, we can access the returned value via the `form` pr diff --git a/content/tutorial/02-sveltekit/04-forms/03-form-validation/app-b/src/lib/server/database.js b/content/tutorial/02-sveltekit/04-forms/03-form-validation/app-b/src/lib/server/database.js index ff6a48db8..4a59d5609 100644 --- a/content/tutorial/02-sveltekit/04-forms/03-form-validation/app-b/src/lib/server/database.js +++ b/content/tutorial/02-sveltekit/04-forms/03-form-validation/app-b/src/lib/server/database.js @@ -3,6 +3,14 @@ const db = new Map(); export function getTodos(userid) { + if (!db.get(userid)) { + db.set(userid, [{ + id: crypto.randomUUID(), + description: 'Learn SvelteKit', + done: false + }]); + } + return db.get(userid); } @@ -11,10 +19,6 @@ export function createTodo(userid, description) { throw new Error('todo must have a description'); } - if (!db.has(userid)) { - db.set(userid, []); - } - const todos = db.get(userid); if (todos.find((todo) => todo.description === description)) { diff --git a/content/tutorial/02-sveltekit/04-forms/03-form-validation/app-b/src/routes/+page.svelte b/content/tutorial/02-sveltekit/04-forms/03-form-validation/app-b/src/routes/+page.svelte index fdc24c779..8346527df 100644 --- a/content/tutorial/02-sveltekit/04-forms/03-form-validation/app-b/src/routes/+page.svelte +++ b/content/tutorial/02-sveltekit/04-forms/03-form-validation/app-b/src/routes/+page.svelte @@ -3,32 +3,72 @@ export let form; -

        todos

        - -{#if form?.error} -

        {form.error}

        -{/if} - - - -
        - -
          - {#each data.todos as todo (todo.id)} -
        • -
          - - - - {todo.description} -
          -
        • - {/each} -
        +
        +

        todos

        + + {#if form?.error} +

        {form.error}

        + {/if} + +
        + +
        + +
          + {#each data.todos as todo (todo.id)} +
        • +
          + + {todo.description} +
        • + {/each} +
        +
        + + diff --git a/content/tutorial/02-sveltekit/04-forms/04-progressive-enhancement/README.md b/content/tutorial/02-sveltekit/04-forms/04-progressive-enhancement/README.md index efe5f3292..66b9f2969 100644 --- a/content/tutorial/02-sveltekit/04-forms/04-progressive-enhancement/README.md +++ b/content/tutorial/02-sveltekit/04-forms/04-progressive-enhancement/README.md @@ -52,5 +52,5 @@ Now that we're updating the page rather than reloading it, we can get fancy with ```svelte /// file: src/routes/+page.svelte -
      • ...
      • +
      • ...
      • ``` diff --git a/content/tutorial/02-sveltekit/04-forms/04-progressive-enhancement/app-b/src/routes/+page.svelte b/content/tutorial/02-sveltekit/04-forms/04-progressive-enhancement/app-b/src/routes/+page.svelte index 629d09091..f45a7a244 100644 --- a/content/tutorial/02-sveltekit/04-forms/04-progressive-enhancement/app-b/src/routes/+page.svelte +++ b/content/tutorial/02-sveltekit/04-forms/04-progressive-enhancement/app-b/src/routes/+page.svelte @@ -6,32 +6,72 @@ export let form; -

        todos

        - -{#if form?.error} -

        {form.error}

        -{/if} - -
        - -
        - -
          - {#each data.todos as todo (todo.id)} -
        • -
          - - - - {todo.description} -
          -
        • - {/each} -
        +
        +

        todos

        + + {#if form?.error} +

        {form.error}

        + {/if} + +
        + +
        + +
          + {#each data.todos as todo (todo.id)} +
        • +
          + + {todo.description} +
        • + {/each} +
        +
        + + diff --git a/content/tutorial/02-sveltekit/04-forms/05-customizing-use-enhance/README.md b/content/tutorial/02-sveltekit/04-forms/05-customizing-use-enhance/README.md index 2024db87b..a29366f18 100644 --- a/content/tutorial/02-sveltekit/04-forms/05-customizing-use-enhance/README.md +++ b/content/tutorial/02-sveltekit/04-forms/05-customizing-use-enhance/README.md @@ -52,24 +52,38 @@ When we create or delete items, it now takes a full second before the UI updates }}+++ > ``` +We can then show a message while we're saving data: + +```svelte +/// file: App.svelte +
          + +
        + ++++{#if creating} + saving... +{/if}+++ +``` + In the case of deletions, we don't really need to wait for the server to validate anything — we can just update the UI immediately: ```svelte /// file: src/routes/+page.svelte -
          +
            {#each +++data.todos.filter((todo) => !deleting.includes(todo.id))+++ as todo (todo.id)} -
          • +
          • -

            todos

            - -{#if form?.error} -

            {form.error}

            -{/if} - - { - creating = true; - - return async ({ update }) => { - await update(); - creating = false; - }; - }} -> - -
            - -
              - {#each data.todos.filter((todo) => !deleting.includes(todo.id)) as todo (todo.id)} -
            • -
              { - deleting = [...deleting, todo.id]; - return async ({ update }) => { - await update(); - deleting = deleting.filter((id) => id !== todo.id); - }; - }} - > - - - - {todo.description} -
              -
            • - {/each} -
            +
            +

            todos

            + + {#if form?.error} +

            {form.error}

            + {/if} + +
            { + creating = true; + + return async ({ update }) => { + await update(); + creating = false; + }; + }} + > + +
            + +
              + {#each data.todos.filter((todo) => !deleting.includes(todo.id)) as todo (todo.id)} +
            • +
              { + deleting = [...deleting, todo.id]; + return async ({ update }) => { + await update(); + deleting = deleting.filter((id) => id !== todo.id); + }; + }} + > + + {todo.description} +
            • + {/each} +
            + + {#if creating} + saving... + {/if} +
            + + diff --git a/content/tutorial/common/src/app.html b/content/tutorial/common/src/app.html index ec30998cc..f8f202fc1 100644 --- a/content/tutorial/common/src/app.html +++ b/content/tutorial/common/src/app.html @@ -184,6 +184,29 @@ border-radius: var(--border-radius); } + ul.todos { + padding: 0; + } + + ul.todos li:not(:has(> form)), + ul.todos li form { + position: relative; + display: flex; + align-items: center; + padding-left: 1em; + height: 3em; + margin: 0 0 0.5em 0; + gap: 0.5em; + border-radius: 5px; + user-select: none; + background: white; + filter: drop-shadow(2px 3px 6px rgba(0,0,0,0.1)); + } + + ul.todos .done { + + } + @media (prefers-color-scheme: dark) { body { --bg-1: hsl(0, 0%, 18%); From 2c4e0df4f6a76c0bb575bc29c750b539a68af29b Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Wed, 5 Apr 2023 17:46:24 -0400 Subject: [PATCH 129/303] dark mode styles --- .../app-a/src/routes/remove.svg | 2 +- .../app-b/src/routes/+page.svelte | 15 ---- .../09-deferred-transitions/README.md | 7 +- .../app-a/src/lib/App.svelte | 4 +- .../app-a/src/lib/TodoList.svelte | 71 +++++++---------- .../app-a/src/lib/remove.svg | 2 +- .../app-b/src/lib/TodoList.svelte | 76 +++++++----------- .../03-animations/01-animate/README.md | 10 ++- .../01-animate/app-b/src/lib/TodoList.svelte | 78 +++++++------------ content/tutorial/common/src/app.html | 24 +++++- 10 files changed, 121 insertions(+), 168 deletions(-) diff --git a/content/tutorial/02-sveltekit/04-forms/01-the-form-element/app-a/src/routes/remove.svg b/content/tutorial/02-sveltekit/04-forms/01-the-form-element/app-a/src/routes/remove.svg index d338b3349..434ab0956 100644 --- a/content/tutorial/02-sveltekit/04-forms/01-the-form-element/app-a/src/routes/remove.svg +++ b/content/tutorial/02-sveltekit/04-forms/01-the-form-element/app-a/src/routes/remove.svg @@ -1,3 +1,3 @@ - + \ No newline at end of file diff --git a/content/tutorial/02-sveltekit/04-forms/04-progressive-enhancement/app-b/src/routes/+page.svelte b/content/tutorial/02-sveltekit/04-forms/04-progressive-enhancement/app-b/src/routes/+page.svelte index f45a7a244..88dd03d93 100644 --- a/content/tutorial/02-sveltekit/04-forms/04-progressive-enhancement/app-b/src/routes/+page.svelte +++ b/content/tutorial/02-sveltekit/04-forms/04-progressive-enhancement/app-b/src/routes/+page.svelte @@ -56,21 +56,6 @@ flex: 1; } - button { - border: none; - background: url(http://github.com/remove.svg) no-repeat 50% 50%; - background-size: 1rem 1rem; - cursor: pointer; - height: 100%; - aspect-ratio: 1; - opacity: 0.5; - transition: opacity 0.2s; - } - - button:hover { - opacity: 1; - } - .saving { opacity: 0.5; } diff --git a/content/tutorial/03-advanced-svelte/02-transitions/09-deferred-transitions/README.md b/content/tutorial/03-advanced-svelte/02-transitions/09-deferred-transitions/README.md index a71642a06..8a3a945fb 100644 --- a/content/tutorial/03-advanced-svelte/02-transitions/09-deferred-transitions/README.md +++ b/content/tutorial/03-advanced-svelte/02-transitions/09-deferred-transitions/README.md @@ -16,15 +16,16 @@ Open `TodoList.svelte`. First, import the `send` and `receive` transitions from +++import { send, receive } from './transition.js';+++ export let store; - export let filter; + export let done; ``` -Then, add them to the `
          • ` element, using the `todo.id` property as a key to match the elements: ```svelte /// file: TodoList.svelte -
      diff --git a/content/tutorial/03-advanced-svelte/02-transitions/09-deferred-transitions/app-a/src/lib/TodoList.svelte b/content/tutorial/03-advanced-svelte/02-transitions/09-deferred-transitions/app-a/src/lib/TodoList.svelte index 47b1e1a1f..43e6dc9af 100644 --- a/content/tutorial/03-advanced-svelte/02-transitions/09-deferred-transitions/app-a/src/lib/TodoList.svelte +++ b/content/tutorial/03-advanced-svelte/02-transitions/09-deferred-transitions/app-a/src/lib/TodoList.svelte @@ -1,35 +1,37 @@ -{#each $store.filter(filter) as todo (todo.id)} -
    \ No newline at end of file diff --git a/content/tutorial/03-advanced-svelte/02-transitions/09-deferred-transitions/app-a/src/lib/remove.svg b/content/tutorial/03-advanced-svelte/02-transitions/09-deferred-transitions/app-a/src/lib/remove.svg index d338b3349..434ab0956 100644 --- a/content/tutorial/03-advanced-svelte/02-transitions/09-deferred-transitions/app-a/src/lib/remove.svg +++ b/content/tutorial/03-advanced-svelte/02-transitions/09-deferred-transitions/app-a/src/lib/remove.svg @@ -1,3 +1,3 @@ - + \ No newline at end of file diff --git a/content/tutorial/03-advanced-svelte/02-transitions/09-deferred-transitions/app-b/src/lib/TodoList.svelte b/content/tutorial/03-advanced-svelte/02-transitions/09-deferred-transitions/app-b/src/lib/TodoList.svelte index 91dff8305..4354a6de6 100644 --- a/content/tutorial/03-advanced-svelte/02-transitions/09-deferred-transitions/app-b/src/lib/TodoList.svelte +++ b/content/tutorial/03-advanced-svelte/02-transitions/09-deferred-transitions/app-b/src/lib/TodoList.svelte @@ -2,39 +2,40 @@ import { send, receive } from './transition.js'; export let store; - export let filter; + export let done; -{#each $store.filter(filter) as todo (todo.id)} -