diff --git a/site/content/faq/100-im-new-to-svelte.md b/site/content/faq/100-im-new-to-svelte.md new file mode 100644 index 0000000000..18e4b6742f --- /dev/null +++ b/site/content/faq/100-im-new-to-svelte.md @@ -0,0 +1,7 @@ +--- +question: I'm new to Svelte. Where should I start? +--- + +We think the best way to get started is playing through the interactive [Tutorial](https://svelte.dev/tutorial). Each step there is mainly focused on one specific aspect and is easy to follow. You'll be editing and running real Svelte components right in your browser. + +Five to ten minutes should be enough to get you up and running. An hour and a half should get you through the entire tutorial. \ No newline at end of file diff --git a/site/content/faq/1000-how-can-i-update-my-v2-components.md b/site/content/faq/1000-how-can-i-update-my-v2-components.md new file mode 100644 index 0000000000..0800dff89b --- /dev/null +++ b/site/content/faq/1000-how-can-i-update-my-v2-components.md @@ -0,0 +1,5 @@ +--- +question: How can I update my components written in Svelte v2? +--- + +svelte-upgrade isn't fully working for v2->v3 yet, [but it's close](https://github.com/sveltejs/svelte-upgrade/pull/12). \ No newline at end of file diff --git a/site/content/faq/1100-is-svelte-v2-still-availabile.md b/site/content/faq/1100-is-svelte-v2-still-availabile.md new file mode 100644 index 0000000000..0fbc4c039c --- /dev/null +++ b/site/content/faq/1100-is-svelte-v2-still-availabile.md @@ -0,0 +1,7 @@ +--- +question: Is Svelte v2 still available? +--- + +New features aren't being added to it, and bugs will probably only be fixed if they are extremely nasty or present some sort of security vulnerability. + +The documentation is still available [here](https://v2.svelte.dev/guide). \ No newline at end of file diff --git a/site/content/faq/1200-how-do-i-do-hmr.md b/site/content/faq/1200-how-do-i-do-hmr.md new file mode 100644 index 0000000000..88d08b252f --- /dev/null +++ b/site/content/faq/1200-how-do-i-do-hmr.md @@ -0,0 +1,5 @@ +--- +question: How do I do hot module reloading? +--- + +Use the community plugins for [rollup](https://github.com/rixo/rollup-plugin-svelte-hot) and [webpack](https://github.com/rixo/svelte-loader-hot). diff --git a/site/content/faq/200-are-there-any-video-courses.md b/site/content/faq/200-are-there-any-video-courses.md new file mode 100644 index 0000000000..0c2c1f680e --- /dev/null +++ b/site/content/faq/200-are-there-any-video-courses.md @@ -0,0 +1,10 @@ +--- +question: Are there any video courses? +--- + +There are no official ones, but here are a couple of third-part ones that we know of. + +- [Egghead](https://egghead.io/playlists/getting-started-with-svelte-3-05a8541a) +- [Udemy](https://www.udemy.com/sveltejs-the-complete-guide/) + +Note that Udemy very frequently has discounts over 90%. diff --git a/site/content/faq/300-is-svelte-dev-down.md b/site/content/faq/300-is-svelte-dev-down.md new file mode 100644 index 0000000000..a7ce9984b7 --- /dev/null +++ b/site/content/faq/300-is-svelte-dev-down.md @@ -0,0 +1,5 @@ +--- +question: Is svelte.dev down? +--- + +Probably not, but it's possible. If you can't seem to access any `.dev` sites, check out [this SuperUser question and answer](https://superuser.com/q/1413402). \ No newline at end of file diff --git a/site/content/faq/400-how-can-i-get-syntax-highlighting.md b/site/content/faq/400-how-can-i-get-syntax-highlighting.md new file mode 100644 index 0000000000..90f10b254f --- /dev/null +++ b/site/content/faq/400-how-can-i-get-syntax-highlighting.md @@ -0,0 +1,5 @@ +--- +question: How can I get VSCode to syntax-highlight my .svelte files? +--- + +There is an [official VSCode extension for Svelte](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode), however it is still in the **beta** testing stage, and not all issues have been ironed out. \ No newline at end of file diff --git a/site/content/faq/500-what-about-typescript-support.md b/site/content/faq/500-what-about-typescript-support.md new file mode 100644 index 0000000000..dae27143ed --- /dev/null +++ b/site/content/faq/500-what-about-typescript-support.md @@ -0,0 +1,5 @@ +--- +question: What about Typescript support? +--- + +You need to install a [community supported preprocessor](https://github.com/sveltejs/integrations#preprocessors) such as [svelte-preprocess](https://github.com/kaisermann/svelte-preprocess). Work is ongoing to improve [IDE support](https://github.com/sveltejs/language-tools/issues/83) and build [additional CLI tooling](https://github.com/sveltejs/language-tools/issues/68) \ No newline at end of file diff --git a/site/content/faq/600-does-svelte-scale.md b/site/content/faq/600-does-svelte-scale.md new file mode 100644 index 0000000000..06c9b58a97 --- /dev/null +++ b/site/content/faq/600-does-svelte-scale.md @@ -0,0 +1,5 @@ +--- +question: Does Svelte scale? +--- + +There will be a blog post about this eventually, but in the meantime, check out [this issue](https://github.com/sveltejs/svelte/issues/2546). diff --git a/site/content/faq/700-is-there-a-component-library.md b/site/content/faq/700-is-there-a-component-library.md new file mode 100644 index 0000000000..fd771eabda --- /dev/null +++ b/site/content/faq/700-is-there-a-component-library.md @@ -0,0 +1,5 @@ +--- +question: Is there a UI component library? +--- + +There are several UI component libraries. Find them under the [code section](https://svelte-community.netlify.com/code) of the Svelte Community website. diff --git a/site/content/faq/800-how-do-i-test-svelte-apps.md b/site/content/faq/800-how-do-i-test-svelte-apps.md new file mode 100644 index 0000000000..af67bebf3f --- /dev/null +++ b/site/content/faq/800-how-do-i-test-svelte-apps.md @@ -0,0 +1,6 @@ +--- +question: How do I test Svelte apps? +--- + +We don't have a good answer to this yet, but it is a priority. There are a few approaches that people take when testing, but it generally involves compiling the component and mounting it to something and then performing the tests. +You essentially need to create a bundle for each component you're testing (since svelte is a compiler and not a normal library) and then mount them. You can mount to a JSDOM instance, or you can use Puppeteer if you need a real browser, or you can use a tool like Cypress. There is an example of this in the Sapper starter template. diff --git a/site/content/faq/900-is-there-a-router.md b/site/content/faq/900-is-there-a-router.md new file mode 100644 index 0000000000..a78c478943 --- /dev/null +++ b/site/content/faq/900-is-there-a-router.md @@ -0,0 +1,13 @@ +--- +question: Is there a router? +--- + +You can use any router lib you want. A lot of people use [page.js](https://github.com/visionmedia/page.js). There's also [navaid](https://github.com/lukeed/navaid), which is very similar. + +If you prefer a declarative HTML approach, there's [svelte-routing](https://github.com/EmilTholin/svelte-routing). + +If you need hash-based routing on the client side, check out [svelte-spa-router](https://github.com/ItalyPaleAle/svelte-spa-router), or [abstract-state-router](https://github.com/TehShrike/abstract-state-router/), a mature router for business software. + +For filesystem-based routing, you can take a look at [Routify](https://routify.dev). + +For an official solution, there's nothing that's simply a routing library. There is, however, the official [Sapper](https://sapper.svelte.dev/) framework, a Next.js-style application framework built on Svelte, which includes its own filesystem-based routing. \ No newline at end of file diff --git a/site/src/routes/blog/[slug].svelte b/site/src/routes/blog/[slug].svelte index 610fb6506b..d5fd6c0676 100644 --- a/site/src/routes/blog/[slug].svelte +++ b/site/src/routes/blog/[slug].svelte @@ -133,44 +133,14 @@ border: 0.8rem solid var(--second); } - /* headers anchors */ - - .post :global(.offset-anchor) { - position: relative; - display: block; - top: calc(-1 * (var(--nav-h) + var(--top-offset) - 1rem)); - width: 0; - height: 0; - } - .post :global(.anchor) { - position: absolute; - display: block; - background: url(/icons/link.svg) 0 50% no-repeat; - background-size: 1em 1em; - width: 1.4em; - height: 1em; top: calc((var(--h3) - 24px) / 2); - left: -1.4em; - opacity: 0; - transition: opacity 0.2s; - border: none !important; /* TODO get rid of linkify */ } - .post :global(h2):hover :global(.anchor), - .post :global(h3):hover :global(.anchor), - .post :global(h4):hover :global(.anchor), - .post :global(h5):hover :global(.anchor), - .post :global(h6):hover :global(.anchor) { - opacity: 1; - } - - @media (max-width: 768px) { .post :global(.anchor) { transform: scale(0.6); opacity: 1; - top: calc((1em - 0.6 * 24px) / 2); left: -1.0em; } } diff --git a/site/src/routes/faq.js b/site/src/routes/faq.js deleted file mode 100644 index 6263494a4c..0000000000 --- a/site/src/routes/faq.js +++ /dev/null @@ -1,4 +0,0 @@ -export function get(req, res) { - res.writeHead(302, { Location: 'https://github.com/sveltejs/svelte/wiki/FAQ' }); - res.end(); -} \ No newline at end of file diff --git a/site/src/routes/faq/_faqs.js b/site/src/routes/faq/_faqs.js new file mode 100644 index 0000000000..fa48e02282 --- /dev/null +++ b/site/src/routes/faq/_faqs.js @@ -0,0 +1,58 @@ +import fs from 'fs'; +import path from 'path'; +import { extract_frontmatter, link_renderer } from '@sveltejs/site-kit/utils/markdown.js'; +import marked from 'marked'; +import { makeSlugProcessor } from '../../utils/slug'; +import { highlight } from '../../utils/highlight'; +import { SLUG_PRESERVE_UNICODE } from '../../../config'; + +const makeSlug = makeSlugProcessor(SLUG_PRESERVE_UNICODE); + +export default function get_faqs() { + return fs + .readdirSync('content/faq') + .map(file => { + if (path.extname(file) !== '.md') return; + + const match = /^([0-9]+)-(.+)\.md$/.exec(file); + if (!match) throw new Error(`Invalid filename '${file}'`); + + const [, order, slug] = match; + + const markdown = fs.readFileSync(`content/faq/${file}`, 'utf-8'); + + const { content, metadata } = extract_frontmatter(markdown); + + const renderer = new marked.Renderer(); + + renderer.link = link_renderer; + + renderer.code = highlight; + + renderer.heading = (text, level, rawtext) => { + const fragment = makeSlug(rawtext); + + return ` + + + + ${text} + `; + }; + + const answer = marked( + content.replace(/^\t+/gm, match => match.split('\t').join(' ')), + { renderer } + ); + + const fragment = makeSlug(slug); + + return { + fragment, + order, + answer, + metadata + }; + }) + .sort((a, b) => a.order - b.order); +} diff --git a/site/src/routes/faq/index.json.js b/site/src/routes/faq/index.json.js new file mode 100644 index 0000000000..b6810a984e --- /dev/null +++ b/site/src/routes/faq/index.json.js @@ -0,0 +1,24 @@ +import send from '@polka/send'; +import get_faqs from './_faqs.js'; + +let json; + +export function get(req, res) { + if (!json || process.env.NODE_ENV !== 'production') { + const faqs = get_faqs() + .map(faq => { + return { + fragment: faq.fragment, + answer: faq.answer, + metadata: faq.metadata + }; + }); + + json = JSON.stringify(faqs); + } + + send(res, 200, json, { + 'Content-Type': 'application/json', + 'Cache-Control': `max-age=${5 * 60 * 1e3}` // 5 minutes + }); +} diff --git a/site/src/routes/faq/index.svelte b/site/src/routes/faq/index.svelte new file mode 100644 index 0000000000..c426f5bf3d --- /dev/null +++ b/site/src/routes/faq/index.svelte @@ -0,0 +1,89 @@ + + + + + + Frequently Asked Questions • Svelte + + + + + + +
+

Frequently Asked Questions

+ {#each faqs as faq} + +
+

+ +   + {faq.metadata.question} +

+

{@html faq.answer}

+
+ {/each} +
+ + diff --git a/site/src/template.html b/site/src/template.html index 344684d766..28ea1910a5 100644 --- a/site/src/template.html +++ b/site/src/template.html @@ -7,6 +7,7 @@ %sapper.base% + diff --git a/site/static/global.css b/site/static/global.css index 14e4e0a0c0..7aa0715a98 100644 --- a/site/static/global.css +++ b/site/static/global.css @@ -1,500 +1,31 @@ -/* ------------------------------------------------ - vars – css custom-properties +/* headers anchors */ - NOTE - - some vars change inside media-queries! - - under normal conditions, there's no need to touch these ------------------------------------------------ -*/ -:root { - --nav-h: 6rem; - --top-offset: 6rem; - --sidebar-w: 30rem; - --sidebar-mid-w: 36rem; - --sidebar-large-w: 48rem; - --main-width: 80rem; - --code-w: 72em; - --side-nav: 3.2rem; - --side-page: var(--side-nav); - - /* easings */ - --in-cubic: cubic-bezier(0.55, 0.055, 0.675, 0.19); - --out-cubic: cubic-bezier(0.215, 0.61, 0.355, 1); - --inout-cubic: cubic-bezier(0.645, 0.045, 0.355, 1); - - --in-back: cubic-bezier(0.6, -0.28, 0.735, 0.045); - --out-back: cubic-bezier(0.175, 0.885, 0.32, 1.275); - --inout-back: cubic-bezier(0.68, -0.55, 0.265, 1.55); -} - -@media screen and (min-width: 768px) { - :root { - --side-page: 14vw; - --top-offset: 10rem; - --side-nav: 4.8rem; - } -} - -/* theme vars */ -.theme-default { - --back: #ffffff; - --back-light: #f6fafd; - --back-api: #eff8ff; - --prime: #ff3e00; - --second: #676778; - --flash: #40b3ff; - --heading: var(--second); - --text: #444; - --sidebar-text: rgba(255, 255, 255, .75); - --border-w: .3rem; /* border-width */ - --border-r: .4rem; /* border-radius */ -} - -/* typo vars */ -.typo-default { - --unit: .8rem; - --code-fs: 1.3rem; - --h6: 1.4rem; - --h5: 1.6rem; - --h4: 1.8rem; /* default font-size */ - --h3: 2.6rem; - --h2: 3rem; - --h1: 3.2rem; - --linemax: 42em; /* max line-length */ - --lh: 1.5; /* base line-height */ -} - -body { - --font: 'Overpass', sans-serif; - --font-mono: 'Fira Mono', monospace; - --font-ui: var(--font-mono); - --font-system: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif; -} - - -/* fonts ---------------------------------- */ -/* overpass-300normal - latin */ -@font-face { - font-family: 'Overpass'; - font-style: normal; - font-weight: 300; - font-display: fallback; - src: - local('Overpass Light '), - local('Overpass-Light'), - url('fonts/overpass/overpass-latin-300.woff2') format('woff2'); -} - -/* overpass-600normal - latin */ -@font-face { - font-family: 'Overpass'; - font-style: normal; - font-weight: 600; - font-display: fallback; - src: - local('Overpass Bold '), - local('Overpass-Bold'), - url('fonts/overpass/overpass-latin-600.woff2') format('woff2'); -} - -/* fira-mono-400normal - latin */ -@font-face { - font-family: 'Fira Mono'; - font-style: normal; - font-weight: 400; - font-display: fallback; - src: - local('Fira Mono Regular '), - local('Fira Mono-Regular'), - url('fonts/fira-mono/fira-mono-latin-400.woff2') format('woff2'); -} - -/* base reset ----------------------------- */ -html { - font-size: 62.5%; - -ms-text-size-adjust: 62.5%; - -webkit-text-size-adjust: 62.5%; - -ms-overflow-style: -ms-autohiding-scrollbar; - box-sizing: border-box; - border-collapse: collapse; -} - -html, -body, -#sapper { - width: 100%; - height: 100%; -} - -* { - box-sizing: inherit; - margin: 0; - padding: 0; -} - -/* link reset ----------------------------- */ -a { - text-decoration: none; - cursor: pointer; - color: inherit; -} - -a:hover, a:active { color: var(--flash) } -a:focus { outline: none } - -/* ------------------------------------------------ - global styles ------------------------------------------------ -*/ - -/* typography ----------------------------- */ -body { - font: 300 var(--h4)/var(--lh) var(--font); - background-color: var(--back); - color: var(--text); - - /* default spacing of Overpass is a bit too airy */ - /* letter-spacing: -.013em; */ -} - -h1, h2, h3, h4, h5, h6, blockquote { - position: relative; - margin: 0; - color: var(--heading); -} - -/* h1, h2, h3, h4, h5, h6 { font-weight: 600 } */ -h6 { font-size: var(--h6) } -h5 { font-size: var(--h5) } -h4 { font-size: var(--h4) } -h3 { font-size: var(--h3) } -h2 { font-size: var(--h2) } -h1 { font-size: var(--h1) } - -h1, h2 { - font-family: var(--font); - line-height: 1.25; -} - -h3 { font-weight: 300 } - -p, ol, ul { - margin: 0 0 1em 0; -} - -.b, b, strong { font-weight: 600 } - -tt, code, kbd, samp { - font: 400 var(--code-fs)/1.7 var(--font-mono); -} - -code { - position: relative; - border-radius: .3em; - white-space: nowrap; - color: #444; - -webkit-font-smoothing: initial; -} - -pre code { - top: 0; - white-space: inherit; - background-color: none; -} - -/* sync CodeMirror with prism */ -.CodeMirror { - font-size: var(--code-fs) !important; -} - -::selection { - background: var(--flash); - color: white; -} - -/* opinionated styles --------------------- */ - -li:not(.white) > h2 { - color: var(--second) -} - -blockquote { - position: relative; - margin: 1.6rem 0 2.4rem; - padding: 2rem 2.4rem 1.8rem 2.4rem; - border-radius: var(--border-r); - font-family: var(--font); - max-width: var(--linemax); -} - -blockquote p { - font-size: var(--h5); -} - -blockquote :last-child { - margin: 0; -} - -/* buttons -------------------------------- */ -button { - font-family: inherit; - font-size: inherit; - background-color: transparent; - border: none; - color: currentColor; - cursor: pointer; -} - -button:focus, -.btn:focus { outline: 0 } - -button[disabled], -.btn[disabled], -.btn:hover[disabled] { - opacity: .55; - pointer-events: none; -} - -button > svg, -.btn > svg { - position: relative; - top: -.1rem; - width: 2rem !important; - height: 2rem !important; - stroke: currentColor !important; -} - -/* reset ------- */ -.btn { - --btn-h: 4rem; - --btn-outline: .2rem; - --btn-font: var(--font); - --btn-calc-h: calc(var(--btn-h) - var(--btn-outline) * 2); - --btn-hover: linear-gradient(to top, rgba(0,0,0,.07), rgba(0,0,0,.07)); - - position: relative; - margin: 0 .8rem .8rem 0; - vertical-align: middle; - white-space: nowrap; - display: inline-block; - zoom: 1; - border: none transparent; - font: var(--h4) var(--btn-font); - border-radius: var(--border-r); - color: currentColor; - cursor: pointer; -} - -/* default */ -.btn { - line-height: var(--btn-h); - height: var(--btn-h); - padding: 0 1.6rem; - transition: all .1s; -} - -.btn:hover { - transform: scale(.98); - mix-blend-mode: multiply; - background-image: var(--btn-hover); -} - -/* optional */ -.btn[outline] { - line-height: var(--btn-calc-h); - height: var(--btn-calc-h); - border: var(--btn-outline) solid currentColor; - background-color: white; - color: currentColor; -} - -/* links ------------------------------------- */ -a { - position: relative; - padding: 0 0 1px 0; - border-bottom: 1px solid currentColor; - user-select: none; - color: var(--prime); - transition: color .2s, border .2s, padding .2s; -} - -a:hover { - color: var(--flash); -} - -a:hover { - padding: 0; - border-bottom: 2px solid currentColor; -} - -a.no-underline { - border-bottom: none; - padding: 0; -} - -/* a:hover:not(.disabled) > .icon { stroke: var(--flash) } */ - -/* lists ---------------------------------- */ -.listify ol, -.listify ul { - --list-padding: 2.9rem; - - list-style: none; - color: currentColor; - margin-left: var(--list-padding); -} - -.listify ol > li, -.listify ul > li { - max-width: calc(var(--linemax) - var(--list-padding)); - line-height: 1.5; - margin: 0 0 0.4rem 0; -} - -.listify ul > li:before { - content: ''; - position: absolute; - margin-top: 1.1rem; - margin-left: -1.8rem; - background-color: var(--second); - width: .6rem; - height: .6rem; - border-radius: 2px; - opacity: 0.7; -} - -.listify ol { list-style: decimal } - -/* tables --------------------------------- */ -table { - width: 100%; - font-size: var(--h5); -} - -td, th { - text-align: left; - border-bottom: 1px solid #eee; - padding: 0.4rem 0.8rem 0.4rem 0; -} - -table code, table span { - white-space: pre; -} - -/* grid ----------------------------------- */ -.grid, .grid.half { - display: grid; - grid-gap: 2.4rem; - grid-template-columns: 1fr; - align-items: center; -} - -.grid.stretch { align-items: stretch } - -.grid > .cols-2, -.grid > .cols-3 { grid-column: span 1 } - -@media screen and (min-width: 840px) { - .grid.half, - .grid { grid-template-columns: repeat(2, 1fr) } - .grid > .cols-2, - .grid > .cols-3 { grid-column: span 2 } -} - -@media screen and (min-width: 1100px) { - .grid { grid-template-columns: repeat(3, 1fr) } - .grid > .cols-2 { grid-column: span 2 } - .grid > .cols-3 { grid-column: span 3 } -} - -/* helper styles -------------------------- */ -.flex-auto { flex: 1 0 auto } - -.py0 { - padding-top: 0 !important; - padding-bottom: 0 !important; -} - -.legend, figcaption, .post aside { - max-width: none; - margin: 0 auto; - padding: 1.6rem 0 0 .8rem; - font: 1.2rem/1.6 var(--font-ui); -} - -.filename { - display: inline-block; - padding: 1.6rem 0 0 1rem; - font: var(--h6) var(--font-ui); -} - -.box { - padding: 2.4rem 3.2rem; - border-radius: var(--border-r); -} - -/* theme colors --------------------------- */ -.prime { color: var(--prime) !important } -.second { color: var(--second) !important } -.flash { color: var(--flash) !important } -.black { color: black !important } -.white { color: white !important } - -.back { background-color: var(--back) !important } -.back-light { background-color: var(--back-light) !important } -.bg-prime { background-color: var(--prime) !important } -.bg-second { background-color: var(--second) !important } -.bg-flash { background-color: var(--flash) !important } - -/* inputs --------------------------------- */ -input[type="checkbox"] { - /* display: block; */ +.offset-anchor { position: relative; - height: 1em; - width: calc(100% - 0.6em); - max-width: 2em; - top: -2px; - border-radius: 0.5em; - -webkit-appearance: none; - outline: none; - margin: 0 0.6em 0 0; -} - -input[type="checkbox"]::before { - content: ""; - position: absolute; display: block; - height: 100%; - width: 100%; - padding: 2px; - border-radius: 1em; - top: 0; - left: 0; - background: var(--second); - /* box-sizing: border-box; */ - box-sizing: content-box; + top: calc(-1 * (var(--nav-h) + var(--top-offset)) + 11rem); + width: 0; + height: 0; } -input[type="checkbox"]:checked::before { - background: var(--prime); -} - -input[type="checkbox"]::after { - content: ""; +.anchor { position: absolute; display: block; + background: url(/icons/link.svg) 0 50% no-repeat; + background-size: 1em 1em; + width: 1.4em; height: 1em; - width: 1em; - top: 2px; - left: 2px; - border-radius: 1em; - background: white; - box-shadow: 0 0px 1px rgba(0,0,0,.4), 0 4px 2px rgba(0,0,0,.1); - -webkit-transition: background .2s ease-out, left .2s ease-out; -} - -input[type="checkbox"]:checked::after { - left: calc(100% - 9px); + top: calc(((var(--h3) - 24px) / 2) + 0.6em); + left: -1.4em; + opacity: 0; + transition: opacity 0.2s; + border: none !important; /* TODO get rid of linkify */ +} + +h2:hover .anchor, +h3:hover .anchor, +h4:hover .anchor, +h5:hover .anchor, +h6:hover .anchor { + opacity: 1; }