Merge branch 'master' into announcement

pull/2451/head
Richard Harris 5 years ago
commit 190d86701c

@ -1,151 +1,16 @@
# Svelte
<p align="center">
<a href="https://svelte.dev">
<img alt="Cybernetically enhanced web apps: Svelte" src="banner.png">
</a>
</p>
The magical disappearing UI framework.
* [Read the introductory blog post](https://svelte.technology/blog/frameworks-without-the-framework)
* [Read the guide](https://svelte.technology/guide)
* [Try it out](https://svelte.technology/repl)
* [Chat on Discord](https://discord.gg/yy75DKs)
## What is Svelte?
---
Svelte is a new way to build web applications. It's a compiler that takes your declarative components and converts them into efficient JavaScript that surgically updates the DOM.
## Tooling
Learn more at the [Svelte website](https://svelte.dev), or stop by the [Discord chatroom](https://discord.gg/yy75DKs).
This is the Svelte compiler, which is primarily intended for authors of tooling that integrates Svelte with different build systems. If you just want to write Svelte components and use them in your app, you probably want one of those tools:
### Build Systems
* [gulp-svelte](https://github.com/shinnn/gulp-svelte) - gulp plugin
* [metalsmith-svelte](https://github.com/shinnn/metalsmith-svelte) - Metalsmith plugin
* [system-svelte](https://github.com/CanopyTax/system-svelte)  System.js loader
* [svelte-loader](https://github.com/sveltejs/svelte-loader) Webpack loader
* [meteor-svelte](https://github.com/klaussner/meteor-svelte) Meteor build plugin
* [sveltejs-brunch](https://github.com/StarpTech/sveltejs-brunch) Brunch build plugin
* [rollup-plugin-svelte](https://github.com/rollup/rollup-plugin-svelte) Rollup plugin
* [parcel-plugin-svelte](https://github.com/DeMoorJasper/parcel-plugin-svelte) - Parcel build plugin
* [sveltify](https://github.com/tehshrike/sveltify) - Browserify transform
* [rules_svelte](https://github.com/thelgevold/rules_svelte) - Bazel Rules
### CSS Preprocessors
* [Less](https://github.com/ls-age/svelte-preprocess-less)
* [modular-css](https://github.com/tivac/modular-css/tree/master/packages/svelte)
* [PostCSS](https://github.com/TehShrike/svelte-preprocess-postcss)
* [Sass](https://github.com/ls-age/svelte-preprocess-sass)
### Additional tools
* [svelte-dev-store](https://github.com/GarethOates/svelte-dev-store) - Use Redux tools to visualise Svelte store
* More to come!
## Example usage
```js
import * as svelte from 'svelte';
const { js, css, ast } = svelte.compile(source, {
// the target module format defaults to 'es' (ES2015 modules), can
// also be 'amd', 'cjs', 'umd', 'iife' or 'eval'
format: 'umd',
// the filename of the source file, used in e.g. generating sourcemaps
filename: 'MyComponent.html',
// the name of the constructor. Required for 'iife' and 'umd' output,
// but otherwise mostly useful for debugging. Defaults to 'SvelteComponent'
name: 'MyComponent',
// for 'amd' and 'umd' output, you can optionally specify an AMD module ID
amd: {
id: 'my-component'
},
// custom error/warning handlers. By default, errors will throw, and
// warnings will be printed to the console. Where applicable, the
// error/warning object will have `pos`, `loc` and `frame` properties
onerror: err => {
console.error( err.message );
},
onwarn: warning => {
console.warn( warning.message );
}
});
```
## API
The Svelte compiler exposes the following API:
* `compile(source [, options]) => { js, css, ast }` - Compile the component with the given options (see below). Returns an object containing the compiled JavaScript, a sourcemap, an AST and transformed CSS.
* `create(source [, options]) => function` - Compile the component and return the component itself.
* `preprocess(source, options) => Promise` — Preprocess a source file, e.g. to use PostCSS or CoffeeScript
* `VERSION` - The version of this copy of the Svelte compiler as a string, `'x.x.x'`.
### Compiler options
The Svelte compiler optionally takes a second argument, an object of configuration options:
| | **Values** | **Description** | **Default** |
|---|---|---|---|
| `generate` | `'dom'`, `'ssr'`, `false` | Whether to generate JavaScript code intended for use on the client (`'dom'`), or for use in server-side rendering (`'ssr'`). If `false`, component will be parsed and validated but no code will be emitted | `'dom'` |
| `dev` | `true`, `false` | Whether to enable run-time checks in the compiled component. These are helpful during development, but slow your component down. | `false` |
| `css` | `true`, `false` | Whether to include code to inject your component's styles into the DOM. | `true` |
| `hydratable` | `true`, `false` | Whether to support hydration on the compiled component. | `false` |
| `customElement` | `true`, `false`, `{ tag, props }` | Whether to compile this component to a custom element. If `tag`/`props` are passed, compiles to a custom element and overrides the values exported by the component. | `false` |
| `bind` | `boolean` | If `false`, disallows `bind:` directives | `true` |
| | | |
| `shared` | `true`, `false`, `string` | Whether to import various helpers from a shared external library. When you have a project with multiple components, this reduces the overall size of your JavaScript bundle, at the expense of having immediately-usable component. You can pass a string of the module path to use, or `true` will import from `'svelte/shared.js'`. | `false` |
| `legacy` | `true`, `false` | Ensures compatibility with very old browsers, at the cost of some extra code. | `false` |
| | | |
| `format` | `'es'`, `'amd'`, `'cjs'`, `'umd'`, `'iife'`, `'eval'` | The format to output in the compiled component.<br>`'es'` - ES6/ES2015 module, suitable for consumption by a bundler<br>`'amd'` - AMD module<br>`'cjs'` - CommonJS module<br>`'umd'` - UMD module<br>`'iife'` - IIFE-wrapped function defining a global variable, suitable for use directly in browser<br>`'eval'` - standalone function, suitable for passing to `eval()` | `'es'` for `generate: 'dom'`<br>`'cjs'` for `generate: 'ssr'` |
| `name` | `string` | The name of the constructor in the compiled component. | `'SvelteComponent'` |
| `filename` | `string` | The filename to use in sourcemaps and compiler error and warning messages. | `'SvelteComponent.html'` |
| `amd`.`id` | `string` | The AMD module ID to use for the `'amd'` and `'umd'` output formats. | `undefined` |
| `globals` | `object`, `function` | When outputting to the `'umd'`, `'iife'` or `'eval'` formats, an object or function mapping the names of imported dependencies to the names of global variables. | `{}` |
| `preserveComments` | `boolean` | Include comments in rendering. Currently, only applies to SSR rendering | `false` |
| | | |
| `onwarn` | `function` | Specify a callback for when Svelte encounters a non-fatal warning while compiling the component. Passed two arguments: the warning object, and another function that is Svelte's default onwarn handling. | (warning is logged to console) |
### Preprocessor options
`svelte.preprocess` returns a Promise that resolves to an object with a `toString` method (other properties will be added in future). It takes an options object with `markup`, `style` or `script` properties:
```js
const processed = await svelte.preprocess(source, {
markup: ({ content }) => {
// `content` is the entire component string
return { code: '...', map: {...} };
},
style: ({ content, attributes }) => {
// `content` is what's inside the <style> element, if present
// `attributes` is a map of attributes on the element
if (attributes.type !== 'text/scss') return;
return { code: '...', map: {...} };
},
script: ({ content, attributes }) => {
// `content` is what's inside the <script> element, if present
// `attributes` is a map of attributes on the element
if (attributes.type !== 'text/coffeescript') return;
return { code: '...', map: {...} };
}
});
```
The `style` and `script` preprocessors will run *after* the `markup` preprocessor. Each preprocessor can return a) nothing (in which case no transformation takes place), b) a `{ code, map }` object, or c) a Promise that resolves to a) or b). Note that sourcemaps are currently discarded, but will be used in future versions of Svelte.
## Example/starter repos
* [sveltejs/template](https://github.com/sveltejs/template) — the 'official' starter template
* [sveltejs/template-webpack](https://github.com/sveltejs/template-webpack) — using webpack for bundling
* [charpeni/svelte-example](https://github.com/charpeni/svelte-example) - Some Svelte examples with configured Rollup, Babel, ESLint, directives, Two-Way binding, and nested components
* [EmilTholin/svelte-test](https://github.com/EmilTholin/svelte-test)
* [lukechinworth/codenames](https://github.com/lukechinworth/codenames/tree/svelte)  example integration with Redux
* [khtdr/svelte-redux-shopping-cart](https://github.com/khtdr/svelte-redux-shopping-cart) Redux Shopping Cart example (with devtools and hot-reloading)
* [svelte-bazel-example](https://github.com/thelgevold/svelte-bazel-example) — Building Svelte with Bazel
## Development
@ -157,43 +22,46 @@ To install and work on Svelte locally:
git clone git@github.com:sveltejs/svelte.git
cd svelte
npm install
npm run dev
```
The compiler is written in [TypeScript](https://www.typescriptlang.org/), but don't let that put you off — it's basically just JavaScript with type annotations. You'll pick it up in no time. If you're using an editor other than [VSCode](https://code.visualstudio.com/) you may need to install a plugin in order to get syntax highlighting and code hints etc.
### Linking to a Live Project
To build the compiler, and all the other modules included in the package:
You can make changes locally to Svelte and test it against any Svelte project. You can also use a [default template](https://github.com/sveltejs/template) for development. Instruction on setup are found in that project repository.
```bash
npm run build
```
From your project:
To watch for changes and continually rebuild the package (this is useful if you're using [npm link](https://docs.npmjs.com/cli/link.html) to test out changes in a project locally):
```bash
cd ~/path/to/your-svelte-project
npm install ~/path/to/svelte
npm run dev
```
And you should be good to test changes locally.
The compiler is written in [TypeScript](https://www.typescriptlang.org/), but don't let that put you off — it's basically just JavaScript with type annotations. You'll pick it up in no time. If you're using an editor other than [VSCode](https://code.visualstudio.com/) you may need to install a plugin in order to get syntax highlighting and code hints etc.
To undo this and link to the official latest Svelte release, just run:
### Running Tests
```bash
npm install svelte@latest
npm run test
```
### Running Tests
To filter tests, use `-g` (aka `--grep`). For example, to only run tests involving transitions:
```bash
npm run test
npm run test -- -g transition
```
For running single tests, you can use pattern matching:
## svelte.dev
The source code for https://svelte.dev, including all the documentation, lives in the [site](site) directory. The site is built with [Sapper](https://sapper.svelte.technology) To develop locally:
```bash
npm run test -- -g "includes AST in svelte.compile output"
cd site
npm install
npm run dev
```
Alternately, you can add `solo: true` to any given `test/../_config.js` file, but **remember never to commit that setting.**
## License

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

@ -1,7 +1,6 @@
---
title: Frameworks without the framework: why didn't we think of this sooner?
description: You can't write serious applications in vanilla JavaScript without hitting a complexity wall. But a compiler can do it for you.
pubdate: 2016-11-26
author: Rich Harris
authorURL: https://twitter.com/Rich_Harris
---

@ -1,7 +1,6 @@
---
title: The easiest way to get started with Svelte
description: This'll only take a minute.
pubdate: 2017-08-07
author: Rich Harris
authorURL: https://twitter.com/Rich_Harris
---

@ -1,7 +1,6 @@
---
title: The zen of Just Writing CSS
description: I would say this is the future, but we're already doing it.
pubdate: 2017-09-06
author: Rich Harris
authorURL: https://twitter.com/Rich_Harris
---

@ -1,7 +1,6 @@
---
title: Sapper: Towards the ideal web app framework
description: Taking the next-plus-one step
pubdate: 2017-12-31
author: Rich Harris
authorURL: https://twitter.com/Rich_Harris
---

@ -1,7 +1,6 @@
---
title: Svelte v2 is out!
description: Here's what you need to know
pubdate: 2018-04-18
author: Rich Harris
authorURL: https://twitter.com/Rich_Harris
---

@ -1,7 +1,6 @@
---
title: Using CSS-in-JS with Svelte
description: You don't need to, but you can
pubdate: 2018-12-26
author: Rich Harris
authorURL: https://twitter.com/Rich_Harris
---
@ -17,11 +16,13 @@ But Svelte's style handling does have some limitations. It's too difficult to sh
Here, we're using [Emotion](https://emotion.sh) to generate scoped class names that can be used across multiple components:
<iframe
title="Aphrodite example"
src="/repl/embed?gist=ad495ff5ba9ceefe5984fe62c1f15e19"
scrolling="no"
></iframe>
<div class="max">
<iframe
title="Aphrodite example"
src="/repl/embed?gist=ad495ff5ba9ceefe5984fe62c1f15e19"
scrolling="no"
></iframe>
</div>
It's important to note that most CSS-in-JS libraries have a runtime library, and many don't support statically extracting styles out into a separate <code>.css</code> file at build time (which is essential for the best performance). You should therefore only use CSS-in-JS if it's necessary for your application!

@ -1,7 +1,6 @@
---
title: Virtual DOM is pure overhead
description: Let's retire the 'virtual DOM is fast' myth once and for all
pubdate: 2018-12-27
author: Rich Harris
authorURL: https://twitter.com/Rich_Harris
---

@ -1,7 +1,6 @@
---
title: Svelte on The Changelog
description: Listen to the interview here
pubdate: 2019-01-31
author: Rich Harris
authorURL: https://twitter.com/Rich_Harris
---

@ -0,0 +1,13 @@
---
title: Setting up your editor
description: Instructions for configuring linting and syntax highlighting
author: Rich Harris
authorURL: https://twitter.com/Rich_Harris
draft: true
---
*Coming soon* This post will walk you through setting up your editor so that recognises Svelte files:
* eslint-plugin-svelte3
* svelte-vscode
* associating .svelte files with HTML in VSCode, Sublime, Atom, etc etc etc

@ -0,0 +1,9 @@
---
title: Svelte for new developers
description: Never used Node.js or the command line? No problem
author: Rich Harris
authorURL: https://twitter.com/Rich_Harris
draft: true
---
*Coming soon* This blog post will walk you through installing Node.js and git and using Terminal.app to clone a project template and start developing with Svelte

@ -0,0 +1,164 @@
---
title: Write less code
description: The most important metric you're not paying attention to
author: Rich Harris
authorURL: https://twitter.com/Rich_Harris
---
All code is buggy. It stands to reason, therefore, that the more code you have to write the buggier your apps will be.
Writing more code also takes more time, leaving less time for other things like optimisation, nice-to-have features, or being outdoors instead of hunched over a laptop.
In fact it's widely acknowledged that [project development time](https://blog.codinghorror.com/diseconomies-of-scale-and-lines-of-code/) and [bug count](https://www.mayerdan.com/ruby/2012/11/11/bugs-per-line-of-code-ratio) grow *quadratically*, not linearly, with the size of a codebase. That tracks with our intuitions: a ten-line pull request will get a level of scrutiny rarely applied to a 100-line one. And once a given module becomes too big to fit on a single screen, the cognitive effort required to understand it increases significantly. We compensate by refactoring and adding comments — activities that almost always result in *more* code. It's a vicious cycle.
Yet while we obsess — rightly! — over performance numbers, bundle size and anything else we can measure, we rarely pay attention to the amount of code we're writing.
## Readability is important
I'm certainly not claiming that we should use clever tricks to scrunch our code into the most compact form possible at the expense of readability. Nor am I claiming that reducing *lines* of code is necessarily a worthwhile goal, since it encourages turning readable code like this...
```js
for (let i = 0; i <= 100; i += 1) {
if (i % 2 === 0) {
console.log(`${i} is even`);
}
}
```
...into something much harder to parse:
```js
for (let i = 0; i <= 100; i += 1) if (i % 2 === 0) console.log(`${i} is even`);
```
Instead, I'm claiming that we should favour languages and patterns that allow us to naturally write less code.
## Yes, I'm talking about Svelte
Reducing the amount of code you have to write is an explicit goal of Svelte. To illustrate, let's look at a very simple component implemented in React, Vue and Svelte. First, the Svelte version:
<div class="max">
<iframe
title="Simple component example"
src="/repl/embed?gist=6b573f1819d12defc441098236fb9abe"
scrolling="no"
></iframe>
</div>
How would we build this in React? It would probably look something like this:
```js
import React, { useState } from 'react';
export default () => {
const [a, setA] = useState(1);
const [b, setB] = useState(2);
function handleChangeA(event) {
setA(+event.target.value);
}
function handleChangeB(event) {
setB(+event.target.value);
}
return (
<div>
<input type="number" value={a} onChange={handleChangeA}/>
<input type="number" value={b} onChange={handleChangeB}/>
<p>{a} + {b} = {a + b}</p>
</div>
);
};
```
Here's an equivalent component in Vue:
```html
<template>
<div>
<input type="number" v-model.number="a">
<input type="number" v-model.number="b">
<p>{{a}} + {{b}} = {{a + b}}</p>
</div>
</template>
<script>
export default {
data: function() {
return {
a: 1,
b: 2
};
}
};
</script>
```
<aside>
<p>I'm counting by copying the source code to the clipboard and running `pbpaste | wc -c` in my terminal</p>
</aside>
In other words, it takes 442 characters in React, and 263 characters in Vue, to achieve something that takes 145 characters in Svelte. The React version is literally three times larger!
It's unusual for the difference to be *quite* so obvious — in my experience, a React component is typically around 40% larger than its Svelte equivalent. Let's look at the features of Svelte's design that enable you to express ideas more concisely:
### Top-level elements
In Svelte, a component can have as many top-level elements as you like. In React and Vue, a component must have a single top-level element — in React's case, trying to return two top-level elements from a component function would result in syntactically invalid code. (You can use a fragment — `<>` instead of a `<div>`, but it's the same basic idea, and still results in an extra level of indentation).
In Vue, your markup must be wrapped in a `<template>` element, which I'd argue is redundant.
### Bindings
In React, we have to respond to input events ourselves:
```js
function handleChangeA(event) {
setA(+event.target.value);
}
```
This isn't just boring plumbing that takes up extra space on the screen, it's also extra surface area for bugs. Conceptually, the value of the input is bound to the value of `a` and vice versa, but that relationship isn't cleanly expressed — instead we have two tightly-coupled but physically separate chunks of code (the event handler and the `value={a}` prop). Not only that, but we have to remember to coerce the string value with the `+` operator, otherwise `2 + 2` will equal `22` instead of `4`.
Like Svelte, Vue does have a way of expressing the binding — the `v-model` attribute, though again we have to be careful to use `v-model.number` even though it's a numeric input.
### State
In Svelte, you update local component state with an assignment operator:
```js
let count = 0;
function increment() {
count += 1;
}
```
In React, we use the `useState` hook:
```js
const [count, setCount] = useState(0);
function increment() {
setCount(count + 1);
}
```
This is much *noisier* — it expresses the exact same concept but with over 60% more characters. As you're reading the code, you have to do that much more work to understand the author's intent.
In Vue, meanwhile, we have a default export with a `data` function that returns an object literal with properties corresponding to our local state. Things like helper functions and child components can't simply be imported and used in the template, but must instead be 'registered' by attaching them to the correct part of the default export.
## Death to boilerplate
These are just some of the ways that Svelte helps you build user interfaces with a minimum of fuss. There are plenty of others — for example, [reactive declarations](https://svelte.dev/tutorial/reactive-declarations) essentially do the work of React's `useMemo`, `useCallback` and `useEffect` without the boilerplate (or indeed the garbage collection overhead of creating inline functions and arrays on each state change).
How? By choosing a different set of constraints. Because [Svelte is a compiler](blog/frameworks-without-the-framework), we're not bound to the peculiarities of JavaScript: we can *design* a component authoring experience, rather than having to fit it around the semantics of the language. Paradoxically, this results in *more* idiomatic code — for example using variables naturally rather than via proxies or hooks — while delivering significantly more performant apps.

@ -17,7 +17,7 @@ But there's a more *idiomatic* solution:
```js
function addNumber() {
numbers = [...numbers, numbers.length + 1;]
numbers = [...numbers, numbers.length + 1];
}
```

@ -15,17 +15,9 @@
border-top: 1px solid var(--second);
}
input {
display: block;
}
span {
color: #ccc;
}
.active {
color: #555;
}
input { display: block }
span { color: #ccc }
.active { color: #555 }
</style>
<label class="input-output-toggle">

@ -1,13 +1,18 @@
<script>
import { onMount } from 'svelte';
import Icon from './Icon.svelte';
import Logo from './Logo.svelte';
import { page } from '@sapper/app';
export let segment;
let open = false;
let visible = true;
// hide nav whenever we navigate
page.subscribe(() => {
open = false;
});
// TODO remove this post-https://github.com/sveltejs/svelte/issues/1914
let ul;
onMount(() => {
@ -78,17 +83,6 @@
box-shadow: none;
}
h2 {
display: block;
text-transform: uppercase;
font-weight: 300;
font-size: 2.8rem;
letter-spacing: .12em;
line-height: 1;
margin: 0;
top: .1rem;
}
.primary {
list-style: none;
font-family: var(--font);
@ -107,7 +101,7 @@
ul {
position: relative;
padding: 0 2em 0 0;
padding: 0 3rem 0 0;
background: url(/icons/chevron.svg) calc(100% - 1em) 0.05em no-repeat;
background-size: 1em 1em;
}
@ -123,7 +117,7 @@
}
ul.open {
padding: 0 2em 1em 2em;
padding: 0 0 1em 0;
background: white;
border-left: 1px solid #eee;
border-right: 1px solid #eee;
@ -142,15 +136,19 @@
}
ul li a {
font-size: var(--h6);
font-size: var(--h5);
padding: 0 .8rem;
}
ul.open li a {
padding: 2.3rem .7rem 0 .8rem;
padding: 1.5rem 3.7rem 1.5rem 4rem;
display: block;
}
ul.open li:first-child a {
padding-top: 2.3rem;
}
.primary :global(svg) {
width: 2rem;
height: 2rem;
@ -158,21 +156,29 @@
.home {
position: relative;
top: 0;
top: -.1rem;
width: 18rem;
color: var(--second);
height: 4.2rem;
-webkit-tap-highlight-color: transparent;
-webkit-touch-callout: none;
z-index: 11;
padding: 0.5rem 0 0.3rem 4.2rem;
background: url(/logo.svg) 0 50% no-repeat;
background: url(/svelte-logo-horizontal.svg) 0 50% no-repeat;
background-size: auto 100%;
/* z-index: 11; */
}
.active {
color: var(--prime)
}
.modal-background {
position: fixed;
width: 100%;
height: 100%;
left: 0;
top: 0;
background-color: rgba(255, 255, 255, 0.9);
}
@media (min-width: 840px) {
ul {
padding: 0;
@ -192,7 +198,7 @@
}
ul.open li a {
font-size: var(--h6);
font-size: var(--h5);
padding: 0 .8rem;
display: inline;
}
@ -211,13 +217,15 @@
}
</style>
<svelte:window on:click="{() => open = false}" on:scroll={handle_scroll}/>
<svelte:window on:scroll={handle_scroll}/>
<header class:visible="{visible || open}">
<nav>
<a rel="prefetch" href='.' class="home" title='Homepage'>
<h2>Svelte</h2>
</a>
<a rel="prefetch" href='.' class="home" title='Homepage'></a>
{#if open}
<div class="modal-background hide-if-desktop" on:click="{() => open = false}"></div>
{/if}
<ul
bind:this={ul}
@ -247,4 +255,4 @@
</li>
</ul>
</nav>
</header>
</header>

@ -32,21 +32,19 @@
font-size: var(--h5);
}
.box a {
.learn-more {
position: relative;
text-align: right;
margin-top: auto;
padding: 0 1.2em 0 0;
font-family: Roboto, sans-serif;
font-size: 1.6rem;
}
.box a:hover {
.box:hover .learn-more {
color: white;
text-decoration: underline;
}
.box a::after, .cta a::after {
.learn-more::after, .cta a::after {
content: '';
position: absolute;
display: block;
@ -121,26 +119,26 @@
</style>
<section class='container'>
<div class='box bg-prime white' style="grid-area: one">
<h2 style='padding:2.4rem 0 0 0'>Write less code</h2>
<a href="blog/write-less-code" class='box bg-prime white' style="grid-area: one">
<h2>Write less code</h2>
<p>Build boilerplate-free components using languages you already know — HTML, CSS and JavaScript</p>
<a href="TODO-blog-post-on-loc">learn more</a>
</div>
<a class="learn-more">learn more</a>
</a>
<div class='box bg-flash white' style="grid-area: two">
<h2 style='padding:2.4rem 0 0 0'>No virtual DOM</h2>
<a href="blog/virtual-dom-is-pure-overhead" class='box bg-flash white' style="grid-area: two">
<h2>No virtual DOM</h2>
<p>Svelte compiles your code to tiny, framework-less vanilla JS — your app starts fast and stays fast</p>
<a href="TODO-blog-post-on-vdom-overhead">learn more</a>
</div>
<a class="learn-more">learn more</a>
</a>
<div class='box bg-second white' style="grid-area: three">
<h2 style='padding:2.4rem 0 0 0'>Truly reactive</h2>
<a href="TODO-blog-post-on-reactivity" class='box bg-second white' style="grid-area: three">
<h2>Truly reactive</h2>
<p>No more complex state management libraries — Svelte brings reactivity to JavaScript itself</p>
<a href="TODO-blog-post-on-reactivity">learn more</a>
</div>
<a class="learn-more">learn more</a>
</a>
<div class="linkify description" style="grid-area: what;">
<p>Svelte is a radical new approach to building user interfaces. Whereas traditional frameworks like React and Vue do the bulk of their work in the <em>browser</em>, Svelte shifts that work into a <em>compile step</em> that happens when you build your app.</p>
@ -150,8 +148,8 @@
<p><a href="TODO-svelte-3-blog-post">Read the introductory blog post</a> to learn more.</p>
</div>
<div style="grid-area: start; display: flex; flex-direction: column">
<pre class="language-bash" style="margin: 0 0 1em 0">
<div style="grid-area: start; display: flex; flex-direction: column; min-width: 0">
<pre class="language-bash" style="margin: 0 0 1em 0; min-width: 0; min-height: 0">
npx degit sveltejs/template my-svelte-project
cd my-svelte-project

@ -19,7 +19,7 @@
height: 40px;
margin: 0 0.5em 0.5em 0;
text-decoration: none;
border: 1px solid #aaa;
border: 2px solid var(--second);
padding: 5px 10px;
border-radius: 20px;
}
@ -27,7 +27,7 @@
.add-yourself {
display: flex;
align-items: center;
border: 1px solid #eee;
border: 2px solid var(--second);
}
img {
@ -55,4 +55,4 @@
<a href="https://nytimes.com"><img src="organisations/nyt.svg" alt="The New York Times logo"></a>
<a href="https://www.stone.co"><img src="organisations/stone.svg" alt="Stone Payments logo"></a>
<a href="https://github.com/sveltejs/svelte/blob/master/site/src/routes/_components/WhosUsingSvelte.svelte" class="add-yourself"><span>+ your company?</span></a>
</div>
</div>

@ -17,9 +17,7 @@
{/if}
<style>
h1, p {
margin: 0 auto;
}
h1, p { margin: 0 auto }
h1 {
font-size: 2.8em;
@ -27,13 +25,9 @@
margin: 0 0 0.5em 0;
}
p {
margin: 1em auto;
}
p { margin: 1em auto }
@media (min-width: 480px) {
h1 {
font-size: 4em;
}
h1 { font-size: 4em }
}
</style>

@ -16,5 +16,8 @@ export function get(req, res) {
'Cache-Control': `max-age=${5 * 60 * 1e3}` // 5 minutes
});
res.end(lookup.get(req.params.slug));
} else {
res.statusCode = 404;
res.end(JSON.stringify({ message: 'not found' }));
}
}

@ -1,7 +1,7 @@
<script context="module">
export async function preload({ params }) {
const post = await this.fetch(`blog/${params.slug}.json`).then(r => r.json());
return { post };
const res = await this.fetch(`blog/${params.slug}.json`);
return res.ok ? { post: await res.json() } : this.error(404, 'Not found');
}
</script>
@ -24,33 +24,41 @@
<style>
.post {
padding: var(--top-offset) var(--side-nav) 0 var(--side-nav);
padding: var(--top-offset) var(--side-nav) 6rem var(--side-nav);
max-width: var(--main-width);
margin: 0 auto;
}
.byline {
font-size: 0.8em;
border-bottom: 1px solid #eee;
padding: 0;
margin: 0 0 4rem 0;
padding: 0 0 1.6rem 0;
border-bottom: var(--border-w) solid #6767785b;
font-size: var(--h6);
}
.byline a {
border-bottom: none;
font-weight: 600;
}
.byline a:hover {
border-bottom: 2px solid var(--prime);
}
.post h1 {
color: var(--second);
max-width: 20em;
margin: 0 0 1.2rem 0;
margin: 0 0 .8rem 0;
}
.post :global(h2) {
margin: 2em 0 0.5em 0;
color: var(--second);
/* color: var(--second); */
color: var(--text);
font-size: var(--h3);
font-weight: 300;
}
/* .post p,
.post :global(p) {
max-width: var(--linemax)
} */
.post :global(figure) {
margin: 1.6rem 0 3.2rem 0;
}
@ -78,7 +86,7 @@
padding: .3rem .8rem .3rem;
margin: 0 0.2rem;
top: -.1rem;
background: #f4f4f4;
background: var(--back-api);
}
.post :global(pre) :global(code) {
@ -102,6 +110,10 @@
z-index: 2;
}
.post :global(.max) {
width: 100%;
}
.post :global(iframe) {
width: 100%;
height: 420px;
@ -111,13 +123,20 @@
}
@media (min-width: 910px) {
.post :global(iframe) {
.post :global(.max) {
width: calc(100vw - 2 * var(--side-nav));
margin: 2em calc(400px + var(--side-nav) - 50vw);
margin: 0 calc(var(--main-width) / 2 - 50vw);
text-align: center;
}
.post :global(iframe) {
width: 100%;
max-width: 1100px;
margin: 2em auto;
}
}
@media (min-width: 1460px) {
/* @media (min-width: 1460px) {
.post :global(iframe) {
width: 1360px;
margin: 2em -280px;
@ -128,5 +147,5 @@
.post :global(iframe) {
height: 640px;
}
}
} */
</style>

@ -5,17 +5,23 @@ import marked from 'marked';
import PrismJS from 'prismjs';
import 'prismjs/components/prism-bash';
export default function() {
export default function get_posts() {
return fs
.readdirSync('content/blog')
.map(file => {
if (path.extname(file) !== '.md') return;
const match = /^(\d+-\d+-\d+)-(.+)\.md$/.exec(file);
if (!match) throw new Error(`Invalid filename '${file}'`);
const [, pubdate, slug] = match;
const markdown = fs.readFileSync(`content/blog/${file}`, 'utf-8');
const { content, metadata } = extract_frontmatter(markdown);
const date = new Date(`${metadata.pubdate} EDT`); // cheeky hack
const date = new Date(`${pubdate} EDT`); // cheeky hack
metadata.pubdate = pubdate;
metadata.dateString = date.toDateString();
const renderer = new marked.Renderer();
@ -41,7 +47,7 @@ export default function() {
return {
html,
metadata,
slug: file.replace(/^[\d-]+/, '').replace(/\.md$/, ''),
slug
};
})
.sort((a, b) => a.metadata.pubdate < b.metadata.pubdate ? 1 : -1);

@ -4,12 +4,16 @@ let json;
export function get(req, res) {
if (!json || process.env.NODE_ENV !== 'production') {
json = JSON.stringify(get_posts().map(post => {
return {
slug: post.slug,
metadata: post.metadata
};
}));
const posts = get_posts()
.filter(post => !post.metadata.draft)
.map(post => {
return {
slug: post.slug,
metadata: post.metadata
};
});
json = JSON.stringify(posts);
}
res.set({

@ -30,40 +30,44 @@
grid-template-columns: 1fr 1fr;
grid-gap: 1em;
min-height: calc(100vh - var(--nav-h));
padding: var(--top-offset) var(--side-nav) 0 var(--side-nav);
padding: var(--top-offset) var(--side-nav) 6rem var(--side-nav);
max-width: var(--main-width);
margin: 0 auto;
}
h2 {
display: inline-block;
margin: 2rem 0 0.5rem 0;
color: var(--second);
/* max-width: 18em; */
font-size: 2rem;
margin: 3.2rem 0 0.4rem 0;
color: var(--text);
max-width: 18em;
font-size: var(--h3);
font-weight: 300;
}
.post:first-child {
margin: 0 0 2em 0;
border-bottom: 1px solid #eee;
margin: 0 0 2rem 0;
padding: 0 0 4rem 0;
border-bottom: var(--border-w) solid #6767785b; /* based on --second */
}
.post:first-child h2 {
font-size: 4rem;
font-weight: 600;
color: var(--second);
}
.post:first-child::before {
.post:first-child::before,
.post:nth-child(2)::before {
content: 'Latest post • ' attr(data-pubdate);
font-weight: 400;
color: #aaa;
color: var(--flash);
font-size: var(--h6);
font-weight: 600;
letter-spacing: .05em;
text-transform: uppercase;
}
.post:nth-child(2)::before {
content: 'Older posts';
font-weight: 400;
color: #aaa;
text-transform: uppercase;
}
.post p {
@ -72,12 +76,10 @@
color: var(--second);
}
.post > a {
display: block;
}
.post > a { display: block }
.posts a:hover,
.posts a:hover > h2 {
color: var(--flash)
}
</style>
</style>

@ -7,38 +7,6 @@
export let show_contents;
export let prevent_sidebar_scroll = false;
onMount(() => {
// ------------------------------------------
// TODO smooth-scroll
// must be something that makes more sense
// this one is too annoying (area too tall)
// maybe svelte-transitions are a solution?
// unfortunately I have no idea how. For now.
// ------------------------------------------
// methods: {
// scrollTo(e, item) {
// e.preventDefault();
// let top = document.querySelector('#' + item).getBoundingClientRect().top;
// window.scrollTo({
// top,
// behavior: "smooth"
// });
// }
// },
const onhashchange = _ => {
// TODO wire this up
// this.store.set({active_section: window.location.hash.slice(1) });
};
window.addEventListener('hashchange', onhashchange, false);
onhashchange();
return () => {
window.removeEventListener('hashchange', onhashchange, false);
};
});
let ul;
afterUpdate(() => {
@ -75,22 +43,22 @@
.reference-toc li {
display: block;
line-height: 1.2;
margin: 0 0 4.8rem 0;
margin: 0 0 4rem 0;
}
a {
position: relative;
opacity: 0.7;
opacity: 0.75;
transition: opacity 0.2s;
}
.section {
display: block;
padding: 0 0 .8rem 0;
font: 400 var(--h6) var(--font);
font-size: var(--h6);
text-transform: uppercase;
letter-spacing: 0.12em;
font-weight: 700;
letter-spacing: 0.1em;
font-weight: 600;
}
.subsection {
@ -107,18 +75,15 @@
}
.subsection[data-level="4"] {
padding-left: 1em;
padding-left: 1.2rem;
}
.active {
opacity: 1;
/* font-weight: 700; */
}
.active { opacity: 1 }
.icon-container {
position: absolute;
top: -.3rem;
right: 3.2rem;
top: -.2rem;
right: 2.4rem;
}
</style>

@ -74,7 +74,6 @@
<style>
aside {
/* display: none; */
position: fixed;
background-color: white;
left: 0.8rem;
@ -84,7 +83,6 @@
overflow: hidden;
border: 1px solid #eee;
box-shadow: 1px 1px 6px rgba(0,0,0,0.1);
padding: 1.6rem;
transition: width 0.2s, height 0.2s;
}
@ -130,17 +128,16 @@
overflow-y: auto;
width: calc(100vw - 4.8rem);
height: calc(100vh - var(--nav-h) - 10.8rem);
padding: 2em 0;
padding: 2em 1.6rem 2em 3.2rem;
bottom: 2em;
}
.content {
width: 100%;
/* max-width: calc(var(--main-width) + var(--side-nav)); */
margin: 0;
-moz-tab-size: 2;
padding: var(--top-offset) var(--side-nav);
tab-size: 2;
-moz-tab-size: 2;
}
@media (min-width: 832px) { /* can't use vars in @media :( */
@ -174,7 +171,7 @@
}
.sidebar {
padding: var(--top-offset) 0;
padding: var(--top-offset) 0 6.4rem 3.2rem;
font-family: var(--font);
overflow-y: auto;
height: 100%;
@ -183,7 +180,6 @@
}
.content {
/* max-width: none; */
padding-left: calc(var(--sidebar-w) + var(--side-nav));
}
@ -194,23 +190,14 @@
}
}
@media (min-width: 1200px) { /* can't use vars in @media :( */
aside {
display: block;
}
.content {
/* box-sizing: content-box; */
/* padding-right: calc(50% - 50rem); */
}
}
.content h2 {
margin-top: 16rem;
padding: 2rem 1.6rem 5.6rem 0.2rem;
border-top: 2px solid var(--second);
color: var(--second);
margin-top: 8rem;
padding: 2rem 1.6rem 4rem 0.2rem;
border-top: var(--border-w) solid #6767785b; /* based on --second */
color: var(--text);
line-height: 1;
font-size: var(--h3);
letter-spacing: .05em;
text-transform: uppercase;
}
@ -260,18 +247,31 @@
.content :global(h3),
.content :global(h3 > code) {
font-weight: 700;
font-size: var(--h3);
color: var(--second);
margin: 6.4rem 0 1.6rem 0;
padding-left: 0;
margin: 6.4rem 0 0 0;
padding: 2rem 1.6rem 5.6rem .2rem;
color: var(--text);
border-top: var(--border-w) solid #6767781f; /* based on --second */
background: transparent;
line-height: 1;
}
.content :global(h3):first-of-type {
border: none;
margin: 0;
}
/* avoid doubled border-top */
.content :global(h3 > code) {
border-radius: 0 0 0 0;
border: none;
font-size: var(--h4);
line-height: 1.2;
}
.content :global(h4),
.content :global(h4 > code) {
font-weight: 700;
font-weight: 600;
font-size: var(--h4);
color: var(--second);
margin: 6.4rem 0 1.6rem 0;
@ -289,7 +289,7 @@
padding: .3rem .8rem .3rem;
margin: 0 0.2rem;
top: -.1rem;
background: #f4f4f4;
background: var(--back-api);
}
.content :global(pre) :global(code) {
@ -304,8 +304,8 @@
}
.content :global(.icon) {
width: 20px;
height: 20px;
width: 2rem;
height: 2rem;
stroke: currentColor;
stroke-width: 2;
stroke-linecap: round;
@ -317,22 +317,20 @@
margin: 0 0 2em 0;
}
section > :global(.code-block)> :global(pre) {
section > :global(.code-block) > :global(pre) {
display: inline-block;
background: transparent;
background: var(--back-api);
color: white;
padding: 0.4em 0.8em;
padding: .3rem .8rem;
margin: 0;
border: 1px solid #81b9e0;
box-shadow: none;
max-width: 100%;
}
section > :global(.code-block)> :global(pre.language-markup) {
background: #f7fcff;
padding: .3rem .8rem .2rem;
background: var(--back-api);
}
/* max line-length ~60 chars */
section > :global(p) {
max-width: var(--linemax)
}
@ -352,24 +350,12 @@
section :global(blockquote) {
color: hsl(204, 100%, 50%);
border: 2px solid var(--flash);
/* padding-left: 8.8rem; */
}
section :global(blockquote) :global(code) {
background: hsl(204, 100%, 95%) !important;
color: hsl(204, 100%, 50%);
}
section :global(blockquote::before) {
content: ' ';
position: absolute;
top: 1.5rem;
left: 3.2rem;
width: 3rem;
height: 3rem;
background-repeat: no-repeat;
background-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='#40b3ff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z'/%3E%3Cline x1='12' y1='9' x2='12' y2='13'/%3E%3Cline x1='12' y1='17' x2='12' y2='17'/%3E%3C/svg%3E");
}
</style>
<svelte:head>
@ -389,6 +375,7 @@
<Icon name='edit' /></a>
</small>
</h2>
{@html section.html}
</section>
{/each}

@ -19,75 +19,72 @@
margin: 0 auto;
}
h1 {
margin: 4rem 0 4rem -0.05em;
font-size: 4rem;
}
h1 { margin: 6rem 0 6rem -0.05em }
h2 {
margin: 0 0 1em 0;
font-size: 18px;
border-bottom: 1px solid #eee;
font: 600 var(--h4) var(--font);
border-bottom: var(--border-w) solid #eee;
text-transform: uppercase;
padding: 0 0 0.5em 0;
letter-spacing: .05em;
padding: 0 0 0.2em 0;
}
section {
margin: 0 0 2em 0;
}
section { margin: 0 0 4rem 0 }
.example {
position: relative;
display: flex;
flex-wrap: wrap;
align-items: center;
padding: 0 0 0 85px;
min-height: 50px;
font-weight: 300;
justify-content: center;
text-align: center;
font: 300 var(--h5) var(--font);
}
.grid {
grid-template-columns: repeat(1, 1fr);
grid-gap: 0.5em;
.thumbnail {
position: relative;
background: white 50% 50% no-repeat;
background-size: contain;
width: 5rem;
height: 5rem;
margin: .8rem 33%;
border: 1px solid #ccc;
border-radius: var(--border-r);
box-shadow: 1px 1px 2px rgba(0,0,0,0.13);
}
.e-grid {
display: grid;
/* grid-gap: 2.4rem; */
grid-template-columns: repeat(2, 1fr);
align-items: center;
}
@media (min-width: 720px) {
.grid {
grid-template-columns: repeat(2, 1fr);
.e-grid {
grid-template-columns: repeat(4, 1fr);
}
}
@media (min-width: 1080px) {
.grid {
grid-template-columns: repeat(3, 1fr);
.e-grid {
grid-template-columns: repeat(6, 1fr);
}
}
.thumbnail {
position: absolute;
background: white 50% 50% no-repeat;
background-size: contain;
width: 75px;
height: 50px;
left: 0;
top: 0;
border: 1px solid #ccc;
border-radius: 2px;
box-shadow: 1px 1px 3px rgba(0,0,0,0.1);
}
</style>
<div class="content">
<h1>Examples</h1>
{#each groups as group}
<section>
<section class="">
<h2>{group.title}</h2>
<div class="grid">
<div class="e-grid">
{#each group.examples as example}
<a class="example" href="repl?example={example.slug}">
<div class="thumbnail" style="background-image: url(examples/thumbnails/{example.slug}.png)"></div>
<span>{example.title}</span>
<p>{example.title}</p>
</a>
{/each}
</div>

@ -1,6 +1,4 @@
<script>
import Icon from '../components/Icon.svelte';
import Logo from '../components/Logo.svelte';
import Blurb from './_components/Blurb.svelte';
import WhosUsingSvelte from './_components/WhosUsingSvelte.svelte';
import IntersectionObserver from '../components/IntersectionObserver.svelte';
@ -25,9 +23,8 @@
max-width: 120rem;
}
.container ul {
list-style: none;
}
.container h3 { color: var(--text) }
.container ul { list-style: none }
/* max line-length ~60 chars */
li:not(.box) > p {
@ -39,65 +36,53 @@
--text: hsl(36, 3%, 44%);
}
.logo {
position: absolute;
left: -120px;
top: -120px;
width: 80vmin;
height: 80vmin;
opacity: 0.1;
will-change: transform;
.hero {
margin: 10rem auto;
}
.hero h1 {
text-align: center;
margin: 2rem 0;
font-size: 6rem;
color: var(--heading);
font-weight: 100;
letter-spacing: .12em;
text-transform: uppercase;
.hero h3, .logotype {
position: relative;
left: 1.6rem;
}
.hero h2 {
text-align: center;
display: block;
position: relative;
font-size: 3.2rem;
text-align: center;
width: 100%;
text-transform: lowercase;
font-weight: 300;
opacity: 0.7;
.hero h3 {
font-size: 2rem;
}
.logotype {
height: 4rem;
}
.logo {
position: absolute;
top: -4rem;
right: 0rem;
width: 52rem;
will-change: transform;
display: none;
}
.examples {
background: var(--second);
color: white;
/* padding: 2em 0; */
overflow: hidden;
}
.example {
/* background: var(--second);
color: white;
padding: 0.8rem;
border-radius: var(--border-r); */
width: 100%;
height: 420px;
}
.example > p {
margin: 4.4rem 2.4rem 2.4rem 0;
}
.repl-container {
width: 100%;
height: 100%;
height: 420px;
border-radius: var(--border-r);
overflow: hidden;
}
.example > div:first-child {
/* padding: 0.8rem; */
}
.contributor {
width: 2.4em;
height: 2.4em;
@ -107,48 +92,67 @@
background: no-repeat url(/contributors.jpg);
background-size: auto 102%;
margin: 0 0.5em 0.5em 0;
border: 1px solid var(--second);
border: 2px solid var(--second);
}
@media (min-width: 640px) {
.logotype {
height: 6rem;
}
.hero h3 {
font-size: var(--h3);
}
}
@media (min-width: 800px) {
.logo {
display: block;
}
.hero {
margin: 15rem auto;
}
.hero h3, .logotype {
left: 3rem;
}
}
@media (min-width: 920px) {
.example {
display: grid;
grid-template-columns: 1fr 4fr;
grid-template-columns: 1fr 3fr;
grid-gap: 0.5em;
align-items: start;
}
}
@media screen and (min-width: 870px) {
.hero h1 {
position: relative;
top: -.8rem;
font-size: 18rem;
margin: 2rem 2rem 0 1rem;
@media (min-width: 1200px) {
.logo {
right: calc(50vw - 60rem);
}
}
</style>
<svelte:head>
<title>Svelte • The magical disappearing UI framework</title>
<title>Svelte • Cybernetically enhanced web apps</title>
</svelte:head>
<svelte:window bind:scrollY={sy}/>
<img alt="Svelte logo" class="logo" src="logo.svg" style="transform: translate(0,{sy * 0.2}px)">
<img alt="Svelte logo" class="logo" src="svelte-logo-outline.svg" style="transform: translate(0, {sy * .2}px)">
<section class="hero container">
<h2>Cybernetically enhanced web apps</h2>
<h1>Svelte</h1>
<img alt="Svelte logotype" class="logotype" src="svelte-logotype.svg">
<h3>Cybernetically enhanced web apps</h3>
</section>
<Blurb/>
<div class="examples">
<section class="container example linkify">
<div>
<p>Svelte components are built on top of HTML. Just add data.</p>
</div>
<p>Svelte components are built on top of HTML. Just add data.</p>
<div class="repl-container">
<IntersectionObserver once let:intersecting top={400}>
@ -161,9 +165,7 @@
</section>
<section class="container example linkify">
<div>
<p>CSS is component-scoped by default — no more style collisions or specificity wars. Or you can <a href="TODO-blog-post-on-css-in-js">use your favourite CSS-in-JS library</a>.</p>
</div>
<p>CSS is component-scoped by default — no more style collisions or specificity wars. Or you can <a href="TODO-blog-post-on-css-in-js">use your favourite CSS-in-JS library</a>.</p>
<div class="repl-container">
<IntersectionObserver once let:intersecting top={400}>
@ -176,9 +178,7 @@
</section>
<section class="container example linkify">
<div>
<p>Trigger efficient, granular updates by assigning to local variables. The compiler does the rest.</p>
</div>
<p>Trigger efficient, granular updates by assigning to local variables. The compiler does the rest.</p>
<div class="repl-container">
<IntersectionObserver once let:intersecting top={400}>
@ -191,9 +191,7 @@
</section>
<section class="container example linkify">
<div>
<p>Build beautiful UIs with a powerful, performant transition engine built right into the framework.</p>
</div>
<p>Build beautiful UIs with a powerful, performant transition engine built right into the framework.</p>
<div class="repl-container">
<IntersectionObserver once let:intersecting top={400}>
@ -224,4 +222,4 @@
href="https://github.com/{contributor}"
>{contributor}</a>
{/each}
</section>
</section>

@ -7,7 +7,7 @@
position: fixed;
bottom: 0;
width: 100%;
height: 42px;
height: 4.6rem;
display: flex;
justify-content: center;
align-items: center;
@ -16,15 +16,15 @@
}
button {
padding: 0.3em 0.6em;
border-radius: 1em;
line-height: 1;
margin: 0 .15em;
width: 4em;
height: 1em;
padding: .2em .4em .3em;
border-radius: var(--border-r);
line-height: 1;
box-sizing: content-box;
color: #999;
border: 1px solid #f4f4f4;
width: 4em;
margin: 0 0.15em;
color: #888;
border: 1px solid var(--back-light);
}
.selected {
@ -37,4 +37,4 @@
<button class:selected={offset === 0} on:click={() => offset = 0}>tutorial</button>
<button class:selected={offset === 1} on:click={() => offset = 1}>input</button>
<button class:selected={offset === 2} on:click={() => offset = 2}>output</button>
</div>
</div>

@ -28,7 +28,7 @@
a {
display: block;
padding: 0.75em 0;
padding: 0.7em 0;
text-align: center;
opacity: 0.7;
}
@ -40,11 +40,11 @@
span {
white-space: nowrap;
position: relative;
top: 0.3em;
}
strong {
opacity: 0.7;
}
strong { opacity: 0.7 }
select {
position: absolute;
@ -86,4 +86,4 @@
<a rel="prefetch" href="tutorial/{(selected.next || selected).slug}" class:disabled={!selected.next}>
<Icon name="arrow-right" />
</a>
</nav>
</nav>

@ -114,7 +114,6 @@
height: calc(100vh - var(--nav-h));
overflow: hidden;
padding: 0 0 42px 0;
/* margin: 0 calc(var(--side-nav) * -1); */
box-sizing: border-box;
}
@ -123,7 +122,7 @@
width: 300%;
height: 100%;
grid-template-columns: 33.333% 66.666%;
transition: transform 0.3s;
transition: transform .3s;
grid-auto-rows: 100%;
}
@ -131,9 +130,7 @@
.offset-2 { transform: translate(-66.666%, 0); }
@media (min-width: 768px) {
.tutorial-outer {
padding: 0;
}
.tutorial-outer { padding: 0 }
.viewport {
width: 100%;
@ -157,19 +154,23 @@
}
.chapter-markup {
padding: 1em;
padding: 3.2rem 4rem;
overflow: auto;
flex: 1;
height: 0;
}
.chapter-markup :global(h2) {
margin: 4rem 0 1.6rem 0;
font-size: var(--h3);
margin: 3.2rem 0 1.6rem 0;
line-height: 1;
color: white;
}
.chapter-markup :global(h2:first-child) {
margin-top: .4rem;
}
.chapter-markup :global(a) {
text-decoration: underline;
}
@ -179,7 +180,7 @@
}
.chapter-markup :global(blockquote) {
background-color: rgba(255,255,255,0.1);
background-color: rgba(255,255,255,.1);
color: white;
}
@ -189,7 +190,7 @@
}
.chapter-markup::-webkit-scrollbar-thumb {
background-color: rgba(255,255,255,0.7);
background-color: rgba(255,255,255,.7);
border-radius: 1em;
outline: 1px solid green;
}
@ -197,45 +198,51 @@
.chapter-markup :global(p) > :global(code),
.chapter-markup :global(ul) :global(code) {
color: white;
background: rgba(255,255,255,0.1);
padding: 0.2em 0.4em;
background: rgba(255,255,255,.1);
padding: .2em .4em;
white-space: nowrap;
position: relative;
top: -0.1em;
}
.controls {
border-top: 1px solid rgba(255,255,255,0.1);
border-top: 1px solid rgba(255,255,255,.1);
padding: 1em 0 0 0;
display: flex;
}
.show {
text-transform: uppercase;
background: rgba(255,255,255,0.1);
padding: 0.2em 0.7em;
border-radius: 2em;
top: 0.1em;
background: rgba(255,255,255,.1);
padding: .2em .7em .3em;
border-radius: var(--border-r);
top: .1em;
position: relative;
font-size: var(--h5);
font-weight: 300;
}
.show:hover {
background: rgba(255,255,255,0.2);
background: rgba(255,255,255,.2);
}
a.next {
text-decoration: none;
margin-left: auto;
}
a.next:hover {
text-decoration: underline;
}
.improve-chapter {
padding: 1em 0 .5em 0;
}
.improve-chapter a {
padding: 0 .1em;
font-size: 14px;
text-decoration: none;
opacity: 0.3;
padding: 0 0.1em;
opacity: .3;
}
.improve-chapter a:hover {

@ -3,7 +3,7 @@
<head>
<meta charset='utf-8'>
<meta name='viewport' content='width=device-width'>
<meta name='theme-color' content='#aa1e1e'>
<meta name='theme-color' content='#ff3e00'>
%sapper.base%

@ -1,16 +1,76 @@
/* fonts */
/*
-----------------------------------------------
vars css custom-properties
/* overpass-100normal - latin */
@font-face {
font-family: 'Overpass';
font-style: normal;
font-weight: 100;
src:
local('Overpass Thin '),
local('Overpass-Thin'),
url('fonts/overpass/overpass-latin-100.woff2') format('woff2');
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;
--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;
--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';
@ -22,26 +82,15 @@
url('fonts/overpass/overpass-latin-300.woff2') format('woff2');
}
/* overpass-400normal - latin */
/* overpass-600normal - latin */
@font-face {
font-family: 'Overpass';
font-style: normal;
font-weight: 400;
src:
local('Overpass Light '),
local('Overpass-Light'),
url('fonts/overpass/overpass-latin-400.woff2') format('woff2');
}
/* overpass-700normal - latin */
@font-face {
font-family: 'Overpass';
font-style: normal;
font-weight: 700;
font-weight: 600;
src:
local('Overpass Bold '),
local('Overpass-Bold'),
url('fonts/overpass/overpass-latin-700.woff2') format('woff2');
url('fonts/overpass/overpass-latin-600.woff2') format('woff2');
}
/* fira-mono-400normal - latin */
@ -55,65 +104,6 @@
url('fonts/fira-mono/fira-mono-latin-400.woff2') format('woff2');
}
/* roboto-400normal - latin */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-display: swap;
font-weight: 400;
src:
local('Roboto Regular '),
local('Roboto-Regular'),
url('fonts/roboto/roboto-latin-400.woff2') format('woff2');
}
/* roboto-400italic - latin */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-display: swap;
font-weight: 400;
src:
local('Roboto Regular italic'),
local('Roboto-Regularitalic'),
url('fonts/roboto/roboto-latin-400italic.woff2') format('woff2');
}
/* roboto-500normal - latin */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-display: swap;
font-weight: 500;
src:
local('Roboto Medium '),
local('Roboto-Medium'),
url('fonts/roboto/roboto-latin-500.woff2') format('woff2');
}
/* roboto-500italic - latin */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-display: swap;
font-weight: 500;
src:
local('Roboto Medium italic'),
local('Roboto-Mediumitalic'),
url('fonts/roboto/roboto-latin-500italic.woff2') format('woff2');
}
body {
--font: 'Overpass', sans-serif;
/* --font: 'Roboto', 'sans-serif'; */
/* --font-mono: 'Overpass Mono', monospace; */
/* --font-mono: 'IBM Plex Mono'; */
--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;
}
/* base reset ----------------------------- */
html {
font-size: 62.5%;
@ -130,99 +120,39 @@ html {
padding: 0;
}
/* links reset ---------------------------- */
/* link reset ----------------------------- */
a {
text-decoration: none;
cursor: pointer;
color: inherit;
}
a:hover,
a:active {
color: var(--flash);
}
a:focus {
outline: none
}
a:hover, a:active { color: var(--flash) }
a:focus { outline: none }
/*
-----------------------------------------------
global styles
NOTE
!important overrides class-definitions
- some vars change inside media-queries!
-----------------------------------------------
*/
/* constants and calc -----------------------
- commonly used values
- under normal conditions, there's no need to touch these
- look confusing/cluttering at first,
but they simplify life immensely
-----------------------------------------------
*/
:root {
--nav-h: 6rem;
--top-offset: 6rem;
--sidebar-w: 30rem;
--main-width: 80rem;
--code-w: 72em;
--side-nav: 1.6rem;
--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);
}
/* theme vars ----------------------------- */
.theme-default {
--back: #ffffff;
--back-light: #fbfcfd;
--prime: #ff3e00;
--second: #676778;
--flash: #40b3ff;
--heading: var(--second);
--text: #333; /* hsl(36, 3%, 62%) */
--border-w: .3rem; /* border-width */
--border-r: .4rem; /* border-radius */
}
/* typo vars ------------------------------ */
.typo-default {
--unit: .8rem;
--code-fs: 1.3rem;
--h6: 1.6rem;
--h5: 1.6rem;
--h4: 1.8rem;
--h3: 2.4rem;
--h2: 3rem;
--h1: 3.2rem;
--linemax: 42em; /* max line-length */
--lh: calc(4/2.2); /* base line-height */
}
/* typography ----------------------------- */
body {
font: 400 var(--h4)/var(--lh) var(--font);
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);
position: relative;
}
h1, h2, h3, h4, h5, h6 { font-weight: 700 }
/* h1, h2, h3, h4, h5, h6 { font-weight: 600 } */
h6 { font-size: var(--h6) }
h5 { font-size: var(--h5) }
h4 { font-size: var(--h4) }
@ -230,15 +160,18 @@ 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 {
line-height: 1.5;
margin: 0 0 1em 0;
font-family: Roboto, sans-serif;
-webkit-font-smoothing: antialiased;
/* font-family: var(--font-system); */
}
.b, b, strong { font-weight: 500 }
.b, b, strong { font-weight: 600 }
tt, code, kbd, samp {
font: 400 var(--code-fs)/1.7 var(--font-mono);
@ -246,11 +179,8 @@ tt, code, kbd, samp {
code {
position: relative;
border-radius: 0.3em;
border-radius: .3em;
white-space: nowrap;
/* border-top: .1rem solid #e5e5e9;
border-left: .1rem solid #e5e5e9; */
/* color: inherit; */
color: #444;
-webkit-font-smoothing: initial;
}
@ -261,16 +191,17 @@ pre code {
background-color: none;
}
/* sync CodeMirror with prism */
.CodeMirror {
font-size: var(--code-fs) !important;
}
::selection {
background: var(--flash);
color: white;
}
/* opinionated styles --------------------- */
h1, h2 {
font-family: var(--font);
line-height: 1.2;
}
li:not(.white) > h2 {
color: var(--second)
@ -293,7 +224,6 @@ blockquote :last-child {
margin: 0;
}
/* buttons -------------------------------- */
button {
font-family: inherit;
@ -301,50 +231,78 @@ button {
background-color: transparent;
border: none;
color: currentColor;
cursor: pointer;
}
button:focus { outline: 0 }
button:focus,
.btn:focus { outline: 0 }
button[disabled] {
button[disabled],
.btn[disabled],
.btn:hover[disabled] {
opacity: .55;
pointer-events: none;
}
button > svg {
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;
}
/* options */
button[outline] {
min-height: var(--bttn-calc-h);
line-height: var(--bttn-calc-h);
border: var(--bttn-outline) solid currentColor;
background-color: white;
color: currentColor;
/* default */
.btn {
line-height: var(--btn-h);
height: var(--btn-h);
padding: 0 1.6rem;
transition: all .1s;
}
/* links -------------------------------------
- idea from https://up.docs.apex.sh
How can this be solved?
Setup for all links is risky/tricky
.btn:hover {
transform: scale(.98);
mix-blend-mode: multiply;
background-image: var(--btn-hover);
}
We need global <a>-styles and <ul>-styles inside markdown.
These bleed into places, where not wanted (i.e. nav, homepage)
Same with lists - see below
/* 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;
}
THIS WAY IS SHITTY!!
I'm too blind to see...
*/
/* links ------------------------------------- */
.linkify a:not(.open-in-repl) {
position: relative;
padding: 0 0 .1rem 0;
border-bottom: .1rem solid hsla(15, 100%, 50%, 0.5); /* muted --prime */
user-select: none;
/* white-space: nowrap; */
color: inherit;
transition: color .2s, border .2s, padding .2s;
}
@ -358,28 +316,6 @@ button[outline] {
border-bottom: .2rem solid hsla(15, 100%, 50%, 1);
}
/* .linkify a:not(.open-in-repl):before {
content: '';
position: absolute;
width: 100%;
height: .2rem;
bottom: -.2rem;
left: 0;
white-space: nowrap;
background: var(--prime);
border-radius: var(--border-r);
visibility: hidden;
transform: scaleX(0);
transform-origin: left center;
transition: all .15s var(--out-cubic);
z-index: -1;
}
.linkify a:not(.open-in-repl):hover:before {
visibility: visible;
transform: scaleX(1);
} */
a:hover:not(.disabled) > .icon { stroke: var(--flash) }
/* lists ---------------------------------- */
@ -405,8 +341,8 @@ a:hover:not(.disabled) > .icon { stroke: var(--flash) }
margin-top: 1.1rem;
margin-left: -1.8rem;
background-color: var(--second);
width: .8rem;
height: 0.8rem;
width: .6rem;
height: .6rem;
border-radius: 2px;
opacity: 0.7;
}
@ -425,14 +361,12 @@ td, th {
padding: 0.4rem 0.8rem 0.4rem 0;
}
table code,
table span {
table code, table span {
white-space: pre;
}
/* grid ----------------------------------- */
.grid,
.grid.half {
.grid, .grid.half {
display: grid;
grid-gap: 2.4rem;
grid-template-columns: 1fr;
@ -444,6 +378,18 @@ table span {
.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 }
@ -453,8 +399,7 @@ table span {
padding-bottom: 0 !important;
}
.legend, figcaption,
.post aside {
.legend, figcaption, .post aside {
max-width: none;
margin: 0 auto;
padding: 1.6rem 0 0 .8rem;
@ -487,7 +432,7 @@ table span {
/* theme colors --------------------------- */
.prime { color: var(--prime) !important }
.second { color: var(--second) !important }
.flash { color: var(--flash) !important }
.flash { color: var(--flash) !important }
.black { color: black !important }
.white { color: white !important }
@ -495,15 +440,9 @@ table span {
.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
-----------------------------------------------
*/
.bg-flash { background-color: var(--flash) !important }
/* inputs --------------------------------- */
input[type="checkbox"] {
/* display: block; */
position: relative;
@ -523,13 +462,13 @@ input[type="checkbox"]::before {
display: block;
height: 100%;
width: 100%;
padding: 2px;
border-radius: 1em;
top: 0px;
left: 0px;
top: 0;
left: 0;
background: var(--second);
box-sizing: border-box;
-webkit-transition: .25s ease-out;
padding: 2px;
/* box-sizing: border-box; */
box-sizing: content-box;
}
@ -554,30 +493,3 @@ input[type="checkbox"]::after {
input[type="checkbox"]:checked::after {
left: calc(100% - 9px);
}
/*
-----------------------------------------------
media-queries
-----------------------------------------------
*/
@media screen and (min-width: 768px) {
:root {
--side-page: 14vw;
--top-offset: 10rem;
--side-nav: 4.8rem;
}
}
@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 }
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 20 KiB

@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 103 124">
<path style="fill:#ff3e00" d='M96.33,20.61C85.38,4.93,63.74.28,48.09,10.25L20.61,27.77A31.46,31.46,0,0,0,6.37,48.88,33.22,33.22,0,0,0,9.64,70.2,31.52,31.52,0,0,0,4.93,82a33.61,33.61,0,0,0,5.73,25.41c11,15.68,32.6,20.33,48.25,10.36l27.48-17.52a31.48,31.48,0,0,0,14.24-21.11A33.22,33.22,0,0,0,97.36,57.8,31.52,31.52,0,0,0,102.07,46a33.57,33.57,0,0,0-5.74-25.41' />
<path style="fill:white" d='M45.41,108.86A21.81,21.81,0,0,1,22,100.18,20.2,20.2,0,0,1,18.53,84.9a19,19,0,0,1,.65-2.57l.52-1.58,1.41,1a35.32,35.32,0,0,0,10.75,5.37l1,.31-.1,1a6.2,6.2,0,0,0,1.11,4.08A6.57,6.57,0,0,0,41,95.19a6,6,0,0,0,1.68-.74L70.11,76.94a5.76,5.76,0,0,0,2.59-3.83,6.09,6.09,0,0,0-1-4.6,6.58,6.58,0,0,0-7.06-2.62,6.21,6.21,0,0,0-1.69.74L52.43,73.31a19.88,19.88,0,0,1-5.58,2.45,21.82,21.82,0,0,1-23.43-8.68A20.2,20.2,0,0,1,20,51.8a19,19,0,0,1,8.56-12.7L56,21.59a19.88,19.88,0,0,1,5.58-2.45A21.81,21.81,0,0,1,85,27.82,20.2,20.2,0,0,1,88.47,43.1a19,19,0,0,1-.65,2.57l-.52,1.58-1.41-1a35.32,35.32,0,0,0-10.75-5.37l-1-.31.1-1a6.2,6.2,0,0,0-1.11-4.08,6.57,6.57,0,0,0-7.06-2.62,6,6,0,0,0-1.68.74L36.89,51.06a5.71,5.71,0,0,0-2.58,3.83,6,6,0,0,0,1,4.6,6.58,6.58,0,0,0,7.06,2.62,6.21,6.21,0,0,0,1.69-.74l10.48-6.68a19.88,19.88,0,0,1,5.58-2.45,21.82,21.82,0,0,1,23.43,8.68A20.2,20.2,0,0,1,87,76.2a19,19,0,0,1-8.56,12.7L51,106.41a19.88,19.88,0,0,1-5.58,2.45' />
</svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

@ -41,7 +41,7 @@ pre[class*='language-'] {
margin: .8rem 0 2.4rem;
/* max-width: var(--code-w); */
border-radius: var(--border-r);
box-shadow: 1px 1px 0.1rem rgba(68, 68, 68, 0.05) inset;
box-shadow: 1px 1px 1px rgba(68, 68, 68, .12) inset;
}
:not(pre) > code[class*='language-'],

@ -0,0 +1,3 @@
<svg id="svelte" xmlns="http://www.w3.org/2000/svg" width="519" height="139" viewBox="0 0 519 139"><path id="logotype" fill="#4a4a55" d="M172.39,100.41a24.1,24.1,0,0,1-13.72-3.87,19.86,19.86,0,0,1-8-10.61L159,82.86a15.4,15.4,0,0,0,5.45,6.6,14.37,14.37,0,0,0,8.27,2.43,12.14,12.14,0,0,0,7.88-2.38,8.29,8.29,0,0,0,2.94-6.82,7.43,7.43,0,0,0-.81-3.45,10.32,10.32,0,0,0-1.83-2.6,12.36,12.36,0,0,0-3.16-2.09c-1.42-.71-2.59-1.25-3.53-1.62s-2.32-.87-4.13-1.49c-2.28-.8-4-1.42-5.12-1.88a37.86,37.86,0,0,1-4.47-2.25,16.37,16.37,0,0,1-4.18-3.16A15.43,15.43,0,0,1,153.81,60a14.77,14.77,0,0,1,4-16.79q5.12-4.51,13.89-4.51,7.34,0,12.06,3.23a15.63,15.63,0,0,1,6.35,8.61l-8.18,2.73a9.57,9.57,0,0,0-4-4.39A13.3,13.3,0,0,0,171,47.24a10.7,10.7,0,0,0-6.69,1.87,6.28,6.28,0,0,0-2.42,5.29,5.52,5.52,0,0,0,1.87,4.09,13,13,0,0,0,3.92,2.64c1.36.57,3.44,1.33,6.22,2.3,1.7.63,3,1.09,3.79,1.41s2,.83,3.62,1.57a25.79,25.79,0,0,1,3.67,2,34.36,34.36,0,0,1,3,2.43,12.86,12.86,0,0,1,2.6,3.11,17.06,17.06,0,0,1,1.53,3.84,17.42,17.42,0,0,1,.64,4.81q0,8.36-5.71,13.08T172.39,100.41Zm54.62-1L206.56,39.74h9.54l13.55,41.58a66.19,66.19,0,0,1,1.88,6.82,63.43,63.43,0,0,1,1.87-6.82l13.38-41.58h9.46L235.87,99.39Zm47.29,0V39.74h37v8.35H283.17V64.45h18.15V72.8H283.17V91h30v8.35Zm61.44,0V39.74h8.87V90.87h29.14v8.52Zm71.41-51.13V99.39h-8.86V48.26H381.42V39.74H424v8.52Zm35.2,51.13V39.74h37v8.35H451.21V64.45h18.15V72.8H451.21V91h30v8.35Z"/>
<path id="back" fill="#ff3e00" d="M110.23,28.39C99.83,13.51,79.29,9.1,64.44,18.56L38.36,35.18a29.9,29.9,0,0,0-13.52,20,31.53,31.53,0,0,0,3.1,20.24,29.94,29.94,0,0,0-4.47,11.18,31.86,31.86,0,0,0,5.45,24.12c10.4,14.88,30.94,19.29,45.79,9.83L100.79,104a30,30,0,0,0,13.52-20,31.52,31.52,0,0,0-3.11-20.23,30.13,30.13,0,0,0,4.48-11.18,31.9,31.9,0,0,0-5.45-24.12"/>
<path id="front" fill="#fff" d="M61.89,112.16a20.73,20.73,0,0,1-22.24-8.25,19.14,19.14,0,0,1-3.27-14.5A17,17,0,0,1,37,87l.49-1.5,1.34,1A33.78,33.78,0,0,0,49,91.56l1,.29-.09,1A5.9,5.9,0,0,0,51,96.7a6.25,6.25,0,0,0,6.7,2.48,5.85,5.85,0,0,0,1.6-.7L85.34,81.86a5.42,5.42,0,0,0,2.45-3.64,5.77,5.77,0,0,0-1-4.37,6.25,6.25,0,0,0-6.7-2.48,5.72,5.72,0,0,0-1.6.7l-10,6.35a19.1,19.1,0,0,1-5.29,2.32A20.72,20.72,0,0,1,41,72.5,19.16,19.16,0,0,1,37.75,58a18,18,0,0,1,8.13-12.06L72,29.32A19.05,19.05,0,0,1,77.26,27a20.71,20.71,0,0,1,22.23,8.25,19.14,19.14,0,0,1,3.28,14.5,20.15,20.15,0,0,1-.62,2.43l-.5,1.5-1.33-1a33.78,33.78,0,0,0-10.2-5.1l-1-.29.09-1a5.86,5.86,0,0,0-1.06-3.88A6.23,6.23,0,0,0,81.49,40a5.72,5.72,0,0,0-1.6.7L53.8,57.29a5.45,5.45,0,0,0-2.45,3.63,5.84,5.84,0,0,0,1,4.38A6.25,6.25,0,0,0,59,67.78a6,6,0,0,0,1.6-.7l10-6.34a18.61,18.61,0,0,1,5.3-2.33,20.7,20.7,0,0,1,22.23,8.24,19.16,19.16,0,0,1,3.28,14.5,18,18,0,0,1-8.13,12.06L67.19,109.83a19.18,19.18,0,0,1-5.3,2.33"/></svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 103 124">
<path style="fill:black" d='M96.33,20.61C85.38,4.93,63.74.28,48.09,10.25L20.61,27.77A31.46,31.46,0,0,0,6.37,48.88,33.22,33.22,0,0,0,9.64,70.2,31.52,31.52,0,0,0,4.93,82a33.61,33.61,0,0,0,5.73,25.41c11,15.68,32.6,20.33,48.25,10.36l27.48-17.52a31.48,31.48,0,0,0,14.24-21.11A33.22,33.22,0,0,0,97.36,57.8,31.52,31.52,0,0,0,102.07,46a33.57,33.57,0,0,0-5.74-25.41
<path fill="black" d='M96.33,20.61C85.38,4.93,63.74.28,48.09,10.25L20.61,27.77A31.46,31.46,0,0,0,6.37,48.88,33.22,33.22,0,0,0,9.64,70.2,31.52,31.52,0,0,0,4.93,82a33.61,33.61,0,0,0,5.73,25.41c11,15.68,32.6,20.33,48.25,10.36l27.48-17.52a31.48,31.48,0,0,0,14.24-21.11A33.22,33.22,0,0,0,97.36,57.8,31.52,31.52,0,0,0,102.07,46a33.57,33.57,0,0,0-5.74-25.41
M45.41,108.86A21.81,21.81,0,0,1,22,100.18,20.2,20.2,0,0,1,18.53,84.9a19,19,0,0,1,.65-2.57l.52-1.58,1.41,1a35.32,35.32,0,0,0,10.75,5.37l1,.31-.1,1a6.2,6.2,0,0,0,1.11,4.08A6.57,6.57,0,0,0,41,95.19a6,6,0,0,0,1.68-.74L70.11,76.94a5.76,5.76,0,0,0,2.59-3.83,6.09,6.09,0,0,0-1-4.6,6.58,6.58,0,0,0-7.06-2.62,6.21,6.21,0,0,0-1.69.74L52.43,73.31a19.88,19.88,0,0,1-5.58,2.45,21.82,21.82,0,0,1-23.43-8.68A20.2,20.2,0,0,1,20,51.8a19,19,0,0,1,8.56-12.7L56,21.59a19.88,19.88,0,0,1,5.58-2.45A21.81,21.81,0,0,1,85,27.82,20.2,20.2,0,0,1,88.47,43.1a19,19,0,0,1-.65,2.57l-.52,1.58-1.41-1a35.32,35.32,0,0,0-10.75-5.37l-1-.31.1-1a6.2,6.2,0,0,0-1.11-4.08,6.57,6.57,0,0,0-7.06-2.62,6,6,0,0,0-1.68.74L36.89,51.06a5.71,5.71,0,0,0-2.58,3.83,6,6,0,0,0,1,4.6,6.58,6.58,0,0,0,7.06,2.62,6.21,6.21,0,0,0,1.69-.74l10.48-6.68a19.88,19.88,0,0,1,5.58-2.45,21.82,21.82,0,0,1,23.43,8.68A20.2,20.2,0,0,1,87,76.2a19,19,0,0,1-8.56,12.7L51,106.41a19.88,19.88,0,0,1-5.58,2.45' />
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 103 124">
<path fill="none" stroke="#ff3e00" stroke-width=".25" d='M96.33,20.61C85.38,4.93,63.74.28,48.09,10.25L20.61,27.77A31.46,31.46,0,0,0,6.37,48.88,33.22,33.22,0,0,0,9.64,70.2,31.52,31.52,0,0,0,4.93,82a33.61,33.61,0,0,0,5.73,25.41c11,15.68,32.6,20.33,48.25,10.36l27.48-17.52a31.48,31.48,0,0,0,14.24-21.11A33.22,33.22,0,0,0,97.36,57.8,31.52,31.52,0,0,0,102.07,46a33.57,33.57,0,0,0-5.74-25.41' />
<path fill="none" stroke="#ff3e00" stroke-width=".25" d='M45.41,108.86A21.81,21.81,0,0,1,22,100.18,20.2,20.2,0,0,1,18.53,84.9a19,19,0,0,1,.65-2.57l.52-1.58,1.41,1a35.32,35.32,0,0,0,10.75,5.37l1,.31-.1,1a6.2,6.2,0,0,0,1.11,4.08A6.57,6.57,0,0,0,41,95.19a6,6,0,0,0,1.68-.74L70.11,76.94a5.76,5.76,0,0,0,2.59-3.83,6.09,6.09,0,0,0-1-4.6,6.58,6.58,0,0,0-7.06-2.62,6.21,6.21,0,0,0-1.69.74L52.43,73.31a19.88,19.88,0,0,1-5.58,2.45,21.82,21.82,0,0,1-23.43-8.68A20.2,20.2,0,0,1,20,51.8a19,19,0,0,1,8.56-12.7L56,21.59a19.88,19.88,0,0,1,5.58-2.45A21.81,21.81,0,0,1,85,27.82,20.2,20.2,0,0,1,88.47,43.1a19,19,0,0,1-.65,2.57l-.52,1.58-1.41-1a35.32,35.32,0,0,0-10.75-5.37l-1-.31.1-1a6.2,6.2,0,0,0-1.11-4.08,6.57,6.57,0,0,0-7.06-2.62,6,6,0,0,0-1.68.74L36.89,51.06a5.71,5.71,0,0,0-2.58,3.83,6,6,0,0,0,1,4.6,6.58,6.58,0,0,0,7.06,2.62,6.21,6.21,0,0,0,1.69-.74l10.48-6.68a19.88,19.88,0,0,1,5.58-2.45,21.82,21.82,0,0,1,23.43,8.68A20.2,20.2,0,0,1,87,76.2a19,19,0,0,1-8.56,12.7L51,106.41a19.88,19.88,0,0,1-5.58,2.45' />
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

@ -0,0 +1,4 @@
<svg id="svelte" xmlns="http://www.w3.org/2000/svg" width="256" height="300" viewBox="0 0 256 300">
<path id="logotype" fill="#4a4a55" d="M44.41,265.87a14,14,0,0,1-8-2.26,11.53,11.53,0,0,1-4.66-6.18l4.86-1.78a9,9,0,0,0,3.18,3.84,8.31,8.31,0,0,0,4.81,1.42,7,7,0,0,0,4.59-1.39,4.83,4.83,0,0,0,1.71-4,4.25,4.25,0,0,0-.47-2A5.93,5.93,0,0,0,49.38,252a7,7,0,0,0-1.84-1.22c-.83-.41-1.51-.73-2.06-.94s-1.35-.51-2.41-.87c-1.32-.46-2.31-.83-3-1.09a23.69,23.69,0,0,1-2.61-1.32,9.63,9.63,0,0,1-2.43-1.83,8.76,8.76,0,0,1-1.46-2.41A8.11,8.11,0,0,1,33,239a8.29,8.29,0,0,1,3-6.45A11.79,11.79,0,0,1,44,229.94a12.16,12.16,0,0,1,7,1.89,9.11,9.11,0,0,1,3.69,5L50,238.43a5.53,5.53,0,0,0-2.31-2.56,7.77,7.77,0,0,0-4-1,6.23,6.23,0,0,0-3.9,1.09,3.66,3.66,0,0,0-1.41,3.07,3.22,3.22,0,0,0,1.09,2.39A7.61,7.61,0,0,0,41.68,243c.8.34,2,.78,3.63,1.34l2.2.82c.48.19,1.19.49,2.11.92a14.36,14.36,0,0,1,2.14,1.17,19.05,19.05,0,0,1,1.73,1.41A7.66,7.66,0,0,1,55,250.46a10.77,10.77,0,0,1,.89,2.24,10.13,10.13,0,0,1,.37,2.8A9.38,9.38,0,0,1,53,263.12,13,13,0,0,1,44.41,265.87Zm31.81-.6L64.31,230.54h5.56l7.89,24.21a39.48,39.48,0,0,1,1.09,4,39.48,39.48,0,0,1,1.09-4l7.79-24.21h5.51L81.38,265.27Zm27.54,0V230.54H125.3v4.86H108.92v9.53h10.57v4.86H108.92v10.62h17.47v4.86Zm35.78,0V230.54h5.16v29.77h17v5Zm41.58-29.77v29.77H176V235.5h-9.83v-5h24.81v5Zm20.49,29.77V230.54h21.54v4.86H206.77v9.53h10.57v4.86H206.77v10.62h17.47v4.86Z"/>
<path id="back" fill="#ff3e00" d="M191.87,52.11c-16.34-23.39-48.61-30.32-71.94-15.45L79,62.77A47,47,0,0,0,57.72,94.26,49.49,49.49,0,0,0,62.6,126a47.16,47.16,0,0,0-7,17.57,50.1,50.1,0,0,0,8.56,37.89c16.34,23.38,48.61,30.31,71.94,15.45l41-26.12a47,47,0,0,0,21.24-31.49,49.51,49.51,0,0,0-4.88-31.78,47.16,47.16,0,0,0,7-17.57,50.07,50.07,0,0,0-8.56-37.88"/>
<path id="front" fill="#fff" d="M115.93,183.7A32.55,32.55,0,0,1,81,170.75,30.11,30.11,0,0,1,75.85,148a29.12,29.12,0,0,1,1-3.83l.77-2.35,2.1,1.54a52.87,52.87,0,0,0,16,8l1.52.46-.14,1.52a9.17,9.17,0,0,0,1.65,6.09,9.79,9.79,0,0,0,10.52,3.9,9,9,0,0,0,2.52-1.1l41-26.11a8.53,8.53,0,0,0,3.85-5.71,9,9,0,0,0-1.55-6.87,9.82,9.82,0,0,0-10.52-3.9,9.08,9.08,0,0,0-2.51,1.1l-15.64,10a30.08,30.08,0,0,1-8.32,3.66A32.55,32.55,0,0,1,83.15,121.4,30.15,30.15,0,0,1,78,98.61,28.24,28.24,0,0,1,90.77,79.68l41-26.12a30,30,0,0,1,8.33-3.65,32.54,32.54,0,0,1,34.93,13,30.11,30.11,0,0,1,5.15,22.78,29.12,29.12,0,0,1-1,3.83l-.77,2.35-2.1-1.54a52.64,52.64,0,0,0-16-8l-1.52-.46.14-1.52a9.2,9.2,0,0,0-1.65-6.1,9.82,9.82,0,0,0-10.52-3.9,9,9,0,0,0-2.52,1.11l-41,26.11a8.49,8.49,0,0,0-3.85,5.7,9,9,0,0,0,1.55,6.87A9.81,9.81,0,0,0,111.45,114a9,9,0,0,0,2.52-1.11l15.63-10a29.5,29.5,0,0,1,8.32-3.66,32.54,32.54,0,0,1,34.93,12.95A30.11,30.11,0,0,1,178,135a28.26,28.26,0,0,1-12.77,18.94l-41,26.11a30.27,30.27,0,0,1-8.33,3.66"/></svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 103 124">
<path fill="#ff3e00" d='M96.33,20.61C85.38,4.93,63.74.28,48.09,10.25L20.61,27.77A31.46,31.46,0,0,0,6.37,48.88,33.22,33.22,0,0,0,9.64,70.2,31.52,31.52,0,0,0,4.93,82a33.61,33.61,0,0,0,5.73,25.41c11,15.68,32.6,20.33,48.25,10.36l27.48-17.52a31.48,31.48,0,0,0,14.24-21.11A33.22,33.22,0,0,0,97.36,57.8,31.52,31.52,0,0,0,102.07,46a33.57,33.57,0,0,0-5.74-25.41' />
<path fill="white" d='M45.41,108.86A21.81,21.81,0,0,1,22,100.18,20.2,20.2,0,0,1,18.53,84.9a19,19,0,0,1,.65-2.57l.52-1.58,1.41,1a35.32,35.32,0,0,0,10.75,5.37l1,.31-.1,1a6.2,6.2,0,0,0,1.11,4.08A6.57,6.57,0,0,0,41,95.19a6,6,0,0,0,1.68-.74L70.11,76.94a5.76,5.76,0,0,0,2.59-3.83,6.09,6.09,0,0,0-1-4.6,6.58,6.58,0,0,0-7.06-2.62,6.21,6.21,0,0,0-1.69.74L52.43,73.31a19.88,19.88,0,0,1-5.58,2.45,21.82,21.82,0,0,1-23.43-8.68A20.2,20.2,0,0,1,20,51.8a19,19,0,0,1,8.56-12.7L56,21.59a19.88,19.88,0,0,1,5.58-2.45A21.81,21.81,0,0,1,85,27.82,20.2,20.2,0,0,1,88.47,43.1a19,19,0,0,1-.65,2.57l-.52,1.58-1.41-1a35.32,35.32,0,0,0-10.75-5.37l-1-.31.1-1a6.2,6.2,0,0,0-1.11-4.08,6.57,6.57,0,0,0-7.06-2.62,6,6,0,0,0-1.68.74L36.89,51.06a5.71,5.71,0,0,0-2.58,3.83,6,6,0,0,0,1,4.6,6.58,6.58,0,0,0,7.06,2.62,6.21,6.21,0,0,0,1.69-.74l10.48-6.68a19.88,19.88,0,0,1,5.58-2.45,21.82,21.82,0,0,1,23.43,8.68A20.2,20.2,0,0,1,87,76.2a19,19,0,0,1-8.56,12.7L51,106.41a19.88,19.88,0,0,1-5.58,2.45' />
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

@ -0,0 +1,2 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="37.72 38.72 330.55 61.698">
<path id="logotype" fill="#4a4a55" d="M59.44,100.41a24.12,24.12,0,0,1-13.72-3.87,20,20,0,0,1-8-10.61l8.35-3.07a15.42,15.42,0,0,0,5.46,6.6,14.34,14.34,0,0,0,8.26,2.43,12.12,12.12,0,0,0,7.88-2.38,8.29,8.29,0,0,0,3-6.82,7.56,7.56,0,0,0-.81-3.45A10.34,10.34,0,0,0,68,76.64a12.28,12.28,0,0,0-3.15-2.09q-2.13-1.06-3.54-1.62c-.93-.37-2.31-.87-4.13-1.49-2.27-.8-4-1.42-5.11-1.88a37.85,37.85,0,0,1-4.48-2.25,16.48,16.48,0,0,1-4.17-3.16A15.19,15.19,0,0,1,40.86,60a14.8,14.8,0,0,1,4-16.79Q50,38.72,58.76,38.72c4.89,0,8.9,1.08,12.06,3.23a15.68,15.68,0,0,1,6.35,8.61L69,53.29a9.54,9.54,0,0,0-4-4.39,13.26,13.26,0,0,0-6.94-1.66,10.7,10.7,0,0,0-6.69,1.87A6.29,6.29,0,0,0,49,54.4a5.52,5.52,0,0,0,1.87,4.09,13,13,0,0,0,3.92,2.64c1.37.57,3.44,1.33,6.23,2.3,1.7.63,3,1.09,3.79,1.41s2,.83,3.62,1.57a25.58,25.58,0,0,1,3.66,2,32.87,32.87,0,0,1,3,2.43A13.09,13.09,0,0,1,77.64,74a18.05,18.05,0,0,1,1.53,3.84,17.42,17.42,0,0,1,.64,4.81q0,8.36-5.71,13.08T59.44,100.41Zm54.62-1L93.61,39.74h9.55l13.55,41.58a65.86,65.86,0,0,1,1.87,6.82,63.74,63.74,0,0,1,1.88-6.82l13.37-41.58h9.46L122.93,99.39Zm47.3,0V39.74h37v8.35H170.22V64.45h18.15V72.8H170.22V91h30v8.35Zm61.44,0V39.74h8.86V90.87h29.15v8.52Zm71.41-51.13V99.39h-8.86V48.26H268.47V39.74h42.61v8.52ZM329.4,99.39V39.74h37v8.35H338.27V64.45h18.15V72.8H338.27V91h30v8.35Z"/></svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

Loading…
Cancel
Save