update to zine v0.6.1

This commit is contained in:
Norman Köhring 2024-09-16 22:02:39 +02:00
parent 2e916d5111
commit e572f3d5c8
76 changed files with 1050 additions and 906 deletions

View file

@ -2,11 +2,28 @@ const std = @import("std");
const zine = @import("zine"); const zine = @import("zine");
pub fn build(b: *std.Build) !void { pub fn build(b: *std.Build) !void {
try zine.addWebsite(b, .{ zine.website(b, .{
.title = "the codeartist — programmer and engineer based in Berlin", .title = "the codeartist — programmer and engineer based in Berlin",
.host_url = "https://koehr.ing", .host_url = "https://koehr.ing",
.layouts_dir_path = "layouts", .layouts_dir_path = "layouts",
.content_dir_path = "content", .content_dir_path = "content",
.static_dir_path = "static", .assets_dir_path = "static",
.static_assets = &.{
"rubik-regular-minimal.woff2",
"posts.css",
"style.css",
"fediverse.svg",
"gitforge.svg",
"github.svg",
"header.jpg",
"instagram.svg",
"linkedin.svg",
"mail.svg",
"mastodon.svg",
"reddit.svg",
"threads.svg",
"twitter.svg",
},
.debug = false,
}); });
} }

View file

@ -3,8 +3,8 @@
.version = "0.0.0", .version = "0.0.0",
.dependencies = .{ .dependencies = .{
.zine = .{ .zine = .{
.url = "git+https://github.com/kristoff-it/zine#c4924570fa54ab204bb8b1bf1a140d0cc04ab08a", .url = "git+https://github.com/kristoff-it/zine?ref=v0.6.1#872c474b33dab2dd35e37bcf156149d20498197c",
.hash = "1220e2050b5fb6788675c0af6b2bfb601226fc90fb32aeeccc95cf9f4945543bd13a", .hash = "1220a59c2cf0e42a6f42cf1bf9b6a6c2691abfd91fcafa0e81a6282c4a197d05c41a",
}, },
}, },
.paths = .{"."}, .paths = .{"."},

View file

@ -4,7 +4,7 @@
.date = @date("2016-12-04T00:00:00"), .date = @date("2016-12-04T00:00:00"),
.author = "koehr", .author = "koehr",
.draft = false, .draft = false,
.layout = "page.html", .layout = "blog.shtml",
.description = "Nearly six years ago, I wrote about password complexity and showed how long it takes to crack passwords per length.", .description = "Nearly six years ago, I wrote about password complexity and showed how long it takes to crack passwords per length.",
.tags = [], .tags = [],
} }

View file

@ -4,7 +4,7 @@
.date = @date("2017-04-09T00:00:00"), .date = @date("2017-04-09T00:00:00"),
.author = "koehr", .author = "koehr",
.draft = false, .draft = false,
.layout = "page.html", .layout = "blog.shtml",
.description = "I built a web application with file upload functionality. Some Vue.js in the front and a CouchDB in the back. Everything should be pretty simple and straigt forward. But…", .description = "I built a web application with file upload functionality. Some Vue.js in the front and a CouchDB in the back. Everything should be pretty simple and straigt forward. But…",
.tags = [], .tags = [],
} }

View file

@ -4,16 +4,17 @@
.date = @date("2017-08-17T00:00:00"), .date = @date("2017-08-17T00:00:00"),
.author = "koehr", .author = "koehr",
.draft = false, .draft = false,
.layout = "page.html", .layout = "blog.shtml",
.description = "Vuejs is the star newcomer in the Javascript Framework world. People love how it makes complicated things very simple yet performant. One of the more exciting features is its seemingly magic reactivity. Plain data objects in components magically invoke a rerender when a property changes.", .description = "Vuejs is the star newcomer in the Javascript Framework world. People love how it makes complicated things very simple yet performant. One of the more exciting features is its seemingly magic reactivity. Plain data objects in components magically invoke a rerender when a property changes.",
.tags = [], .tags = [],
} }
--- ---
<style>iframe{width:640px;max-width:100%;height:30em;}</style>
_NOTE_: This is a copy of the original article from Aug 17th, 2017. You can [read the archived original on archive.org](https://web.archive.org/web/20190113013559/https://log.koehr.in/2017/08/17/vuejs-reactivity-from-scratch) _NOTE_: This is a copy of the original article from Aug 17th, 2017. You can [read the archived original on archive.org](https://web.archive.org/web/20190113013559/https://log.koehr.in/2017/08/17/vuejs-reactivity-from-scratch)
```=html
<iframe src="https://jsfiddle.net/ajwchnko/embedded/?username=koehr" width="640" height="400" frameborder="0" sandbox="allow-modals allow-forms allow-scripts allow-same-origin allow-popups"></iframe> <iframe src="https://jsfiddle.net/ajwchnko/embedded/?username=koehr" width="640" height="400" frameborder="0" sandbox="allow-modals allow-forms allow-scripts allow-same-origin allow-popups"></iframe>
```
The button click invokes a function that just assigns a new value to a property. Still the template gets automagically rerendered. But we all know there is no fairydust involved, right? So how does it actually work? The button click invokes a function that just assigns a new value to a property. Still the template gets automagically rerendered. But we all know there is no fairydust involved, right? So how does it actually work?
@ -35,11 +36,15 @@ Abstract: A function that gets an object and returns one with the properties rep
Let's start with a very simple approach: Let's start with a very simple approach:
```=html
<iframe src="https://jsfiddle.net/e2q9vme3/embedded/?username=koehr" width="640" height="400" frameborder="0" sandbox="allow-modals allow-forms allow-scripts allow-same-origin allow-popups"></iframe> <iframe src="https://jsfiddle.net/e2q9vme3/embedded/?username=koehr" width="640" height="400" frameborder="0" sandbox="allow-modals allow-forms allow-scripts allow-same-origin allow-popups"></iframe>
```
The function iterates through all object keys and creates a new object with getters and setters in their place. It could also directly manipulate the original object: The function iterates through all object keys and creates a new object with getters and setters in their place. It could also directly manipulate the original object:
```=html
<iframe src="https://jsfiddle.net/k72aoorc/1/embedded/?username=koehr" width="640" height="400" frameborder="0" sandbox="allow-modals allow-forms allow-scripts allow-same-origin allow-popups"></iframe> <iframe src="https://jsfiddle.net/k72aoorc/1/embedded/?username=koehr" width="640" height="400" frameborder="0" sandbox="allow-modals allow-forms allow-scripts allow-same-origin allow-popups"></iframe>
```
I personally don't like to manipulate the existing object and prefer the first way. I personally don't like to manipulate the existing object and prefer the first way.
@ -49,7 +54,9 @@ Now before we go on with destroying our fantasies of fairydust computing, let's
With this new knowlegde, the code can be made a bit more readable, by condensing everything into one call: With this new knowlegde, the code can be made a bit more readable, by condensing everything into one call:
```=html
<iframe src="https://jsfiddle.net/e2q9vme3/2/embedded/?username=koehr" width="640" height="400" frameborder="0" sandbox="allow-modals allow-forms allow-scripts allow-same-origin allow-popups"></iframe> <iframe src="https://jsfiddle.net/e2q9vme3/2/embedded/?username=koehr" width="640" height="400" frameborder="0" sandbox="allow-modals allow-forms allow-scripts allow-same-origin allow-popups"></iframe>
```
All those underscores where pretty annoying anyways. I generally suggest you to read more about `Object.defineProperty`. It extends the range of possibilities significantly! All those underscores where pretty annoying anyways. I generally suggest you to read more about `Object.defineProperty`. It extends the range of possibilities significantly!
@ -57,7 +64,9 @@ All those underscores where pretty annoying anyways. I generally suggest you to
To be able to rerender a component on data change, we should really introduce some components that can actually render and under the right circumstances rerender a template. To be able to rerender a component on data change, we should really introduce some components that can actually render and under the right circumstances rerender a template.
```=html
<iframe src="https://jsfiddle.net/e2q9vme3/3/embedded/?username=koehr" width="640" height="400" frameborder="0" sandbox="allow-modals allow-forms allow-scripts allow-same-origin allow-popups"></iframe> <iframe src="https://jsfiddle.net/e2q9vme3/3/embedded/?username=koehr" width="640" height="400" frameborder="0" sandbox="allow-modals allow-forms allow-scripts allow-same-origin allow-popups"></iframe>
```
This code describes a very simple component, that has a data object and a render function. If this is called, it replaces the `innerHTML` of the given content element with the rendered output. Neat! Let's make the data reactive! This code describes a very simple component, that has a data object and a render function. If this is called, it replaces the `innerHTML` of the given content element with the rendered output. Neat! Let's make the data reactive!
@ -65,15 +74,21 @@ This code describes a very simple component, that has a data object and a render
As a start, it should be enough to simply make the data property reactive: As a start, it should be enough to simply make the data property reactive:
```=html
<iframe src="https://jsfiddle.net/e2q9vme3/4/embedded/?username=koehr" width="640" height="400" frameborder="0" sandbox="allow-modals allow-forms allow-scripts allow-same-origin allow-popups"></iframe> <iframe src="https://jsfiddle.net/e2q9vme3/4/embedded/?username=koehr" width="640" height="400" frameborder="0" sandbox="allow-modals allow-forms allow-scripts allow-same-origin allow-popups"></iframe>
```
Yes, that seems to be good but it doesn't really update the template. Which becomes clear after a look at line 11-14: There is no render call ever. But `reactive` shouldn't know about component rendering, right? Let's try a more general approach with a callback: Yes, that seems to be good but it doesn't really update the template. Which becomes clear after a look at line 11-14: There is no render call ever. But `reactive` shouldn't know about component rendering, right? Let's try a more general approach with a callback:
```=html
<iframe src="https://jsfiddle.net/e2q9vme3/5/embedded/?username=koehr" width="640" height="400" frameborder="0" sandbox="allow-modals allow-forms allow-scripts allow-same-origin allow-popups"></iframe> <iframe src="https://jsfiddle.net/e2q9vme3/5/embedded/?username=koehr" width="640" height="400" frameborder="0" sandbox="allow-modals allow-forms allow-scripts allow-same-origin allow-popups"></iframe>
```
Yeah, that works and so on but it looks like we slowly stumble away from elegance in our code. The changes in `reactive()` seem to be okay, but that function bind monstrosity in line 31 is something we better hide from our parents. Let's introduce a component factory before we get kicked out or end up in self hatred: Yeah, that works and so on but it looks like we slowly stumble away from elegance in our code. The changes in `reactive()` seem to be okay, but that function bind monstrosity in line 31 is something we better hide from our parents. Let's introduce a component factory before we get kicked out or end up in self hatred:
```=html
<iframe src="https://jsfiddle.net/e2q9vme3/6/embedded/?username=koehr" width="640" height="400" frameborder="0" sandbox="allow-modals allow-forms allow-scripts allow-same-origin allow-popups"></iframe> <iframe src="https://jsfiddle.net/e2q9vme3/6/embedded/?username=koehr" width="640" height="400" frameborder="0" sandbox="allow-modals allow-forms allow-scripts allow-same-origin allow-popups"></iframe>
```
Cool! That works. The `createComponent()` function just does all the dirty work for us and returns a nice, reactive component, that is still just a simple object. If you have that code in a local setup and run something like `component.data.name = 'Ada Lovelace'`, then it will automagically rerender the template to show 'Hello Ada Lovelace'. Cool! That works. The `createComponent()` function just does all the dirty work for us and returns a nice, reactive component, that is still just a simple object. If you have that code in a local setup and run something like `component.data.name = 'Ada Lovelace'`, then it will automagically rerender the template to show 'Hello Ada Lovelace'.
@ -81,15 +96,21 @@ Cool! That works. The `createComponent()` function just does all the dirty work
All cool and hip stuff but what happens in the following scenario: All cool and hip stuff but what happens in the following scenario:
```=html
<iframe src="https://jsfiddle.net/e2q9vme3/7/embedded/?username=koehr" width="640" height="400" frameborder="0" sandbox="allow-modals allow-forms allow-scripts allow-same-origin allow-popups"></iframe> <iframe src="https://jsfiddle.net/e2q9vme3/7/embedded/?username=koehr" width="640" height="400" frameborder="0" sandbox="allow-modals allow-forms allow-scripts allow-same-origin allow-popups"></iframe>
```
Setting deeper nested properties (line 44,45) doesn't work at all. The reason is that the reactivity only works on the first nesting level of the data object. Now you could say: Easy, we just set the whole object at once: Setting deeper nested properties (line 44,45) doesn't work at all. The reason is that the reactivity only works on the first nesting level of the data object. Now you could say: Easy, we just set the whole object at once:
```=html
<iframe src="https://jsfiddle.net/e2q9vme3/8/embedded/?username=koehr" width="640" height="400" frameborder="0" sandbox="allow-modals allow-forms allow-scripts allow-same-origin allow-popups"></iframe> <iframe src="https://jsfiddle.net/e2q9vme3/8/embedded/?username=koehr" width="640" height="400" frameborder="0" sandbox="allow-modals allow-forms allow-scripts allow-same-origin allow-popups"></iframe>
```
But this is not really what we strive for, isn't it? What we need is a way that makes all nested objects reactive in a recursive way. Surprisingly, this just needs a coupe of lines: But this is not really what we strive for, isn't it? What we need is a way that makes all nested objects reactive in a recursive way. Surprisingly, this just needs a coupe of lines:
```=html
<iframe src="https://jsfiddle.net/e2q9vme3/9/embedded/?username=koehr" width="640" height="400" frameborder="0" sandbox="allow-modals allow-forms allow-scripts allow-same-origin allow-popups"></iframe> <iframe src="https://jsfiddle.net/e2q9vme3/9/embedded/?username=koehr" width="640" height="400" frameborder="0" sandbox="allow-modals allow-forms allow-scripts allow-same-origin allow-popups"></iframe>
```
Only three lines (7-9) where added. They call `reactive()` on the given value in case it is an object. Now the nesting level doesn't matter anymore. REACTIVE ALL THE THINGS!! Only three lines (7-9) where added. They call `reactive()` on the given value in case it is an object. Now the nesting level doesn't matter anymore. REACTIVE ALL THE THINGS!!
@ -97,7 +118,9 @@ Only three lines (7-9) where added. They call `reactive()` on the given value in
Considering that components are usually very gregarious, what happens if we find a friend for our component? Will it blend? Erm I mean, react? Considering that components are usually very gregarious, what happens if we find a friend for our component? Will it blend? Erm I mean, react?
```=html
<iframe src="https://jsfiddle.net/e2q9vme3/10/embedded/?username=koehr" width="640" height="400" frameborder="0" sandbox="allow-modals allow-forms allow-scripts allow-same-origin allow-popups"></iframe> <iframe src="https://jsfiddle.net/e2q9vme3/10/embedded/?username=koehr" width="640" height="400" frameborder="0" sandbox="allow-modals allow-forms allow-scripts allow-same-origin allow-popups"></iframe>
```
It does! Hooray! It does! Hooray!
@ -105,7 +128,9 @@ The attentive reader might have seen the change that sneaked into line 7: Becaus
But what happens now when we manipulate the Array directly? But what happens now when we manipulate the Array directly?
```=html
<iframe src="https://jsfiddle.net/e2q9vme3/11/embedded/?username=koehr" width="640" height="400" frameborder="0" sandbox="allow-modals allow-forms allow-scripts allow-same-origin allow-popups"></iframe> <iframe src="https://jsfiddle.net/e2q9vme3/11/embedded/?username=koehr" width="640" height="400" frameborder="0" sandbox="allow-modals allow-forms allow-scripts allow-same-origin allow-popups"></iframe>
```
Bummer! Setting the whole array works as expected but manipulating it doesn't trigger any change. Bummer! Setting the whole array works as expected but manipulating it doesn't trigger any change.
@ -120,7 +145,9 @@ Okay, fair enough. So what does happen in Vue to make Arrays reactive? Fairydust
Vuejs' approach is rather sophisticated but can be condensed down to something like what is seen in the first 24 lines here: Vuejs' approach is rather sophisticated but can be condensed down to something like what is seen in the first 24 lines here:
```=html
<iframe src="https://jsfiddle.net/e2q9vme3/12/embedded/?username=koehr" width="640" height="400" frameborder="0" sandbox="allow-modals allow-forms allow-scripts allow-same-origin allow-popups"></iframe> <iframe src="https://jsfiddle.net/e2q9vme3/12/embedded/?username=koehr" width="640" height="400" frameborder="0" sandbox="allow-modals allow-forms allow-scripts allow-same-origin allow-popups"></iframe>
```
So this is a fairly big chunk to digest. The new function `reactiveArray` starts with creating a copy of the original array (Remember? I don't like manipulating the original object). Then, for each function in the list of manipulative array functions the original is saved which is then replaced by a wrapper function. This wrapper function simply calls the render callback additionally to the original array function. So this is a fairly big chunk to digest. The new function `reactiveArray` starts with creating a copy of the original array (Remember? I don't like manipulating the original object). Then, for each function in the list of manipulative array functions the original is saved which is then replaced by a wrapper function. This wrapper function simply calls the render callback additionally to the original array function.
@ -130,7 +157,9 @@ Now also `lipsumComponent.data.content` is not set directly anymore but uses the
For now the setter function didn't care about the value. If it would be a nested object, its children wouldn't be reactive. That means, if you set `data.x` to an object `{foo: 1}` and then change foo `data.x.foo++`, the template wouldn't rerender. This should be changed: For now the setter function didn't care about the value. If it would be a nested object, its children wouldn't be reactive. That means, if you set `data.x` to an object `{foo: 1}` and then change foo `data.x.foo++`, the template wouldn't rerender. This should be changed:
```=html
<iframe src="https://jsfiddle.net/e2q9vme3/14/embedded/?username=koehr" width="640" height="400" frameborder="0" sandbox="allow-modals allow-forms allow-scripts allow-same-origin allow-popups"></iframe> <iframe src="https://jsfiddle.net/e2q9vme3/14/embedded/?username=koehr" width="640" height="400" frameborder="0" sandbox="allow-modals allow-forms allow-scripts allow-same-origin allow-popups"></iframe>
```
Instead of setting the plain value, `reactive(value, callback)` is called in line 49. This small change works only up to a certain point on its own though. The function has to decide what to do with non-objects or arrays, which happens now as a first step in `reactive()`. A plain non-object (remember: arrays are objects) simply gets returned as it is (line 30), arrays will be returned in their reactive version (line 31). Instead of setting the plain value, `reactive(value, callback)` is called in line 49. This small change works only up to a certain point on its own though. The function has to decide what to do with non-objects or arrays, which happens now as a first step in `reactive()`. A plain non-object (remember: arrays are objects) simply gets returned as it is (line 30), arrays will be returned in their reactive version (line 31).

View file

@ -4,7 +4,7 @@
.date = @date("2019-01-10T00:00:00"), .date = @date("2019-01-10T00:00:00"),
.author = "koehr", .author = "koehr",
.draft = false, .draft = false,
.layout = "page.html", .layout = "blog.shtml",
.description = "What was necessary to make cross-compiling work for newer WriteFreely versions with SQLite support.", .description = "What was necessary to make cross-compiling work for newer WriteFreely versions with SQLite support.",
.tags = [], .tags = [],
} }

View file

@ -4,7 +4,7 @@
.date = @date("2019-01-10T00:00:00"), .date = @date("2019-01-10T00:00:00"),
.author = "koehr", .author = "koehr",
.draft = false, .draft = false,
.layout = "page.html", .layout = "blog.shtml",
.description = "Yesterday Frederic Cambus changed the default console font in OpenBSD to his self made font.", .description = "Yesterday Frederic Cambus changed the default console font in OpenBSD to his self made font.",
.tags = [], .tags = [],
} }

View file

@ -4,7 +4,7 @@
.date = @date("2019-05-03T00:00:00"), .date = @date("2019-05-03T00:00:00"),
.author = "koehr", .author = "koehr",
.draft = false, .draft = false,
.layout = "page.html", .layout = "blog.shtml",
.description = "I will tell you how I created a simple top-down shooter in JavaScript without using any additional libraries. But this article is not replicating the full game but instead tries to show which steps to take to start writing a game from scratch.", .description = "I will tell you how I created a simple top-down shooter in JavaScript without using any additional libraries. But this article is not replicating the full game but instead tries to show which steps to take to start writing a game from scratch.",
.tags = [], .tags = [],
} }
@ -19,7 +19,7 @@ To share some of the fun, I created a tiny top down shooter for a tech session i
To give you an impression of what I created: To give you an impression of what I created:
![screenshot](https://github.com/nkoehring/FreddyvsJSON/raw/master/screenshot.jpg) ![screenshot](screenshot.jpg)
The little gray box is your ship. You are controlling the little gray box with either WASD or Arrow keys and you can shoot tiny yellow boxes at your enemies — the red boxes — by pressing Space or Enter. The enemies shoot back though. They don't really aim well, but at some point they'll flood the screen with tiny red boxes. If they hit you, they hurt. Every time you get hurt you shrink, until you completely disappear. The same happens with your opponents. The little gray box is your ship. You are controlling the little gray box with either WASD or Arrow keys and you can shoot tiny yellow boxes at your enemies — the red boxes — by pressing Space or Enter. The enemies shoot back though. They don't really aim well, but at some point they'll flood the screen with tiny red boxes. If they hit you, they hurt. Every time you get hurt you shrink, until you completely disappear. The same happens with your opponents.
@ -348,7 +348,7 @@ class Game {
Now the boxes are only drawn while holding down the mouse button. Boom, one step closer to the ease of use of Photoshop! It is incredible, what you can do with it already. Just check out this incredible piece of art: Now the boxes are only drawn while holding down the mouse button. Boom, one step closer to the ease of use of Photoshop! It is incredible, what you can do with it already. Just check out this incredible piece of art:
![incredible piece of art](https://github.com/nkoehring/FreddyvsJSON/raw/master/blogpost/drawing.jpg) ![incredible piece of art](drawing.jpg)
### Key Events ### Key Events

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

View file

@ -4,7 +4,7 @@
.date = @date("2020-06-29T00:00:00"), .date = @date("2020-06-29T00:00:00"),
.author = "koehr", .author = "koehr",
.draft = false, .draft = false,
.layout = "page.html", .layout = "blog.shtml",
.description = "I've built a store implementation that allows name-spaced actions and helps with the separation of concerns. The new Composition API in Vue3 also allows completely new, convenient ways of using it.", .description = "I've built a store implementation that allows name-spaced actions and helps with the separation of concerns. The new Composition API in Vue3 also allows completely new, convenient ways of using it.",
.tags = [], .tags = [],
} }

View file

@ -0,0 +1,17 @@
---
{
.title = "Search Engine Alternatives",
.date = @date("2024-09-14T00:00:00"),
.author = "koehr",
.draft = true,
.layout = "blog.shtml",
.description = "Trying to avoid Google Search? Lets talk about alternatives!",
.tags = [],
}
---
It is
https://clew.se/about/
https://mwmbl.org/

View file

@ -4,7 +4,7 @@
.date = @date("2024-05-13T00:00:00"), .date = @date("2024-05-13T00:00:00"),
.author = "koehr", .author = "koehr",
.draft = false, .draft = false,
.layout = "blog.html", .layout = "blog.shtml",
.description = "Sometimes, I write long-form articles about a topic that I find interesting. I use this as a way to dive deeper into a topic, while often create an example project on the side.", .description = "Sometimes, I write long-form articles about a topic that I find interesting. I use this as a way to dive deeper into a topic, while often create an example project on the side.",
.tags = [], .tags = [],
} }

View file

@ -4,7 +4,7 @@
.date = @date("2024-07-16T00:00:00"), .date = @date("2024-07-16T00:00:00"),
.author = "koehr", .author = "koehr",
.draft = false, .draft = false,
.layout = "page.html", .layout = "page.shtml",
.description = "Websites that inspired me, that I think are worth reading, useful and I don't want to forget about.", .description = "Websites that inspired me, that I think are worth reading, useful and I don't want to forget about.",
.tags = [], .tags = [],
} }

View file

@ -4,7 +4,7 @@
.date = @date("2024-05-20T00:00:00"), .date = @date("2024-05-20T00:00:00"),
.author = "koehr", .author = "koehr",
.draft = false, .draft = false,
.layout = "page.html", .layout = "page.shtml",
.description = "My Curriculum Vitae / Résumé. I know, there is a difference. This page is technically a résumé, while the whole site would be closer to a CV.", .description = "My Curriculum Vitae / Résumé. I know, there is a difference. This page is technically a résumé, while the whole site would be closer to a CV.",
.tags = [], .tags = [],
} }

View file

@ -4,7 +4,7 @@
.date = @date("2024-06-16T00:00:00"), .date = @date("2024-06-16T00:00:00"),
.author = "koehr", .author = "koehr",
.draft = false, .draft = false,
.layout = "homepage.html", .layout = "homepage.shtml",
.description = "", .description = "",
.tags = [], .tags = [],
} }
@ -29,28 +29,3 @@ Im the organizer of Vuejs // Berlin, a monthly meetup group around Vue and we
Many people want to learn and grow. Whenever I can I try to help those people by sharing my experience and knowledge. I already voluntarily coached at Code Curious, Frauenloop and Jugend Hackt. I also helped children with their first steps into the world of programming at the Berlin CoderDojo. Many people want to learn and grow. Whenever I can I try to help those people by sharing my experience and knowledge. I already voluntarily coached at Code Curious, Frauenloop and Jugend Hackt. I also helped children with their first steps into the world of programming at the Berlin CoderDojo.
# contact
> You can find me all over the interwebs
<div id="contact" class="contacts">
<img title="Mail" src="/mail.svg" /> n@[thisdomain]
<img title="Fediverse / Mastodon" src="/fediverse.svg" /> [@Koehr\@mstdn.io](https://mstdn.io/@Koehr/)
<img title="Gitforge" src="/gitforge.svg" /> [git.k0r.in](https://git.k0r.in/)
<img title="LinkedIn" src="/linkedin.svg" /> [Norman Köhring](https://linkedin.com/in/norman-köhring-950448109/)
<img title="Instagram" src="/instagram.svg" /> [coffee_n_code](https://instagram.com/coffee_n_code/)
<img title="Threads" src="/threads.svg" /> [coffee_n_code](https://threads.net/@coffee_n_code/)
<img title="Reddit" src="/reddit.svg" /> [/u/koehr](https://www.reddit.com/user/koehr/)
<img title="Github" src="/github.svg" /> [nkoehring](https://github.com/nkoehring/)
<img title="Twitter" src="/twitter.svg" /> [koehr_in](https://twitter.com/koehr_in/)
</div>

View file

@ -4,7 +4,7 @@
.date = @date("2024-08-18T00:00:00"), .date = @date("2024-08-18T00:00:00"),
.author = "koehr", .author = "koehr",
.draft = false, .draft = false,
.layout = "page.html", .layout = "page.shtml",
.description = "This page shows what I'm up to at the moment, following the idea of Derek Sivers.", .description = "This page shows what I'm up to at the moment, following the idea of Derek Sivers.",
.tags = [], .tags = [],
} }

View file

@ -4,7 +4,7 @@
.date = @date("2024-07-15T00:00:00"), .date = @date("2024-07-15T00:00:00"),
.author = "koehr", .author = "koehr",
.draft = false, .draft = false,
.layout = "page.html", .layout = "page.shtml",
.description = "Stuff I made. This is mostly about software, but might also include some TTRPG related things, from time to time.", .description = "Stuff I made. This is mostly about software, but might also include some TTRPG related things, from time to time.",
.tags = [], .tags = [],
} }
@ -14,7 +14,7 @@ I tend to host my code on multiple places, typically [Sourcehut](https://sr.ht)
## 250kB Club [🔗](https://250kb.club) ## 250kB Club [🔗](https://250kb.club)
<img src="250kb.jpg" title="250kB Club Screenshot" alt="250kB Club Screenshot" /> [250kB Club Screenshot]($image.asset('250kb.jpg').title('250kB Club'))
I am the creator of 250kB Club, which should actually be called 256kb.club, but that thought reached me only after I got the domain. I am the creator of 250kB Club, which should actually be called 256kb.club, but that thought reached me only after I got the domain.
@ -24,7 +24,7 @@ Source code: [github](https://github.com/nkoehring/250kb-club), [sourcehut](http
## Starsy [🔗](https://starsy.netlify.app) ## Starsy [🔗](https://starsy.netlify.app)
<img src="starsy.jpg" title="Starsy Screenshot" alt="Starsy Screenshot" /> [Starsy Screenshot]($image.asset('starsy.jpg').title('Starsy'))
For a hard sci-fi campaign setting, I once planned, I created this star system generator. I wanted to recreate the style of some image I found on reddit, a while ago. For a hard sci-fi campaign setting, I once planned, I created this star system generator. I wanted to recreate the style of some image I found on reddit, a while ago.
@ -32,7 +32,7 @@ Source code: [github](https://github.com/nkoehring/starsy), [selfhosted](https:/
## RPG-Cards-ng [🔗](https://rpg-cards-ng.netlify.app) ## RPG-Cards-ng [🔗](https://rpg-cards-ng.netlify.app)
<img src="rpgcards.jpg" title="RPG-Cards-ng Screenshot" alt="RPG-Cards-ng Screenshot" /> [RPG-Cards-ng Screenshot]($image.asset('rpgcards.jpg').title('RPG-Cards-ng'))
I wanted to be able to create good looking cards for RPG sessions but didn't find a good tool that makes designing them simple and intuitive. So I created my own tool. I wanted to be able to create good looking cards for RPG sessions but didn't find a good tool that makes designing them simple and intuitive. So I created my own tool.
@ -40,7 +40,7 @@ Source code: [github](https://github.com/nkoehring/rpg-cards-ng), [selfhosted](h
## Vuejs//Berlin [🔗](https://vuejs.berlin) ## Vuejs//Berlin [🔗](https://vuejs.berlin)
<img src="vuejsberlin.jpg" title="Vuejs Berlin Screenshot" alt="Vuejs Berlin Screenshot" /> [Vue.js Berlin Screenshot]($image.asset('vuejsberlin.jpg').title('Vuejs//Berlin'))
I host the monthly Vuejs//Berlin meetup and created this homepage to publish details about the upcoming and former meetups. It also hosts a newsletter archive. I host the monthly Vuejs//Berlin meetup and created this homepage to publish details about the upcoming and former meetups. It also hosts a newsletter archive.

View file

@ -4,7 +4,7 @@
.date = @date("2024-05-20T00:00:00"), .date = @date("2024-05-20T00:00:00"),
.author = "koehr", .author = "koehr",
.draft = false, .draft = false,
.layout = "page.html", .layout = "page.shtml",
.description = "As a software engineer, the tools I use define how I work and I find it inspiring to see which tools other people use.", .description = "As a software engineer, the tools I use define how I work and I find it inspiring to see which tools other people use.",
.tags = [], .tags = [],
} }

View file

@ -4,7 +4,7 @@
.date = @date("2024-08-30T00:00:00"), .date = @date("2024-08-30T00:00:00"),
.author = "koehr", .author = "koehr",
.draft = false, .draft = false,
.layout = "page.html", .layout = "page.shtml",
.description = "As a software engineer, the tools I use define how I work and I find it inspiring to see which tools other people use.", .description = "As a software engineer, the tools I use define how I work and I find it inspiring to see which tools other people use.",
.tags = [], .tags = [],
} }
@ -34,13 +34,13 @@ My work laptop has a GNOME desktop with some extensions, that make it work well
Most of my life, I used [ViM](https://www.vim.org/). It made me more productive and helped me to focus on the things that matter most for my productivity. One day, I found [Kakoune](https://kakoune.org), which blew me away by being so similar and yet different to ViM, in a (in my opinion) good way. What Kakoune does is to to switch around the command order. While ViM's command language is VERB-MODIFIER-OBJECT. For example: `d2w` means delete two words. Kakoune switches that to MODIFIER-VERB-OBJECT and introduces selecting and non-selecting movement, which allows you to see your selection before applying an action. `d2w` changes to `2Wd`, which translates to select next two words, then delete them. I finally settled with [Helix](https://helix-editor.com/), an editor that uses Kakounes command language, but implements many useful things by default, while still being very configurable. Most of my life, I used [ViM](https://www.vim.org/). It made me more productive and helped me to focus on the things that matter most for my productivity. One day, I found [Kakoune](https://kakoune.org), which blew me away by being so similar and yet different to ViM, in a (in my opinion) good way. What Kakoune does is to to switch around the command order. While ViM's command language is VERB-MODIFIER-OBJECT. For example: `d2w` means delete two words. Kakoune switches that to MODIFIER-VERB-OBJECT and introduces selecting and non-selecting movement, which allows you to see your selection before applying an action. `d2w` changes to `2Wd`, which translates to select next two words, then delete them. I finally settled with [Helix](https://helix-editor.com/), an editor that uses Kakounes command language, but implements many useful things by default, while still being very configurable.
## Terminal: foot + zellij + zsh + starship ## Terminal: foot + <s>zellij</s> tmux + zsh + starship
Almost all of my day-to-day applications are in the terminal. I am so used to it, that I started trusting GUI applications less. This is obviously my issue, but luckily I'm not alone, so many great CLI applications exist. Almost all of my day-to-day applications are in the terminal. I am so used to it, that I started trusting GUI applications less. This is obviously my issue, but luckily I'm not alone, so many great CLI applications exist.
I use [foot](https://codeberg.org/dnkl/foot) as terminal emulator. It is lightweight, supports 24bit colours and works with Wayland. I use [foot](https://codeberg.org/dnkl/foot) as terminal emulator. It is lightweight, supports 24bit colours and works with Wayland.
Inside foot runs [zellij](https://zellij.dev/), which is a terminal multiplexer similar to [screen](https://www.gnu.org/software/screen/) and [tmux](https://github.com/tmux/tmux/wiki). It allows me to run multiple applications in one terminal, keeps sessions alive after closing the terminal emulator and so on. I actually configured zellij to feel a lot more like tmux, because I'm so used to the latter and honestly I might just switch back to tmux, who knows. Inside foot runs [tmux](https://github.com/tmux/tmux/wiki), which is a terminal multiplexer similar to [screen](https://www.gnu.org/software/screen/) and [zellij](https://zellij.dev). It allows me to run multiple applications in one terminal, keeps sessions alive after closing the terminal emulator and so on. I tried the newer zellij for a bit, but ended up configuring it to feel a lot more like tmux, because I'm so used to it and eventually I switched back to tmux.
My shell of choice is [zsh](https://www.zsh.org/) with [oh-my-zsh](https://ohmyz.sh/). It is by far the most versatile shell and the only one (to my knowledge) that supports RPROMPT, a prompts at the end of the line. My shell of choice is [zsh](https://www.zsh.org/) with [oh-my-zsh](https://ohmyz.sh/). It is by far the most versatile shell and the only one (to my knowledge) that supports RPROMPT, a prompts at the end of the line.

View file

@ -4,7 +4,7 @@
.date = @date("2021-08-31T00:00:00"), .date = @date("2021-08-31T00:00:00"),
.author = "koehr", .author = "koehr",
.draft = false, .draft = false,
.layout = "til.html", .layout = "til.shtml",
.description = "", .description = "",
.tags = [], .tags = [],
.custom = { .source = "https://www.w3schools.com/TAGS/tag_wbr.asp" }, .custom = { .source = "https://www.w3schools.com/TAGS/tag_wbr.asp" },

View file

@ -4,7 +4,7 @@
.date = @date("2021-09-03T00:00:00"), .date = @date("2021-09-03T00:00:00"),
.author = "koehr", .author = "koehr",
.draft = false, .draft = false,
.layout = "til.html", .layout = "til.shtml",
.description = "", .description = "",
.tags = [], .tags = [],
.custom = { .source = "https://www.theguardian.com/world/2001/oct/14/afghanistan.terrorism5" }, .custom = { .source = "https://www.theguardian.com/world/2001/oct/14/afghanistan.terrorism5" },

View file

@ -4,7 +4,7 @@
.date = @date("2021-09-04T00:00:00"), .date = @date("2021-09-04T00:00:00"),
.author = "koehr", .author = "koehr",
.draft = false, .draft = false,
.layout = "til.html", .layout = "til.shtml",
.description = "", .description = "",
.tags = [], .tags = [],
.custom = { .source = "https://twitter.com/lucas59356/status/1433507127570669569" }, .custom = { .source = "https://twitter.com/lucas59356/status/1433507127570669569" },

View file

@ -4,7 +4,7 @@
.date = @date("2021-09-05T00:00:00"), .date = @date("2021-09-05T00:00:00"),
.author = "koehr", .author = "koehr",
.draft = false, .draft = false,
.layout = "til.html", .layout = "til.shtml",
.description = "", .description = "",
.tags = [], .tags = [],
.custom = { .source = "https://twitter.com/claranellist/status/1433539284779220997" }, .custom = { .source = "https://twitter.com/claranellist/status/1433539284779220997" },

View file

@ -4,7 +4,7 @@
.date = @date("2022-02-22T00:00:00"), .date = @date("2022-02-22T00:00:00"),
.author = "koehr", .author = "koehr",
.draft = false, .draft = false,
.layout = "til.html", .layout = "til.shtml",
.description = "", .description = "",
.tags = [], .tags = [],
.custom = { .source = "" }, .custom = { .source = "" },

View file

@ -4,7 +4,7 @@
.date = @date("2022-03-22T00:00:00"), .date = @date("2022-03-22T00:00:00"),
.author = "koehr", .author = "koehr",
.draft = false, .draft = false,
.layout = "til.html", .layout = "til.shtml",
.description = "", .description = "",
.tags = [], .tags = [],
.custom = { .source = "https://www.kernel.org/doc/html/latest/filesystems/efivarfs.html" }, .custom = { .source = "https://www.kernel.org/doc/html/latest/filesystems/efivarfs.html" },

View file

@ -4,7 +4,7 @@
.date = @date("2022-03-28T00:00:00"), .date = @date("2022-03-28T00:00:00"),
.author = "koehr", .author = "koehr",
.draft = false, .draft = false,
.layout = "til.html", .layout = "til.shtml",
.description = "", .description = "",
.tags = [], .tags = [],
.custom = { .source = "https://twitter.com/mani_maranp/status/1508476973529825281)" }, .custom = { .source = "https://twitter.com/mani_maranp/status/1508476973529825281)" },

View file

@ -4,7 +4,7 @@
.date = @date("2022-04-25T00:00:00"), .date = @date("2022-04-25T00:00:00"),
.author = "koehr", .author = "koehr",
.draft = false, .draft = false,
.layout = "til.html", .layout = "til.shtml",
.description = "", .description = "",
.tags = [], .tags = [],
} }

View file

@ -4,7 +4,7 @@
.date = @date("2022-06-15T00:00:00"), .date = @date("2022-06-15T00:00:00"),
.author = "koehr", .author = "koehr",
.draft = false, .draft = false,
.layout = "til.html", .layout = "til.shtml",
.description = "", .description = "",
.tags = [], .tags = [],
} }

View file

@ -4,7 +4,7 @@
.date = @date("2024-05-11T00:00:00"), .date = @date("2024-05-11T00:00:00"),
.author = "koehr", .author = "koehr",
.draft = false, .draft = false,
.layout = "til.html", .layout = "til.shtml",
.description = "", .description = "",
.tags = [], .tags = [],
.custom = { .source = "https://users.ece.utexas.edu/~adnan/pike.html" }, .custom = { .source = "https://users.ece.utexas.edu/~adnan/pike.html" },

View file

@ -4,7 +4,7 @@
.date = @date("2024-05-12T00:00:00"), .date = @date("2024-05-12T00:00:00"),
.author = "koehr", .author = "koehr",
.draft = false, .draft = false,
.layout = "til.html", .layout = "til.shtml",
.description = "", .description = "",
.tags = [], .tags = [],
.custom = { .source = "https://stackoverflow.com/questions/6712034/sort-array-by-firstname-alphabetically-in-javascript" }, .custom = { .source = "https://stackoverflow.com/questions/6712034/sort-array-by-firstname-alphabetically-in-javascript" },

View file

@ -4,7 +4,7 @@
.date = @date("2024-05-13T00:00:00"), .date = @date("2024-05-13T00:00:00"),
.author = "koehr", .author = "koehr",
.draft = false, .draft = false,
.layout = "til.html", .layout = "til.shtml",
.description = "", .description = "",
.tags = [], .tags = [],
.custom = { .source = "https://thereadtime.com/" }, .custom = { .source = "https://thereadtime.com/" },

View file

@ -4,7 +4,7 @@
.date = @date("2024-09-06T00:00:00"), .date = @date("2024-09-06T00:00:00"),
.author = "koehr", .author = "koehr",
.draft = false, .draft = false,
.layout = "til.html", .layout = "til.shtml",
.description = "", .description = "",
.tags = [], .tags = [],
.custom = {}, .custom = {},

View file

@ -4,7 +4,7 @@
.date = @date("2024-05-13T00:00:00"), .date = @date("2024-05-13T00:00:00"),
.author = "koehr", .author = "koehr",
.draft = false, .draft = false,
.layout = "til.html", .layout = "til.shtml",
.description = "This page contains short notes and sometimes code snippets, of interesting things I just found out.", .description = "This page contains short notes and sometimes code snippets, of interesting things I just found out.",
.tags = [], .tags = [],
} }

View file

@ -1,34 +0,0 @@
<extend template=base.html />
<title id=title var=$page.title></title>
<head id=head>
<style>
.posts { padding: 0; }
.posts>li { display: block; margin: 2rem 0; }
.posts>li>div { line-height: 2; }
.posts>li>p { line-height: 1.4; }
.posts>li>time, .posts>li>div>.reading-time { color: gray; }
</style>
</head>
<main id=main>
<header>
<h1 var=$page.title></h1>
<em var=$page.description></em>
</header>
<div var=$page.content></div>
<ol class="posts">
<li loop=$page.subpages()>
<time datetime="$loop.it.date.formatHTTP()" var='$loop.it.date.format("January 02, 2006")'></time>
<div>
<a href="$loop.it.permalink()" var="$loop.it.title"></a>
(<span class="reading-time">~<span var="$loop.it.wordCount().div(183)"></span> mins</span>)
</div>
<p var=$page.description></p>
</li>
</ol>
</main>
<footer id=footer></footer>

34
layouts/blog.shtml Normal file
View file

@ -0,0 +1,34 @@
<extend template=base.shtml>
<title id=title :text=$page.title></title>
<head id=head>
<style>
.posts { padding: 0; }
.posts>li { display: block; margin: 2rem 0; }
.posts>li>div { line-height: 2; }
.posts>li>p { line-height: 1.4; }
.posts>li>time, .posts>li>div>.reading-time { color: gray; }
</style>
</head>
<main id=main>
<header>
<h1 :text=$page.title></h1>
<em :text=$page.description></em>
</header>
<div :html=$page.content()></div>
<ol class="posts">
<li :loop=$page.subpages()>
<time datetime="$loop.it.date.formatHTTP()" :text='$loop.it.date.format("January 02, 2006")'></time>
<div>
<a href="$loop.it.link()" :text="$loop.it.title"></a>
(<span class="reading-time">~<span :text="$loop.it.wordCount().div(183)"></span> mins</span>)
</div>
<p :text=$page.description></p>
</li>
</ol>
</main>
<footer id=footer></footer>

View file

@ -1,6 +1,6 @@
<extend template=base.html /> <extend template=base.shtml>
<title id=title var=$page.title></title> <title id=title :text=$page.title></title>
<head id=head></head> <head id=head></head>
<main id=main> <main id=main>
@ -47,8 +47,22 @@
</div> </div>
</div> </div>
<div id=content var=$page.content></div> <div id="content" :html=$page.content()></div>
<div id="contact">
<header><h1>contact</h1></header>
<ul class="contacts">
<li><img title="Mail" src="/mail.svg"> n@[thisdomain]</li>
<li><img title="Fediverse / Mastodon" src="/fediverse.svg"> <a href="https://mstdn.io/@Koehr/">@Koehr\@mstdn.io</a></li>
<li><img title="Gitforge" src="/gitforge.svg"> <a href="https://git.k0r.in/">git.k0r.in</a></li>
<li><img title="LinkedIn" src="/linkedin.svg"> <a href="https://linkedin.com/in/norman-köhring-950448109/">Norman Köhring</a></li>
<li><img title="Instagram" src="/instagram.svg"> <a href="https://instagram.com/coffee_n_code/">coffee_n_code</a></li>
<li><img title="Threads" src="/threads.svg"> <a href="https://threads.net/@coffee_n_code/">coffee_n_code</a></li>
<li><img title="Reddit" src="/reddit.svg"> <a href="https://www.reddit.com/user/koehr/">/u/koehr</a></li>
<li><img title="Github" src="/github.svg"> <a href="https://github.com/nkoehring/">nkoehring</a></li>
<li><img title="Twitter" src="/twitter.svg"> <a href="https://twitter.com/koehr_in/">koehr_in</a></li>
</ul>
</div>
<footer> <footer>
<a href="#intro">back to top</a> <a href="#intro">back to top</a>
</footer> </footer>

View file

@ -1,17 +0,0 @@
<extend template=base.html />
<title id=title var=$page.title></title>
<head id=head></head>
<main id=main>
<header>
<h1 var=$page.title></h1>
<em var=$page.description></em>
<br/>
Last updated: <time datetime="$page.date.formatHTTP()" var='$page.date.format("January 02, 2006")'></time>
</header>
<div var=$page.content></div>
</main>
<footer id="footer"></footer>

17
layouts/page.shtml Normal file
View file

@ -0,0 +1,17 @@
<extend template=base.shtml>
<title id=title :text=$page.title></title>
<head id=head></head>
<main id=main>
<header>
<h1 :text=$page.title></h1>
<em :text=$page.description></em>
<br>
Last updated: <time datetime="$page.date.formatHTTP()" :text='$page.date.format("January 02, 2006")'></time>
</header>
<div :html=$page.content()></div>
</main>
<footer id="footer"></footer>

View file

@ -3,7 +3,7 @@
<head id="head"> <head id="head">
<meta charset=utf-8> <meta charset=utf-8>
<title id=title var=$site.title><super/></title> <title id=title var=$site.title><super></title>
<meta name=description content="The personal page and weblog of Norman Köhring"> <meta name=description content="The personal page and weblog of Norman Köhring">
<meta name=author content="Norman Köhring"> <meta name=author content="Norman Köhring">
<meta name=DC.title content="the codeartist — programmer and engineer based in Berlin"> <meta name=DC.title content="the codeartist — programmer and engineer based in Berlin">
@ -15,8 +15,8 @@
<meta name="og:title" content="$page.title.suffix(' // the codeartist')"> <meta name="og:title" content="$page.title.suffix(' // the codeartist')">
<meta property="og:type" content="website"> <meta property="og:type" content="website">
<meta http-equiv="x-ua-compatible" content="ie=edge"/> <meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"/> <meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no">
<meta name=ICBM content="52.4595, 13.5335"> <meta name=ICBM content="52.4595, 13.5335">
<meta name=geo.position content="52.4595; 13.5335"> <meta name=geo.position content="52.4595; 13.5335">
@ -26,7 +26,7 @@
<link rel=me href=https://k0r.in> <link rel=me href=https://k0r.in>
<link rel=me href=https://koehr.ing> <link rel=me href=https://koehr.ing>
<link rel=me href=@Koehr@mstdn.io> <link rel=me href=@Koehr@mstdn.io>
<link rel=me href=https://sr.ht/~koehr/> <link rel=me href=https://sr.ht/~koehr>
<link rel=me href=https://git.k0r.in> <link rel=me href=https://git.k0r.in>
<link rel=me href=https://threads.net/@coffee_n_code> <link rel=me href=https://threads.net/@coffee_n_code>
<link rel=me href=https://instagram.com/@coffee_n_code> <link rel=me href=https://instagram.com/@coffee_n_code>
@ -34,13 +34,13 @@
<link rel=me href=https://reddit.com/user/koehr> <link rel=me href=https://reddit.com/user/koehr>
<link rel=icon href=/favicon.png type=image/x-icon> <link rel=icon href=/favicon.png type=image/x-icon>
<link rel=stylesheet href=/style.css> <link rel=stylesheet href=/style.css>
<super /> <super>
</head> </head>
<body> <body>
<main id="main"> <main id="main">
<super /> <super>
</main> </main>
<div id="spacer"></div> <div id="spacer"></div>
@ -48,21 +48,21 @@
<a href="/"> <a href="/">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 832.4 143.1"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 832.4 143.1">
<path id="header-underscore" <path id="header-underscore"
d="M832.4 131.1q0 5.5-3.1 8.6-3 3.4-8.2 3.3h-75.5q-5.2 0-8.2-3.3-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8 0-5.5 3.1-8.7 1.6-1.7 3.7-2.4 2.2-.8 4.5-.8h75.5q5.2 0 8.2 3.2 3 3.1 3 8.7z" /> d="M832.4 131.1q0 5.5-3.1 8.6-3 3.4-8.2 3.3h-75.5q-5.2 0-8.2-3.3-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8 0-5.5 3.1-8.7 1.6-1.7 3.7-2.4 2.2-.8 4.5-.8h75.5q5.2 0 8.2 3.2 3 3.1 3 8.7z"></path>
<path id="header-bracket" <path id="header-bracket"
d="M731.9 81.4q0 6.7-6.5 10.7l-1 .6-74.3 39.2q-2.5 1.3-5.2 1.2-4.8 0-8.1-3.8-3.2-3.6-3.2-8.4 0-3.3 1.7-6 1.8-2.9 4.6-4.4l55.3-29.1-55.3-29q-2.8-1.6-4.6-4.3-1.7-2.7-1.7-6.2 0-4.7 3.2-8.4 3.3-4 8-3.7 2.7 0 5.3 1.2l74.4 39.2q3.3 1.7 5.3 4.7 2 2.8 2 6.5z" /> d="M731.9 81.4q0 6.7-6.5 10.7l-1 .6-74.3 39.2q-2.5 1.3-5.2 1.2-4.8 0-8.1-3.8-3.2-3.6-3.2-8.4 0-3.3 1.7-6 1.8-2.9 4.6-4.4l55.3-29.1-55.3-29q-2.8-1.6-4.6-4.3-1.7-2.7-1.7-6.2 0-4.7 3.2-8.4 3.3-4 8-3.7 2.7 0 5.3 1.2l74.4 39.2q3.3 1.7 5.3 4.7 2 2.8 2 6.5z"></path>
<path id="header-r" <path id="header-r"
d="M588.7 66.5q0 5-3.5 8.5-3.5 3.4-8.1 3.5-4.4 0-8.3-4.3-10-10.7-20.9-10.6-2.2 0-4.3.3-2.1.3-4 1-1.8.6-3.7 1.6-1.7 1-3.4 2.3-1.7 1.3-3.3 2.9-7.8 8.2-7.6 19.7V131q0 5.5-3.1 8.6-3 3.4-8.3 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V51.6q0-5.4 3-8.6 3-3.4 8.3-3.3 2 0 3.7.6 1.8.6 3.3 1.8 1.4 1 2.2 2.7 1 1.5 1.6 3.3 11.8-8.4 27-8.4 10.6 0 21 5 11.3 5.4 17.2 14.5 2.5 3.7 2.5 7.3z" /> d="M588.7 66.5q0 5-3.5 8.5-3.5 3.4-8.1 3.5-4.4 0-8.3-4.3-10-10.7-20.9-10.6-2.2 0-4.3.3-2.1.3-4 1-1.8.6-3.7 1.6-1.7 1-3.4 2.3-1.7 1.3-3.3 2.9-7.8 8.2-7.6 19.7V131q0 5.5-3.1 8.6-3 3.4-8.3 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V51.6q0-5.4 3-8.6 3-3.4 8.3-3.3 2 0 3.7.6 1.8.6 3.3 1.8 1.4 1 2.2 2.7 1 1.5 1.6 3.3 11.8-8.4 27-8.4 10.6 0 21 5 11.3 5.4 17.2 14.5 2.5 3.7 2.5 7.3z"></path>
<path id="header-h" <path id="header-h"
d="M483.9 131.1q0 5.5-3.1 8.6-3 3.4-8.3 3.3-5.2 0-8.2-3.3-3.2-3.1-3.1-8.6V84.8q0-4.6-1.5-8.2-1.4-3.5-4.4-6.9-2.1-2-4.3-3.4-2.2-1.4-4.7-2-2.4-.7-5.3-.7-4.3 0-7.8 1.5-3.3 1.5-6.4 4.6-5.9 6.3-5.8 15v46.4q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v33q1.5-1 3-1.6l3.2-1.2 3.4-1q1.6-.5 3.3-.8l3.5-.4 3.6-.2q4.4 0 8.5 1 4.1.7 7.9 2.4 3.8 1.6 7.3 4.1 3.5 2.5 6.6 5.8Q484 66 484 84.8z" /> d="M483.9 131.1q0 5.5-3.1 8.6-3 3.4-8.3 3.3-5.2 0-8.2-3.3-3.2-3.1-3.1-8.6V84.8q0-4.6-1.5-8.2-1.4-3.5-4.4-6.9-2.1-2-4.3-3.4-2.2-1.4-4.7-2-2.4-.7-5.3-.7-4.3 0-7.8 1.5-3.3 1.5-6.4 4.6-5.9 6.3-5.8 15v46.4q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v33q1.5-1 3-1.6l3.2-1.2 3.4-1q1.6-.5 3.3-.8l3.5-.4 3.6-.2q4.4 0 8.5 1 4.1.7 7.9 2.4 3.8 1.6 7.3 4.1 3.5 2.5 6.6 5.8Q484 66 484 84.8z"></path>
<path id="header-e" <path id="header-e"
d="M387.5 111.1q0 1.2-.3 2.3-.1 1-.5 2l-.9 2q-6.6 12-19.4 19-12 6.6-25.4 6.6-20.8 0-35.8-14.6-15.9-15-15.9-37 0-22.1 15.9-37.1 15-14.6 35.8-14.6 3.9 0 7.8.7 4 .7 8 2.2 9.2 3.1 18.2 10 6 4.6 9.1 9.3 3.3 4.7 3.3 10 0 1.3-.3 2.5-.2 1.3-.7 2.4-1.5 3.4-5 5.3l-56.9 32.2q7.2 4.9 16.5 4.9 7.2 0 12.6-2.5 5.5-2.5 9.7-7.4l.7-1 .8-1 .9-1.3 1-1.5q3.3-4.2 7.4-5.1l1.8-.2q4.4 0 8 3.4 3.6 3.5 3.6 8.5zm-29.9-42.7q-7.2-4.8-16.6-4.8-6 0-11 2-4.9 1.8-9.3 6-4.5 4-6.7 9-2 4.8-2 10.8l.1 2.9z" /> d="M387.5 111.1q0 1.2-.3 2.3-.1 1-.5 2l-.9 2q-6.6 12-19.4 19-12 6.6-25.4 6.6-20.8 0-35.8-14.6-15.9-15-15.9-37 0-22.1 15.9-37.1 15-14.6 35.8-14.6 3.9 0 7.8.7 4 .7 8 2.2 9.2 3.1 18.2 10 6 4.6 9.1 9.3 3.3 4.7 3.3 10 0 1.3-.3 2.5-.2 1.3-.7 2.4-1.5 3.4-5 5.3l-56.9 32.2q7.2 4.9 16.5 4.9 7.2 0 12.6-2.5 5.5-2.5 9.7-7.4l.7-1 .8-1 .9-1.3 1-1.5q3.3-4.2 7.4-5.1l1.8-.2q4.4 0 8 3.4 3.6 3.5 3.6 8.5zm-29.9-42.7q-7.2-4.8-16.6-4.8-6 0-11 2-4.9 1.8-9.3 6-4.5 4-6.7 9-2 4.8-2 10.8l.1 2.9z"></path>
<path id="header-o" <path id="header-o"
d="M286.8 91.4q0 4.2-.6 8.3-.6 4-1.8 7.7-1.1 3.8-2.9 7.4-1.7 3.5-4 6.9-2.4 3.3-5.2 6.1Q258 143 237.7 143T203 128q-14.3-15.2-14.3-36.6 0-21.5 14.3-36.6 14.4-15 34.7-15 4 0 7.8.5 3.9.7 7.5 1.9t7 3q3.3 1.9 6.4 4.3 3.2 2.4 5.9 5.4 14.4 15 14.5 36.5zm-22.6 0q0-2.4-.4-4.5-.2-2.2-.9-4.2-.6-2-1.5-3.9-1-2-2.2-3.7-1.2-1.7-2.8-3.4-4-4.2-8.6-6.1-4.5-2-10-2-11 0-18.7 8.2-7.8 8-7.8 19.6 0 11.4 7.8 19.7 7.8 8 18.6 8 5.6 0 10.1-1.9 4.6-2 8.6-6.1 4-4.3 5.8-9 2-4.9 2-10.7z" /> d="M286.8 91.4q0 4.2-.6 8.3-.6 4-1.8 7.7-1.1 3.8-2.9 7.4-1.7 3.5-4 6.9-2.4 3.3-5.2 6.1Q258 143 237.7 143T203 128q-14.3-15.2-14.3-36.6 0-21.5 14.3-36.6 14.4-15 34.7-15 4 0 7.8.5 3.9.7 7.5 1.9t7 3q3.3 1.9 6.4 4.3 3.2 2.4 5.9 5.4 14.4 15 14.5 36.5zm-22.6 0q0-2.4-.4-4.5-.2-2.2-.9-4.2-.6-2-1.5-3.9-1-2-2.2-3.7-1.2-1.7-2.8-3.4-4-4.2-8.6-6.1-4.5-2-10-2-11 0-18.7 8.2-7.8 8-7.8 19.6 0 11.4 7.8 19.7 7.8 8 18.6 8 5.6 0 10.1-1.9 4.6-2 8.6-6.1 4-4.3 5.8-9 2-4.9 2-10.7z"></path>
<path id="header-k" <path id="header-k"
d="M186.3 131q0 4.7-3.3 8.3-1.5 1.8-3.7 2.7-2 1.1-4.3 1.1-3.5 0-6.6-2L119.2 105v26q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v65.9l49.2-36.1q3.2-2 6.6-2 4.7 0 8 3.7t3.3 8.4q-.2 6-5 9.6l-41 30 41 29.9q2.3 1.7 3.6 4.2 1.4 2.5 1.4 5.4z" /> d="M186.3 131q0 4.7-3.3 8.3-1.5 1.8-3.7 2.7-2 1.1-4.3 1.1-3.5 0-6.6-2L119.2 105v26q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v65.9l49.2-36.1q3.2-2 6.6-2 4.7 0 8 3.7t3.3 8.4q-.2 6-5 9.6l-41 30 41 29.9q2.3 1.7 3.6 4.2 1.4 2.5 1.4 5.4z"></path>
<path id="header-tilde" <path id="header-tilde"
d="M73.1 91q0 2-.6 3.9T71 98.6q-3.2 5.7-8.9 8.5-5.6 2.8-12.9 2.8-8.8 0-18-7.8-2.4-2.3-4.5-3.7-2.1-1.5-3-1.7-1.5 0-2.1.3l-.8 1.3q-.3.7-.8 1.2l-1 1-.9.8q-2.7 2-6.4 2-1.7 0-3.2-.3-1.4-.3-3-1.1-1.5-.8-2.6-2.1-2.8-3.1-2.8-8v-1.3q0-.7.2-1.2l.2-1 .4-1 .4-1q.1-.6.5-1.1l.5-1q3.2-5.7 8.8-8.5 5.7-2.9 13-2.9 3.2 0 6.2 1 3 .9 6 2.7 2.9 1.6 5.7 4.2 5.2 4.6 7.6 5.4 1 0 1.6-.2l.7-.4q.3-.1.5-.4 3.6-5.6 9.2-5.6 5.7 0 8.8 3.5 2.8 3 2.8 8z" /> d="M73.1 91q0 2-.6 3.9T71 98.6q-3.2 5.7-8.9 8.5-5.6 2.8-12.9 2.8-8.8 0-18-7.8-2.4-2.3-4.5-3.7-2.1-1.5-3-1.7-1.5 0-2.1.3l-.8 1.3q-.3.7-.8 1.2l-1 1-.9.8q-2.7 2-6.4 2-1.7 0-3.2-.3-1.4-.3-3-1.1-1.5-.8-2.6-2.1-2.8-3.1-2.8-8v-1.3q0-.7.2-1.2l.2-1 .4-1 .4-1q.1-.6.5-1.1l.5-1q3.2-5.7 8.8-8.5 5.7-2.9 13-2.9 3.2 0 6.2 1 3 .9 6 2.7 2.9 1.6 5.7 4.2 5.2 4.6 7.6 5.4 1 0 1.6-.2l.7-.4q.3-.1.5-.4 3.6-5.6 9.2-5.6 5.7 0 8.8 3.5 2.8 3 2.8 8z"></path>
</svg> </svg>
Homepage of Homepage of
<div class=p-name> <div class=p-name>
@ -85,7 +85,7 @@
</menu> </menu>
</div> </div>
<footer id="footer"> <footer id="footer">
<super /> <super>
</footer> </footer>
<script defer> <script defer>
const el = document.getElementById('header') const el = document.getElementById('header')

View file

@ -1,34 +0,0 @@
<extend template=base.html />
<title id=title var=$page.title></title>
<head id=head>
<style>
.til { padding: 0; }
.til>li { display: block; margin: 2rem 0; }
.til>li>div { line-height: 2; }
.til>li>time, .til>li>div>a.external { color: gray; }
</style>
</head>
<main id=main>
<header>
<h1 var=$page.title></h1>
<em var=$page.description></em>
<br/>
Last updated: <time datetime="$page.date.formatHTTP()" var='$page.date.format("January 02, 2006")'></time>
</header>
<div var=$page.content></div>
<ol class="til">
<li loop=$page.subpages()>
<time datetime="$loop.it.date.formatHTTP()" var='$loop.it.date.format("January 02, 2006")'></time>
<div>
<a href="$loop.it.permalink()" var="$loop.it.title"></a>
(<a rel="nofollow noopener" class="external" href="$page.custom.get('source', '#')">source</a>)
</div>
</li>
</ol>
</main>
<footer id=footer></footer>

36
layouts/til.shtml Normal file
View file

@ -0,0 +1,36 @@
<extend template=base.shtml>
<title id=title :title=$page.title></title>
<head id=head>
<style>
.til { padding: 0; }
.til>li { display: block; margin: 2rem 0; }
.til>li>div { line-height: 2; }
.til>li>time, .til>li>div>a.external { color: gray; }
</style>
</head>
<main id=main>
<header>
<h1 :title=$page.title></h1>
<em :title=$page.description></em>
<br>
Last updated: <time datetime="$page.date.formatHTTP()" :title='$page.date.format("January 02, 2006")'></time>
</header>
<div :html=$page.content()></div>
<ol class="til">
<li :loop=$page.subpages()>
<time datetime="$loop.it.date.formatHTTP()" :text='$loop.it.date.format("January 02, 2006")'></time>
<div>
<a href="$loop.it.link()" :text="$loop.it.title"></a>
<ctx :if="$page.custom.get?('source')">
(<a rel="nofollow noopener" class="external" href="$if">source</a>)
</ctx>
</div>
</li>
</ol>
</main>
<footer id=footer></footer>

View file

@ -161,6 +161,7 @@ code {
padding-top: 2rem; padding-top: 2rem;
} }
#content>h1, #content>h1,
#contact h1,
main > header > h1 { main > header > h1 {
margin: 0 0 .25em; margin: 0 0 .25em;
font-size: 2rem; font-size: 2rem;
@ -168,7 +169,8 @@ main > header > h1 {
text-shadow: 1px 1px 0 var(--emboss-color); text-shadow: 1px 1px 0 var(--emboss-color);
color: var(--header-fg-color); color: var(--header-fg-color);
} }
#content>h1 { #content>h1,
#contact h1 {
padding-top: 2em; padding-top: 2em;
} }
h2 { h2 {
@ -221,7 +223,8 @@ h2 {
column-fill: balance; column-fill: balance;
} }
.contacts p {
.contacts>li {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 1rem; gap: 1rem;
@ -322,3 +325,4 @@ span[title] {
columns: 1; columns: 1;
} }
} }
iframe{width:640px;max-width:100%;height:30em;}

View file

@ -3,7 +3,7 @@
<head id="head"> <head id="head">
<meta charset=utf-8> <meta charset=utf-8>
<title id=title >the codeartist — programmer and engineer based in BerlinThe price to crack your password</title> <title id="title " var="the codeartist — programmer and engineer based in Berlin">The price to crack your password</title>
<meta name=description content="The personal page and weblog of Norman Köhring"> <meta name=description content="The personal page and weblog of Norman Köhring">
<meta name=author content="Norman Köhring"> <meta name=author content="Norman Köhring">
<meta name=DC.title content="the codeartist — programmer and engineer based in Berlin"> <meta name=DC.title content="the codeartist — programmer and engineer based in Berlin">
@ -15,8 +15,8 @@
<meta name="og:title" content="The price to crack your password // the codeartist"> <meta name="og:title" content="The price to crack your password // the codeartist">
<meta property="og:type" content="website"> <meta property="og:type" content="website">
<meta http-equiv="x-ua-compatible" content="ie=edge"/> <meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"/> <meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no">
<meta name=ICBM content="52.4595, 13.5335"> <meta name=ICBM content="52.4595, 13.5335">
<meta name=geo.position content="52.4595; 13.5335"> <meta name=geo.position content="52.4595; 13.5335">
@ -26,7 +26,7 @@
<link rel=me href=https://k0r.in> <link rel=me href=https://k0r.in>
<link rel=me href=https://koehr.ing> <link rel=me href=https://koehr.ing>
<link rel=me href=@Koehr@mstdn.io> <link rel=me href=@Koehr@mstdn.io>
<link rel=me href=https://sr.ht/~koehr/> <link rel=me href=https://sr.ht/~koehr>
<link rel=me href=https://git.k0r.in> <link rel=me href=https://git.k0r.in>
<link rel=me href=https://threads.net/@coffee_n_code> <link rel=me href=https://threads.net/@coffee_n_code>
<link rel=me href=https://instagram.com/@coffee_n_code> <link rel=me href=https://instagram.com/@coffee_n_code>
@ -35,6 +35,14 @@
<link rel=icon href=/favicon.png type=image/x-icon> <link rel=icon href=/favicon.png type=image/x-icon>
<link rel=stylesheet href=/style.css> <link rel=stylesheet href=/style.css>
<style>
.posts { padding: 0; }
.posts>li { display: block; margin: 2rem 0; }
.posts>li>div { line-height: 2; }
.posts>li>p { line-height: 1.4; }
.posts>li>time, .posts>li>div>.reading-time { color: gray; }
</style>
</head> </head>
<body> <body>
@ -44,11 +52,9 @@
<header> <header>
<h1>The price to crack your password</h1> <h1>The price to crack your password</h1>
<em>Nearly six years ago, I wrote about password complexity and showed how long it takes to crack passwords per length.</em> <em>Nearly six years ago, I wrote about password complexity and showed how long it takes to crack passwords per length.</em>
<br/>
Last updated: <time datetime="Sun, 04 Dec 2016 00:00:00 +0000" >December 04, 2016</time>
</header> </header>
<div ><p>You can find the original <a href="https://github.com/nkoehring/hexo-blog/blob/master/source/_posts/spas-mit-passwortern.md">article on github</a> (in German).</p><p>So, times changed and I thought about a reiteration of that topic, but instead focussing on the amount of money you need to crack the password using Amazons biggest GPU computing instances <a href="https://aws.amazon.com/ec2/instance-types/">p2.16xlarge</a>, which at the time of writing this - costs 14.4 USD per hour. I will also compare this with the much faster <a href="https://sagitta.pw/hardware/gpu-compute-nodes/brutalis/">Sagitta Brutalis</a> (nice name, eh?), a 18500 USD computer optimised for GPU calculation.</p><h2>Disclaimer</h2><p>The numbers on this article always assume brute-force attacks, that means the attacker uses a program that tries all possible combinations until it finds the password. The numbers indicate average time to compute <i>all</i> possible entries. If the program simply adds up, for example, from 000000 to 999999 and your password is 000001, it will be found much faster of course.</p><p>How long a single calculation needs also depends on the used hashing algorithm. I will compare some of the typically used algorithms. In case you have to implement a password security system, please use BCrypt which is in most cases the best choice but <i>NEVER</i> try to implement something on your own! It is never ever a good idea to create an own password hashing scheme, even if it is just assembled out of existing building blocks. Use the battle-tested standard solutions. They are peer-reviewed and the safest and most robust you can get.</p><h2>Password complexity basics</h2><p>Password complexity is calculated out of the possible number of combinations. So a 10-character password that only contains numbers is far less complex than a mix of letters and numbers of the same length. Usually an attacker has no idea if a specific password only contains numbers or letters, but a brute-force attack will try simpler combinations first.</p><p>To calculate the complexity of a password, find the amount of possible combinations first:</p><ul><li><p>Numbers: 10</p></li><li><p>ASCII Lowercase letters: 26</p></li><li><p>ASCII Uppercase letters: 26</p></li><li><p>ASCII Punctuation: 33</p></li><li><p>Other ASCII Characters: 128</p></li><li><p>Unicode: millions</p></li></ul><p>To get the complexity of your password, simply add up the numbers. A typical password contains numbers, lowercase and uppercase letters which results in 62 possible combinations per character. Add some punctuation to raise that number to 95.</p><p>Other ASCII Characters are the less typical ones like ÿ and Ø which add to the complexity but might be hard to type on foreign keyboards. Unicode is super hard (if not impossible) to type on some computers but would theoretically add millions of possible characters. Fancy some ਪੰਜਾਬੀ ਦੇ in your password?</p><p>A very important factor in the password complexity is of course also the length. And because random passwords with crazy combinations of numbers, letters and punctuation are hard to remember, <a href="https://xkcd.com/936/">some people suggest to use long combination of normal words instead</a>.</p><p>The password <code>ke1r$u@U</code> is considered a very secure password as the time of writing this article. Its complexity calculates like this:</p><p>8 characters with 95 possibilites:</p><p><code>95^8 = 6634204312890625 = ~6.6×10^15</code></p><p><code>log2(x)</code> calculates the complexity in bits:</p><p><code>log2(6634204312890625) = ~52.56 bits</code></p><h2>Data sources</h2><p>I didn't try the password cracking myself, and neither did I ask a friend (insert trollface here). Instead I used publicly available benchmark results:</p><ul><li><p><a href="https://medium.com/@iraklis/running-hashcat-in-amazons-aws-new-16-gpu-p2-16xlarge-instance-9963f607164c#.bzyi0ystz">hashcat benchmark for p2.16xlarge</a></p></li><li><p><a href="https://gist.github.com/epixoip/a83d38f412b4737e99bbef804a270c40">hashcat benchmark for sagitta brutalis</a></p></li></ul><h2>The results</h2><p>I will compare some widely used password hashing methods, programs and protocols for four different password complexity categories:</p><ul><li><p>eight numeric digits (might be your birthday)</p></li><li><p>eight alphanumeric characters (eg 'pa55W0Rd')</p></li><li><p>eigth alphanumeric characters mixed with special character (eg 'pa$$W0Rd')</p></li><li><p>a long memorisable pass sentence ('correct horse battery staple')</p></li></ul><h3>eight numeric digits (might be your birthday)</h3><table> <div><p>You can find the original <a href="https://github.com/nkoehring/hexo-blog/blob/master/source/_posts/spas-mit-passwortern.md" target="_blank">article on github</a> (in German).</p><p>So, times changed and I thought about a reiteration of that topic, but instead focussing on the amount of money you need to crack the password using Amazons biggest GPU computing instances <a href="https://aws.amazon.com/ec2/instance-types/" target="_blank">p2.16xlarge</a>, which at the time of writing this - costs 14.4 USD per hour. I will also compare this with the much faster <a href="https://sagitta.pw/hardware/gpu-compute-nodes/brutalis/" target="_blank">Sagitta Brutalis</a> (nice name, eh?), a 18500 USD computer optimised for GPU calculation.</p><h2>Disclaimer</h2><p>The numbers on this article always assume brute-force attacks, that means the attacker uses a program that tries all possible combinations until it finds the password. The numbers indicate average time to compute <em>all</em> possible entries. If the program simply adds up, for example, from 000000 to 999999 and your password is 000001, it will be found much faster of course.</p><p>How long a single calculation needs also depends on the used hashing algorithm. I will compare some of the typically used algorithms. In case you have to implement a password security system, please use BCrypt which is in most cases the best choice but <em>NEVER</em> try to implement something on your own! It is never ever a good idea to create an own password hashing scheme, even if it is just assembled out of existing building blocks. Use the battle-tested standard solutions. They are peer-reviewed and the safest and most robust you can get.</p><h2>Password complexity basics</h2><p>Password complexity is calculated out of the possible number of combinations. So a 10-character password that only contains numbers is far less complex than a mix of letters and numbers of the same length. Usually an attacker has no idea if a specific password only contains numbers or letters, but a brute-force attack will try simpler combinations first.</p><p>To calculate the complexity of a password, find the amount of possible combinations first:</p><ul><li>Numbers: 10</li><li>ASCII Lowercase letters: 26</li><li>ASCII Uppercase letters: 26</li><li>ASCII Punctuation: 33</li><li>Other ASCII Characters: 128</li><li>Unicode: millions</li></ul><p>To get the complexity of your password, simply add up the numbers. A typical password contains numbers, lowercase and uppercase letters which results in 62 possible combinations per character. Add some punctuation to raise that number to 95.</p><p>Other ASCII Characters are the less typical ones like ÿ and Ø which add to the complexity but might be hard to type on foreign keyboards. Unicode is super hard (if not impossible) to type on some computers but would theoretically add millions of possible characters. Fancy some ਪੰਜਾਬੀ ਦੇ in your password?</p><p>A very important factor in the password complexity is of course also the length. And because random passwords with crazy combinations of numbers, letters and punctuation are hard to remember, <a href="https://xkcd.com/936/" target="_blank">some people suggest to use long combination of normal words instead</a>.</p><p>The password <code>ke1r$u@U</code> is considered a very secure password as the time of writing this article. Its complexity calculates like this:</p><p>8 characters with 95 possibilites:</p><p><code>95^8 = 6634204312890625 = ~6.6×10^15</code></p><p><code>log2(x)</code> calculates the complexity in bits:</p><p><code>log2(6634204312890625) = ~52.56 bits</code></p><h2>Data sources</h2><p>I didn't try the password cracking myself, and neither did I ask a friend (insert trollface here). Instead I used publicly available benchmark results:</p><ul><li><a href="https://medium.com/@iraklis/running-hashcat-in-amazons-aws-new-16-gpu-p2-16xlarge-instance-9963f607164c#.bzyi0ystz" target="_blank">hashcat benchmark for p2.16xlarge</a></li><li><a href="https://gist.github.com/epixoip/a83d38f412b4737e99bbef804a270c40" target="_blank">hashcat benchmark for sagitta brutalis</a></li></ul><h2>The results</h2><p>I will compare some widely used password hashing methods, programs and protocols for four different password complexity categories:</p><ul><li>eight numeric digits (might be your birthday)</li><li>eight alphanumeric characters (eg 'pa55W0Rd')</li><li>eigth alphanumeric characters mixed with special character (eg 'pa$$W0Rd')</li><li>a long memorisable pass sentence ('correct horse battery staple')</li></ul><h3>eight numeric digits (might be your birthday)</h3><table>
<thead> <thead>
<tr> <tr>
<th>hash</th> <th>hash</th>
@ -93,7 +99,11 @@
WPA2 | 160y | 67y | ~$14.9M (806 Brutalis) WPA2 | 160y | 67y | ~$14.9M (806 Brutalis)
SHA256 | 7d | 4d | ~$2162 (1 EC2 instance) SHA256 | 7d | 4d | ~$2162 (1 EC2 instance)
BCrypt | 6194y | 1989y | ~$448M (24,215 Brutalis) BCrypt | 6194y | 1989y | ~$448M (24,215 Brutalis)
</code></pre><p>AndroidPIN | 10y | 5y | ~$1.09M (59 Brutalis) MyWallet³ | 265d | 191d | ~$129500 (7 Brutalis) BitcoinWallet | 14996y | 5835y | ~$1.3B (71,038 Brutalis) LastPass | 24y | 12y | ~$2.6M (139 Brutalis) TrueCrypt² | 1144y | 718y | ~$162M (8,742 Brutalis) VeraCrypt¹ | 588867y | 353320y | ~$79.6B (4,301,668 Brutalis)</p><ol><li><p>VeraCrypt PBKDF2-HMAC-Whirlpool + XTS 512bit (super duper paranoid settings)</p></li><li><p>TrueCrypt PBKDF2-HMAC-Whirlpool + XTS 512bit</p></li><li><p>Blockchain MyWallet: https://blockchain.info/wallet/</p></li></ol><h3>a long memorisable pass sentence ('correct horse battery staple')</h3><p>Okay, this doesn't need a table. It takes millions of billions of years to even crack this in MD5.</p><p>As illustration: The solar system needs around 225 Million years to rotate around the core of the Milkyway. This is the so called <a href="https://en.wikipedia.org/wiki/Galactic_year">galactic year</a>. The sun exists since around 20 galactic years. To crack such a password, even when hashed in MD5 takes 3 trillion (million million) galactic years.</p><p>Of course nobody would ever attempt to do this. There are many possibilities to crack a password faster. Explaining some of them would easily fill another article, so I leave you here. Sorry.</p><h2>Links</h2><p>To find your way into the topic, you might visit some of the following links:</p><ul><li><p><a href="http://hashcat.net/hashcat/">The fastest bruteforce password cracker</a></p></li><li><p><a href="https://www.praetorian.com/blog/statistics-will-crack-your-password-mask-structure">More about password cracking methods</a></p></li><li><p><a href="https://password-hashing.net/">Password hashing competition</a></p></li><li><p><a href="https://www.randomlists.com/random-words">Random word generator for long but memorisable passwords</a></p></li></ul></div> </code></pre><p>AndroidPIN | 10y | 5y | ~$1.09M (59 Brutalis) MyWallet³ | 265d | 191d | ~$129500 (7 Brutalis) BitcoinWallet | 14996y | 5835y | ~$1.3B (71,038 Brutalis) LastPass | 24y | 12y | ~$2.6M (139 Brutalis) TrueCrypt² | 1144y | 718y | ~$162M (8,742 Brutalis) VeraCrypt¹ | 588867y | 353320y | ~$79.6B (4,301,668 Brutalis)</p><ol><li>VeraCrypt PBKDF2-HMAC-Whirlpool + XTS 512bit (super duper paranoid settings)</li><li>TrueCrypt PBKDF2-HMAC-Whirlpool + XTS 512bit</li><li>Blockchain MyWallet: https://blockchain.info/wallet/</li></ol><h3>a long memorisable pass sentence ('correct horse battery staple')</h3><p>Okay, this doesn't need a table. It takes millions of billions of years to even crack this in MD5.</p><p>As illustration: The solar system needs around 225 Million years to rotate around the core of the Milkyway. This is the so called <a href="https://en.wikipedia.org/wiki/Galactic_year" target="_blank">galactic year</a>. The sun exists since around 20 galactic years. To crack such a password, even when hashed in MD5 takes 3 trillion (million million) galactic years.</p><p>Of course nobody would ever attempt to do this. There are many possibilities to crack a password faster. Explaining some of them would easily fill another article, so I leave you here. Sorry.</p><h2>Links</h2><p>To find your way into the topic, you might visit some of the following links:</p><ul><li><a href="http://hashcat.net/hashcat/" target="_blank">The fastest bruteforce password cracker</a></li><li><a href="https://www.praetorian.com/blog/statistics-will-crack-your-password-mask-structure" target="_blank">More about password cracking methods</a></li><li><a href="https://password-hashing.net/" target="_blank">Password hashing competition</a></li><li><a href="https://www.randomlists.com/random-words" target="_blank">Random word generator for long but memorisable passwords</a></li></ul></div>
<ol class="posts">
<li></li>
</ol>
</main> </main>
@ -102,21 +112,21 @@
<a href="/"> <a href="/">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 832.4 143.1"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 832.4 143.1">
<path id="header-underscore" <path id="header-underscore"
d="M832.4 131.1q0 5.5-3.1 8.6-3 3.4-8.2 3.3h-75.5q-5.2 0-8.2-3.3-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8 0-5.5 3.1-8.7 1.6-1.7 3.7-2.4 2.2-.8 4.5-.8h75.5q5.2 0 8.2 3.2 3 3.1 3 8.7z" /> d="M832.4 131.1q0 5.5-3.1 8.6-3 3.4-8.2 3.3h-75.5q-5.2 0-8.2-3.3-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8 0-5.5 3.1-8.7 1.6-1.7 3.7-2.4 2.2-.8 4.5-.8h75.5q5.2 0 8.2 3.2 3 3.1 3 8.7z"></path>
<path id="header-bracket" <path id="header-bracket"
d="M731.9 81.4q0 6.7-6.5 10.7l-1 .6-74.3 39.2q-2.5 1.3-5.2 1.2-4.8 0-8.1-3.8-3.2-3.6-3.2-8.4 0-3.3 1.7-6 1.8-2.9 4.6-4.4l55.3-29.1-55.3-29q-2.8-1.6-4.6-4.3-1.7-2.7-1.7-6.2 0-4.7 3.2-8.4 3.3-4 8-3.7 2.7 0 5.3 1.2l74.4 39.2q3.3 1.7 5.3 4.7 2 2.8 2 6.5z" /> d="M731.9 81.4q0 6.7-6.5 10.7l-1 .6-74.3 39.2q-2.5 1.3-5.2 1.2-4.8 0-8.1-3.8-3.2-3.6-3.2-8.4 0-3.3 1.7-6 1.8-2.9 4.6-4.4l55.3-29.1-55.3-29q-2.8-1.6-4.6-4.3-1.7-2.7-1.7-6.2 0-4.7 3.2-8.4 3.3-4 8-3.7 2.7 0 5.3 1.2l74.4 39.2q3.3 1.7 5.3 4.7 2 2.8 2 6.5z"></path>
<path id="header-r" <path id="header-r"
d="M588.7 66.5q0 5-3.5 8.5-3.5 3.4-8.1 3.5-4.4 0-8.3-4.3-10-10.7-20.9-10.6-2.2 0-4.3.3-2.1.3-4 1-1.8.6-3.7 1.6-1.7 1-3.4 2.3-1.7 1.3-3.3 2.9-7.8 8.2-7.6 19.7V131q0 5.5-3.1 8.6-3 3.4-8.3 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V51.6q0-5.4 3-8.6 3-3.4 8.3-3.3 2 0 3.7.6 1.8.6 3.3 1.8 1.4 1 2.2 2.7 1 1.5 1.6 3.3 11.8-8.4 27-8.4 10.6 0 21 5 11.3 5.4 17.2 14.5 2.5 3.7 2.5 7.3z" /> d="M588.7 66.5q0 5-3.5 8.5-3.5 3.4-8.1 3.5-4.4 0-8.3-4.3-10-10.7-20.9-10.6-2.2 0-4.3.3-2.1.3-4 1-1.8.6-3.7 1.6-1.7 1-3.4 2.3-1.7 1.3-3.3 2.9-7.8 8.2-7.6 19.7V131q0 5.5-3.1 8.6-3 3.4-8.3 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V51.6q0-5.4 3-8.6 3-3.4 8.3-3.3 2 0 3.7.6 1.8.6 3.3 1.8 1.4 1 2.2 2.7 1 1.5 1.6 3.3 11.8-8.4 27-8.4 10.6 0 21 5 11.3 5.4 17.2 14.5 2.5 3.7 2.5 7.3z"></path>
<path id="header-h" <path id="header-h"
d="M483.9 131.1q0 5.5-3.1 8.6-3 3.4-8.3 3.3-5.2 0-8.2-3.3-3.2-3.1-3.1-8.6V84.8q0-4.6-1.5-8.2-1.4-3.5-4.4-6.9-2.1-2-4.3-3.4-2.2-1.4-4.7-2-2.4-.7-5.3-.7-4.3 0-7.8 1.5-3.3 1.5-6.4 4.6-5.9 6.3-5.8 15v46.4q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v33q1.5-1 3-1.6l3.2-1.2 3.4-1q1.6-.5 3.3-.8l3.5-.4 3.6-.2q4.4 0 8.5 1 4.1.7 7.9 2.4 3.8 1.6 7.3 4.1 3.5 2.5 6.6 5.8Q484 66 484 84.8z" /> d="M483.9 131.1q0 5.5-3.1 8.6-3 3.4-8.3 3.3-5.2 0-8.2-3.3-3.2-3.1-3.1-8.6V84.8q0-4.6-1.5-8.2-1.4-3.5-4.4-6.9-2.1-2-4.3-3.4-2.2-1.4-4.7-2-2.4-.7-5.3-.7-4.3 0-7.8 1.5-3.3 1.5-6.4 4.6-5.9 6.3-5.8 15v46.4q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v33q1.5-1 3-1.6l3.2-1.2 3.4-1q1.6-.5 3.3-.8l3.5-.4 3.6-.2q4.4 0 8.5 1 4.1.7 7.9 2.4 3.8 1.6 7.3 4.1 3.5 2.5 6.6 5.8Q484 66 484 84.8z"></path>
<path id="header-e" <path id="header-e"
d="M387.5 111.1q0 1.2-.3 2.3-.1 1-.5 2l-.9 2q-6.6 12-19.4 19-12 6.6-25.4 6.6-20.8 0-35.8-14.6-15.9-15-15.9-37 0-22.1 15.9-37.1 15-14.6 35.8-14.6 3.9 0 7.8.7 4 .7 8 2.2 9.2 3.1 18.2 10 6 4.6 9.1 9.3 3.3 4.7 3.3 10 0 1.3-.3 2.5-.2 1.3-.7 2.4-1.5 3.4-5 5.3l-56.9 32.2q7.2 4.9 16.5 4.9 7.2 0 12.6-2.5 5.5-2.5 9.7-7.4l.7-1 .8-1 .9-1.3 1-1.5q3.3-4.2 7.4-5.1l1.8-.2q4.4 0 8 3.4 3.6 3.5 3.6 8.5zm-29.9-42.7q-7.2-4.8-16.6-4.8-6 0-11 2-4.9 1.8-9.3 6-4.5 4-6.7 9-2 4.8-2 10.8l.1 2.9z" /> d="M387.5 111.1q0 1.2-.3 2.3-.1 1-.5 2l-.9 2q-6.6 12-19.4 19-12 6.6-25.4 6.6-20.8 0-35.8-14.6-15.9-15-15.9-37 0-22.1 15.9-37.1 15-14.6 35.8-14.6 3.9 0 7.8.7 4 .7 8 2.2 9.2 3.1 18.2 10 6 4.6 9.1 9.3 3.3 4.7 3.3 10 0 1.3-.3 2.5-.2 1.3-.7 2.4-1.5 3.4-5 5.3l-56.9 32.2q7.2 4.9 16.5 4.9 7.2 0 12.6-2.5 5.5-2.5 9.7-7.4l.7-1 .8-1 .9-1.3 1-1.5q3.3-4.2 7.4-5.1l1.8-.2q4.4 0 8 3.4 3.6 3.5 3.6 8.5zm-29.9-42.7q-7.2-4.8-16.6-4.8-6 0-11 2-4.9 1.8-9.3 6-4.5 4-6.7 9-2 4.8-2 10.8l.1 2.9z"></path>
<path id="header-o" <path id="header-o"
d="M286.8 91.4q0 4.2-.6 8.3-.6 4-1.8 7.7-1.1 3.8-2.9 7.4-1.7 3.5-4 6.9-2.4 3.3-5.2 6.1Q258 143 237.7 143T203 128q-14.3-15.2-14.3-36.6 0-21.5 14.3-36.6 14.4-15 34.7-15 4 0 7.8.5 3.9.7 7.5 1.9t7 3q3.3 1.9 6.4 4.3 3.2 2.4 5.9 5.4 14.4 15 14.5 36.5zm-22.6 0q0-2.4-.4-4.5-.2-2.2-.9-4.2-.6-2-1.5-3.9-1-2-2.2-3.7-1.2-1.7-2.8-3.4-4-4.2-8.6-6.1-4.5-2-10-2-11 0-18.7 8.2-7.8 8-7.8 19.6 0 11.4 7.8 19.7 7.8 8 18.6 8 5.6 0 10.1-1.9 4.6-2 8.6-6.1 4-4.3 5.8-9 2-4.9 2-10.7z" /> d="M286.8 91.4q0 4.2-.6 8.3-.6 4-1.8 7.7-1.1 3.8-2.9 7.4-1.7 3.5-4 6.9-2.4 3.3-5.2 6.1Q258 143 237.7 143T203 128q-14.3-15.2-14.3-36.6 0-21.5 14.3-36.6 14.4-15 34.7-15 4 0 7.8.5 3.9.7 7.5 1.9t7 3q3.3 1.9 6.4 4.3 3.2 2.4 5.9 5.4 14.4 15 14.5 36.5zm-22.6 0q0-2.4-.4-4.5-.2-2.2-.9-4.2-.6-2-1.5-3.9-1-2-2.2-3.7-1.2-1.7-2.8-3.4-4-4.2-8.6-6.1-4.5-2-10-2-11 0-18.7 8.2-7.8 8-7.8 19.6 0 11.4 7.8 19.7 7.8 8 18.6 8 5.6 0 10.1-1.9 4.6-2 8.6-6.1 4-4.3 5.8-9 2-4.9 2-10.7z"></path>
<path id="header-k" <path id="header-k"
d="M186.3 131q0 4.7-3.3 8.3-1.5 1.8-3.7 2.7-2 1.1-4.3 1.1-3.5 0-6.6-2L119.2 105v26q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v65.9l49.2-36.1q3.2-2 6.6-2 4.7 0 8 3.7t3.3 8.4q-.2 6-5 9.6l-41 30 41 29.9q2.3 1.7 3.6 4.2 1.4 2.5 1.4 5.4z" /> d="M186.3 131q0 4.7-3.3 8.3-1.5 1.8-3.7 2.7-2 1.1-4.3 1.1-3.5 0-6.6-2L119.2 105v26q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v65.9l49.2-36.1q3.2-2 6.6-2 4.7 0 8 3.7t3.3 8.4q-.2 6-5 9.6l-41 30 41 29.9q2.3 1.7 3.6 4.2 1.4 2.5 1.4 5.4z"></path>
<path id="header-tilde" <path id="header-tilde"
d="M73.1 91q0 2-.6 3.9T71 98.6q-3.2 5.7-8.9 8.5-5.6 2.8-12.9 2.8-8.8 0-18-7.8-2.4-2.3-4.5-3.7-2.1-1.5-3-1.7-1.5 0-2.1.3l-.8 1.3q-.3.7-.8 1.2l-1 1-.9.8q-2.7 2-6.4 2-1.7 0-3.2-.3-1.4-.3-3-1.1-1.5-.8-2.6-2.1-2.8-3.1-2.8-8v-1.3q0-.7.2-1.2l.2-1 .4-1 .4-1q.1-.6.5-1.1l.5-1q3.2-5.7 8.8-8.5 5.7-2.9 13-2.9 3.2 0 6.2 1 3 .9 6 2.7 2.9 1.6 5.7 4.2 5.2 4.6 7.6 5.4 1 0 1.6-.2l.7-.4q.3-.1.5-.4 3.6-5.6 9.2-5.6 5.7 0 8.8 3.5 2.8 3 2.8 8z" /> d="M73.1 91q0 2-.6 3.9T71 98.6q-3.2 5.7-8.9 8.5-5.6 2.8-12.9 2.8-8.8 0-18-7.8-2.4-2.3-4.5-3.7-2.1-1.5-3-1.7-1.5 0-2.1.3l-.8 1.3q-.3.7-.8 1.2l-1 1-.9.8q-2.7 2-6.4 2-1.7 0-3.2-.3-1.4-.3-3-1.1-1.5-.8-2.6-2.1-2.8-3.1-2.8-8v-1.3q0-.7.2-1.2l.2-1 .4-1 .4-1q.1-.6.5-1.1l.5-1q3.2-5.7 8.8-8.5 5.7-2.9 13-2.9 3.2 0 6.2 1 3 .9 6 2.7 2.9 1.6 5.7 4.2 5.2 4.6 7.6 5.4 1 0 1.6-.2l.7-.4q.3-.1.5-.4 3.6-5.6 9.2-5.6 5.7 0 8.8 3.5 2.8 3 2.8 8z"></path>
</svg> </svg>
Homepage of Homepage of
<div class=p-name> <div class=p-name>

View file

@ -3,7 +3,7 @@
<head id="head"> <head id="head">
<meta charset=utf-8> <meta charset=utf-8>
<title id=title >the codeartist — programmer and engineer based in BerlinThe Magic 0xC2</title> <title id="title " var="the codeartist — programmer and engineer based in Berlin">The Magic 0xC2</title>
<meta name=description content="The personal page and weblog of Norman Köhring"> <meta name=description content="The personal page and weblog of Norman Köhring">
<meta name=author content="Norman Köhring"> <meta name=author content="Norman Köhring">
<meta name=DC.title content="the codeartist — programmer and engineer based in Berlin"> <meta name=DC.title content="the codeartist — programmer and engineer based in Berlin">
@ -15,8 +15,8 @@
<meta name="og:title" content="The Magic 0xC2 // the codeartist"> <meta name="og:title" content="The Magic 0xC2 // the codeartist">
<meta property="og:type" content="website"> <meta property="og:type" content="website">
<meta http-equiv="x-ua-compatible" content="ie=edge"/> <meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"/> <meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no">
<meta name=ICBM content="52.4595, 13.5335"> <meta name=ICBM content="52.4595, 13.5335">
<meta name=geo.position content="52.4595; 13.5335"> <meta name=geo.position content="52.4595; 13.5335">
@ -26,7 +26,7 @@
<link rel=me href=https://k0r.in> <link rel=me href=https://k0r.in>
<link rel=me href=https://koehr.ing> <link rel=me href=https://koehr.ing>
<link rel=me href=@Koehr@mstdn.io> <link rel=me href=@Koehr@mstdn.io>
<link rel=me href=https://sr.ht/~koehr/> <link rel=me href=https://sr.ht/~koehr>
<link rel=me href=https://git.k0r.in> <link rel=me href=https://git.k0r.in>
<link rel=me href=https://threads.net/@coffee_n_code> <link rel=me href=https://threads.net/@coffee_n_code>
<link rel=me href=https://instagram.com/@coffee_n_code> <link rel=me href=https://instagram.com/@coffee_n_code>
@ -35,6 +35,14 @@
<link rel=icon href=/favicon.png type=image/x-icon> <link rel=icon href=/favicon.png type=image/x-icon>
<link rel=stylesheet href=/style.css> <link rel=stylesheet href=/style.css>
<style>
.posts { padding: 0; }
.posts>li { display: block; margin: 2rem 0; }
.posts>li>div { line-height: 2; }
.posts>li>p { line-height: 1.4; }
.posts>li>time, .posts>li>div>.reading-time { color: gray; }
</style>
</head> </head>
<body> <body>
@ -44,15 +52,13 @@
<header> <header>
<h1>The Magic 0xC2</h1> <h1>The Magic 0xC2</h1>
<em>I built a web application with file upload functionality. Some Vue.js in the front and a CouchDB in the back. Everything should be pretty simple and straigt forward. But…</em> <em>I built a web application with file upload functionality. Some Vue.js in the front and a CouchDB in the back. Everything should be pretty simple and straigt forward. But…</em>
<br/>
Last updated: <time datetime="Sun, 09 Apr 2017 00:00:00 +0000" >April 09, 2017</time>
</header> </header>
<div><p>When I uploaded image files, they somehow got mangled. The uploaded file was bigger than the original and the new "file format" was not readable by any means. I got intrigued. What is it, that happens to the files? The changes seemed very random but reproducible, so I created a few test files to see what exactly changes and when.</p><p>My first file looked like this:</p><pre><code>0123456789 <div><p>When I uploaded image files, they somehow got mangled. The uploaded file was bigger than the original and the new "file format" was not readable by any means. I got intrigued. What is it, that happens to the files? The changes seemed very random but reproducible, so I created a few test files to see what exactly changes and when.</p><p>My first file looked like this:</p><pre><code>0123456789
ABCDEFGHIJKLMNOPQRSTUVWXYZ ABCDEFGHIJKLMNOPQRSTUVWXYZ
abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz
</code></pre><p>To my surprise, the file stayed the same! My curiosity grew. In the meantime I found a very intriguing pattern in uploads hexdump: <code>C3 BF C3</code>. It was everywhere. In another file, I found similar patterns with <code>C2</code>. So I wrote my next test file. This time a binary file:</p><pre><code>00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 |................| </code></pre><p>To my surprise, the file stayed the same! My curiosity grew. In the meantime I found a very intriguing pattern in uploads hexdump: <code>C3 BF C3</code>. It was everywhere. In another file, I found similar patterns with <code>C2</code>. So I wrote my next test file. This time a binary file:</p><pre><code>00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 |................|
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |.... !"#$%&'()01| 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |.... !&quot;#$%&&apos;()01|
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |23456789@ABCDEFG| 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |23456789@ABCDEFG|
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |HIPQRSTUVWXY`abc| 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |HIPQRSTUVWXY`abc|
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |defghipqrstuvwxy| 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |defghipqrstuvwxy|
@ -61,7 +67,7 @@ abcdefghijklmnopqrstuvwxyz
ac ad ae af b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bb |................| ac ad ae af b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bb |................|
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
</code></pre><p><strong>EDIT</strong>: As you probably already noticed, I counted up like in Base10 but it is actually Base16. So I skipped A-F until reaching A0. This might look weird but didn't affect the test.</p><p>The result after uploading was</p><pre><code>00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 |................| </code></pre><p><strong>EDIT</strong>: As you probably already noticed, I counted up like in Base10 but it is actually Base16. So I skipped A-F until reaching A0. This might look weird but didn't affect the test.</p><p>The result after uploading was</p><pre><code>00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 |................|
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |.... !"#$%&'()01| 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |.... !&quot;#$%&&apos;()01|
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |23456789@ABCDEFG| 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |23456789@ABCDEFG|
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |HIPQRSTUVWXY`abc| 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |HIPQRSTUVWXY`abc|
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |defghipqrstuvwxy| 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |defghipqrstuvwxy|
@ -72,7 +78,11 @@ c2 a4 c2 a5 c2 a6 c2 a7 c2 a8 c2 a9 c2 aa c2 ab |................|
c2 ac c2 ad c2 ae c2 af c2 b0 c2 b1 c2 b2 c2 b3 |................| c2 ac c2 ad c2 ae c2 af c2 b0 c2 b1 c2 b2 c2 b3 |................|
c2 b4 c2 b5 c2 b6 c2 b7 c2 b8 c2 b9 c2 ba c2 bb |................| c2 b4 c2 b5 c2 b6 c2 b7 c2 b8 c2 b9 c2 ba c2 bb |................|
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
</code></pre><p>There it was again: The magic <strong>0xC2</strong>!</p><p>So all bytes with a value higher than <i>0x79</i> got followed by a <i>0xC2</i>. <i>0x79</i> is the ASCII code for <i>y</i>. This is at least what I thought. It actually is the other way around: All bytes with value <i>0x80</i> or higher got prefixed by a <i>0xC2</i>! — there the scales fell from my eyes: <strong>UTF-8 encoding</strong>!</p><p>In <i>UTF-8</i> all characters after <i>0x7F</i> are at least two bytes long. They get prefixed with <i>0xC2</i> until <i>0xC2BF</i> (which is the inverted question mark <code>¿</code>), which is then followed by <i>0xC380</i>. So what happened is, that on the way to the server, the file got encoded to UTF-8 ¯\_(ツ)_/¯</p><p><strong>EDIT:</strong> Corrected some mistakes after some comments on <a href="https://news.ycombinator.com/item?id=14089827">Hackernews</a></p></div> </code></pre><p>There it was again: The magic <strong>0xC2</strong>!</p><p>So all bytes with a value higher than <em>0x79</em> got followed by a <em>0xC2</em>. <em>0x79</em> is the ASCII code for <em>y</em>. This is at least what I thought. It actually is the other way around: All bytes with value <em>0x80</em> or higher got prefixed by a <em>0xC2</em>! — there the scales fell from my eyes: <strong>UTF-8 encoding</strong>!</p><p>In <em>UTF-8</em> all characters after <em>0x7F</em> are at least two bytes long. They get prefixed with <em>0xC2</em> until <em>0xC2BF</em> (which is the inverted question mark <code>¿</code>), which is then followed by <em>0xC380</em>. So what happened is, that on the way to the server, the file got encoded to UTF-8 ¯\_(ツ)_/¯</p><p><strong>EDIT:</strong> Corrected some mistakes after some comments on <a href="https://news.ycombinator.com/item?id=14089827" target="_blank">Hackernews</a></p></div>
<ol class="posts">
<li></li>
</ol>
</main> </main>
@ -81,21 +91,21 @@ c2 b4 c2 b5 c2 b6 c2 b7 c2 b8 c2 b9 c2 ba c2 bb |................|
<a href="/"> <a href="/">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 832.4 143.1"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 832.4 143.1">
<path id="header-underscore" <path id="header-underscore"
d="M832.4 131.1q0 5.5-3.1 8.6-3 3.4-8.2 3.3h-75.5q-5.2 0-8.2-3.3-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8 0-5.5 3.1-8.7 1.6-1.7 3.7-2.4 2.2-.8 4.5-.8h75.5q5.2 0 8.2 3.2 3 3.1 3 8.7z" /> d="M832.4 131.1q0 5.5-3.1 8.6-3 3.4-8.2 3.3h-75.5q-5.2 0-8.2-3.3-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8 0-5.5 3.1-8.7 1.6-1.7 3.7-2.4 2.2-.8 4.5-.8h75.5q5.2 0 8.2 3.2 3 3.1 3 8.7z"></path>
<path id="header-bracket" <path id="header-bracket"
d="M731.9 81.4q0 6.7-6.5 10.7l-1 .6-74.3 39.2q-2.5 1.3-5.2 1.2-4.8 0-8.1-3.8-3.2-3.6-3.2-8.4 0-3.3 1.7-6 1.8-2.9 4.6-4.4l55.3-29.1-55.3-29q-2.8-1.6-4.6-4.3-1.7-2.7-1.7-6.2 0-4.7 3.2-8.4 3.3-4 8-3.7 2.7 0 5.3 1.2l74.4 39.2q3.3 1.7 5.3 4.7 2 2.8 2 6.5z" /> d="M731.9 81.4q0 6.7-6.5 10.7l-1 .6-74.3 39.2q-2.5 1.3-5.2 1.2-4.8 0-8.1-3.8-3.2-3.6-3.2-8.4 0-3.3 1.7-6 1.8-2.9 4.6-4.4l55.3-29.1-55.3-29q-2.8-1.6-4.6-4.3-1.7-2.7-1.7-6.2 0-4.7 3.2-8.4 3.3-4 8-3.7 2.7 0 5.3 1.2l74.4 39.2q3.3 1.7 5.3 4.7 2 2.8 2 6.5z"></path>
<path id="header-r" <path id="header-r"
d="M588.7 66.5q0 5-3.5 8.5-3.5 3.4-8.1 3.5-4.4 0-8.3-4.3-10-10.7-20.9-10.6-2.2 0-4.3.3-2.1.3-4 1-1.8.6-3.7 1.6-1.7 1-3.4 2.3-1.7 1.3-3.3 2.9-7.8 8.2-7.6 19.7V131q0 5.5-3.1 8.6-3 3.4-8.3 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V51.6q0-5.4 3-8.6 3-3.4 8.3-3.3 2 0 3.7.6 1.8.6 3.3 1.8 1.4 1 2.2 2.7 1 1.5 1.6 3.3 11.8-8.4 27-8.4 10.6 0 21 5 11.3 5.4 17.2 14.5 2.5 3.7 2.5 7.3z" /> d="M588.7 66.5q0 5-3.5 8.5-3.5 3.4-8.1 3.5-4.4 0-8.3-4.3-10-10.7-20.9-10.6-2.2 0-4.3.3-2.1.3-4 1-1.8.6-3.7 1.6-1.7 1-3.4 2.3-1.7 1.3-3.3 2.9-7.8 8.2-7.6 19.7V131q0 5.5-3.1 8.6-3 3.4-8.3 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V51.6q0-5.4 3-8.6 3-3.4 8.3-3.3 2 0 3.7.6 1.8.6 3.3 1.8 1.4 1 2.2 2.7 1 1.5 1.6 3.3 11.8-8.4 27-8.4 10.6 0 21 5 11.3 5.4 17.2 14.5 2.5 3.7 2.5 7.3z"></path>
<path id="header-h" <path id="header-h"
d="M483.9 131.1q0 5.5-3.1 8.6-3 3.4-8.3 3.3-5.2 0-8.2-3.3-3.2-3.1-3.1-8.6V84.8q0-4.6-1.5-8.2-1.4-3.5-4.4-6.9-2.1-2-4.3-3.4-2.2-1.4-4.7-2-2.4-.7-5.3-.7-4.3 0-7.8 1.5-3.3 1.5-6.4 4.6-5.9 6.3-5.8 15v46.4q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v33q1.5-1 3-1.6l3.2-1.2 3.4-1q1.6-.5 3.3-.8l3.5-.4 3.6-.2q4.4 0 8.5 1 4.1.7 7.9 2.4 3.8 1.6 7.3 4.1 3.5 2.5 6.6 5.8Q484 66 484 84.8z" /> d="M483.9 131.1q0 5.5-3.1 8.6-3 3.4-8.3 3.3-5.2 0-8.2-3.3-3.2-3.1-3.1-8.6V84.8q0-4.6-1.5-8.2-1.4-3.5-4.4-6.9-2.1-2-4.3-3.4-2.2-1.4-4.7-2-2.4-.7-5.3-.7-4.3 0-7.8 1.5-3.3 1.5-6.4 4.6-5.9 6.3-5.8 15v46.4q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v33q1.5-1 3-1.6l3.2-1.2 3.4-1q1.6-.5 3.3-.8l3.5-.4 3.6-.2q4.4 0 8.5 1 4.1.7 7.9 2.4 3.8 1.6 7.3 4.1 3.5 2.5 6.6 5.8Q484 66 484 84.8z"></path>
<path id="header-e" <path id="header-e"
d="M387.5 111.1q0 1.2-.3 2.3-.1 1-.5 2l-.9 2q-6.6 12-19.4 19-12 6.6-25.4 6.6-20.8 0-35.8-14.6-15.9-15-15.9-37 0-22.1 15.9-37.1 15-14.6 35.8-14.6 3.9 0 7.8.7 4 .7 8 2.2 9.2 3.1 18.2 10 6 4.6 9.1 9.3 3.3 4.7 3.3 10 0 1.3-.3 2.5-.2 1.3-.7 2.4-1.5 3.4-5 5.3l-56.9 32.2q7.2 4.9 16.5 4.9 7.2 0 12.6-2.5 5.5-2.5 9.7-7.4l.7-1 .8-1 .9-1.3 1-1.5q3.3-4.2 7.4-5.1l1.8-.2q4.4 0 8 3.4 3.6 3.5 3.6 8.5zm-29.9-42.7q-7.2-4.8-16.6-4.8-6 0-11 2-4.9 1.8-9.3 6-4.5 4-6.7 9-2 4.8-2 10.8l.1 2.9z" /> d="M387.5 111.1q0 1.2-.3 2.3-.1 1-.5 2l-.9 2q-6.6 12-19.4 19-12 6.6-25.4 6.6-20.8 0-35.8-14.6-15.9-15-15.9-37 0-22.1 15.9-37.1 15-14.6 35.8-14.6 3.9 0 7.8.7 4 .7 8 2.2 9.2 3.1 18.2 10 6 4.6 9.1 9.3 3.3 4.7 3.3 10 0 1.3-.3 2.5-.2 1.3-.7 2.4-1.5 3.4-5 5.3l-56.9 32.2q7.2 4.9 16.5 4.9 7.2 0 12.6-2.5 5.5-2.5 9.7-7.4l.7-1 .8-1 .9-1.3 1-1.5q3.3-4.2 7.4-5.1l1.8-.2q4.4 0 8 3.4 3.6 3.5 3.6 8.5zm-29.9-42.7q-7.2-4.8-16.6-4.8-6 0-11 2-4.9 1.8-9.3 6-4.5 4-6.7 9-2 4.8-2 10.8l.1 2.9z"></path>
<path id="header-o" <path id="header-o"
d="M286.8 91.4q0 4.2-.6 8.3-.6 4-1.8 7.7-1.1 3.8-2.9 7.4-1.7 3.5-4 6.9-2.4 3.3-5.2 6.1Q258 143 237.7 143T203 128q-14.3-15.2-14.3-36.6 0-21.5 14.3-36.6 14.4-15 34.7-15 4 0 7.8.5 3.9.7 7.5 1.9t7 3q3.3 1.9 6.4 4.3 3.2 2.4 5.9 5.4 14.4 15 14.5 36.5zm-22.6 0q0-2.4-.4-4.5-.2-2.2-.9-4.2-.6-2-1.5-3.9-1-2-2.2-3.7-1.2-1.7-2.8-3.4-4-4.2-8.6-6.1-4.5-2-10-2-11 0-18.7 8.2-7.8 8-7.8 19.6 0 11.4 7.8 19.7 7.8 8 18.6 8 5.6 0 10.1-1.9 4.6-2 8.6-6.1 4-4.3 5.8-9 2-4.9 2-10.7z" /> d="M286.8 91.4q0 4.2-.6 8.3-.6 4-1.8 7.7-1.1 3.8-2.9 7.4-1.7 3.5-4 6.9-2.4 3.3-5.2 6.1Q258 143 237.7 143T203 128q-14.3-15.2-14.3-36.6 0-21.5 14.3-36.6 14.4-15 34.7-15 4 0 7.8.5 3.9.7 7.5 1.9t7 3q3.3 1.9 6.4 4.3 3.2 2.4 5.9 5.4 14.4 15 14.5 36.5zm-22.6 0q0-2.4-.4-4.5-.2-2.2-.9-4.2-.6-2-1.5-3.9-1-2-2.2-3.7-1.2-1.7-2.8-3.4-4-4.2-8.6-6.1-4.5-2-10-2-11 0-18.7 8.2-7.8 8-7.8 19.6 0 11.4 7.8 19.7 7.8 8 18.6 8 5.6 0 10.1-1.9 4.6-2 8.6-6.1 4-4.3 5.8-9 2-4.9 2-10.7z"></path>
<path id="header-k" <path id="header-k"
d="M186.3 131q0 4.7-3.3 8.3-1.5 1.8-3.7 2.7-2 1.1-4.3 1.1-3.5 0-6.6-2L119.2 105v26q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v65.9l49.2-36.1q3.2-2 6.6-2 4.7 0 8 3.7t3.3 8.4q-.2 6-5 9.6l-41 30 41 29.9q2.3 1.7 3.6 4.2 1.4 2.5 1.4 5.4z" /> d="M186.3 131q0 4.7-3.3 8.3-1.5 1.8-3.7 2.7-2 1.1-4.3 1.1-3.5 0-6.6-2L119.2 105v26q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v65.9l49.2-36.1q3.2-2 6.6-2 4.7 0 8 3.7t3.3 8.4q-.2 6-5 9.6l-41 30 41 29.9q2.3 1.7 3.6 4.2 1.4 2.5 1.4 5.4z"></path>
<path id="header-tilde" <path id="header-tilde"
d="M73.1 91q0 2-.6 3.9T71 98.6q-3.2 5.7-8.9 8.5-5.6 2.8-12.9 2.8-8.8 0-18-7.8-2.4-2.3-4.5-3.7-2.1-1.5-3-1.7-1.5 0-2.1.3l-.8 1.3q-.3.7-.8 1.2l-1 1-.9.8q-2.7 2-6.4 2-1.7 0-3.2-.3-1.4-.3-3-1.1-1.5-.8-2.6-2.1-2.8-3.1-2.8-8v-1.3q0-.7.2-1.2l.2-1 .4-1 .4-1q.1-.6.5-1.1l.5-1q3.2-5.7 8.8-8.5 5.7-2.9 13-2.9 3.2 0 6.2 1 3 .9 6 2.7 2.9 1.6 5.7 4.2 5.2 4.6 7.6 5.4 1 0 1.6-.2l.7-.4q.3-.1.5-.4 3.6-5.6 9.2-5.6 5.7 0 8.8 3.5 2.8 3 2.8 8z" /> d="M73.1 91q0 2-.6 3.9T71 98.6q-3.2 5.7-8.9 8.5-5.6 2.8-12.9 2.8-8.8 0-18-7.8-2.4-2.3-4.5-3.7-2.1-1.5-3-1.7-1.5 0-2.1.3l-.8 1.3q-.3.7-.8 1.2l-1 1-.9.8q-2.7 2-6.4 2-1.7 0-3.2-.3-1.4-.3-3-1.1-1.5-.8-2.6-2.1-2.8-3.1-2.8-8v-1.3q0-.7.2-1.2l.2-1 .4-1 .4-1q.1-.6.5-1.1l.5-1q3.2-5.7 8.8-8.5 5.7-2.9 13-2.9 3.2 0 6.2 1 3 .9 6 2.7 2.9 1.6 5.7 4.2 5.2 4.6 7.6 5.4 1 0 1.6-.2l.7-.4q.3-.1.5-.4 3.6-5.6 9.2-5.6 5.7 0 8.8 3.5 2.8 3 2.8 8z"></path>
</svg> </svg>
Homepage of Homepage of
<div class=p-name> <div class=p-name>

View file

@ -3,7 +3,7 @@
<head id="head"> <head id="head">
<meta charset=utf-8> <meta charset=utf-8>
<title id=title >the codeartist — programmer and engineer based in BerlinVuejs Reactivity From Scratch</title> <title id="title " var="the codeartist — programmer and engineer based in Berlin">Vuejs Reactivity From Scratch</title>
<meta name=description content="The personal page and weblog of Norman Köhring"> <meta name=description content="The personal page and weblog of Norman Köhring">
<meta name=author content="Norman Köhring"> <meta name=author content="Norman Köhring">
<meta name=DC.title content="the codeartist — programmer and engineer based in Berlin"> <meta name=DC.title content="the codeartist — programmer and engineer based in Berlin">
@ -15,8 +15,8 @@
<meta name="og:title" content="Vuejs Reactivity From Scratch // the codeartist"> <meta name="og:title" content="Vuejs Reactivity From Scratch // the codeartist">
<meta property="og:type" content="website"> <meta property="og:type" content="website">
<meta http-equiv="x-ua-compatible" content="ie=edge"/> <meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"/> <meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no">
<meta name=ICBM content="52.4595, 13.5335"> <meta name=ICBM content="52.4595, 13.5335">
<meta name=geo.position content="52.4595; 13.5335"> <meta name=geo.position content="52.4595; 13.5335">
@ -26,7 +26,7 @@
<link rel=me href=https://k0r.in> <link rel=me href=https://k0r.in>
<link rel=me href=https://koehr.ing> <link rel=me href=https://koehr.ing>
<link rel=me href=@Koehr@mstdn.io> <link rel=me href=@Koehr@mstdn.io>
<link rel=me href=https://sr.ht/~koehr/> <link rel=me href=https://sr.ht/~koehr>
<link rel=me href=https://git.k0r.in> <link rel=me href=https://git.k0r.in>
<link rel=me href=https://threads.net/@coffee_n_code> <link rel=me href=https://threads.net/@coffee_n_code>
<link rel=me href=https://instagram.com/@coffee_n_code> <link rel=me href=https://instagram.com/@coffee_n_code>
@ -35,6 +35,14 @@
<link rel=icon href=/favicon.png type=image/x-icon> <link rel=icon href=/favicon.png type=image/x-icon>
<link rel=stylesheet href=/style.css> <link rel=stylesheet href=/style.css>
<style>
.posts { padding: 0; }
.posts>li { display: block; margin: 2rem 0; }
.posts>li>div { line-height: 2; }
.posts>li>p { line-height: 1.4; }
.posts>li>time, .posts>li>div>.reading-time { color: gray; }
</style>
</head> </head>
<body> <body>
@ -44,30 +52,31 @@
<header> <header>
<h1>Vuejs Reactivity From Scratch</h1> <h1>Vuejs Reactivity From Scratch</h1>
<em>Vuejs is the star newcomer in the Javascript Framework world. People love how it makes complicated things very simple yet performant. One of the more exciting features is its seemingly magic reactivity. Plain data objects in components magically invoke a rerender when a property changes.</em> <em>Vuejs is the star newcomer in the Javascript Framework world. People love how it makes complicated things very simple yet performant. One of the more exciting features is its seemingly magic reactivity. Plain data objects in components magically invoke a rerender when a property changes.</em>
<br/>
Last updated: <time datetime="Thu, 17 Aug 2017 00:00:00 +0000" >August 17, 2017</time>
</header> </header>
<div ><style>iframe{width:640px;max-width:100%;height:30em;}</style> <div><p><em>NOTE</em>: This is a copy of the original article from Aug 17th, 2017. You can <a href="https://web.archive.org/web/20190113013559/https://log.koehr.in/2017/08/17/vuejs-reactivity-from-scratch" target="_blank">read the archived original on archive.org</a></p><iframe src="https://jsfiddle.net/ajwchnko/embedded/?username=koehr" width="640" height="400" frameborder="0" sandbox="allow-modals allow-forms allow-scripts allow-same-origin allow-popups"></iframe>
<p><i>NOTE</i>: This is a copy of the original article from Aug 17th, 2017. You can <a href="https://web.archive.org/web/20190113013559/https://log.koehr.in/2017/08/17/vuejs-reactivity-from-scratch">read the archived original on archive.org</a></p><iframe src="https://jsfiddle.net/ajwchnko/embedded/?username=koehr" width="640" height="400" frameborder="0" sandbox="allow-modals allow-forms allow-scripts allow-same-origin allow-popups"></iframe> <p>The button click invokes a function that just assigns a new value to a property. Still the template gets automagically rerendered. But we all know there is no fairydust involved, right? So how does it actually work?</p><hr><h2>The magic of getters and setters</h2><p>With the <a href="http://www.ecma-international.org/ecma-262/5.1/" target="_blank">ES5 standard</a> JavaScript got lots of exciting new features. Some of them highly underrated and underused in my opinion. <a href="http://www.ecma-international.org/ecma-262/5.1/#sec-8.6.1" target="_blank">Getters and setters</a> are an example. If you never heard of them, I would recommend you to read <a href="https://johnresig.com/blog/javascript-getters-and-setters/" target="_blank">John Riesigs piece</a> on them.</p><p>As soon as you know what getters and setters are: functions transparently called on every property access, you might already know where this goes. Boom! All the fairydust suddenly disappears.</p><h2>Automatic getters and setters</h2><p>Now that we at least in theory know how Vuejs realises the template data magic, let's build it ourselves for the sake of full understanding!</p><p>Abstract: A function that gets an object and returns one with the properties replaced by getters and setters that, on call, rerender a template. So far so good. If you are really impatient, you can find <a href="https://jsfiddle.net/koehr/e2q9vme3/15/" target="_blank">the final code in JSFiddle</a>.</p><p>Let's start with a very simple approach:</p><iframe src="https://jsfiddle.net/e2q9vme3/embedded/?username=koehr" width="640" height="400" frameborder="0" sandbox="allow-modals allow-forms allow-scripts allow-same-origin allow-popups"></iframe>
<p>The button click invokes a function that just assigns a new value to a property. Still the template gets automagically rerendered. But we all know there is no fairydust involved, right? So how does it actually work?</p><hr><h2>The magic of getters and setters</h2><p>With the <a href="http://www.ecma-international.org/ecma-262/5.1/">ES5 standard</a> JavaScript got lots of exciting new features. Some of them highly underrated and underused in my opinion. <a href="http://www.ecma-international.org/ecma-262/5.1/#sec-8.6.1">Getters and setters</a> are an example. If you never heard of them, I would recommend you to read <a href="https://johnresig.com/blog/javascript-getters-and-setters/">John Riesigs piece</a> on them.</p><p>As soon as you know what getters and setters are: functions transparently called on every property access, you might already know where this goes. Boom! All the fairydust suddenly disappears.</p><h2>Automatic getters and setters</h2><p>Now that we at least in theory know how Vuejs realises the template data magic, let's build it ourselves for the sake of full understanding!</p><p>Abstract: A function that gets an object and returns one with the properties replaced by getters and setters that, on call, rerender a template. So far so good. If you are really impatient, you can find <a href="https://jsfiddle.net/koehr/e2q9vme3/15/">the final code in JSFiddle</a>.</p><p>Let's start with a very simple approach:</p><iframe src="https://jsfiddle.net/e2q9vme3/embedded/?username=koehr" width="640" height="400" frameborder="0" sandbox="allow-modals allow-forms allow-scripts allow-same-origin allow-popups"></iframe>
<p>The function iterates through all object keys and creates a new object with getters and setters in their place. It could also directly manipulate the original object:</p><iframe src="https://jsfiddle.net/k72aoorc/1/embedded/?username=koehr" width="640" height="400" frameborder="0" sandbox="allow-modals allow-forms allow-scripts allow-same-origin allow-popups"></iframe> <p>The function iterates through all object keys and creates a new object with getters and setters in their place. It could also directly manipulate the original object:</p><iframe src="https://jsfiddle.net/k72aoorc/1/embedded/?username=koehr" width="640" height="400" frameborder="0" sandbox="allow-modals allow-forms allow-scripts allow-same-origin allow-popups"></iframe>
<p>I personally don't like to manipulate the existing object and prefer the first way.</p><h2>Introducing: Object.defineProperty</h2><p>Now before we go on with destroying our fantasies of fairydust computing, let's see if there is a more convenient way to what we've done for now. Here I introduce <code>Object.defineProperty</code>, which allows to set all possible attributes for the properties of an object. You can find a <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty">detailed description on MDN</a>.</p><p>With this new knowlegde, the code can be made a bit more readable, by condensing everything into one call:</p><iframe src="https://jsfiddle.net/e2q9vme3/2/embedded/?username=koehr" width="640" height="400" frameborder="0" sandbox="allow-modals allow-forms allow-scripts allow-same-origin allow-popups"></iframe> <p>I personally don't like to manipulate the existing object and prefer the first way.</p><h2>Introducing: Object.defineProperty</h2><p>Now before we go on with destroying our fantasies of fairydust computing, let's see if there is a more convenient way to what we've done for now. Here I introduce <code>Object.defineProperty</code>, which allows to set all possible attributes for the properties of an object. You can find a <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty" target="_blank">detailed description on MDN</a>.</p><p>With this new knowlegde, the code can be made a bit more readable, by condensing everything into one call:</p><iframe src="https://jsfiddle.net/e2q9vme3/2/embedded/?username=koehr" width="640" height="400" frameborder="0" sandbox="allow-modals allow-forms allow-scripts allow-same-origin allow-popups"></iframe>
<p>All those underscores where pretty annoying anyways. I generally suggest you to read more about <code>Object.defineProperty</code>. It extends the range of possibilities significantly!</p><h2>Templating for the poor</h2><p>To be able to rerender a component on data change, we should really introduce some components that can actually render and under the right circumstances rerender a template.</p><iframe src="https://jsfiddle.net/e2q9vme3/3/embedded/?username=koehr" width="640" height="400" frameborder="0" sandbox="allow-modals allow-forms allow-scripts allow-same-origin allow-popups"></iframe> <p>All those underscores where pretty annoying anyways. I generally suggest you to read more about <code>Object.defineProperty</code>. It extends the range of possibilities significantly!</p><h2>Templating for the poor</h2><p>To be able to rerender a component on data change, we should really introduce some components that can actually render and under the right circumstances rerender a template.</p><iframe src="https://jsfiddle.net/e2q9vme3/3/embedded/?username=koehr" width="640" height="400" frameborder="0" sandbox="allow-modals allow-forms allow-scripts allow-same-origin allow-popups"></iframe>
<p>This code describes a very simple component, that has a data object and a render function. If this is called, it replaces the <code>innerHTML</code> of the given content element with the rendered output. Neat! Let's make the data reactive!</p><h2>Reactive Component</h2><p>As a start, it should be enough to simply make the data property reactive:</p><iframe src="https://jsfiddle.net/e2q9vme3/4/embedded/?username=koehr" width="640" height="400" frameborder="0" sandbox="allow-modals allow-forms allow-scripts allow-same-origin allow-popups"></iframe> <p>This code describes a very simple component, that has a data object and a render function. If this is called, it replaces the <code>innerHTML</code> of the given content element with the rendered output. Neat! Let's make the data reactive!</p><h2>Reactive Component</h2><p>As a start, it should be enough to simply make the data property reactive:</p><iframe src="https://jsfiddle.net/e2q9vme3/4/embedded/?username=koehr" width="640" height="400" frameborder="0" sandbox="allow-modals allow-forms allow-scripts allow-same-origin allow-popups"></iframe>
<p>Yes, that seems to be good but it doesn't really update the template. Which becomes clear after a look at line 11-14: There is no render call ever. But <code>reactive</code> shouldn't know about component rendering, right? Let's try a more general approach with a callback:</p><iframe src="https://jsfiddle.net/e2q9vme3/5/embedded/?username=koehr" width="640" height="400" frameborder="0" sandbox="allow-modals allow-forms allow-scripts allow-same-origin allow-popups"></iframe> <p>Yes, that seems to be good but it doesn't really update the template. Which becomes clear after a look at line 11-14: There is no render call ever. But <code>reactive</code> shouldn't know about component rendering, right? Let's try a more general approach with a callback:</p><iframe src="https://jsfiddle.net/e2q9vme3/5/embedded/?username=koehr" width="640" height="400" frameborder="0" sandbox="allow-modals allow-forms allow-scripts allow-same-origin allow-popups"></iframe>
<p>Yeah, that works and so on but it looks like we slowly stumble away from elegance in our code. The changes in <code>reactive()</code> seem to be okay, but that function bind monstrosity in line 31 is something we better hide from our parents. Let's introduce a component factory before we get kicked out or end up in self hatred:</p><iframe src="https://jsfiddle.net/e2q9vme3/6/embedded/?username=koehr" width="640" height="400" frameborder="0" sandbox="allow-modals allow-forms allow-scripts allow-same-origin allow-popups"></iframe> <p>Yeah, that works and so on but it looks like we slowly stumble away from elegance in our code. The changes in <code>reactive()</code> seem to be okay, but that function bind monstrosity in line 31 is something we better hide from our parents. Let's introduce a component factory before we get kicked out or end up in self hatred:</p><iframe src="https://jsfiddle.net/e2q9vme3/6/embedded/?username=koehr" width="640" height="400" frameborder="0" sandbox="allow-modals allow-forms allow-scripts allow-same-origin allow-popups"></iframe>
<p>Cool! That works. The <code>createComponent()</code> function just does all the dirty work for us and returns a nice, reactive component, that is still just a simple object. If you have that code in a local setup and run something like <code>component.data.name = 'Ada Lovelace'</code>, then it will automagically rerender the template to show 'Hello Ada Lovelace'.</p><h2>Nested Data structures</h2><p>All cool and hip stuff but what happens in the following scenario:</p><iframe src="https://jsfiddle.net/e2q9vme3/7/embedded/?username=koehr" width="640" height="400" frameborder="0" sandbox="allow-modals allow-forms allow-scripts allow-same-origin allow-popups"></iframe> <p>Cool! That works. The <code>createComponent()</code> function just does all the dirty work for us and returns a nice, reactive component, that is still just a simple object. If you have that code in a local setup and run something like <code>component.data.name = &apos;Ada Lovelace&apos;</code>, then it will automagically rerender the template to show 'Hello Ada Lovelace'.</p><h2>Nested Data structures</h2><p>All cool and hip stuff but what happens in the following scenario:</p><iframe src="https://jsfiddle.net/e2q9vme3/7/embedded/?username=koehr" width="640" height="400" frameborder="0" sandbox="allow-modals allow-forms allow-scripts allow-same-origin allow-popups"></iframe>
<p>Setting deeper nested properties (line 44,45) doesn't work at all. The reason is that the reactivity only works on the first nesting level of the data object. Now you could say: Easy, we just set the whole object at once:</p><iframe src="https://jsfiddle.net/e2q9vme3/8/embedded/?username=koehr" width="640" height="400" frameborder="0" sandbox="allow-modals allow-forms allow-scripts allow-same-origin allow-popups"></iframe> <p>Setting deeper nested properties (line 44,45) doesn't work at all. The reason is that the reactivity only works on the first nesting level of the data object. Now you could say: Easy, we just set the whole object at once:</p><iframe src="https://jsfiddle.net/e2q9vme3/8/embedded/?username=koehr" width="640" height="400" frameborder="0" sandbox="allow-modals allow-forms allow-scripts allow-same-origin allow-popups"></iframe>
<p>But this is not really what we strive for, isn't it? What we need is a way that makes all nested objects reactive in a recursive way. Surprisingly, this just needs a coupe of lines:</p><iframe src="https://jsfiddle.net/e2q9vme3/9/embedded/?username=koehr" width="640" height="400" frameborder="0" sandbox="allow-modals allow-forms allow-scripts allow-same-origin allow-popups"></iframe> <p>But this is not really what we strive for, isn't it? What we need is a way that makes all nested objects reactive in a recursive way. Surprisingly, this just needs a coupe of lines:</p><iframe src="https://jsfiddle.net/e2q9vme3/9/embedded/?username=koehr" width="640" height="400" frameborder="0" sandbox="allow-modals allow-forms allow-scripts allow-same-origin allow-popups"></iframe>
<p>Only three lines (7-9) where added. They call <code>reactive()</code> on the given value in case it is an object. Now the nesting level doesn't matter anymore. REACTIVE ALL THE THINGS!!</p><h2>Multiple Components</h2><p>Considering that components are usually very gregarious, what happens if we find a friend for our component? Will it blend? Erm I mean, react?</p><iframe src="https://jsfiddle.net/e2q9vme3/10/embedded/?username=koehr" width="640" height="400" frameborder="0" sandbox="allow-modals allow-forms allow-scripts allow-same-origin allow-popups"></iframe> <p>Only three lines (7-9) where added. They call <code>reactive()</code> on the given value in case it is an object. Now the nesting level doesn't matter anymore. REACTIVE ALL THE THINGS!!</p><h2>Multiple Components</h2><p>Considering that components are usually very gregarious, what happens if we find a friend for our component? Will it blend? Erm I mean, react?</p><iframe src="https://jsfiddle.net/e2q9vme3/10/embedded/?username=koehr" width="640" height="400" frameborder="0" sandbox="allow-modals allow-forms allow-scripts allow-same-origin allow-popups"></iframe>
<p>It does! Hooray!</p><p>The attentive reader might have seen the change that sneaked into line 7: Because the type of array is object, an extra check has to be made here. Otherwise the array would be transformed to a plain object with keys 0, 1, etc.</p><p>But what happens now when we manipulate the Array directly?</p><iframe src="https://jsfiddle.net/e2q9vme3/11/embedded/?username=koehr" width="640" height="400" frameborder="0" sandbox="allow-modals allow-forms allow-scripts allow-same-origin allow-popups"></iframe> <p>It does! Hooray!</p><p>The attentive reader might have seen the change that sneaked into line 7: Because the type of array is object, an extra check has to be made here. Otherwise the array would be transformed to a plain object with keys 0, 1, etc.</p><p>But what happens now when we manipulate the Array directly?</p><iframe src="https://jsfiddle.net/e2q9vme3/11/embedded/?username=koehr" width="640" height="400" frameborder="0" sandbox="allow-modals allow-forms allow-scripts allow-same-origin allow-popups"></iframe>
<p>Bummer! Setting the whole array works as expected but manipulating it doesn't trigger any change.</p><h2>Reactive Arrays</h2><p>As described in <a href="https://vuejs.org/v2/guide/list.html#Caveats">the caveats section</a> of the Vuejs guide about list rendering, there are several …well caveats with array reactivity. It writes:</p><pre><code>Due to limitations in JavaScript, Vue cannot detect the following changes to an array: <p>Bummer! Setting the whole array works as expected but manipulating it doesn't trigger any change.</p><h2>Reactive Arrays</h2><p>As described in <a href="https://vuejs.org/v2/guide/list.html#Caveats" target="_blank">the caveats section</a> of the Vuejs guide about list rendering, there are several …well caveats with array reactivity. It writes:</p><pre><code>Due to limitations in JavaScript, Vue cannot detect the following changes to an array:
1. When you directly set an item with the index, e.g. vm.items[indexOfItem] = newValue 1. When you directly set an item with the index, e.g. vm.items[indexOfItem] = newValue
2. When you modify the length of the array, e.g. vm.items.length = newLength 2. When you modify the length of the array, e.g. vm.items.length = newLength
</code></pre><p>Okay, fair enough. So what does happen in Vue to make Arrays reactive? Fairydust? Unfortunately yes. And this stuff is expensive! Nah, just kidding. Of course it is again no magic involved. I'm sorry my dear role-playing friends. What actually happens is that Arrays get their manipulating functions replaced by a wrapped version that notifies the component about changes. The source to this functionality is in <a href="https://github.com/vuejs/vue/blob/dev/src/core/observer/array.js">core/observer/array.js</a>.</p><p>Vuejs' approach is rather sophisticated but can be condensed down to something like what is seen in the first 24 lines here:</p><iframe src="https://jsfiddle.net/e2q9vme3/12/embedded/?username=koehr" width="640" height="400" frameborder="0" sandbox="allow-modals allow-forms allow-scripts allow-same-origin allow-popups"></iframe> </code></pre><p>Okay, fair enough. So what does happen in Vue to make Arrays reactive? Fairydust? Unfortunately yes. And this stuff is expensive! Nah, just kidding. Of course it is again no magic involved. I'm sorry my dear role-playing friends. What actually happens is that Arrays get their manipulating functions replaced by a wrapped version that notifies the component about changes. The source to this functionality is in <a href="https://github.com/vuejs/vue/blob/dev/src/core/observer/array.js" target="_blank">core/observer/array.js</a>.</p><p>Vuejs' approach is rather sophisticated but can be condensed down to something like what is seen in the first 24 lines here:</p><iframe src="https://jsfiddle.net/e2q9vme3/12/embedded/?username=koehr" width="640" height="400" frameborder="0" sandbox="allow-modals allow-forms allow-scripts allow-same-origin allow-popups"></iframe>
<p>So this is a fairly big chunk to digest. The new function <code>reactiveArray</code> starts with creating a copy of the original array (Remember? I don't like manipulating the original object). Then, for each function in the list of manipulative array functions the original is saved which is then replaced by a wrapper function. This wrapper function simply calls the render callback additionally to the original array function.</p><p>Now also <code>lipsumComponent.data.content</code> is not set directly anymore but uses the overwritten push method. Setting it directly wouldn't work. Fixing that leads us to the last step:</p><h2>Reactivity on set</h2><p>For now the setter function didn't care about the value. If it would be a nested object, its children wouldn't be reactive. That means, if you set <code>data.x</code> to an object <code>{foo: 1}</code> and then change foo <code>data.x.foo++</code>, the template wouldn't rerender. This should be changed:</p><iframe src="https://jsfiddle.net/e2q9vme3/14/embedded/?username=koehr" width="640" height="400" frameborder="0" sandbox="allow-modals allow-forms allow-scripts allow-same-origin allow-popups"></iframe> <p>So this is a fairly big chunk to digest. The new function <code>reactiveArray</code> starts with creating a copy of the original array (Remember? I don't like manipulating the original object). Then, for each function in the list of manipulative array functions the original is saved which is then replaced by a wrapper function. This wrapper function simply calls the render callback additionally to the original array function.</p><p>Now also <code>lipsumComponent.data.content</code> is not set directly anymore but uses the overwritten push method. Setting it directly wouldn't work. Fixing that leads us to the last step:</p><h2>Reactivity on set</h2><p>For now the setter function didn't care about the value. If it would be a nested object, its children wouldn't be reactive. That means, if you set <code>data.x</code> to an object <code>{foo: 1}</code> and then change foo <code>data.x.foo++</code>, the template wouldn't rerender. This should be changed:</p><iframe src="https://jsfiddle.net/e2q9vme3/14/embedded/?username=koehr" width="640" height="400" frameborder="0" sandbox="allow-modals allow-forms allow-scripts allow-same-origin allow-popups"></iframe>
<p>Instead of setting the plain value, <code>reactive(value, callback)</code> is called in line 49. This small change works only up to a certain point on its own though. The function has to decide what to do with non-objects or arrays, which happens now as a first step in <code>reactive()</code>. A plain non-object (remember: arrays are objects) simply gets returned as it is (line 30), arrays will be returned in their reactive version (line 31).</p><h2>Conclusion</h2><p>Congratulations! You made it this far or just skipped to read only the Conclusion, which is fine, I do that too sometimes.</p><p>In about <a href="https://jsfiddle.net/koehr/e2q9vme3/15/">70 SLOC</a>, we built a fully reactive component system. We made use of getters, setters and <code>Object.defineProperty</code> and learned, that I don't like to manipulate objects directly. Except for the last point, this should be valuable information that might become handy in future.</p><p>What else can be done you might ask? Vuejs' code is more sophisticated and handles some egde cases that I didn't mention for the sake of simplicity. For example if the yet to become reactive object has some getters and/or setters already, they would be overwritten by our simple solution. Vuejs' <code>defineReactive</code> uses <code>Object.getOwnPropertyDescription</code> to get a detailed information about the property it is going to wrap and incorporates existing getters and setters if applicable. It also ignores non-configurable (not meant to be changed at all) properties. How that works can be found <a href="https://github.com/vuejs/vue/blob/dev/src/core/observer/index.js#L140">in the source code</a>.</p></div> <p>Instead of setting the plain value, <code>reactive(value, callback)</code> is called in line 49. This small change works only up to a certain point on its own though. The function has to decide what to do with non-objects or arrays, which happens now as a first step in <code>reactive()</code>. A plain non-object (remember: arrays are objects) simply gets returned as it is (line 30), arrays will be returned in their reactive version (line 31).</p><h2>Conclusion</h2><p>Congratulations! You made it this far or just skipped to read only the Conclusion, which is fine, I do that too sometimes.</p><p>In about <a href="https://jsfiddle.net/koehr/e2q9vme3/15/" target="_blank">70 SLOC</a>, we built a fully reactive component system. We made use of getters, setters and <code>Object.defineProperty</code> and learned, that I don't like to manipulate objects directly. Except for the last point, this should be valuable information that might become handy in future.</p><p>What else can be done you might ask? Vuejs' code is more sophisticated and handles some egde cases that I didn't mention for the sake of simplicity. For example if the yet to become reactive object has some getters and/or setters already, they would be overwritten by our simple solution. Vuejs' <code>defineReactive</code> uses <code>Object.getOwnPropertyDescription</code> to get a detailed information about the property it is going to wrap and incorporates existing getters and setters if applicable. It also ignores non-configurable (not meant to be changed at all) properties. How that works can be found <a href="https://github.com/vuejs/vue/blob/dev/src/core/observer/index.js#L140" target="_blank">in the source code</a>.</p></div>
<ol class="posts">
<li></li>
</ol>
</main> </main>
@ -76,21 +85,21 @@
<a href="/"> <a href="/">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 832.4 143.1"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 832.4 143.1">
<path id="header-underscore" <path id="header-underscore"
d="M832.4 131.1q0 5.5-3.1 8.6-3 3.4-8.2 3.3h-75.5q-5.2 0-8.2-3.3-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8 0-5.5 3.1-8.7 1.6-1.7 3.7-2.4 2.2-.8 4.5-.8h75.5q5.2 0 8.2 3.2 3 3.1 3 8.7z" /> d="M832.4 131.1q0 5.5-3.1 8.6-3 3.4-8.2 3.3h-75.5q-5.2 0-8.2-3.3-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8 0-5.5 3.1-8.7 1.6-1.7 3.7-2.4 2.2-.8 4.5-.8h75.5q5.2 0 8.2 3.2 3 3.1 3 8.7z"></path>
<path id="header-bracket" <path id="header-bracket"
d="M731.9 81.4q0 6.7-6.5 10.7l-1 .6-74.3 39.2q-2.5 1.3-5.2 1.2-4.8 0-8.1-3.8-3.2-3.6-3.2-8.4 0-3.3 1.7-6 1.8-2.9 4.6-4.4l55.3-29.1-55.3-29q-2.8-1.6-4.6-4.3-1.7-2.7-1.7-6.2 0-4.7 3.2-8.4 3.3-4 8-3.7 2.7 0 5.3 1.2l74.4 39.2q3.3 1.7 5.3 4.7 2 2.8 2 6.5z" /> d="M731.9 81.4q0 6.7-6.5 10.7l-1 .6-74.3 39.2q-2.5 1.3-5.2 1.2-4.8 0-8.1-3.8-3.2-3.6-3.2-8.4 0-3.3 1.7-6 1.8-2.9 4.6-4.4l55.3-29.1-55.3-29q-2.8-1.6-4.6-4.3-1.7-2.7-1.7-6.2 0-4.7 3.2-8.4 3.3-4 8-3.7 2.7 0 5.3 1.2l74.4 39.2q3.3 1.7 5.3 4.7 2 2.8 2 6.5z"></path>
<path id="header-r" <path id="header-r"
d="M588.7 66.5q0 5-3.5 8.5-3.5 3.4-8.1 3.5-4.4 0-8.3-4.3-10-10.7-20.9-10.6-2.2 0-4.3.3-2.1.3-4 1-1.8.6-3.7 1.6-1.7 1-3.4 2.3-1.7 1.3-3.3 2.9-7.8 8.2-7.6 19.7V131q0 5.5-3.1 8.6-3 3.4-8.3 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V51.6q0-5.4 3-8.6 3-3.4 8.3-3.3 2 0 3.7.6 1.8.6 3.3 1.8 1.4 1 2.2 2.7 1 1.5 1.6 3.3 11.8-8.4 27-8.4 10.6 0 21 5 11.3 5.4 17.2 14.5 2.5 3.7 2.5 7.3z" /> d="M588.7 66.5q0 5-3.5 8.5-3.5 3.4-8.1 3.5-4.4 0-8.3-4.3-10-10.7-20.9-10.6-2.2 0-4.3.3-2.1.3-4 1-1.8.6-3.7 1.6-1.7 1-3.4 2.3-1.7 1.3-3.3 2.9-7.8 8.2-7.6 19.7V131q0 5.5-3.1 8.6-3 3.4-8.3 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V51.6q0-5.4 3-8.6 3-3.4 8.3-3.3 2 0 3.7.6 1.8.6 3.3 1.8 1.4 1 2.2 2.7 1 1.5 1.6 3.3 11.8-8.4 27-8.4 10.6 0 21 5 11.3 5.4 17.2 14.5 2.5 3.7 2.5 7.3z"></path>
<path id="header-h" <path id="header-h"
d="M483.9 131.1q0 5.5-3.1 8.6-3 3.4-8.3 3.3-5.2 0-8.2-3.3-3.2-3.1-3.1-8.6V84.8q0-4.6-1.5-8.2-1.4-3.5-4.4-6.9-2.1-2-4.3-3.4-2.2-1.4-4.7-2-2.4-.7-5.3-.7-4.3 0-7.8 1.5-3.3 1.5-6.4 4.6-5.9 6.3-5.8 15v46.4q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v33q1.5-1 3-1.6l3.2-1.2 3.4-1q1.6-.5 3.3-.8l3.5-.4 3.6-.2q4.4 0 8.5 1 4.1.7 7.9 2.4 3.8 1.6 7.3 4.1 3.5 2.5 6.6 5.8Q484 66 484 84.8z" /> d="M483.9 131.1q0 5.5-3.1 8.6-3 3.4-8.3 3.3-5.2 0-8.2-3.3-3.2-3.1-3.1-8.6V84.8q0-4.6-1.5-8.2-1.4-3.5-4.4-6.9-2.1-2-4.3-3.4-2.2-1.4-4.7-2-2.4-.7-5.3-.7-4.3 0-7.8 1.5-3.3 1.5-6.4 4.6-5.9 6.3-5.8 15v46.4q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v33q1.5-1 3-1.6l3.2-1.2 3.4-1q1.6-.5 3.3-.8l3.5-.4 3.6-.2q4.4 0 8.5 1 4.1.7 7.9 2.4 3.8 1.6 7.3 4.1 3.5 2.5 6.6 5.8Q484 66 484 84.8z"></path>
<path id="header-e" <path id="header-e"
d="M387.5 111.1q0 1.2-.3 2.3-.1 1-.5 2l-.9 2q-6.6 12-19.4 19-12 6.6-25.4 6.6-20.8 0-35.8-14.6-15.9-15-15.9-37 0-22.1 15.9-37.1 15-14.6 35.8-14.6 3.9 0 7.8.7 4 .7 8 2.2 9.2 3.1 18.2 10 6 4.6 9.1 9.3 3.3 4.7 3.3 10 0 1.3-.3 2.5-.2 1.3-.7 2.4-1.5 3.4-5 5.3l-56.9 32.2q7.2 4.9 16.5 4.9 7.2 0 12.6-2.5 5.5-2.5 9.7-7.4l.7-1 .8-1 .9-1.3 1-1.5q3.3-4.2 7.4-5.1l1.8-.2q4.4 0 8 3.4 3.6 3.5 3.6 8.5zm-29.9-42.7q-7.2-4.8-16.6-4.8-6 0-11 2-4.9 1.8-9.3 6-4.5 4-6.7 9-2 4.8-2 10.8l.1 2.9z" /> d="M387.5 111.1q0 1.2-.3 2.3-.1 1-.5 2l-.9 2q-6.6 12-19.4 19-12 6.6-25.4 6.6-20.8 0-35.8-14.6-15.9-15-15.9-37 0-22.1 15.9-37.1 15-14.6 35.8-14.6 3.9 0 7.8.7 4 .7 8 2.2 9.2 3.1 18.2 10 6 4.6 9.1 9.3 3.3 4.7 3.3 10 0 1.3-.3 2.5-.2 1.3-.7 2.4-1.5 3.4-5 5.3l-56.9 32.2q7.2 4.9 16.5 4.9 7.2 0 12.6-2.5 5.5-2.5 9.7-7.4l.7-1 .8-1 .9-1.3 1-1.5q3.3-4.2 7.4-5.1l1.8-.2q4.4 0 8 3.4 3.6 3.5 3.6 8.5zm-29.9-42.7q-7.2-4.8-16.6-4.8-6 0-11 2-4.9 1.8-9.3 6-4.5 4-6.7 9-2 4.8-2 10.8l.1 2.9z"></path>
<path id="header-o" <path id="header-o"
d="M286.8 91.4q0 4.2-.6 8.3-.6 4-1.8 7.7-1.1 3.8-2.9 7.4-1.7 3.5-4 6.9-2.4 3.3-5.2 6.1Q258 143 237.7 143T203 128q-14.3-15.2-14.3-36.6 0-21.5 14.3-36.6 14.4-15 34.7-15 4 0 7.8.5 3.9.7 7.5 1.9t7 3q3.3 1.9 6.4 4.3 3.2 2.4 5.9 5.4 14.4 15 14.5 36.5zm-22.6 0q0-2.4-.4-4.5-.2-2.2-.9-4.2-.6-2-1.5-3.9-1-2-2.2-3.7-1.2-1.7-2.8-3.4-4-4.2-8.6-6.1-4.5-2-10-2-11 0-18.7 8.2-7.8 8-7.8 19.6 0 11.4 7.8 19.7 7.8 8 18.6 8 5.6 0 10.1-1.9 4.6-2 8.6-6.1 4-4.3 5.8-9 2-4.9 2-10.7z" /> d="M286.8 91.4q0 4.2-.6 8.3-.6 4-1.8 7.7-1.1 3.8-2.9 7.4-1.7 3.5-4 6.9-2.4 3.3-5.2 6.1Q258 143 237.7 143T203 128q-14.3-15.2-14.3-36.6 0-21.5 14.3-36.6 14.4-15 34.7-15 4 0 7.8.5 3.9.7 7.5 1.9t7 3q3.3 1.9 6.4 4.3 3.2 2.4 5.9 5.4 14.4 15 14.5 36.5zm-22.6 0q0-2.4-.4-4.5-.2-2.2-.9-4.2-.6-2-1.5-3.9-1-2-2.2-3.7-1.2-1.7-2.8-3.4-4-4.2-8.6-6.1-4.5-2-10-2-11 0-18.7 8.2-7.8 8-7.8 19.6 0 11.4 7.8 19.7 7.8 8 18.6 8 5.6 0 10.1-1.9 4.6-2 8.6-6.1 4-4.3 5.8-9 2-4.9 2-10.7z"></path>
<path id="header-k" <path id="header-k"
d="M186.3 131q0 4.7-3.3 8.3-1.5 1.8-3.7 2.7-2 1.1-4.3 1.1-3.5 0-6.6-2L119.2 105v26q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v65.9l49.2-36.1q3.2-2 6.6-2 4.7 0 8 3.7t3.3 8.4q-.2 6-5 9.6l-41 30 41 29.9q2.3 1.7 3.6 4.2 1.4 2.5 1.4 5.4z" /> d="M186.3 131q0 4.7-3.3 8.3-1.5 1.8-3.7 2.7-2 1.1-4.3 1.1-3.5 0-6.6-2L119.2 105v26q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v65.9l49.2-36.1q3.2-2 6.6-2 4.7 0 8 3.7t3.3 8.4q-.2 6-5 9.6l-41 30 41 29.9q2.3 1.7 3.6 4.2 1.4 2.5 1.4 5.4z"></path>
<path id="header-tilde" <path id="header-tilde"
d="M73.1 91q0 2-.6 3.9T71 98.6q-3.2 5.7-8.9 8.5-5.6 2.8-12.9 2.8-8.8 0-18-7.8-2.4-2.3-4.5-3.7-2.1-1.5-3-1.7-1.5 0-2.1.3l-.8 1.3q-.3.7-.8 1.2l-1 1-.9.8q-2.7 2-6.4 2-1.7 0-3.2-.3-1.4-.3-3-1.1-1.5-.8-2.6-2.1-2.8-3.1-2.8-8v-1.3q0-.7.2-1.2l.2-1 .4-1 .4-1q.1-.6.5-1.1l.5-1q3.2-5.7 8.8-8.5 5.7-2.9 13-2.9 3.2 0 6.2 1 3 .9 6 2.7 2.9 1.6 5.7 4.2 5.2 4.6 7.6 5.4 1 0 1.6-.2l.7-.4q.3-.1.5-.4 3.6-5.6 9.2-5.6 5.7 0 8.8 3.5 2.8 3 2.8 8z" /> d="M73.1 91q0 2-.6 3.9T71 98.6q-3.2 5.7-8.9 8.5-5.6 2.8-12.9 2.8-8.8 0-18-7.8-2.4-2.3-4.5-3.7-2.1-1.5-3-1.7-1.5 0-2.1.3l-.8 1.3q-.3.7-.8 1.2l-1 1-.9.8q-2.7 2-6.4 2-1.7 0-3.2-.3-1.4-.3-3-1.1-1.5-.8-2.6-2.1-2.8-3.1-2.8-8v-1.3q0-.7.2-1.2l.2-1 .4-1 .4-1q.1-.6.5-1.1l.5-1q3.2-5.7 8.8-8.5 5.7-2.9 13-2.9 3.2 0 6.2 1 3 .9 6 2.7 2.9 1.6 5.7 4.2 5.2 4.6 7.6 5.4 1 0 1.6-.2l.7-.4q.3-.1.5-.4 3.6-5.6 9.2-5.6 5.7 0 8.8 3.5 2.8 3 2.8 8z"></path>
</svg> </svg>
Homepage of Homepage of
<div class=p-name> <div class=p-name>

View file

@ -3,7 +3,7 @@
<head id="head"> <head id="head">
<meta charset=utf-8> <meta charset=utf-8>
<title id=title >the codeartist — programmer and engineer based in BerlinRunning writefreely 0.7 on Arm</title> <title id="title " var="the codeartist — programmer and engineer based in Berlin">Running writefreely 0.7 on Arm</title>
<meta name=description content="The personal page and weblog of Norman Köhring"> <meta name=description content="The personal page and weblog of Norman Köhring">
<meta name=author content="Norman Köhring"> <meta name=author content="Norman Köhring">
<meta name=DC.title content="the codeartist — programmer and engineer based in Berlin"> <meta name=DC.title content="the codeartist — programmer and engineer based in Berlin">
@ -15,8 +15,8 @@
<meta name="og:title" content="Running writefreely 0.7 on Arm // the codeartist"> <meta name="og:title" content="Running writefreely 0.7 on Arm // the codeartist">
<meta property="og:type" content="website"> <meta property="og:type" content="website">
<meta http-equiv="x-ua-compatible" content="ie=edge"/> <meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"/> <meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no">
<meta name=ICBM content="52.4595, 13.5335"> <meta name=ICBM content="52.4595, 13.5335">
<meta name=geo.position content="52.4595; 13.5335"> <meta name=geo.position content="52.4595; 13.5335">
@ -26,7 +26,7 @@
<link rel=me href=https://k0r.in> <link rel=me href=https://k0r.in>
<link rel=me href=https://koehr.ing> <link rel=me href=https://koehr.ing>
<link rel=me href=@Koehr@mstdn.io> <link rel=me href=@Koehr@mstdn.io>
<link rel=me href=https://sr.ht/~koehr/> <link rel=me href=https://sr.ht/~koehr>
<link rel=me href=https://git.k0r.in> <link rel=me href=https://git.k0r.in>
<link rel=me href=https://threads.net/@coffee_n_code> <link rel=me href=https://threads.net/@coffee_n_code>
<link rel=me href=https://instagram.com/@coffee_n_code> <link rel=me href=https://instagram.com/@coffee_n_code>
@ -35,6 +35,14 @@
<link rel=icon href=/favicon.png type=image/x-icon> <link rel=icon href=/favicon.png type=image/x-icon>
<link rel=stylesheet href=/style.css> <link rel=stylesheet href=/style.css>
<style>
.posts { padding: 0; }
.posts>li { display: block; margin: 2rem 0; }
.posts>li>div { line-height: 2; }
.posts>li>p { line-height: 1.4; }
.posts>li>time, .posts>li>div>.reading-time { color: gray; }
</style>
</head> </head>
<body> <body>
@ -44,11 +52,9 @@
<header> <header>
<h1>Running writefreely 0.7 on Arm</h1> <h1>Running writefreely 0.7 on Arm</h1>
<em>What was necessary to make cross-compiling work for newer WriteFreely versions with SQLite support.</em> <em>What was necessary to make cross-compiling work for newer WriteFreely versions with SQLite support.</em>
<br/>
Last updated: <time datetime="Thu, 10 Jan 2019 00:00:00 +0000" >January 10, 2019</time>
</header> </header>
<div ><hr><p>This is a follow-up on <a href="https://write.as/buttpicker/the-expected-tutorial-how-to-install-writefreely-on-a-raspberry-pi-3-in-10">The expected tutorial: How to install WriteFreely on a Raspberry pi 3 in 10 steps</a>.</p><hr><p>I did it! I finally got WriteFreely to run on my Arm server (check out <a href="https://www.scaleway.com/baremetal-cloud-servers/">Scaleways baremetal cloud servers</a>).</p><p>It wasn't so easy because with 512MB of RAM I couldn't simply download and build the source on my webserver. Only solution: Cross compiling. Easy especially in Go, right?</p><p>If you read the article linked in the beginning you know how easy it could be. But as the article already mentions in an update, since Version 0.6 it is not working anymore because of the new SQLite dependency (newest version as of writing this article is 0.7).</p><p>With a bit of research I figured out what to do to make it work anyhow. There are two solutions. A quick (and slightly dirty) one for people who don't need SQLite support and a correct solution that needs a tad more effort.</p><h2>Quick solution: remove SQLite support</h2><p>SQLite support makes problems with the cross compiling because it needs some C code to be compiled. Before figuring out how to make this working with the otherwise super easy Go cross compiling, removing the feature might be a viable quick fix. For this, simply change or remove all occurences of sqlite in the Makefile:</p><pre><code class="diff"><span class="variable builtin">diff --git a/Makefile b/Makefile</span> <div><hr><p>This is a follow-up on <a href="https://write.as/buttpicker/the-expected-tutorial-how-to-install-writefreely-on-a-raspberry-pi-3-in-10" target="_blank">The expected tutorial: How to install WriteFreely on a Raspberry pi 3 in 10 steps</a>.</p><hr><p>I did it! I finally got WriteFreely to run on my Arm server (check out <a href="https://www.scaleway.com/baremetal-cloud-servers/" target="_blank">Scaleways baremetal cloud servers</a>).</p><p>It wasn't so easy because with 512MB of RAM I couldn't simply download and build the source on my webserver. Only solution: Cross compiling. Easy especially in Go, right?</p><p>If you read the article linked in the beginning you know how easy it could be. But as the article already mentions in an update, since Version 0.6 it is not working anymore because of the new SQLite dependency (newest version as of writing this article is 0.7).</p><p>With a bit of research I figured out what to do to make it work anyhow. There are two solutions. A quick (and slightly dirty) one for people who don't need SQLite support and a correct solution that needs a tad more effort.</p><h2>Quick solution: remove SQLite support</h2><p>SQLite support makes problems with the cross compiling because it needs some C code to be compiled. Before figuring out how to make this working with the otherwise super easy Go cross compiling, removing the feature might be a viable quick fix. For this, simply change or remove all occurences of sqlite in the Makefile:</p><pre><code class="diff"><span class="variable builtin">diff --git a/Makefile b/Makefile</span>
index <span class="constant">5950dfd</span>..<span class="constant">032fd0c</span> 100644 index <span class="constant">5950dfd</span>..<span class="constant">032fd0c</span> 100644
<span class="keyword">--- a/Makefile</span> <span class="keyword">--- a/Makefile</span>
<span class="string">+++ b/Makefile</span> <span class="string">+++ b/Makefile</span>
@ -56,28 +62,28 @@ index <span class="constant">5950dfd</span>..<span class="constant">032fd0c</spa
all : build all : build
build: assets deps build: assets deps
<span class="keyword">- cd cmd/writefreely; $(GOBUILD) -v -tags='sqlite'</span> <span class="keyword">- cd cmd/writefreely; $(GOBUILD) -v -tags=&apos;sqlite&apos;</span>
<span class="string">+ cd cmd/writefreely; $(GOBUILD) -v</span> <span class="string">+ cd cmd/writefreely; $(GOBUILD) -v</span>
build-linux: deps build-linux: deps
@hash xgo &gt; /dev/null 2&gt;&1; if [ $$? -ne 0 ]; then \ @hash xgo &gt; /dev/null 2&gt;&1; if [ $$? -ne 0 ]; then \
$(GOGET) -u github.com/karalabe/xgo; \ $(GOGET) -u github.com/karalabe/xgo; \
fi fi
<span class="keyword">- xgo --targets=linux/amd64, -dest build/ $(LDFLAGS) -tags='sqlite' -out writefreely ./cmd/writefreely</span> <span class="keyword">- xgo --targets=linux/amd64, -dest build/ $(LDFLAGS) -tags=&apos;sqlite&apos; -out writefreely ./cmd/writefreely</span>
<span class="string">+ xgo --targets=linux/amd64, -dest build/ $(LDFLAGS) -out writefreely ./cmd/writefreely</span> <span class="string">+ xgo --targets=linux/amd64, -dest build/ $(LDFLAGS) -out writefreely ./cmd/writefreely</span>
build-windows: deps build-windows: deps
@hash xgo &gt; /dev/null 2&gt;&1; if [ $$? -ne 0 ]; then \ @hash xgo &gt; /dev/null 2&gt;&1; if [ $$? -ne 0 ]; then \
$(GOGET) -u github.com/karalabe/xgo; \ $(GOGET) -u github.com/karalabe/xgo; \
fi fi
<span class="keyword">- xgo --targets=windows/amd64, -dest build/ $(LDFLAGS) -tags='sqlite' -out writefreely ./cmd/writefreely</span> <span class="keyword">- xgo --targets=windows/amd64, -dest build/ $(LDFLAGS) -tags=&apos;sqlite&apos; -out writefreely ./cmd/writefreely</span>
<span class="string">+ xgo --targets=windows/amd64, -dest build/ $(LDFLAGS) -out writefreely ./cmd/writefreely</span> <span class="string">+ xgo --targets=windows/amd64, -dest build/ $(LDFLAGS) -out writefreely ./cmd/writefreely</span>
build-darwin: deps build-darwin: deps
@hash xgo &gt; /dev/null 2&gt;&1; if [ $$? -ne 0 ]; then \ @hash xgo &gt; /dev/null 2&gt;&1; if [ $$? -ne 0 ]; then \
$(GOGET) -u github.com/karalabe/xgo; \ $(GOGET) -u github.com/karalabe/xgo; \
fi fi
<span class="keyword">- xgo --targets=darwin/amd64, -dest build/ $(LDFLAGS) -tags='sqlite' -out writefreely ./cmd/writefreely</span> <span class="keyword">- xgo --targets=darwin/amd64, -dest build/ $(LDFLAGS) -tags=&apos;sqlite&apos; -out writefreely ./cmd/writefreely</span>
<span class="string">+ xgo --targets=darwin/amd64, -dest build/ $(LDFLAGS) -out writefreely ./cmd/writefreely</span> <span class="string">+ xgo --targets=darwin/amd64, -dest build/ $(LDFLAGS) -out writefreely ./cmd/writefreely</span>
build-docker : build-docker :
@ -86,12 +92,12 @@ index <span class="constant">5950dfd</span>..<span class="constant">032fd0c</spa
$(GOTEST) -v ./... $(GOTEST) -v ./...
run: dev-assets run: dev-assets
<span class="keyword">- $(GOINSTALL) -tags='sqlite' ./...</span> <span class="keyword">- $(GOINSTALL) -tags=&apos;sqlite&apos; ./...</span>
<span class="string">+ $(GOINSTALL) ./...</span> <span class="string">+ $(GOINSTALL) ./...</span>
$(BINARY_NAME) --debug $(BINARY_NAME) --debug
deps : deps :
<span class="keyword">- $(GOGET) -tags='sqlite' -v ./...</span> <span class="keyword">- $(GOGET) -tags=&apos;sqlite&apos; -v ./...</span>
<span class="string">+ $(GOGET) -v ./...</span> <span class="string">+ $(GOGET) -v ./...</span>
install : build install : build
@ -141,6 +147,10 @@ index <span class="constant">5950dfd</span>..<span class="constant">032fd0c</spa
</code></pre> </code></pre>
<p>Now <code>./writefreely</code> should run an empty blog at the specified port.</p><p>Have fun!</p></div> <p>Now <code>./writefreely</code> should run an empty blog at the specified port.</p><p>Have fun!</p></div>
<ol class="posts">
<li></li>
</ol>
</main> </main>
<div id="spacer"></div> <div id="spacer"></div>
@ -148,21 +158,21 @@ index <span class="constant">5950dfd</span>..<span class="constant">032fd0c</spa
<a href="/"> <a href="/">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 832.4 143.1"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 832.4 143.1">
<path id="header-underscore" <path id="header-underscore"
d="M832.4 131.1q0 5.5-3.1 8.6-3 3.4-8.2 3.3h-75.5q-5.2 0-8.2-3.3-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8 0-5.5 3.1-8.7 1.6-1.7 3.7-2.4 2.2-.8 4.5-.8h75.5q5.2 0 8.2 3.2 3 3.1 3 8.7z" /> d="M832.4 131.1q0 5.5-3.1 8.6-3 3.4-8.2 3.3h-75.5q-5.2 0-8.2-3.3-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8 0-5.5 3.1-8.7 1.6-1.7 3.7-2.4 2.2-.8 4.5-.8h75.5q5.2 0 8.2 3.2 3 3.1 3 8.7z"></path>
<path id="header-bracket" <path id="header-bracket"
d="M731.9 81.4q0 6.7-6.5 10.7l-1 .6-74.3 39.2q-2.5 1.3-5.2 1.2-4.8 0-8.1-3.8-3.2-3.6-3.2-8.4 0-3.3 1.7-6 1.8-2.9 4.6-4.4l55.3-29.1-55.3-29q-2.8-1.6-4.6-4.3-1.7-2.7-1.7-6.2 0-4.7 3.2-8.4 3.3-4 8-3.7 2.7 0 5.3 1.2l74.4 39.2q3.3 1.7 5.3 4.7 2 2.8 2 6.5z" /> d="M731.9 81.4q0 6.7-6.5 10.7l-1 .6-74.3 39.2q-2.5 1.3-5.2 1.2-4.8 0-8.1-3.8-3.2-3.6-3.2-8.4 0-3.3 1.7-6 1.8-2.9 4.6-4.4l55.3-29.1-55.3-29q-2.8-1.6-4.6-4.3-1.7-2.7-1.7-6.2 0-4.7 3.2-8.4 3.3-4 8-3.7 2.7 0 5.3 1.2l74.4 39.2q3.3 1.7 5.3 4.7 2 2.8 2 6.5z"></path>
<path id="header-r" <path id="header-r"
d="M588.7 66.5q0 5-3.5 8.5-3.5 3.4-8.1 3.5-4.4 0-8.3-4.3-10-10.7-20.9-10.6-2.2 0-4.3.3-2.1.3-4 1-1.8.6-3.7 1.6-1.7 1-3.4 2.3-1.7 1.3-3.3 2.9-7.8 8.2-7.6 19.7V131q0 5.5-3.1 8.6-3 3.4-8.3 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V51.6q0-5.4 3-8.6 3-3.4 8.3-3.3 2 0 3.7.6 1.8.6 3.3 1.8 1.4 1 2.2 2.7 1 1.5 1.6 3.3 11.8-8.4 27-8.4 10.6 0 21 5 11.3 5.4 17.2 14.5 2.5 3.7 2.5 7.3z" /> d="M588.7 66.5q0 5-3.5 8.5-3.5 3.4-8.1 3.5-4.4 0-8.3-4.3-10-10.7-20.9-10.6-2.2 0-4.3.3-2.1.3-4 1-1.8.6-3.7 1.6-1.7 1-3.4 2.3-1.7 1.3-3.3 2.9-7.8 8.2-7.6 19.7V131q0 5.5-3.1 8.6-3 3.4-8.3 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V51.6q0-5.4 3-8.6 3-3.4 8.3-3.3 2 0 3.7.6 1.8.6 3.3 1.8 1.4 1 2.2 2.7 1 1.5 1.6 3.3 11.8-8.4 27-8.4 10.6 0 21 5 11.3 5.4 17.2 14.5 2.5 3.7 2.5 7.3z"></path>
<path id="header-h" <path id="header-h"
d="M483.9 131.1q0 5.5-3.1 8.6-3 3.4-8.3 3.3-5.2 0-8.2-3.3-3.2-3.1-3.1-8.6V84.8q0-4.6-1.5-8.2-1.4-3.5-4.4-6.9-2.1-2-4.3-3.4-2.2-1.4-4.7-2-2.4-.7-5.3-.7-4.3 0-7.8 1.5-3.3 1.5-6.4 4.6-5.9 6.3-5.8 15v46.4q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v33q1.5-1 3-1.6l3.2-1.2 3.4-1q1.6-.5 3.3-.8l3.5-.4 3.6-.2q4.4 0 8.5 1 4.1.7 7.9 2.4 3.8 1.6 7.3 4.1 3.5 2.5 6.6 5.8Q484 66 484 84.8z" /> d="M483.9 131.1q0 5.5-3.1 8.6-3 3.4-8.3 3.3-5.2 0-8.2-3.3-3.2-3.1-3.1-8.6V84.8q0-4.6-1.5-8.2-1.4-3.5-4.4-6.9-2.1-2-4.3-3.4-2.2-1.4-4.7-2-2.4-.7-5.3-.7-4.3 0-7.8 1.5-3.3 1.5-6.4 4.6-5.9 6.3-5.8 15v46.4q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v33q1.5-1 3-1.6l3.2-1.2 3.4-1q1.6-.5 3.3-.8l3.5-.4 3.6-.2q4.4 0 8.5 1 4.1.7 7.9 2.4 3.8 1.6 7.3 4.1 3.5 2.5 6.6 5.8Q484 66 484 84.8z"></path>
<path id="header-e" <path id="header-e"
d="M387.5 111.1q0 1.2-.3 2.3-.1 1-.5 2l-.9 2q-6.6 12-19.4 19-12 6.6-25.4 6.6-20.8 0-35.8-14.6-15.9-15-15.9-37 0-22.1 15.9-37.1 15-14.6 35.8-14.6 3.9 0 7.8.7 4 .7 8 2.2 9.2 3.1 18.2 10 6 4.6 9.1 9.3 3.3 4.7 3.3 10 0 1.3-.3 2.5-.2 1.3-.7 2.4-1.5 3.4-5 5.3l-56.9 32.2q7.2 4.9 16.5 4.9 7.2 0 12.6-2.5 5.5-2.5 9.7-7.4l.7-1 .8-1 .9-1.3 1-1.5q3.3-4.2 7.4-5.1l1.8-.2q4.4 0 8 3.4 3.6 3.5 3.6 8.5zm-29.9-42.7q-7.2-4.8-16.6-4.8-6 0-11 2-4.9 1.8-9.3 6-4.5 4-6.7 9-2 4.8-2 10.8l.1 2.9z" /> d="M387.5 111.1q0 1.2-.3 2.3-.1 1-.5 2l-.9 2q-6.6 12-19.4 19-12 6.6-25.4 6.6-20.8 0-35.8-14.6-15.9-15-15.9-37 0-22.1 15.9-37.1 15-14.6 35.8-14.6 3.9 0 7.8.7 4 .7 8 2.2 9.2 3.1 18.2 10 6 4.6 9.1 9.3 3.3 4.7 3.3 10 0 1.3-.3 2.5-.2 1.3-.7 2.4-1.5 3.4-5 5.3l-56.9 32.2q7.2 4.9 16.5 4.9 7.2 0 12.6-2.5 5.5-2.5 9.7-7.4l.7-1 .8-1 .9-1.3 1-1.5q3.3-4.2 7.4-5.1l1.8-.2q4.4 0 8 3.4 3.6 3.5 3.6 8.5zm-29.9-42.7q-7.2-4.8-16.6-4.8-6 0-11 2-4.9 1.8-9.3 6-4.5 4-6.7 9-2 4.8-2 10.8l.1 2.9z"></path>
<path id="header-o" <path id="header-o"
d="M286.8 91.4q0 4.2-.6 8.3-.6 4-1.8 7.7-1.1 3.8-2.9 7.4-1.7 3.5-4 6.9-2.4 3.3-5.2 6.1Q258 143 237.7 143T203 128q-14.3-15.2-14.3-36.6 0-21.5 14.3-36.6 14.4-15 34.7-15 4 0 7.8.5 3.9.7 7.5 1.9t7 3q3.3 1.9 6.4 4.3 3.2 2.4 5.9 5.4 14.4 15 14.5 36.5zm-22.6 0q0-2.4-.4-4.5-.2-2.2-.9-4.2-.6-2-1.5-3.9-1-2-2.2-3.7-1.2-1.7-2.8-3.4-4-4.2-8.6-6.1-4.5-2-10-2-11 0-18.7 8.2-7.8 8-7.8 19.6 0 11.4 7.8 19.7 7.8 8 18.6 8 5.6 0 10.1-1.9 4.6-2 8.6-6.1 4-4.3 5.8-9 2-4.9 2-10.7z" /> d="M286.8 91.4q0 4.2-.6 8.3-.6 4-1.8 7.7-1.1 3.8-2.9 7.4-1.7 3.5-4 6.9-2.4 3.3-5.2 6.1Q258 143 237.7 143T203 128q-14.3-15.2-14.3-36.6 0-21.5 14.3-36.6 14.4-15 34.7-15 4 0 7.8.5 3.9.7 7.5 1.9t7 3q3.3 1.9 6.4 4.3 3.2 2.4 5.9 5.4 14.4 15 14.5 36.5zm-22.6 0q0-2.4-.4-4.5-.2-2.2-.9-4.2-.6-2-1.5-3.9-1-2-2.2-3.7-1.2-1.7-2.8-3.4-4-4.2-8.6-6.1-4.5-2-10-2-11 0-18.7 8.2-7.8 8-7.8 19.6 0 11.4 7.8 19.7 7.8 8 18.6 8 5.6 0 10.1-1.9 4.6-2 8.6-6.1 4-4.3 5.8-9 2-4.9 2-10.7z"></path>
<path id="header-k" <path id="header-k"
d="M186.3 131q0 4.7-3.3 8.3-1.5 1.8-3.7 2.7-2 1.1-4.3 1.1-3.5 0-6.6-2L119.2 105v26q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v65.9l49.2-36.1q3.2-2 6.6-2 4.7 0 8 3.7t3.3 8.4q-.2 6-5 9.6l-41 30 41 29.9q2.3 1.7 3.6 4.2 1.4 2.5 1.4 5.4z" /> d="M186.3 131q0 4.7-3.3 8.3-1.5 1.8-3.7 2.7-2 1.1-4.3 1.1-3.5 0-6.6-2L119.2 105v26q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v65.9l49.2-36.1q3.2-2 6.6-2 4.7 0 8 3.7t3.3 8.4q-.2 6-5 9.6l-41 30 41 29.9q2.3 1.7 3.6 4.2 1.4 2.5 1.4 5.4z"></path>
<path id="header-tilde" <path id="header-tilde"
d="M73.1 91q0 2-.6 3.9T71 98.6q-3.2 5.7-8.9 8.5-5.6 2.8-12.9 2.8-8.8 0-18-7.8-2.4-2.3-4.5-3.7-2.1-1.5-3-1.7-1.5 0-2.1.3l-.8 1.3q-.3.7-.8 1.2l-1 1-.9.8q-2.7 2-6.4 2-1.7 0-3.2-.3-1.4-.3-3-1.1-1.5-.8-2.6-2.1-2.8-3.1-2.8-8v-1.3q0-.7.2-1.2l.2-1 .4-1 .4-1q.1-.6.5-1.1l.5-1q3.2-5.7 8.8-8.5 5.7-2.9 13-2.9 3.2 0 6.2 1 3 .9 6 2.7 2.9 1.6 5.7 4.2 5.2 4.6 7.6 5.4 1 0 1.6-.2l.7-.4q.3-.1.5-.4 3.6-5.6 9.2-5.6 5.7 0 8.8 3.5 2.8 3 2.8 8z" /> d="M73.1 91q0 2-.6 3.9T71 98.6q-3.2 5.7-8.9 8.5-5.6 2.8-12.9 2.8-8.8 0-18-7.8-2.4-2.3-4.5-3.7-2.1-1.5-3-1.7-1.5 0-2.1.3l-.8 1.3q-.3.7-.8 1.2l-1 1-.9.8q-2.7 2-6.4 2-1.7 0-3.2-.3-1.4-.3-3-1.1-1.5-.8-2.6-2.1-2.8-3.1-2.8-8v-1.3q0-.7.2-1.2l.2-1 .4-1 .4-1q.1-.6.5-1.1l.5-1q3.2-5.7 8.8-8.5 5.7-2.9 13-2.9 3.2 0 6.2 1 3 .9 6 2.7 2.9 1.6 5.7 4.2 5.2 4.6 7.6 5.4 1 0 1.6-.2l.7-.4q.3-.1.5-.4 3.6-5.6 9.2-5.6 5.7 0 8.8 3.5 2.8 3 2.8 8z"></path>
</svg> </svg>
Homepage of Homepage of
<div class=p-name> <div class=p-name>

View file

@ -3,7 +3,7 @@
<head id="head"> <head id="head">
<meta charset=utf-8> <meta charset=utf-8>
<title id=title >the codeartist — programmer and engineer based in BerlinUse OpenBSDs Spleen bitmap font in Linux</title> <title id="title " var="the codeartist — programmer and engineer based in Berlin">Use OpenBSDs Spleen bitmap font in Linux</title>
<meta name=description content="The personal page and weblog of Norman Köhring"> <meta name=description content="The personal page and weblog of Norman Köhring">
<meta name=author content="Norman Köhring"> <meta name=author content="Norman Köhring">
<meta name=DC.title content="the codeartist — programmer and engineer based in Berlin"> <meta name=DC.title content="the codeartist — programmer and engineer based in Berlin">
@ -15,8 +15,8 @@
<meta name="og:title" content="Use OpenBSDs Spleen bitmap font in Linux // the codeartist"> <meta name="og:title" content="Use OpenBSDs Spleen bitmap font in Linux // the codeartist">
<meta property="og:type" content="website"> <meta property="og:type" content="website">
<meta http-equiv="x-ua-compatible" content="ie=edge"/> <meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"/> <meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no">
<meta name=ICBM content="52.4595, 13.5335"> <meta name=ICBM content="52.4595, 13.5335">
<meta name=geo.position content="52.4595; 13.5335"> <meta name=geo.position content="52.4595; 13.5335">
@ -26,7 +26,7 @@
<link rel=me href=https://k0r.in> <link rel=me href=https://k0r.in>
<link rel=me href=https://koehr.ing> <link rel=me href=https://koehr.ing>
<link rel=me href=@Koehr@mstdn.io> <link rel=me href=@Koehr@mstdn.io>
<link rel=me href=https://sr.ht/~koehr/> <link rel=me href=https://sr.ht/~koehr>
<link rel=me href=https://git.k0r.in> <link rel=me href=https://git.k0r.in>
<link rel=me href=https://threads.net/@coffee_n_code> <link rel=me href=https://threads.net/@coffee_n_code>
<link rel=me href=https://instagram.com/@coffee_n_code> <link rel=me href=https://instagram.com/@coffee_n_code>
@ -35,6 +35,14 @@
<link rel=icon href=/favicon.png type=image/x-icon> <link rel=icon href=/favicon.png type=image/x-icon>
<link rel=stylesheet href=/style.css> <link rel=stylesheet href=/style.css>
<style>
.posts { padding: 0; }
.posts>li { display: block; margin: 2rem 0; }
.posts>li>div { line-height: 2; }
.posts>li>p { line-height: 1.4; }
.posts>li>time, .posts>li>div>.reading-time { color: gray; }
</style>
</head> </head>
<body> <body>
@ -44,11 +52,9 @@
<header> <header>
<h1>Use OpenBSDs Spleen bitmap font in Linux</h1> <h1>Use OpenBSDs Spleen bitmap font in Linux</h1>
<em>Yesterday Frederic Cambus changed the default console font in OpenBSD to his self made font.</em> <em>Yesterday Frederic Cambus changed the default console font in OpenBSD to his self made font.</em>
<br/>
Last updated: <time datetime="Thu, 10 Jan 2019 00:00:00 +0000" >January 10, 2019</time>
</header> </header>
<div ><p>The font is called <a href="https://github.com/fcambus/spleen">Spleen</a>, as mentioned in this <a href="https://undeadly.org/cgi?action=article;sid=20190110064857">BSD Journal article</a>.</p><p>To be totally honest, I stopped thinking about TTY (aka console) fonts a long time ago. It just happened to get interesting again when I got a HiRes screen and suddenly a magnifying glass was necessary to read the TTY. Yes I am one of those people who still deny the existence of graphical installers. If you want to change my mind, feel free to write me.</p><p>Anyhow, I figured that Spleen is pretty and useful because it offers glyphs with sizes up to 32x64. Typical fonts in Void Linux are 8x16 or similar, which is very small on high DPI screens. But how to use them? Spleen comes in strange formats like <span title="Glyph Bitmap Distribution Format">BDF</span> or <span title="thats a Macintosh thing">.dfont</span> but we need another strange format called <span title="Linux PC Screen Font Data with unicode directory">PSFU</span>. If we look at the description that comes with Spleen we only get tought how to make yet another strange format called <span title="Portable Compiled Format">PCF</span>. Puh, so confusing. Fonts must have been a real pain back in the "good old times".</p><p>If you managed to read this until this point, I congratulate you. You won a short list of commands:</p><pre><code class="sh"># assuming bdf2psf is installed <div><p>The font is called <a href="https://github.com/fcambus/spleen" target="_blank">Spleen</a>, as mentioned in this <a href="https://undeadly.org/cgi?action=article;sid=20190110064857" target="_blank">BSD Journal article</a>.</p><p>To be totally honest, I stopped thinking about TTY (aka console) fonts a long time ago. It just happened to get interesting again when I got a HiRes screen and suddenly a magnifying glass was necessary to read the TTY. Yes I am one of those people who still deny the existence of graphical installers. If you want to change my mind, feel free to write me.</p><p>Anyhow, I figured that Spleen is pretty and useful because it offers glyphs with sizes up to 32x64. Typical fonts in Void Linux are 8x16 or similar, which is very small on high DPI screens. But how to use them? Spleen comes in strange formats like <span title="Glyph Bitmap Distribution Format">BDF</span> or <span title="thats a Macintosh thing">.dfont</span> but we need another strange format called <span title="Linux PC Screen Font Data with unicode directory">PSFU</span>. If we look at the description that comes with Spleen we only get tought how to make yet another strange format called <span title="Portable Compiled Format">PCF</span>. Puh, so confusing. Fonts must have been a real pain back in the "good old times".</p><p>If you managed to read this until this point, I congratulate you. You won a short list of commands:</p><pre><code class="sh"># assuming bdf2psf is installed
FONTDIR=/usr/share/kbd/consolefonts # or anything you want FONTDIR=/usr/share/kbd/consolefonts # or anything you want
SPLEENDIR=$HOME/src/spleen # or whereever you want the repo SPLEENDIR=$HOME/src/spleen # or whereever you want the repo
EQUIV=/usr/share/bdf2psf/standard.equivalents # check bdf2psf manpage EQUIV=/usr/share/bdf2psf/standard.equivalents # check bdf2psf manpage
@ -64,11 +70,15 @@ do
${FONTDIR}/spleen-${x}.psfu ${FONTDIR}/spleen-${x}.psfu
done done
# assuming you're in the TTY # assuming you&apos;re in the TTY
setfont ${SPLEENDIR}/spleen-16x32.psfu setfont ${SPLEENDIR}/spleen-16x32.psfu
</code></pre> </code></pre>
<p>That worked for me! Except spleen-32x64 didn't work for me. It might be too big for Linux TTYs but would be too big anyways. Lets wait for 8K displays.</p></div> <p>That worked for me! Except spleen-32x64 didn't work for me. It might be too big for Linux TTYs but would be too big anyways. Lets wait for 8K displays.</p></div>
<ol class="posts">
<li></li>
</ol>
</main> </main>
<div id="spacer"></div> <div id="spacer"></div>
@ -76,21 +86,21 @@ setfont ${SPLEENDIR}/spleen-16x32.psfu
<a href="/"> <a href="/">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 832.4 143.1"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 832.4 143.1">
<path id="header-underscore" <path id="header-underscore"
d="M832.4 131.1q0 5.5-3.1 8.6-3 3.4-8.2 3.3h-75.5q-5.2 0-8.2-3.3-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8 0-5.5 3.1-8.7 1.6-1.7 3.7-2.4 2.2-.8 4.5-.8h75.5q5.2 0 8.2 3.2 3 3.1 3 8.7z" /> d="M832.4 131.1q0 5.5-3.1 8.6-3 3.4-8.2 3.3h-75.5q-5.2 0-8.2-3.3-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8 0-5.5 3.1-8.7 1.6-1.7 3.7-2.4 2.2-.8 4.5-.8h75.5q5.2 0 8.2 3.2 3 3.1 3 8.7z"></path>
<path id="header-bracket" <path id="header-bracket"
d="M731.9 81.4q0 6.7-6.5 10.7l-1 .6-74.3 39.2q-2.5 1.3-5.2 1.2-4.8 0-8.1-3.8-3.2-3.6-3.2-8.4 0-3.3 1.7-6 1.8-2.9 4.6-4.4l55.3-29.1-55.3-29q-2.8-1.6-4.6-4.3-1.7-2.7-1.7-6.2 0-4.7 3.2-8.4 3.3-4 8-3.7 2.7 0 5.3 1.2l74.4 39.2q3.3 1.7 5.3 4.7 2 2.8 2 6.5z" /> d="M731.9 81.4q0 6.7-6.5 10.7l-1 .6-74.3 39.2q-2.5 1.3-5.2 1.2-4.8 0-8.1-3.8-3.2-3.6-3.2-8.4 0-3.3 1.7-6 1.8-2.9 4.6-4.4l55.3-29.1-55.3-29q-2.8-1.6-4.6-4.3-1.7-2.7-1.7-6.2 0-4.7 3.2-8.4 3.3-4 8-3.7 2.7 0 5.3 1.2l74.4 39.2q3.3 1.7 5.3 4.7 2 2.8 2 6.5z"></path>
<path id="header-r" <path id="header-r"
d="M588.7 66.5q0 5-3.5 8.5-3.5 3.4-8.1 3.5-4.4 0-8.3-4.3-10-10.7-20.9-10.6-2.2 0-4.3.3-2.1.3-4 1-1.8.6-3.7 1.6-1.7 1-3.4 2.3-1.7 1.3-3.3 2.9-7.8 8.2-7.6 19.7V131q0 5.5-3.1 8.6-3 3.4-8.3 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V51.6q0-5.4 3-8.6 3-3.4 8.3-3.3 2 0 3.7.6 1.8.6 3.3 1.8 1.4 1 2.2 2.7 1 1.5 1.6 3.3 11.8-8.4 27-8.4 10.6 0 21 5 11.3 5.4 17.2 14.5 2.5 3.7 2.5 7.3z" /> d="M588.7 66.5q0 5-3.5 8.5-3.5 3.4-8.1 3.5-4.4 0-8.3-4.3-10-10.7-20.9-10.6-2.2 0-4.3.3-2.1.3-4 1-1.8.6-3.7 1.6-1.7 1-3.4 2.3-1.7 1.3-3.3 2.9-7.8 8.2-7.6 19.7V131q0 5.5-3.1 8.6-3 3.4-8.3 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V51.6q0-5.4 3-8.6 3-3.4 8.3-3.3 2 0 3.7.6 1.8.6 3.3 1.8 1.4 1 2.2 2.7 1 1.5 1.6 3.3 11.8-8.4 27-8.4 10.6 0 21 5 11.3 5.4 17.2 14.5 2.5 3.7 2.5 7.3z"></path>
<path id="header-h" <path id="header-h"
d="M483.9 131.1q0 5.5-3.1 8.6-3 3.4-8.3 3.3-5.2 0-8.2-3.3-3.2-3.1-3.1-8.6V84.8q0-4.6-1.5-8.2-1.4-3.5-4.4-6.9-2.1-2-4.3-3.4-2.2-1.4-4.7-2-2.4-.7-5.3-.7-4.3 0-7.8 1.5-3.3 1.5-6.4 4.6-5.9 6.3-5.8 15v46.4q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v33q1.5-1 3-1.6l3.2-1.2 3.4-1q1.6-.5 3.3-.8l3.5-.4 3.6-.2q4.4 0 8.5 1 4.1.7 7.9 2.4 3.8 1.6 7.3 4.1 3.5 2.5 6.6 5.8Q484 66 484 84.8z" /> d="M483.9 131.1q0 5.5-3.1 8.6-3 3.4-8.3 3.3-5.2 0-8.2-3.3-3.2-3.1-3.1-8.6V84.8q0-4.6-1.5-8.2-1.4-3.5-4.4-6.9-2.1-2-4.3-3.4-2.2-1.4-4.7-2-2.4-.7-5.3-.7-4.3 0-7.8 1.5-3.3 1.5-6.4 4.6-5.9 6.3-5.8 15v46.4q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v33q1.5-1 3-1.6l3.2-1.2 3.4-1q1.6-.5 3.3-.8l3.5-.4 3.6-.2q4.4 0 8.5 1 4.1.7 7.9 2.4 3.8 1.6 7.3 4.1 3.5 2.5 6.6 5.8Q484 66 484 84.8z"></path>
<path id="header-e" <path id="header-e"
d="M387.5 111.1q0 1.2-.3 2.3-.1 1-.5 2l-.9 2q-6.6 12-19.4 19-12 6.6-25.4 6.6-20.8 0-35.8-14.6-15.9-15-15.9-37 0-22.1 15.9-37.1 15-14.6 35.8-14.6 3.9 0 7.8.7 4 .7 8 2.2 9.2 3.1 18.2 10 6 4.6 9.1 9.3 3.3 4.7 3.3 10 0 1.3-.3 2.5-.2 1.3-.7 2.4-1.5 3.4-5 5.3l-56.9 32.2q7.2 4.9 16.5 4.9 7.2 0 12.6-2.5 5.5-2.5 9.7-7.4l.7-1 .8-1 .9-1.3 1-1.5q3.3-4.2 7.4-5.1l1.8-.2q4.4 0 8 3.4 3.6 3.5 3.6 8.5zm-29.9-42.7q-7.2-4.8-16.6-4.8-6 0-11 2-4.9 1.8-9.3 6-4.5 4-6.7 9-2 4.8-2 10.8l.1 2.9z" /> d="M387.5 111.1q0 1.2-.3 2.3-.1 1-.5 2l-.9 2q-6.6 12-19.4 19-12 6.6-25.4 6.6-20.8 0-35.8-14.6-15.9-15-15.9-37 0-22.1 15.9-37.1 15-14.6 35.8-14.6 3.9 0 7.8.7 4 .7 8 2.2 9.2 3.1 18.2 10 6 4.6 9.1 9.3 3.3 4.7 3.3 10 0 1.3-.3 2.5-.2 1.3-.7 2.4-1.5 3.4-5 5.3l-56.9 32.2q7.2 4.9 16.5 4.9 7.2 0 12.6-2.5 5.5-2.5 9.7-7.4l.7-1 .8-1 .9-1.3 1-1.5q3.3-4.2 7.4-5.1l1.8-.2q4.4 0 8 3.4 3.6 3.5 3.6 8.5zm-29.9-42.7q-7.2-4.8-16.6-4.8-6 0-11 2-4.9 1.8-9.3 6-4.5 4-6.7 9-2 4.8-2 10.8l.1 2.9z"></path>
<path id="header-o" <path id="header-o"
d="M286.8 91.4q0 4.2-.6 8.3-.6 4-1.8 7.7-1.1 3.8-2.9 7.4-1.7 3.5-4 6.9-2.4 3.3-5.2 6.1Q258 143 237.7 143T203 128q-14.3-15.2-14.3-36.6 0-21.5 14.3-36.6 14.4-15 34.7-15 4 0 7.8.5 3.9.7 7.5 1.9t7 3q3.3 1.9 6.4 4.3 3.2 2.4 5.9 5.4 14.4 15 14.5 36.5zm-22.6 0q0-2.4-.4-4.5-.2-2.2-.9-4.2-.6-2-1.5-3.9-1-2-2.2-3.7-1.2-1.7-2.8-3.4-4-4.2-8.6-6.1-4.5-2-10-2-11 0-18.7 8.2-7.8 8-7.8 19.6 0 11.4 7.8 19.7 7.8 8 18.6 8 5.6 0 10.1-1.9 4.6-2 8.6-6.1 4-4.3 5.8-9 2-4.9 2-10.7z" /> d="M286.8 91.4q0 4.2-.6 8.3-.6 4-1.8 7.7-1.1 3.8-2.9 7.4-1.7 3.5-4 6.9-2.4 3.3-5.2 6.1Q258 143 237.7 143T203 128q-14.3-15.2-14.3-36.6 0-21.5 14.3-36.6 14.4-15 34.7-15 4 0 7.8.5 3.9.7 7.5 1.9t7 3q3.3 1.9 6.4 4.3 3.2 2.4 5.9 5.4 14.4 15 14.5 36.5zm-22.6 0q0-2.4-.4-4.5-.2-2.2-.9-4.2-.6-2-1.5-3.9-1-2-2.2-3.7-1.2-1.7-2.8-3.4-4-4.2-8.6-6.1-4.5-2-10-2-11 0-18.7 8.2-7.8 8-7.8 19.6 0 11.4 7.8 19.7 7.8 8 18.6 8 5.6 0 10.1-1.9 4.6-2 8.6-6.1 4-4.3 5.8-9 2-4.9 2-10.7z"></path>
<path id="header-k" <path id="header-k"
d="M186.3 131q0 4.7-3.3 8.3-1.5 1.8-3.7 2.7-2 1.1-4.3 1.1-3.5 0-6.6-2L119.2 105v26q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v65.9l49.2-36.1q3.2-2 6.6-2 4.7 0 8 3.7t3.3 8.4q-.2 6-5 9.6l-41 30 41 29.9q2.3 1.7 3.6 4.2 1.4 2.5 1.4 5.4z" /> d="M186.3 131q0 4.7-3.3 8.3-1.5 1.8-3.7 2.7-2 1.1-4.3 1.1-3.5 0-6.6-2L119.2 105v26q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v65.9l49.2-36.1q3.2-2 6.6-2 4.7 0 8 3.7t3.3 8.4q-.2 6-5 9.6l-41 30 41 29.9q2.3 1.7 3.6 4.2 1.4 2.5 1.4 5.4z"></path>
<path id="header-tilde" <path id="header-tilde"
d="M73.1 91q0 2-.6 3.9T71 98.6q-3.2 5.7-8.9 8.5-5.6 2.8-12.9 2.8-8.8 0-18-7.8-2.4-2.3-4.5-3.7-2.1-1.5-3-1.7-1.5 0-2.1.3l-.8 1.3q-.3.7-.8 1.2l-1 1-.9.8q-2.7 2-6.4 2-1.7 0-3.2-.3-1.4-.3-3-1.1-1.5-.8-2.6-2.1-2.8-3.1-2.8-8v-1.3q0-.7.2-1.2l.2-1 .4-1 .4-1q.1-.6.5-1.1l.5-1q3.2-5.7 8.8-8.5 5.7-2.9 13-2.9 3.2 0 6.2 1 3 .9 6 2.7 2.9 1.6 5.7 4.2 5.2 4.6 7.6 5.4 1 0 1.6-.2l.7-.4q.3-.1.5-.4 3.6-5.6 9.2-5.6 5.7 0 8.8 3.5 2.8 3 2.8 8z" /> d="M73.1 91q0 2-.6 3.9T71 98.6q-3.2 5.7-8.9 8.5-5.6 2.8-12.9 2.8-8.8 0-18-7.8-2.4-2.3-4.5-3.7-2.1-1.5-3-1.7-1.5 0-2.1.3l-.8 1.3q-.3.7-.8 1.2l-1 1-.9.8q-2.7 2-6.4 2-1.7 0-3.2-.3-1.4-.3-3-1.1-1.5-.8-2.6-2.1-2.8-3.1-2.8-8v-1.3q0-.7.2-1.2l.2-1 .4-1 .4-1q.1-.6.5-1.1l.5-1q3.2-5.7 8.8-8.5 5.7-2.9 13-2.9 3.2 0 6.2 1 3 .9 6 2.7 2.9 1.6 5.7 4.2 5.2 4.6 7.6 5.4 1 0 1.6-.2l.7-.4q.3-.1.5-.4 3.6-5.6 9.2-5.6 5.7 0 8.8 3.5 2.8 3 2.8 8z"></path>
</svg> </svg>
Homepage of Homepage of
<div class=p-name> <div class=p-name>

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

View file

@ -3,7 +3,7 @@
<head id="head"> <head id="head">
<meta charset=utf-8> <meta charset=utf-8>
<title id=title >the codeartist — programmer and engineer based in BerlinFreddy vs JSON: how to make a top-down shooter</title> <title id="title " var="the codeartist — programmer and engineer based in Berlin">Freddy vs JSON: how to make a top-down shooter</title>
<meta name=description content="The personal page and weblog of Norman Köhring"> <meta name=description content="The personal page and weblog of Norman Köhring">
<meta name=author content="Norman Köhring"> <meta name=author content="Norman Köhring">
<meta name=DC.title content="the codeartist — programmer and engineer based in Berlin"> <meta name=DC.title content="the codeartist — programmer and engineer based in Berlin">
@ -15,8 +15,8 @@
<meta name="og:title" content="Freddy vs JSON: how to make a top-down shooter // the codeartist"> <meta name="og:title" content="Freddy vs JSON: how to make a top-down shooter // the codeartist">
<meta property="og:type" content="website"> <meta property="og:type" content="website">
<meta http-equiv="x-ua-compatible" content="ie=edge"/> <meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"/> <meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no">
<meta name=ICBM content="52.4595, 13.5335"> <meta name=ICBM content="52.4595, 13.5335">
<meta name=geo.position content="52.4595; 13.5335"> <meta name=geo.position content="52.4595; 13.5335">
@ -26,7 +26,7 @@
<link rel=me href=https://k0r.in> <link rel=me href=https://k0r.in>
<link rel=me href=https://koehr.ing> <link rel=me href=https://koehr.ing>
<link rel=me href=@Koehr@mstdn.io> <link rel=me href=@Koehr@mstdn.io>
<link rel=me href=https://sr.ht/~koehr/> <link rel=me href=https://sr.ht/~koehr>
<link rel=me href=https://git.k0r.in> <link rel=me href=https://git.k0r.in>
<link rel=me href=https://threads.net/@coffee_n_code> <link rel=me href=https://threads.net/@coffee_n_code>
<link rel=me href=https://instagram.com/@coffee_n_code> <link rel=me href=https://instagram.com/@coffee_n_code>
@ -35,6 +35,14 @@
<link rel=icon href=/favicon.png type=image/x-icon> <link rel=icon href=/favicon.png type=image/x-icon>
<link rel=stylesheet href=/style.css> <link rel=stylesheet href=/style.css>
<style>
.posts { padding: 0; }
.posts>li { display: block; margin: 2rem 0; }
.posts>li>div { line-height: 2; }
.posts>li>p { line-height: 1.4; }
.posts>li>time, .posts>li>div>.reading-time { color: gray; }
</style>
</head> </head>
<body> <body>
@ -44,30 +52,29 @@
<header> <header>
<h1>Freddy vs JSON: how to make a top-down shooter</h1> <h1>Freddy vs JSON: how to make a top-down shooter</h1>
<em>I will tell you how I created a simple top-down shooter in JavaScript without using any additional libraries. But this article is not replicating the full game but instead tries to show which steps to take to start writing a game from scratch.</em> <em>I will tell you how I created a simple top-down shooter in JavaScript without using any additional libraries. But this article is not replicating the full game but instead tries to show which steps to take to start writing a game from scratch.</em>
<br/>
Last updated: <time datetime="Fri, 03 May 2019 00:00:00 +0000" >May 03, 2019</time>
</header> </header>
<div ><p>A couple of years ago (Oh it's almost a decade! Am I that old already?), when the Canvas API got widely adopted by most browsers, I started experimenting with it. The fascination was high and I immediately tried to use it for interactive toys and games.</p><p>Of course, the games I made (and make) are usually not very sophisticated. That is mainly because I create them only for fun and without much eye-candy or even sound. What really fascinates me is the underlying mechanics. Otherwise, I could just use one of those <a href="https://github.com/collections/javascript-game-engines">awesome game engines</a>, that exist already.</p><p>To share some of the fun, I created a tiny top down shooter for a tech session in my company (<a href="https://wunder.dog">we're hiring, btw</a>). The <a href="https://github.com/nkoehring/FreddyvsJSON">result can be found on Github</a>. I commented the code well so it should be quite helpful to just read it. But if you want to know how I created the game step-by-step, this article is for you.</p><h2>The Game</h2><p>To give you an impression of what I created:</p><p><figure data-title=""><img src="https://github.com/nkoehring/FreddyvsJSON/raw/master/screenshot.jpg" alt="screenshot" title=""></figure></p><p>The little gray box is your ship. You are controlling the little gray box with either WASD or Arrow keys and you can shoot tiny yellow boxes at your enemies — the red boxes — by pressing Space or Enter. The enemies shoot back though. They don't really aim well, but at some point they'll flood the screen with tiny red boxes. If they hit you, they hurt. Every time you get hurt you shrink, until you completely disappear. The same happens with your opponents.</p><h2>Preconditions</h2><p>This post is not about the game itself but about the underlying mechanics and some of the tricks used to make it work. My intention is to provide an entry for understanding more complex game development for people with some existing programming experience. The following things are helpful to fully understand everything:</p><h3>Fundamental Game Engine Mechanics</h3><p>Most — if not all — game engines have the same fundamental building blocks:</p><ul><li><p>The <code>state</code>, that defines the current situation (like main menu, game running, game lost, game won, etc).</p></li><li><p>A place to store all the objects and related data.</p></li><li><p>The <code>main loop</code>, usually running sixty times per second, that reads the object information, draws the screen and applies updates to object data</p></li><li><p>An <code>event handler</code> that maps key presses, mouse movements and clicks to data changes.</p></li></ul><h3>The Canvas Element</h3><p>The Canvas element allows you to handle pixel based data directly inside the browser. It gives you a few functions to draw primitives. It is easy to draw, for example, a blue rectangle but you need more than one action to draw a triangle; to draw a circle you need to know how to use arcs.</p><p>Exactly because drawing rectangles is the easiest and fastest thing to do with the Canvas API, I used them for everything in Freddy vs JSON. That keeps the complexities of drawing more exciting patterns or graphics away and helps focus on the actual game mechanics. This means, after initializing the canvas besides setting colors we only use two functions:</p><pre><code class="js">const ctx = canvas.getContext('2d') // this is the graphics context <div><p>A couple of years ago (Oh it's almost a decade! Am I that old already?), when the Canvas API got widely adopted by most browsers, I started experimenting with it. The fascination was high and I immediately tried to use it for interactive toys and games.</p><p>Of course, the games I made (and make) are usually not very sophisticated. That is mainly because I create them only for fun and without much eye-candy or even sound. What really fascinates me is the underlying mechanics. Otherwise, I could just use one of those <a href="https://github.com/collections/javascript-game-engines" target="_blank">awesome game engines</a>, that exist already.</p><p>To share some of the fun, I created a tiny top down shooter for a tech session in my company (<a href="https://wunder.dog" target="_blank">we're hiring, btw</a>). The <a href="https://github.com/nkoehring/FreddyvsJSON" target="_blank">result can be found on Github</a>. I commented the code well so it should be quite helpful to just read it. But if you want to know how I created the game step-by-step, this article is for you.</p><h2>The Game</h2><p>To give you an impression of what I created:</p><p><figure><img src="/blog/2019-05-03-freddy-vs-json/screenshot.jpg" alt="">
ctx.fillStyle = '#123456' // use color #123456 <figcaption>screenshot</figcaption></figure></p><p>The little gray box is your ship. You are controlling the little gray box with either WASD or Arrow keys and you can shoot tiny yellow boxes at your enemies — the red boxes — by pressing Space or Enter. The enemies shoot back though. They don't really aim well, but at some point they'll flood the screen with tiny red boxes. If they hit you, they hurt. Every time you get hurt you shrink, until you completely disappear. The same happens with your opponents.</p><h2>Preconditions</h2><p>This post is not about the game itself but about the underlying mechanics and some of the tricks used to make it work. My intention is to provide an entry for understanding more complex game development for people with some existing programming experience. The following things are helpful to fully understand everything:</p><h3>Fundamental Game Engine Mechanics</h3><p>Most — if not all — game engines have the same fundamental building blocks:</p><ul><li>The <code>state</code>, that defines the current situation (like main menu, game running, game lost, game won, etc).</li><li>A place to store all the objects and related data.</li><li>The <code>main loop</code>, usually running sixty times per second, that reads the object information, draws the screen and applies updates to object data</li><li>An <code>event handler</code> that maps key presses, mouse movements and clicks to data changes.</li></ul><h3>The Canvas Element</h3><p>The Canvas element allows you to handle pixel based data directly inside the browser. It gives you a few functions to draw primitives. It is easy to draw, for example, a blue rectangle but you need more than one action to draw a triangle; to draw a circle you need to know how to use arcs.</p><p>Exactly because drawing rectangles is the easiest and fastest thing to do with the Canvas API, I used them for everything in Freddy vs JSON. That keeps the complexities of drawing more exciting patterns or graphics away and helps focus on the actual game mechanics. This means, after initializing the canvas besides setting colors we only use two functions:</p><pre><code class="js">const ctx = canvas.getContext(&apos;2d&apos;) // this is the graphics context
ctx.fillStyle = &apos;#123456&apos; // use color #123456
ctx.fillText(text, x, y) // write 'text' at coords x, y ctx.fillText(text, x, y) // write &apos;text&apos; at coords x, y
ctx.fillRect(x, y, width, height) // draw filled rectangle ctx.fillRect(x, y, width, height) // draw filled rectangle
</code></pre> </code></pre>
<h2>Step One: Some HTML and an initialized Canvas</h2><p>Because the code is going to run in the browser, some HTML is necessary. A minimal set would be just the following two lines:</p><pre><code class="html"><span class="punctuation bracket">&lt;</span><span class="tag">canvas</span> <span class="attribute">id</span>="<span class="string">canvas</span>" <span class="punctuation bracket">/&gt;</span> <h2>Step One: Some HTML and an initialized Canvas</h2><p>Because the code is going to run in the browser, some HTML is necessary. A minimal set would be just the following two lines:</p><pre><code class="html"><span class="punctuation bracket">&lt;</span><span class="tag">canvas</span> <span class="attribute">id</span>=&quot;<span class="string">canvas</span>&quot; <span class="punctuation bracket">/&gt;</span>
<span class="punctuation bracket">&lt;</span><span class="tag">script</span> <span class="attribute">src</span>="<span class="string">./app.js</span>"<span class="punctuation bracket">&gt;</span><span class="punctuation bracket">&lt;/</span><span class="tag">script</span><span class="punctuation bracket">&gt;</span> <span class="punctuation bracket">&lt;</span><span class="tag">script</span> <span class="attribute">src</span>=&quot;<span class="string">./app.js</span>&quot;<span class="punctuation bracket">&gt;</span><span class="punctuation bracket">&lt;/</span><span class="tag">script</span><span class="punctuation bracket">&gt;</span>
</code></pre> </code></pre>
<p>This works but of course some styling would be great. And maybe having a title? Check out a <a href="https://github.com/nkoehring/FreddyvsJSON/blob/master/index.html">complete version on Github</a>.</p><p>Initializing a Canvas is also pretty simple. Inside <code>app.js</code> following lines are necessary:</p><pre><code class="js">const canvas = document.getElementById('canvas') <p>This works but of course some styling would be great. And maybe having a title? Check out a <a href="https://github.com/nkoehring/FreddyvsJSON/blob/master/index.html" target="_blank">complete version on Github</a>.</p><p>Initializing a Canvas is also pretty simple. Inside <code>app.js</code> following lines are necessary:</p><pre><code class="js">const canvas = document.getElementById(&apos;canvas&apos;)
// you can set height and width in HTML, too // you can set height and width in HTML, too
canvas.width = 960 canvas.width = 960
canvas.height = 540 canvas.height = 540
const ctx = canvas.getContext('2d') const ctx = canvas.getContext(&apos;2d&apos;)
</code></pre> </code></pre>
<p>I chose rather arbitrary values for width and height. Feel free to change them to your liking. Just know that higher values obviously will result in more work for your computer.</p><h2>Step Two: Game Mode / States</h2><p>To avoid creating a <a href="http://en.wikipedia.org/wiki/Big_ball_of_mud">big ball of mud</a> it is common to use a <a href="https://en.wikipedia.org/wiki/Finite-state_machine">state machine</a>. The idea is to describe the high level states and their valid transitions and using a central state handler to control them.</p><p>There libraries that help with state machines, but it is also not too hard to create this yourself. In the game I created I used a very simple state machine implementation: The possible states and their transitions are described in <a href="https://en.wikipedia.org/wiki/Enumerated_type">Enum-like objects</a>. Here some code to illustrate the idea. The code uses some rather new language features: <a href="https://developer.mozilla.org/en-US/docs/Glossary/Symbol">Symbols</a> and <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer#Computed_property_names">Computed Property Names</a>.</p><pre><code class="js">const STATE = { <p>I chose rather arbitrary values for width and height. Feel free to change them to your liking. Just know that higher values obviously will result in more work for your computer.</p><h2>Step Two: Game Mode / States</h2><p>To avoid creating a <a href="http://en.wikipedia.org/wiki/Big_ball_of_mud" target="_blank">big ball of mud</a> it is common to use a <a href="https://en.wikipedia.org/wiki/Finite-state_machine" target="_blank">state machine</a>. The idea is to describe the high level states and their valid transitions and using a central state handler to control them.</p><p>There libraries that help with state machines, but it is also not too hard to create this yourself. In the game I created I used a very simple state machine implementation: The possible states and their transitions are described in <a href="https://en.wikipedia.org/wiki/Enumerated_type" target="_blank">Enum-like objects</a>. Here some code to illustrate the idea. The code uses some rather new language features: <a href="https://developer.mozilla.org/en-US/docs/Glossary/Symbol" target="_blank">Symbols</a> and <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer#Computed_property_names" target="_blank">Computed Property Names</a>.</p><pre><code class="js">const STATE = {
start: Symbol('start'), // the welcome screen start: Symbol(&apos;start&apos;), // the welcome screen
game: Symbol('game'), // the actual game game: Symbol(&apos;game&apos;), // the actual game
pause: Symbol('pause'), // paused game pause: Symbol(&apos;pause&apos;), // paused game
end: Symbol('end') // after losing the game end: Symbol(&apos;end&apos;) // after losing the game
} }
const STATE_TRANSITION = { const STATE_TRANSITION = {
@ -79,8 +86,8 @@ const STATE_TRANSITION = {
</code></pre> </code></pre>
<p>This is not a full state machine but does the job. For the sake of simplicity I violate the state machine in one occasion though: There is no transition from the running game to the end of the game. This means I have to jump directly, without using the state handler, to the end screen after the player dies. But this saved me from a lot of complexity. Now the state control logic is effectively only one line:</p><pre><code class="js">newState = STATE_TRANSITION[currentState] <p>This is not a full state machine but does the job. For the sake of simplicity I violate the state machine in one occasion though: There is no transition from the running game to the end of the game. This means I have to jump directly, without using the state handler, to the end screen after the player dies. But this saved me from a lot of complexity. Now the state control logic is effectively only one line:</p><pre><code class="js">newState = STATE_TRANSITION[currentState]
</code></pre> </code></pre>
<p>Freddy vs JSON uses this in the click handler. A click into the canvas changes the state from welcome screen to the actual game, pauses and un-pauses the game and brings you back to the welcome screen after losing. All that in only one line. The new state is set to a variable that is respected by the central update loop. More on that later.</p><p>Of course much more could be done with a state. For example weapon or ship upgrades could be realised. The game could transition towards higher difficulty levels and get special game states like an upgrade shop or transfer animations between stages. Your imagination is the limit. And the amount of lines in your state handler, I guess.</p><h2>Step Three: Data Handling</h2><p>Games usually have to handle a lot of information. Some examples are the position and health of the player, the position and health of each enemy, the position of each single bullet that is currently flying around and the amount of hits the player landed so far.</p><p>JavaScript allows different ways to handle this. Of course, the state could just be global. But we all (should) know that global variables are the root of all evil. Global constants are okay because they stay predictable. Just don't use global variables. If you're still not convinced, please read this <a href="https://softwareengineering.stackexchange.com/questions/148108/why-is-global-state-so-evil">entry on stackexchange</a>.</p><p>Instead of global variables, you can put everything into the same scope. A simple example is shown next. The following code examples use template literals, a new language feature. <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals">Learn more about template literals here</a>.</p><pre><code class="js">function Game (canvas) { // the scope <p>Freddy vs JSON uses this in the click handler. A click into the canvas changes the state from welcome screen to the actual game, pauses and un-pauses the game and brings you back to the welcome screen after losing. All that in only one line. The new state is set to a variable that is respected by the central update loop. More on that later.</p><p>Of course much more could be done with a state. For example weapon or ship upgrades could be realised. The game could transition towards higher difficulty levels and get special game states like an upgrade shop or transfer animations between stages. Your imagination is the limit. And the amount of lines in your state handler, I guess.</p><h2>Step Three: Data Handling</h2><p>Games usually have to handle a lot of information. Some examples are the position and health of the player, the position and health of each enemy, the position of each single bullet that is currently flying around and the amount of hits the player landed so far.</p><p>JavaScript allows different ways to handle this. Of course, the state could just be global. But we all (should) know that global variables are the root of all evil. Global constants are okay because they stay predictable. Just don't use global variables. If you're still not convinced, please read this <a href="https://softwareengineering.stackexchange.com/questions/148108/why-is-global-state-so-evil" target="_blank">entry on stackexchange</a>.</p><p>Instead of global variables, you can put everything into the same scope. A simple example is shown next. The following code examples use template literals, a new language feature. <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals" target="_blank">Learn more about template literals here</a>.</p><pre><code class="js">function Game (canvas) { // the scope
const ctx = canvas.getContext('2d') const ctx = canvas.getContext(&apos;2d&apos;)
const playerMaxHealth = 10 const playerMaxHealth = 10
let playerHealth = 10 let playerHealth = 10
@ -91,7 +98,7 @@ const STATE_TRANSITION = {
</code></pre> </code></pre>
<p>This is nice because you have easy access just like with global variables without actually using global variables. It still opens the door to potential problems if you only have one big scope for everything, but the first game is probably small enough to get away with not thinking about this too much.</p><p>Another way is to use classes:</p><pre><code class="js">class Game { <p>This is nice because you have easy access just like with global variables without actually using global variables. It still opens the door to potential problems if you only have one big scope for everything, but the first game is probably small enough to get away with not thinking about this too much.</p><p>Another way is to use classes:</p><pre><code class="js">class Game {
constructor (canvas) { constructor (canvas) {
this.ctx = canvas.getContext('2d') this.ctx = canvas.getContext(&apos;2d&apos;)
this.playerMaxHealth = 10 this.playerMaxHealth = 10
this.playerHealth = 10 this.playerHealth = 10
} }
@ -103,7 +110,7 @@ const STATE_TRANSITION = {
} }
} }
</code></pre> </code></pre>
<p>That looks like a bit more boilerplate but classes are good to encapsulate common functionality. They get even better if your game grows and you want to stay sane. But in JavaScript they are just syntactical sugar. Everything can be achieved with functions and function scopes. So it is up to you, what you use. The two last code examples are essentially the same thing.</p><p>Now that we decided on how to save all the data (Freddy vs JSON uses a class so I'll use classes here too) we can further structure it... or not. Freddy vs JSON saves everything flat. That means for example that each player attribute gets its own variable instead of using a player object that contains a lot of properties. The latter is probably more readable so you might want to go this path. Object access is also pretty fast nowadays so there is probably not a noticeable difference if you write <code>this.player.health</code> instead of <code>this.playerHealth</code>. If you are really serious about performance though, you might want to investigate this topic further. You can check out my <a href="https://jsperf.com/nested-and-flat-property-access/1">jsperf experiment</a> for a start.</p><p>Data manipulation happens in the update loop or when handling events. The next steps explain these topics further.</p><h2>Step Four: The Main Loop</h2><p>If event based changes are enough, like on a website, a separate loop wouldn't be necessary. The user clicks somewhere, which triggers an event that updates something and eventually re-renders a part of the page. But in a game some things happen without direct user interaction. Enemies come into the scene and shoot at you, there might be some background animation, music plays, and so on. To make all this possible a game needs an endlessly running loop which repeatedly calls a function that checks and updates the status of everything. And to make things awesomely smooth it should call this function in a consistent interval — at least thirty, better sixty times per second.</p><p>The following code examples use another rather new language feature called <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions">Arrow Functions</a>.</p><p>Typical approaches to run a function in an regular interval would include the usage of <code>setInterval</code>:</p><pre><code class="js">let someValue = 23 <p>That looks like a bit more boilerplate but classes are good to encapsulate common functionality. They get even better if your game grows and you want to stay sane. But in JavaScript they are just syntactical sugar. Everything can be achieved with functions and function scopes. So it is up to you, what you use. The two last code examples are essentially the same thing.</p><p>Now that we decided on how to save all the data (Freddy vs JSON uses a class so I'll use classes here too) we can further structure it... or not. Freddy vs JSON saves everything flat. That means for example that each player attribute gets its own variable instead of using a player object that contains a lot of properties. The latter is probably more readable so you might want to go this path. Object access is also pretty fast nowadays so there is probably not a noticeable difference if you write <code>this.player.health</code> instead of <code>this.playerHealth</code>. If you are really serious about performance though, you might want to investigate this topic further. You can check out my <a href="https://jsperf.com/nested-and-flat-property-access/1" target="_blank">jsperf experiment</a> for a start.</p><p>Data manipulation happens in the update loop or when handling events. The next steps explain these topics further.</p><h2>Step Four: The Main Loop</h2><p>If event based changes are enough, like on a website, a separate loop wouldn't be necessary. The user clicks somewhere, which triggers an event that updates something and eventually re-renders a part of the page. But in a game some things happen without direct user interaction. Enemies come into the scene and shoot at you, there might be some background animation, music plays, and so on. To make all this possible a game needs an endlessly running loop which repeatedly calls a function that checks and updates the status of everything. And to make things awesomely smooth it should call this function in a consistent interval — at least thirty, better sixty times per second.</p><p>The following code examples use another rather new language feature called <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions" target="_blank">Arrow Functions</a>.</p><p>Typical approaches to run a function in an regular interval would include the usage of <code>setInterval</code>:</p><pre><code class="js">let someValue = 23
setInterval(() =&gt; { setInterval(() =&gt; {
someValue++ someValue++
}, 16) }, 16)
@ -131,7 +138,7 @@ function update () {
lastRun = Date.now() lastRun = Date.now()
update() update()
</code></pre> </code></pre>
<p><code>Date.now()</code> returns the current time in milliseconds. With this information we can figure out how much time has passed since the last run. If more than sixteen milliseconds have passed since then just start the update immediately and crush that poor computer (or better slow down the execution time and be nice to the computer), otherwise wait as long as necessary to stay at around sixty runs per second.</p><p>Please note that Date.now() is not the best way to measure performance. To learn more about performance and high resolution time measurement, check out: <a href="https://developer.mozilla.org/en-US/docs/Web/API/Performance">https://developer.mozilla.org/en-US/docs/Web/API/Performance</a></p><p>Cool. This way you can also slow everything down to a chill thirty frames per second by setting the interval to thirty-three milliseconds. But lets not go that path. Lets do what the cool kids with their shiny new browsers do. Lets use <a href="https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame">requestAnimationFrame</a>.</p><p><code>requestAnimationFrame</code> takes your update function as an argument and will call it right before the next repaint. It also gives you the timestamp of the last call, so that you don't have to ask for another one, which potentially impacts your performance. Lets get down to the details:</p><pre><code class="js">function update () { <p><code>Date.now()</code> returns the current time in milliseconds. With this information we can figure out how much time has passed since the last run. If more than sixteen milliseconds have passed since then just start the update immediately and crush that poor computer (or better slow down the execution time and be nice to the computer), otherwise wait as long as necessary to stay at around sixty runs per second.</p><p>Please note that Date.now() is not the best way to measure performance. To learn more about performance and high resolution time measurement, check out: <a href="https://developer.mozilla.org/en-US/docs/Web/API/Performance" target="_blank">https://developer.mozilla.org/en-US/docs/Web/API/Performance</a></p><p>Cool. This way you can also slow everything down to a chill thirty frames per second by setting the interval to thirty-three milliseconds. But lets not go that path. Lets do what the cool kids with their shiny new browsers do. Lets use <a href="https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame" target="_blank">requestAnimationFrame</a>.</p><p><code>requestAnimationFrame</code> takes your update function as an argument and will call it right before the next repaint. It also gives you the timestamp of the last call, so that you don't have to ask for another one, which potentially impacts your performance. Lets get down to the details:</p><pre><code class="js">function update () {
/* do some heavy calculations */ /* do some heavy calculations */
requestAnimationFrame(update) requestAnimationFrame(update)
} }
@ -159,12 +166,12 @@ requestAnimationFrame(update)
doSomethingWithThat(mouseMoveEvent) doSomethingWithThat(mouseMoveEvent)
} }
</code></pre> </code></pre>
<p>This will be executed on every little movement of the mouse as long as it is on top of the canvas. Usually you want to <a href="https://davidwalsh.name/javascript-debounce-function">debounce</a> that event handler because the event might fire at crazy rates. Another way would be to use it only for something very simple, like to save the mouse coordinates. That information can be used in a function that is not tied to the event firing, like our update function:</p><pre><code class="js">class Game { <p>This will be executed on every little movement of the mouse as long as it is on top of the canvas. Usually you want to <a href="https://davidwalsh.name/javascript-debounce-function" target="_blank">debounce</a> that event handler because the event might fire at crazy rates. Another way would be to use it only for something very simple, like to save the mouse coordinates. That information can be used in a function that is not tied to the event firing, like our update function:</p><pre><code class="js">class Game {
constructor (canvas) { constructor (canvas) {
// don't forget to set canvas width and height, // don&apos;t forget to set canvas width and height,
// if you don't do it, it will set to rather // if you don&apos;t do it, it will set to rather
// small default values // small default values
this.ctx = canvas.getContext('2d') this.ctx = canvas.getContext(&apos;2d&apos;)
this.mouseX = 0 this.mouseX = 0
this.mouseY = 0 this.mouseY = 0
@ -180,18 +187,18 @@ requestAnimationFrame(update)
// gets called at each repaint // gets called at each repaint
update () { update () {
requestAnimationFrame(() =&gt; this.update()) requestAnimationFrame(() =&gt; this.update())
this.fillRect('green', this.mouseX, this.mouseY, 2, 2) this.fillRect(&apos;green&apos;, this.mouseX, this.mouseY, 2, 2)
} }
} }
</code></pre> </code></pre>
<p>The <a href="https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent">MouseEvent object</a> contains a lot more useful information. I suggest you to check out the link and read about it.</p><p>This should draw two pixel wide boxes wherever you touch the canvas with your mouse. Yeah, a drawing program in ten lines! Photoshop, we're coming for you!</p><h3>Mouse Clicks</h3><p>But lets get back to reality. Mouse clicks are another important interaction:</p><pre><code class="js">canvas.onclick = mouseClickEvent =&gt; { <p>The <a href="https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent" target="_blank">MouseEvent object</a> contains a lot more useful information. I suggest you to check out the link and read about it.</p><p>This should draw two pixel wide boxes wherever you touch the canvas with your mouse. Yeah, a drawing program in ten lines! Photoshop, we're coming for you!</p><h3>Mouse Clicks</h3><p>But lets get back to reality. Mouse clicks are another important interaction:</p><pre><code class="js">canvas.onclick = mouseClickEvent =&gt; {
doSomethingWithThat(mouseClickEvent) doSomethingWithThat(mouseClickEvent)
} }
</code></pre> </code></pre>
<p>The event object again contains all kind of useful information. It is the same type of object that you get from mouse movement. Makes life simpler, doesn't it?</p><p>Now to make use of the mouse clicks, lets adapt the former code example:</p><pre><code class="js">class Game { <p>The event object again contains all kind of useful information. It is the same type of object that you get from mouse movement. Makes life simpler, doesn't it?</p><p>Now to make use of the mouse clicks, lets adapt the former code example:</p><pre><code class="js">class Game {
constructor (canvas) { constructor (canvas) {
// set canvas.width and canvas.height here // set canvas.width and canvas.height here
this.ctx = canvas.getContext('2d') this.ctx = canvas.getContext(&apos;2d&apos;)
this.mouseX = 0 this.mouseX = 0
this.mouseY = 0 this.mouseY = 0
this.drawing = false this.drawing = false
@ -213,24 +220,25 @@ requestAnimationFrame(update)
update () { update () {
requestAnimationFrame(() =&gt; this.update()) requestAnimationFrame(() =&gt; this.update())
if (this.drawing) { if (this.drawing) {
this.fillRect('green', this.mouseX, this.mouseY, 2, 2) this.fillRect(&apos;green&apos;, this.mouseX, this.mouseY, 2, 2)
} }
} }
} }
</code></pre> </code></pre>
<p><a href="https://codesandbox.io/s/3qw6q7j535">Check it out on CodeSandbox</a></p><p>Now the boxes are only drawn while holding down the mouse button. Boom, one step closer to the ease of use of Photoshop! It is incredible, what you can do with it already. Just check out this incredible piece of art:</p><p><figure data-title=""><img src="https://github.com/nkoehring/FreddyvsJSON/raw/master/blogpost/drawing.jpg" alt="incredible piece of art" title=""></figure></p><h3>Key Events</h3><p>The last important input comes from key presses. Okay, it is not really the last input type. Other ones would come from joysticks or gamepads. But there are some old-school people like me who still prefer using the keyboard to navigate their space ship.</p><p>Input handling is theoretically simple but in practice it is everything but. That's why this section explains not only how key events work but also how to get them right. Look forward to event handling, the relationship between velocity and acceleration, and frame rate agnostic timing...</p><p>The simplest version of key event handling looks like this:</p><pre><code class="js">document.onkeypress = keyPressEvent =&gt; { <p><a href="https://codesandbox.io/s/3qw6q7j535" target="_blank">Check it out on CodeSandbox</a></p><p>Now the boxes are only drawn while holding down the mouse button. Boom, one step closer to the ease of use of Photoshop! It is incredible, what you can do with it already. Just check out this incredible piece of art:</p><p><figure><img src="/blog/2019-05-03-freddy-vs-json/drawing.jpg" alt="">
<figcaption>incredible piece of art</figcaption></figure></p><h3>Key Events</h3><p>The last important input comes from key presses. Okay, it is not really the last input type. Other ones would come from joysticks or gamepads. But there are some old-school people like me who still prefer using the keyboard to navigate their space ship.</p><p>Input handling is theoretically simple but in practice it is everything but. That's why this section explains not only how key events work but also how to get them right. Look forward to event handling, the relationship between velocity and acceleration, and frame rate agnostic timing...</p><p>The simplest version of key event handling looks like this:</p><pre><code class="js">document.onkeypress = keyPressEvent =&gt; {
doSomethingWithThat(keyPressEvent) doSomethingWithThat(keyPressEvent)
} }
</code></pre> </code></pre>
<p>But <code>keypress</code> is deprecated and should not be used. It is anyways better to separate the <code>keyPress</code> into two events: <code>KeyDown</code> and <code>KeyUp</code> and I'll explain why.</p><p>For now imagine you have that awesome space ship in the middle of the screen and want to make it fly to the right if the user presses <code>d</code> or <code>ArrowRight</code>:</p><pre><code class="js">class Game { <p>But <code>keypress</code> is deprecated and should not be used. It is anyways better to separate the <code>keyPress</code> into two events: <code>KeyDown</code> and <code>KeyUp</code> and I'll explain why.</p><p>For now imagine you have that awesome space ship in the middle of the screen and want to make it fly to the right if the user presses <code>d</code> or <code>ArrowRight</code>:</p><pre><code class="js">class Game {
constructor(canvas, width, height) { constructor(canvas, width, height) {
// we'll need those values // we&apos;ll need those values
this.width = canvas.width = width; this.width = canvas.width = width;
this.height = canvas.height = height; this.height = canvas.height = height;
this.ctx = canvas.getContext("2d"); this.ctx = canvas.getContext(&quot;2d&quot;);
this.shipSize = 10; this.shipSize = 10;
this.shipHalf = this.shipSize / 2.0; // you'll need that a lot this.shipHalf = this.shipSize / 2.0; // you&apos;ll need that a lot
// position the ship in the center of the canvas // position the ship in the center of the canvas
this.shipX = width / 2.0 - this.shipHalf; this.shipX = width / 2.0 - this.shipHalf;
@ -240,7 +248,7 @@ requestAnimationFrame(update)
// https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent // https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent
document.onkeypress = event =&gt; { document.onkeypress = event =&gt; {
const key = event.key; const key = event.key;
if (key === "d" || key === "ArrowRight") { if (key === &quot;d&quot; || key === &quot;ArrowRight&quot;) {
this.shipX++; this.shipX++;
} }
}; };
@ -256,7 +264,7 @@ requestAnimationFrame(update)
update() { update() {
// clean the canvas // clean the canvas
this.rect("black", 0, 0, this.width, this.height); this.rect(&quot;black&quot;, 0, 0, this.width, this.height);
// get everything we need to draw the ship // get everything we need to draw the ship
const size = this.shipSize; const size = this.shipSize;
@ -264,22 +272,22 @@ requestAnimationFrame(update)
const y = this.shipY - this.shipHalf; const y = this.shipY - this.shipHalf;
// draw the ship // draw the ship
this.rect("green", x, y, size, size); this.rect(&quot;green&quot;, x, y, size, size);
// redraw as fast as it makes sense // redraw as fast as it makes sense
requestAnimationFrame(() =&gt; this.update()); requestAnimationFrame(() =&gt; this.update());
} }
} }
</code></pre> </code></pre>
<p><a href="https://codesandbox.io/s/2w10vo897n">check it out on CodeSandbox</a></p><p>Okay, that is kinda working, at least if you press <code>d</code>. But the arrow key is somehow not working and the ship's movement feels a bit jumpy. That doesn't seem to be optimal.</p><p>The problem is that we're relying on repeated key events. If you press and hold a key, the <code>keypress</code> event is repeated a couple of times per second, depending on how you set your key repeat rate. There is no way to use that for a smooth movement because we can not find out how fast the users keys are repeating. Sure, we could try to measure the repeat rate, hoping the user holds the key long enough. But let's try to be smarter than that.</p><p>Lets recap: We hold the key, the ship moves. We leave the key, the movement stops. That is what we want. What a happy coincidence that these two events have ...erm.. events:</p><pre><code class="js">class Game { <p><a href="https://codesandbox.io/s/2w10vo897n" target="_blank">check it out on CodeSandbox</a></p><p>Okay, that is kinda working, at least if you press <code>d</code>. But the arrow key is somehow not working and the ship's movement feels a bit jumpy. That doesn't seem to be optimal.</p><p>The problem is that we're relying on repeated key events. If you press and hold a key, the <code>keypress</code> event is repeated a couple of times per second, depending on how you set your key repeat rate. There is no way to use that for a smooth movement because we can not find out how fast the users keys are repeating. Sure, we could try to measure the repeat rate, hoping the user holds the key long enough. But let's try to be smarter than that.</p><p>Lets recap: We hold the key, the ship moves. We leave the key, the movement stops. That is what we want. What a happy coincidence that these two events have ...erm.. events:</p><pre><code class="js">class Game {
constructor(canvas, width, height) { constructor(canvas, width, height) {
// we'll need those values // we&apos;ll need those values
this.width = canvas.width = width; this.width = canvas.width = width;
this.height = canvas.height = height; this.height = canvas.height = height;
this.ctx = canvas.getContext("2d"); this.ctx = canvas.getContext(&quot;2d&quot;);
this.shipSize = 10; this.shipSize = 10;
this.shipHalf = this.shipSize / 2.0; // you'll need that a lot this.shipHalf = this.shipSize / 2.0; // you&apos;ll need that a lot
// position the ship in the center of the canvas // position the ship in the center of the canvas
this.shipX = width / 2.0 - this.shipHalf; this.shipX = width / 2.0 - this.shipHalf;
@ -291,21 +299,21 @@ requestAnimationFrame(update)
document.onkeydown = event =&gt; { document.onkeydown = event =&gt; {
const key = event.key; const key = event.key;
switch (key) { switch (key) {
case "d": case &quot;d&quot;:
case "ArrowRight": case &quot;ArrowRight&quot;:
this.shipMoves = "right"; this.shipMoves = &quot;right&quot;;
break; break;
case "a": case &quot;a&quot;:
case "ArrowLeft": case &quot;ArrowLeft&quot;:
this.shipMoves = "left"; this.shipMoves = &quot;left&quot;;
break; break;
case "w": case &quot;w&quot;:
case "ArrowUp": case &quot;ArrowUp&quot;:
this.shipMoves = "up"; this.shipMoves = &quot;up&quot;;
break; break;
case "s": case &quot;s&quot;:
case "ArrowDown": case &quot;ArrowDown&quot;:
this.shipMoves = "down"; this.shipMoves = &quot;down&quot;;
break; break;
} }
}; };
@ -326,14 +334,14 @@ requestAnimationFrame(update)
update() { update() {
// move the ship // move the ship
if (this.shipMoves) { if (this.shipMoves) {
if (this.shipMoves === "right") this.shipX++; if (this.shipMoves === &quot;right&quot;) this.shipX++;
else if (this.shipMoves === "left") this.shipX--; else if (this.shipMoves === &quot;left&quot;) this.shipX--;
else if (this.shipMoves === "up") this.shipY--; else if (this.shipMoves === &quot;up&quot;) this.shipY--;
else if (this.shipMoves === "down") this.shipY++; else if (this.shipMoves === &quot;down&quot;) this.shipY++;
} }
// clean the canvas // clean the canvas
this.rect("black", 0, 0, this.width, this.height); this.rect(&quot;black&quot;, 0, 0, this.width, this.height);
// get everything we need to draw the ship // get everything we need to draw the ship
const size = this.shipSize; const size = this.shipSize;
@ -341,14 +349,14 @@ requestAnimationFrame(update)
const y = this.shipY - this.shipHalf; const y = this.shipY - this.shipHalf;
// draw the ship // draw the ship
this.rect("green", x, y, size, size); this.rect(&quot;green&quot;, x, y, size, size);
// redraw as fast as it makes sense // redraw as fast as it makes sense
requestAnimationFrame(() =&gt; this.update()); requestAnimationFrame(() =&gt; this.update());
} }
} }
</code></pre> </code></pre>
<p><a href="https://codesandbox.io/s/nr8r6myz60">check it out on CodeSandbox</a></p><p>I felt like adding all directions right away. Now the movement itself is decoupled from the key events. Instead of changing the coordinates directly on each event, a value is set to a movement direction and the main loop takes care of adapting the coordinates. That's great because we don't care about any key repeat rates anymore.</p><p>But there are still some problems here. First of all, the ship can only move in one direction at a time. Instead it should always be able to move in two directions at a time, like up- and leftwards. Then the movement stops if the switch from one key to another is too fast. That might happen in a heated situation between your ship and the enemies bullets. Also the movement is bound to the frame rate. If the frame rate drops or the screen refreshes on a different rate on the players computer, your ship becomes slower or faster. And last but not least the ship simply jumps to full speed and back to zero. For a more natural feeling it should instead accelerate and decelerate.</p><p>Lots of work. Lets tackle the problems one by one:</p><p>Bidirectional movements are easy to do. We just need a second variable. And to simplify things even more, we can set these variables to numbers instead of identifying strings. Here you see why:</p><pre><code class="js">class Game { <p><a href="https://codesandbox.io/s/nr8r6myz60" target="_blank">check it out on CodeSandbox</a></p><p>I felt like adding all directions right away. Now the movement itself is decoupled from the key events. Instead of changing the coordinates directly on each event, a value is set to a movement direction and the main loop takes care of adapting the coordinates. That's great because we don't care about any key repeat rates anymore.</p><p>But there are still some problems here. First of all, the ship can only move in one direction at a time. Instead it should always be able to move in two directions at a time, like up- and leftwards. Then the movement stops if the switch from one key to another is too fast. That might happen in a heated situation between your ship and the enemies bullets. Also the movement is bound to the frame rate. If the frame rate drops or the screen refreshes on a different rate on the players computer, your ship becomes slower or faster. And last but not least the ship simply jumps to full speed and back to zero. For a more natural feeling it should instead accelerate and decelerate.</p><p>Lots of work. Lets tackle the problems one by one:</p><p>Bidirectional movements are easy to do. We just need a second variable. And to simplify things even more, we can set these variables to numbers instead of identifying strings. Here you see why:</p><pre><code class="js">class Game {
constructor(canvas, width, height) { constructor(canvas, width, height) {
/* ... same as before ... */ /* ... same as before ... */
@ -360,20 +368,20 @@ requestAnimationFrame(update)
document.onkeydown = event =&gt; { document.onkeydown = event =&gt; {
const key = event.key; const key = event.key;
switch (key) { switch (key) {
case "d": case &quot;d&quot;:
case "ArrowRight": case &quot;ArrowRight&quot;:
this.shipMovesHorizontal = 1; this.shipMovesHorizontal = 1;
break; break;
case "a": case &quot;a&quot;:
case "ArrowLeft": case &quot;ArrowLeft&quot;:
this.shipMovesHorizontal = -1; this.shipMovesHorizontal = -1;
break; break;
case "w": case &quot;w&quot;:
case "ArrowUp": case &quot;ArrowUp&quot;:
this.shipMovesVertical = -1; this.shipMovesVertical = -1;
break; break;
case "s": case &quot;s&quot;:
case "ArrowDown": case &quot;ArrowDown&quot;:
this.shipMovesVertical = 1; this.shipMovesVertical = 1;
break; break;
} }
@ -384,16 +392,16 @@ requestAnimationFrame(update)
document.onkeyup = event =&gt; { document.onkeyup = event =&gt; {
const key = event.key; const key = event.key;
switch (key) { switch (key) {
case "d": case &quot;d&quot;:
case "ArrowRight": case &quot;ArrowRight&quot;:
case "a": case &quot;a&quot;:
case "ArrowLeft": case &quot;ArrowLeft&quot;:
this.shipMovesHorizontal = 0; this.shipMovesHorizontal = 0;
break; break;
case "w": case &quot;w&quot;:
case "ArrowUp": case &quot;ArrowUp&quot;:
case "s": case &quot;s&quot;:
case "ArrowDown": case &quot;ArrowDown&quot;:
this.shipMovesVertical = 0; this.shipMovesVertical = 0;
break; break;
} }
@ -413,29 +421,29 @@ requestAnimationFrame(update)
} }
} }
</code></pre> </code></pre>
<p><a href="https://codesandbox.io/s/v0l8v95nr5">Find the full version on CodeSandbox</a></p><p>This not only allows the ship to move in two directions at the same time, it also simplifies everything. But there's still the problem, that fast key presses don't get recognized well.</p><p>What actually happens in those stressful moments is correct from the code's point of view: If a key of the same dimension (horizontal or vertical) is pressed, set the movement direction, if it is released set movement to zero. But humans are not very exact. They might press the left arrow (or <code>a</code>) a split second before they fully released the right arrow (or <code>d</code>). This way, the function switches the movement direction for that split second but then stops because of the released key.</p><p>To fix this, the <code>keyup</code> handler needs a bit more logic:</p><pre><code class="js">document.onkeyup = event =&gt; { <p><a href="https://codesandbox.io/s/v0l8v95nr5" target="_blank">Find the full version on CodeSandbox</a></p><p>This not only allows the ship to move in two directions at the same time, it also simplifies everything. But there's still the problem, that fast key presses don't get recognized well.</p><p>What actually happens in those stressful moments is correct from the code's point of view: If a key of the same dimension (horizontal or vertical) is pressed, set the movement direction, if it is released set movement to zero. But humans are not very exact. They might press the left arrow (or <code>a</code>) a split second before they fully released the right arrow (or <code>d</code>). This way, the function switches the movement direction for that split second but then stops because of the released key.</p><p>To fix this, the <code>keyup</code> handler needs a bit more logic:</p><pre><code class="js">document.onkeyup = event =&gt; {
const key = event.key; const key = event.key;
switch (key) { switch (key) {
case "d": case &quot;d&quot;:
case "ArrowRight": case &quot;ArrowRight&quot;:
if (this.shipMovesHorizontal &gt; 0) { if (this.shipMovesHorizontal &gt; 0) {
this.shipMovesHorizontal = 0; this.shipMovesHorizontal = 0;
} }
break; break;
case "a": case &quot;a&quot;:
case "ArrowLeft": case &quot;ArrowLeft&quot;:
if (this.shipMovesHorizontal &lt; 0) { if (this.shipMovesHorizontal &lt; 0) {
this.shipMovesHorizontal = 0; this.shipMovesHorizontal = 0;
} }
break; break;
case "w": case &quot;w&quot;:
case "ArrowUp": case &quot;ArrowUp&quot;:
if (this.shipMovesVertical &lt; 0) { if (this.shipMovesVertical &lt; 0) {
this.shipMovesVertical = 0; this.shipMovesVertical = 0;
} }
break; break;
case "s": case &quot;s&quot;:
case "ArrowDown": case &quot;ArrowDown&quot;:
if (this.shipMovesVertical &gt; 0) { if (this.shipMovesVertical &gt; 0) {
this.shipMovesVertical = 0; this.shipMovesVertical = 0;
} }
@ -443,7 +451,7 @@ requestAnimationFrame(update)
} }
}; };
</code></pre> </code></pre>
<p><a href="https://codesandbox.io/s/x765pl1zm4">Check out the full code at CodeSandbox</a></p><p>Much better, isn't it? Whatever we do, the ship is flying in the expected direction. Time to tackle the last problems. Lets go with the easier one first: Acceleration.</p><p>For now, the ship simply has a fixed speed. Lets make it faster first, because we want action, right? For that, we'll define the maximum speed of the ship:</p><pre><code class="js">this.shipSpeed = 5 // pixel per frame <p><a href="https://codesandbox.io/s/x765pl1zm4" target="_blank">Check out the full code at CodeSandbox</a></p><p>Much better, isn't it? Whatever we do, the ship is flying in the expected direction. Time to tackle the last problems. Lets go with the easier one first: Acceleration.</p><p>For now, the ship simply has a fixed speed. Lets make it faster first, because we want action, right? For that, we'll define the maximum speed of the ship:</p><pre><code class="js">this.shipSpeed = 5 // pixel per frame
</code></pre> </code></pre>
<p>And use it as a multiplicator:</p><pre><code class="js"> update() { <p>And use it as a multiplicator:</p><pre><code class="js"> update() {
// move the ship // move the ship
@ -485,7 +493,7 @@ requestAnimationFrame(update)
/* drawing stuff */ /* drawing stuff */
} }
</code></pre> </code></pre>
<p>This slowly accelerates the ship until full speed. But it still stops immediately. To decelerate the ship and also make sure the ship actually stops and doesn't randomly float around due to rounding errors, some more lines are needed. You'll find everything in <a href="https://codesandbox.io/s/kxpn09n077">the final version on CodeSandbox</a>.</p><p>Now the last problem has be solved: Framerate-dependent movement. For now, all the values are tweaked in a way that they work nicely at the current speed. Lets assume at sixty frames per second. Now that poor computer has to install updates in the background or maybe it is just Chrome getting messy. Maybe the player has a different screen refresh rate. The result is a drop or increase of the frame rate. Lets take a drop down to the half as an example. Thirty frames per second is still completely smooth for almost everything. Movies have thirty frames per second and they do just fine, right? Yet our ship is suddenly only half as fast and that difference is very noticeable.</p><p>To prevent this, the movement needs to be based on actual time. Instead of a fixed value added to the coordinates each frame, a value is added that respects the time passed since the last update. The same is necessary for velocity changes. So instead of the more or less arbitrary five pixels at sixty frames per second we set the value in pixels per millisecond because everything is in millisecond precision.</p><pre><code class="js">5px*60/s = 300px/s = 0.3px/ms <p>This slowly accelerates the ship until full speed. But it still stops immediately. To decelerate the ship and also make sure the ship actually stops and doesn't randomly float around due to rounding errors, some more lines are needed. You'll find everything in <a href="https://codesandbox.io/s/kxpn09n077" target="_blank">the final version on CodeSandbox</a>.</p><p>Now the last problem has be solved: Framerate-dependent movement. For now, all the values are tweaked in a way that they work nicely at the current speed. Lets assume at sixty frames per second. Now that poor computer has to install updates in the background or maybe it is just Chrome getting messy. Maybe the player has a different screen refresh rate. The result is a drop or increase of the frame rate. Lets take a drop down to the half as an example. Thirty frames per second is still completely smooth for almost everything. Movies have thirty frames per second and they do just fine, right? Yet our ship is suddenly only half as fast and that difference is very noticeable.</p><p>To prevent this, the movement needs to be based on actual time. Instead of a fixed value added to the coordinates each frame, a value is added that respects the time passed since the last update. The same is necessary for velocity changes. So instead of the more or less arbitrary five pixels at sixty frames per second we set the value in pixels per millisecond because everything is in millisecond precision.</p><pre><code class="js">5px*60/s = 300px/s = 0.3px/ms
</code></pre> </code></pre>
<p>This makes the next step rather easy: Count the amount of milliseconds since the last update and multiply it with the maximum speed and acceleration values:</p><pre><code class="js"> constructor () { <p>This makes the next step rather easy: Count the amount of milliseconds since the last update and multiply it with the maximum speed and acceleration values:</p><pre><code class="js"> constructor () {
/* ... */ /* ... */
@ -505,7 +513,7 @@ requestAnimationFrame(update)
/* ...more stuff... */ /* ...more stuff... */
// See the main loop section if "stamp" looks fishy to you. // See the main loop section if &quot;stamp&quot; looks fishy to you.
update (stamp) { update (stamp) {
// calculate how much time passed since last update // calculate how much time passed since last update
const timePassed = stamp - this.lastDraw const timePassed = stamp - this.lastDraw
@ -533,7 +541,11 @@ requestAnimationFrame(update)
/* drawing stuff */ /* drawing stuff */
} }
</code></pre> </code></pre>
<p><a href="https://codesandbox.io/s/j4rzoq5kqy">Check out the full version at CodeSandbox</a></p><p>If everything is the same as before you did everything right. Now independent of the frame rate you ship will move five pixels per millisecond. Unfortunately I didn't find a good way to test that except for changing the refresh rate of your screen or overwriting <code>requestAnimationFrame</code> so I left this part out of the post.</p><h2>The End</h2><p>Congratulations, you made a fully moving ship. This Post ends here but of course there is so much more to learn about game development. <a href="https://nkoehring.github.io/FreddyvsJSON">Freddy vs JSON</a> adds some more elements but uses only techniques described in this article. Feel free to check out <a href="https://github.com/nkoehring/FreddyvsJSON">its source code</a> and create a ton of games like it. Or completely different ones. Be creative and enjoy to use what you've just learned.</p></div> <p><a href="https://codesandbox.io/s/j4rzoq5kqy" target="_blank">Check out the full version at CodeSandbox</a></p><p>If everything is the same as before you did everything right. Now independent of the frame rate you ship will move five pixels per millisecond. Unfortunately I didn't find a good way to test that except for changing the refresh rate of your screen or overwriting <code>requestAnimationFrame</code> so I left this part out of the post.</p><h2>The End</h2><p>Congratulations, you made a fully moving ship. This Post ends here but of course there is so much more to learn about game development. <a href="https://nkoehring.github.io/FreddyvsJSON" target="_blank">Freddy vs JSON</a> adds some more elements but uses only techniques described in this article. Feel free to check out <a href="https://github.com/nkoehring/FreddyvsJSON" target="_blank">its source code</a> and create a ton of games like it. Or completely different ones. Be creative and enjoy to use what you've just learned.</p></div>
<ol class="posts">
<li></li>
</ol>
</main> </main>
@ -542,21 +554,21 @@ requestAnimationFrame(update)
<a href="/"> <a href="/">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 832.4 143.1"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 832.4 143.1">
<path id="header-underscore" <path id="header-underscore"
d="M832.4 131.1q0 5.5-3.1 8.6-3 3.4-8.2 3.3h-75.5q-5.2 0-8.2-3.3-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8 0-5.5 3.1-8.7 1.6-1.7 3.7-2.4 2.2-.8 4.5-.8h75.5q5.2 0 8.2 3.2 3 3.1 3 8.7z" /> d="M832.4 131.1q0 5.5-3.1 8.6-3 3.4-8.2 3.3h-75.5q-5.2 0-8.2-3.3-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8 0-5.5 3.1-8.7 1.6-1.7 3.7-2.4 2.2-.8 4.5-.8h75.5q5.2 0 8.2 3.2 3 3.1 3 8.7z"></path>
<path id="header-bracket" <path id="header-bracket"
d="M731.9 81.4q0 6.7-6.5 10.7l-1 .6-74.3 39.2q-2.5 1.3-5.2 1.2-4.8 0-8.1-3.8-3.2-3.6-3.2-8.4 0-3.3 1.7-6 1.8-2.9 4.6-4.4l55.3-29.1-55.3-29q-2.8-1.6-4.6-4.3-1.7-2.7-1.7-6.2 0-4.7 3.2-8.4 3.3-4 8-3.7 2.7 0 5.3 1.2l74.4 39.2q3.3 1.7 5.3 4.7 2 2.8 2 6.5z" /> d="M731.9 81.4q0 6.7-6.5 10.7l-1 .6-74.3 39.2q-2.5 1.3-5.2 1.2-4.8 0-8.1-3.8-3.2-3.6-3.2-8.4 0-3.3 1.7-6 1.8-2.9 4.6-4.4l55.3-29.1-55.3-29q-2.8-1.6-4.6-4.3-1.7-2.7-1.7-6.2 0-4.7 3.2-8.4 3.3-4 8-3.7 2.7 0 5.3 1.2l74.4 39.2q3.3 1.7 5.3 4.7 2 2.8 2 6.5z"></path>
<path id="header-r" <path id="header-r"
d="M588.7 66.5q0 5-3.5 8.5-3.5 3.4-8.1 3.5-4.4 0-8.3-4.3-10-10.7-20.9-10.6-2.2 0-4.3.3-2.1.3-4 1-1.8.6-3.7 1.6-1.7 1-3.4 2.3-1.7 1.3-3.3 2.9-7.8 8.2-7.6 19.7V131q0 5.5-3.1 8.6-3 3.4-8.3 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V51.6q0-5.4 3-8.6 3-3.4 8.3-3.3 2 0 3.7.6 1.8.6 3.3 1.8 1.4 1 2.2 2.7 1 1.5 1.6 3.3 11.8-8.4 27-8.4 10.6 0 21 5 11.3 5.4 17.2 14.5 2.5 3.7 2.5 7.3z" /> d="M588.7 66.5q0 5-3.5 8.5-3.5 3.4-8.1 3.5-4.4 0-8.3-4.3-10-10.7-20.9-10.6-2.2 0-4.3.3-2.1.3-4 1-1.8.6-3.7 1.6-1.7 1-3.4 2.3-1.7 1.3-3.3 2.9-7.8 8.2-7.6 19.7V131q0 5.5-3.1 8.6-3 3.4-8.3 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V51.6q0-5.4 3-8.6 3-3.4 8.3-3.3 2 0 3.7.6 1.8.6 3.3 1.8 1.4 1 2.2 2.7 1 1.5 1.6 3.3 11.8-8.4 27-8.4 10.6 0 21 5 11.3 5.4 17.2 14.5 2.5 3.7 2.5 7.3z"></path>
<path id="header-h" <path id="header-h"
d="M483.9 131.1q0 5.5-3.1 8.6-3 3.4-8.3 3.3-5.2 0-8.2-3.3-3.2-3.1-3.1-8.6V84.8q0-4.6-1.5-8.2-1.4-3.5-4.4-6.9-2.1-2-4.3-3.4-2.2-1.4-4.7-2-2.4-.7-5.3-.7-4.3 0-7.8 1.5-3.3 1.5-6.4 4.6-5.9 6.3-5.8 15v46.4q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v33q1.5-1 3-1.6l3.2-1.2 3.4-1q1.6-.5 3.3-.8l3.5-.4 3.6-.2q4.4 0 8.5 1 4.1.7 7.9 2.4 3.8 1.6 7.3 4.1 3.5 2.5 6.6 5.8Q484 66 484 84.8z" /> d="M483.9 131.1q0 5.5-3.1 8.6-3 3.4-8.3 3.3-5.2 0-8.2-3.3-3.2-3.1-3.1-8.6V84.8q0-4.6-1.5-8.2-1.4-3.5-4.4-6.9-2.1-2-4.3-3.4-2.2-1.4-4.7-2-2.4-.7-5.3-.7-4.3 0-7.8 1.5-3.3 1.5-6.4 4.6-5.9 6.3-5.8 15v46.4q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v33q1.5-1 3-1.6l3.2-1.2 3.4-1q1.6-.5 3.3-.8l3.5-.4 3.6-.2q4.4 0 8.5 1 4.1.7 7.9 2.4 3.8 1.6 7.3 4.1 3.5 2.5 6.6 5.8Q484 66 484 84.8z"></path>
<path id="header-e" <path id="header-e"
d="M387.5 111.1q0 1.2-.3 2.3-.1 1-.5 2l-.9 2q-6.6 12-19.4 19-12 6.6-25.4 6.6-20.8 0-35.8-14.6-15.9-15-15.9-37 0-22.1 15.9-37.1 15-14.6 35.8-14.6 3.9 0 7.8.7 4 .7 8 2.2 9.2 3.1 18.2 10 6 4.6 9.1 9.3 3.3 4.7 3.3 10 0 1.3-.3 2.5-.2 1.3-.7 2.4-1.5 3.4-5 5.3l-56.9 32.2q7.2 4.9 16.5 4.9 7.2 0 12.6-2.5 5.5-2.5 9.7-7.4l.7-1 .8-1 .9-1.3 1-1.5q3.3-4.2 7.4-5.1l1.8-.2q4.4 0 8 3.4 3.6 3.5 3.6 8.5zm-29.9-42.7q-7.2-4.8-16.6-4.8-6 0-11 2-4.9 1.8-9.3 6-4.5 4-6.7 9-2 4.8-2 10.8l.1 2.9z" /> d="M387.5 111.1q0 1.2-.3 2.3-.1 1-.5 2l-.9 2q-6.6 12-19.4 19-12 6.6-25.4 6.6-20.8 0-35.8-14.6-15.9-15-15.9-37 0-22.1 15.9-37.1 15-14.6 35.8-14.6 3.9 0 7.8.7 4 .7 8 2.2 9.2 3.1 18.2 10 6 4.6 9.1 9.3 3.3 4.7 3.3 10 0 1.3-.3 2.5-.2 1.3-.7 2.4-1.5 3.4-5 5.3l-56.9 32.2q7.2 4.9 16.5 4.9 7.2 0 12.6-2.5 5.5-2.5 9.7-7.4l.7-1 .8-1 .9-1.3 1-1.5q3.3-4.2 7.4-5.1l1.8-.2q4.4 0 8 3.4 3.6 3.5 3.6 8.5zm-29.9-42.7q-7.2-4.8-16.6-4.8-6 0-11 2-4.9 1.8-9.3 6-4.5 4-6.7 9-2 4.8-2 10.8l.1 2.9z"></path>
<path id="header-o" <path id="header-o"
d="M286.8 91.4q0 4.2-.6 8.3-.6 4-1.8 7.7-1.1 3.8-2.9 7.4-1.7 3.5-4 6.9-2.4 3.3-5.2 6.1Q258 143 237.7 143T203 128q-14.3-15.2-14.3-36.6 0-21.5 14.3-36.6 14.4-15 34.7-15 4 0 7.8.5 3.9.7 7.5 1.9t7 3q3.3 1.9 6.4 4.3 3.2 2.4 5.9 5.4 14.4 15 14.5 36.5zm-22.6 0q0-2.4-.4-4.5-.2-2.2-.9-4.2-.6-2-1.5-3.9-1-2-2.2-3.7-1.2-1.7-2.8-3.4-4-4.2-8.6-6.1-4.5-2-10-2-11 0-18.7 8.2-7.8 8-7.8 19.6 0 11.4 7.8 19.7 7.8 8 18.6 8 5.6 0 10.1-1.9 4.6-2 8.6-6.1 4-4.3 5.8-9 2-4.9 2-10.7z" /> d="M286.8 91.4q0 4.2-.6 8.3-.6 4-1.8 7.7-1.1 3.8-2.9 7.4-1.7 3.5-4 6.9-2.4 3.3-5.2 6.1Q258 143 237.7 143T203 128q-14.3-15.2-14.3-36.6 0-21.5 14.3-36.6 14.4-15 34.7-15 4 0 7.8.5 3.9.7 7.5 1.9t7 3q3.3 1.9 6.4 4.3 3.2 2.4 5.9 5.4 14.4 15 14.5 36.5zm-22.6 0q0-2.4-.4-4.5-.2-2.2-.9-4.2-.6-2-1.5-3.9-1-2-2.2-3.7-1.2-1.7-2.8-3.4-4-4.2-8.6-6.1-4.5-2-10-2-11 0-18.7 8.2-7.8 8-7.8 19.6 0 11.4 7.8 19.7 7.8 8 18.6 8 5.6 0 10.1-1.9 4.6-2 8.6-6.1 4-4.3 5.8-9 2-4.9 2-10.7z"></path>
<path id="header-k" <path id="header-k"
d="M186.3 131q0 4.7-3.3 8.3-1.5 1.8-3.7 2.7-2 1.1-4.3 1.1-3.5 0-6.6-2L119.2 105v26q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v65.9l49.2-36.1q3.2-2 6.6-2 4.7 0 8 3.7t3.3 8.4q-.2 6-5 9.6l-41 30 41 29.9q2.3 1.7 3.6 4.2 1.4 2.5 1.4 5.4z" /> d="M186.3 131q0 4.7-3.3 8.3-1.5 1.8-3.7 2.7-2 1.1-4.3 1.1-3.5 0-6.6-2L119.2 105v26q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v65.9l49.2-36.1q3.2-2 6.6-2 4.7 0 8 3.7t3.3 8.4q-.2 6-5 9.6l-41 30 41 29.9q2.3 1.7 3.6 4.2 1.4 2.5 1.4 5.4z"></path>
<path id="header-tilde" <path id="header-tilde"
d="M73.1 91q0 2-.6 3.9T71 98.6q-3.2 5.7-8.9 8.5-5.6 2.8-12.9 2.8-8.8 0-18-7.8-2.4-2.3-4.5-3.7-2.1-1.5-3-1.7-1.5 0-2.1.3l-.8 1.3q-.3.7-.8 1.2l-1 1-.9.8q-2.7 2-6.4 2-1.7 0-3.2-.3-1.4-.3-3-1.1-1.5-.8-2.6-2.1-2.8-3.1-2.8-8v-1.3q0-.7.2-1.2l.2-1 .4-1 .4-1q.1-.6.5-1.1l.5-1q3.2-5.7 8.8-8.5 5.7-2.9 13-2.9 3.2 0 6.2 1 3 .9 6 2.7 2.9 1.6 5.7 4.2 5.2 4.6 7.6 5.4 1 0 1.6-.2l.7-.4q.3-.1.5-.4 3.6-5.6 9.2-5.6 5.7 0 8.8 3.5 2.8 3 2.8 8z" /> d="M73.1 91q0 2-.6 3.9T71 98.6q-3.2 5.7-8.9 8.5-5.6 2.8-12.9 2.8-8.8 0-18-7.8-2.4-2.3-4.5-3.7-2.1-1.5-3-1.7-1.5 0-2.1.3l-.8 1.3q-.3.7-.8 1.2l-1 1-.9.8q-2.7 2-6.4 2-1.7 0-3.2-.3-1.4-.3-3-1.1-1.5-.8-2.6-2.1-2.8-3.1-2.8-8v-1.3q0-.7.2-1.2l.2-1 .4-1 .4-1q.1-.6.5-1.1l.5-1q3.2-5.7 8.8-8.5 5.7-2.9 13-2.9 3.2 0 6.2 1 3 .9 6 2.7 2.9 1.6 5.7 4.2 5.2 4.6 7.6 5.4 1 0 1.6-.2l.7-.4q.3-.1.5-.4 3.6-5.6 9.2-5.6 5.7 0 8.8 3.5 2.8 3 2.8 8z"></path>
</svg> </svg>
Homepage of Homepage of
<div class=p-name> <div class=p-name>

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

View file

@ -3,7 +3,7 @@
<head id="head"> <head id="head">
<meta charset=utf-8> <meta charset=utf-8>
<title id=title >the codeartist — programmer and engineer based in BerlinA store implementation from scratch using Vue3's Composition API</title> <title id="title " var="the codeartist — programmer and engineer based in Berlin">A store implementation from scratch using Vue3&apos;s Composition API</title>
<meta name=description content="The personal page and weblog of Norman Köhring"> <meta name=description content="The personal page and weblog of Norman Köhring">
<meta name=author content="Norman Köhring"> <meta name=author content="Norman Köhring">
<meta name=DC.title content="the codeartist — programmer and engineer based in Berlin"> <meta name=DC.title content="the codeartist — programmer and engineer based in Berlin">
@ -11,12 +11,12 @@
<meta name="twitter:site" content="@koehr_in"> <meta name="twitter:site" content="@koehr_in">
<meta name="twitter:author" content="@koehr_in"> <meta name="twitter:author" content="@koehr_in">
<meta name=twitter:description content="The personal page and weblog of the codeartist Norman Köhring"> <meta name=twitter:description content="The personal page and weblog of the codeartist Norman Köhring">
<meta name="twitter:title" content="A store implementation from scratch using Vue3's Composition API // the codeartist"> <meta name="twitter:title" content="A store implementation from scratch using Vue3&apos;s Composition API // the codeartist">
<meta name="og:title" content="A store implementation from scratch using Vue3's Composition API // the codeartist"> <meta name="og:title" content="A store implementation from scratch using Vue3&apos;s Composition API // the codeartist">
<meta property="og:type" content="website"> <meta property="og:type" content="website">
<meta http-equiv="x-ua-compatible" content="ie=edge"/> <meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"/> <meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no">
<meta name=ICBM content="52.4595, 13.5335"> <meta name=ICBM content="52.4595, 13.5335">
<meta name=geo.position content="52.4595; 13.5335"> <meta name=geo.position content="52.4595; 13.5335">
@ -26,7 +26,7 @@
<link rel=me href=https://k0r.in> <link rel=me href=https://k0r.in>
<link rel=me href=https://koehr.ing> <link rel=me href=https://koehr.ing>
<link rel=me href=@Koehr@mstdn.io> <link rel=me href=@Koehr@mstdn.io>
<link rel=me href=https://sr.ht/~koehr/> <link rel=me href=https://sr.ht/~koehr>
<link rel=me href=https://git.k0r.in> <link rel=me href=https://git.k0r.in>
<link rel=me href=https://threads.net/@coffee_n_code> <link rel=me href=https://threads.net/@coffee_n_code>
<link rel=me href=https://instagram.com/@coffee_n_code> <link rel=me href=https://instagram.com/@coffee_n_code>
@ -35,6 +35,14 @@
<link rel=icon href=/favicon.png type=image/x-icon> <link rel=icon href=/favicon.png type=image/x-icon>
<link rel=stylesheet href=/style.css> <link rel=stylesheet href=/style.css>
<style>
.posts { padding: 0; }
.posts>li { display: block; margin: 2rem 0; }
.posts>li>div { line-height: 2; }
.posts>li>p { line-height: 1.4; }
.posts>li>time, .posts>li>div>.reading-time { color: gray; }
</style>
</head> </head>
<body> <body>
@ -42,23 +50,21 @@
<main id="main"> <main id="main">
<header> <header>
<h1 >A store implementation from scratch using Vue3's Composition API</h1> <h1>A store implementation from scratch using Vue3&apos;s Composition API</h1>
<em >I've built a store implementation that allows name-spaced actions and helps with the separation of concerns. The new Composition API in Vue3 also allows completely new, convenient ways of using it.</em> <em>I&apos;ve built a store implementation that allows name-spaced actions and helps with the separation of concerns. The new Composition API in Vue3 also allows completely new, convenient ways of using it.</em>
<br/>
Last updated: <time datetime="Mon, 29 Jun 2020 00:00:00 +0000" >June 29, 2020</time>
</header> </header>
<div ><hr><p>This article is <a href="https://dev.to/koehr/a-store-implementation-from-scratch-using-vue3-s-composition-api-3p16">crossposted on dev.to</a>. Feel free to join the discussion there.</p><hr><p>At some point I started moving a side project over to <a href="https://github.com/vuejs/vue-next">Vue3</a> (which is still in beta). The side project is in a rather early stage and so I decided to rebuild the whole underlying foundation of it from scratch making use of the new possibilities of Vue3, especially of course the composition API.</p><h2>Nuisance</h2><p>One nuisance I had was the way I handled state. I didn't use <a href="https://vuex.vuejs.org">Vuex</a> but instead left state handling to a global state class that I added to Vue like <code>Vue.prototype.$store = new StorageHandler</code>. That allowed me to access global state from everywhere within Vue components via <code>this.$store</code> and worked pretty well in most cases. But when the store grew a bit more complex I wished back some of the features Vuex offers. Especially actions, name-spacing and with them the much better encapsulation of the state. It also adds extra work as soon as you need to access the state from outside Vue, for example in API call logic.</p><p>When moving to Vue3 I played with the thought to try <a href="https://github.com/vuejs/vuex/tree/4.0">Vuex4</a>. It has the same API as Vuex3 and is meant to be usable as a drop-in when updating a Vue2 application to Vue3. But rather quickly I decided to roll my own, simplified implementation that uses the new Composition API because it would make things much neater. But lets quickly recap first what this Composition API is and how it helped me here:</p><h2>Composition API vs Options API</h2><p>What is the Composition API and what is the Options API? You might not have heard of those terms yet but they will become more popular within the Vue ecosystem as soon as Vue3 is out of beta.</p><p>The Options API is and will be the default way to build components in Vue. It is what we all know. Lets assume the following template:</p><pre><code class="html"><span class="punctuation bracket">&lt;</span><span class="tag">div</span><span class="punctuation bracket">&gt;</span> <div><hr><p>This article is <a href="https://dev.to/koehr/a-store-implementation-from-scratch-using-vue3-s-composition-api-3p16" target="_blank">crossposted on dev.to</a>. Feel free to join the discussion there.</p><hr><p>At some point I started moving a side project over to <a href="https://github.com/vuejs/vue-next" target="_blank">Vue3</a> (which is still in beta). The side project is in a rather early stage and so I decided to rebuild the whole underlying foundation of it from scratch making use of the new possibilities of Vue3, especially of course the composition API.</p><h2>Nuisance</h2><p>One nuisance I had was the way I handled state. I didn't use <a href="https://vuex.vuejs.org" target="_blank">Vuex</a> but instead left state handling to a global state class that I added to Vue like <code>Vue.prototype.$store = new StorageHandler</code>. That allowed me to access global state from everywhere within Vue components via <code>this.$store</code> and worked pretty well in most cases. But when the store grew a bit more complex I wished back some of the features Vuex offers. Especially actions, name-spacing and with them the much better encapsulation of the state. It also adds extra work as soon as you need to access the state from outside Vue, for example in API call logic.</p><p>When moving to Vue3 I played with the thought to try <a href="https://github.com/vuejs/vuex/tree/4.0" target="_blank">Vuex4</a>. It has the same API as Vuex3 and is meant to be usable as a drop-in when updating a Vue2 application to Vue3. But rather quickly I decided to roll my own, simplified implementation that uses the new Composition API because it would make things much neater. But lets quickly recap first what this Composition API is and how it helped me here:</p><h2>Composition API vs Options API</h2><p>What is the Composition API and what is the Options API? You might not have heard of those terms yet but they will become more popular within the Vue ecosystem as soon as Vue3 is out of beta.</p><p>The Options API is and will be the default way to build components in Vue. It is what we all know. Lets assume the following template:</p><pre><code class="html"><span class="punctuation bracket">&lt;</span><span class="tag">div</span><span class="punctuation bracket">&gt;</span>
<span class="punctuation bracket">&lt;</span><span class="tag">div</span> <span class="attribute">class</span>="<span class="string">greeting</span>"<span class="punctuation bracket">&gt;</span>{{ hello }}<span class="punctuation bracket">&lt;/</span><span class="tag">div</span><span class="punctuation bracket">&gt;</span> <span class="punctuation bracket">&lt;</span><span class="tag">div</span> <span class="attribute">class</span>=&quot;<span class="string">greeting</span>&quot;<span class="punctuation bracket">&gt;</span>{{ hello }}<span class="punctuation bracket">&lt;/</span><span class="tag">div</span><span class="punctuation bracket">&gt;</span>
<span class="punctuation bracket">&lt;</span><span class="tag">input</span> <span class="attribute">v-model</span>="<span class="string">name</span>" <span class="attribute">placeholder</span>="<span class="string">change name</span>" <span class="punctuation bracket">/&gt;</span> <span class="punctuation bracket">&lt;</span><span class="tag">input</span> <span class="attribute">v-model</span>=&quot;<span class="string">name</span>&quot; <span class="attribute">placeholder</span>=&quot;<span class="string">change name</span>&quot; <span class="punctuation bracket">/&gt;</span>
<span class="punctuation bracket">&lt;</span><span class="tag">div</span> <span class="attribute">class</span>="<span class="string">counter</span>"<span class="punctuation bracket">&gt;</span>Clicked {{ clicks }} times<span class="punctuation bracket">&lt;/</span><span class="tag">div</span><span class="punctuation bracket">&gt;</span> <span class="punctuation bracket">&lt;</span><span class="tag">div</span> <span class="attribute">class</span>=&quot;<span class="string">counter</span>&quot;<span class="punctuation bracket">&gt;</span>Clicked {{ clicks }} times<span class="punctuation bracket">&lt;/</span><span class="tag">div</span><span class="punctuation bracket">&gt;</span>
<span class="punctuation bracket">&lt;</span><span class="tag">button</span> <span class="attribute">@click</span>="<span class="string">countUp</span>"<span class="punctuation bracket">&gt;</span>click!<span class="punctuation bracket">&lt;/</span><span class="tag">button</span><span class="punctuation bracket">&gt;</span> <span class="punctuation bracket">&lt;</span><span class="tag">button</span> <span class="attribute">@click</span>=&quot;<span class="string">countUp</span>&quot;<span class="punctuation bracket">&gt;</span>click!<span class="punctuation bracket">&lt;/</span><span class="tag">button</span><span class="punctuation bracket">&gt;</span>
<span class="punctuation bracket">&lt;/</span><span class="tag">div</span><span class="punctuation bracket">&gt;</span> <span class="punctuation bracket">&lt;/</span><span class="tag">div</span><span class="punctuation bracket">&gt;</span>
</code></pre> </code></pre>
<p>This is how an Options API example would look like:</p><pre><code class="js">const component = new Vue({ <p>This is how an Options API example would look like:</p><pre><code class="js">const component = new Vue({
return { return {
name 'World', name &apos;World&apos;,
clicks: 0 clicks: 0
} }
}, },
@ -74,13 +80,13 @@
} }
}) })
</code></pre> </code></pre>
<p>This still works the same in Vue3. But additionally it supports a new <code>setup</code> method that runs before initializing all the rest of the component and provides building blocks. Together with new imports this is the Composition API. You can use it side-by-side or exclusively to create your components. In most cased you'll not need it but as soon as you want to reuse logic or simply split a large component into logical chunks, the Composition API comes in very handy.</p><p>Here's one way how the example could look like using <code>setup()</code>:</p><pre><code class="js">import { defineComponent, computed } from 'vue' <p>This still works the same in Vue3. But additionally it supports a new <code>setup</code> method that runs before initializing all the rest of the component and provides building blocks. Together with new imports this is the Composition API. You can use it side-by-side or exclusively to create your components. In most cased you'll not need it but as soon as you want to reuse logic or simply split a large component into logical chunks, the Composition API comes in very handy.</p><p>Here's one way how the example could look like using <code>setup()</code>:</p><pre><code class="js">import { defineComponent, computed } from &apos;vue&apos;
// defineComponent() is now used instead of new Vue() // defineComponent() is now used instead of new Vue()
const component = defineComponent({ const component = defineComponent({
setup () { setup () {
// greeting // greeting
const name = ref('World') const name = ref(&apos;World&apos;)
const hello = computed(() =&gt; `Hello ${name.value}`) const hello = computed(() =&gt; `Hello ${name.value}`)
// counting // counting
const clicks = ref(0) const clicks = ref(0)
@ -90,9 +96,9 @@ const component = defineComponent({
} }
} }
</code></pre> </code></pre>
<p>Some things here might seem odd. <code>computed</code> gets imported, <code>ref</code> and why<code>name.value</code>? Isn't that going to be annoying? It would be out of scope for this article, so I better point you to a source that explains all of this much better than I could: <a href="https://composition-api.vuejs.org/api.html">composition-api.vuejs.org</a> is the place to go! There are also great courses on <a href="https://vuemastery.com">VueMastery</a>.</p><p>Back to topic: The cool new thing now is that we can group concerns. Instead of putting each puzzle piece somewhere else (that is variables in data, reactive properties in computed and methods in methods) we can create everything grouped next to each other. What makes it even better is that thanks to the global imports, every piece can be split out into separate functions:</p><pre><code class="js">// Afraid of becoming React dev? Maybe call it 'hasGreeting' then. <p>Some things here might seem odd. <code>computed</code> gets imported, <code>ref</code> and why<code>name.value</code>? Isn't that going to be annoying? It would be out of scope for this article, so I better point you to a source that explains all of this much better than I could: <a href="https://composition-api.vuejs.org/api.html" target="_blank">composition-api.vuejs.org</a> is the place to go! There are also great courses on <a href="https://vuemastery.com" target="_blank">VueMastery</a>.</p><p>Back to topic: The cool new thing now is that we can group concerns. Instead of putting each puzzle piece somewhere else (that is variables in data, reactive properties in computed and methods in methods) we can create everything grouped next to each other. What makes it even better is that thanks to the global imports, every piece can be split out into separate functions:</p><pre><code class="js">// Afraid of becoming React dev? Maybe call it &apos;hasGreeting&apos; then.
function useGreeting () { function useGreeting () {
const name = ref('World') const name = ref(&apos;World&apos;)
const hello = computed(() =&gt; `Hello ${name.value}`) const hello = computed(() =&gt; `Hello ${name.value}`)
return { name, hello } return { name, hello }
} }
@ -111,25 +117,25 @@ const component = defineComponent({
} }
} }
</code></pre> </code></pre>
<p>This works the same way and it works with everything, including computed properties, watchers and hooks. It makes it also very clear where everything is coming from, unlike mixins. You can play around with this example in this <a href="https://codesandbox.io/s/vue3-playground-lf16m?file=/src/index.js">Code Sandbox</a> I made.</p><h2>Minimalist but convenient state handling</h2><p>While looking at the Composition API I thought about how it could be nice for simple and declarative state handling. Assuming I have somehow name-spaced state collections and actions, a bit like we know from Vuex, for example:</p><pre><code class="js">import { ref } from 'vue' <p>This works the same way and it works with everything, including computed properties, watchers and hooks. It makes it also very clear where everything is coming from, unlike mixins. You can play around with this example in this <a href="https://codesandbox.io/s/vue3-playground-lf16m?file=/src/index.js" target="_blank">Code Sandbox</a> I made.</p><h2>Minimalist but convenient state handling</h2><p>While looking at the Composition API I thought about how it could be nice for simple and declarative state handling. Assuming I have somehow name-spaced state collections and actions, a bit like we know from Vuex, for example:</p><pre><code class="js">import { ref } from &apos;vue&apos;
// using 'ref' here because we want to return the properties directly // using &apos;ref&apos; here because we want to return the properties directly
// otherwise 'reactive' could be used // otherwise &apos;reactive&apos; could be used
export const state = { export const state = {
name: ref('World'), name: ref(&apos;World&apos;),
clicks: ref(0) clicks: ref(0)
} }
export const actions = { export const actions = {
'name/change': (name, newName) =&gt; { &apos;name/change&apos;: (name, newName) =&gt; {
name.value = newName name.value = newName
}, },
'clicks/countUp': (clicks) =&gt; { &apos;clicks/countUp&apos;: (clicks) =&gt; {
clicks.value++ clicks.value++
} }
} }
</code></pre> </code></pre>
<p>Now this is a very simplified example of course but it should illustrate the idea. This could be used directly and the Composition API makes it not too inconvenient alread. Unfortunately it is not exactly beautiful to write (yet):</p><pre><code class="js">import { state, actions } from '@/state' <p>Now this is a very simplified example of course but it should illustrate the idea. This could be used directly and the Composition API makes it not too inconvenient alread. Unfortunately it is not exactly beautiful to write (yet):</p><pre><code class="js">import { state, actions } from &apos;@/state&apos;
defineComponent({ defineComponent({
setup () { setup () {
@ -137,18 +143,18 @@ defineComponent({
name: state.name, name: state.name,
clicks: state.clicks, clicks: state.clicks,
// brrr, not pretty // brrr, not pretty
changeName (newName) { actions['name/change'](state.name, newName) } changeName (newName) { actions[&apos;name/change&apos;](state.name, newName) }
countUp () { actions['clicks/countUp'](state.clicks) } countUp () { actions[&apos;clicks/countUp&apos;](state.clicks) }
} }
} }
}) })
</code></pre> </code></pre>
<p>To make this not only prettier but also less verbose, a helper can be introduced. The goal is to have something like this:</p><pre><code class="js">import { useState } from '@/state' <p>To make this not only prettier but also less verbose, a helper can be introduced. The goal is to have something like this:</p><pre><code class="js">import { useState } from &apos;@/state&apos;
defineComponent({ defineComponent({
setup () { setup () {
const { collection: name, actions: nameActions } = useState('name') const { collection: name, actions: nameActions } = useState(&apos;name&apos;)
const { collection: clicks, actions: clickActions } = useState('clicks') const { collection: clicks, actions: clickActions } = useState(&apos;clicks&apos;)
return { return {
name, name,
@ -165,7 +171,7 @@ defineComponent({
const collection = state[prop] const collection = state[prop]
// assumes available stateActions object with properties // assumes available stateActions object with properties
// in the form 'things/add': function(collection, payload) // in the form &apos;things/add&apos;: function(collection, payload)
const actions = Object.keys(stateActions).reduce((acc, key) =&gt; { const actions = Object.keys(stateActions).reduce((acc, key) =&gt; {
if (key.startsWith(`${prop}/`)) { if (key.startsWith(`${prop}/`)) {
const newKey = key.slice(prop.length + 1) // extracts action name const newKey = key.slice(prop.length + 1) // extracts action name
@ -177,24 +183,24 @@ defineComponent({
return { collection, actions } return { collection, actions }
} }
</code></pre> </code></pre>
<p>Just ten lines and it makes life so much easier! This returns the collection reference and maps all actions accordingly. For the sake of completeness here a full example with state and stateActions:</p><pre><code class="js">import { ref } from 'vue' <p>Just ten lines and it makes life so much easier! This returns the collection reference and maps all actions accordingly. For the sake of completeness here a full example with state and stateActions:</p><pre><code class="js">import { ref } from &apos;vue&apos;
// not using reactive here to be able to send properties directly // not using reactive here to be able to send properties directly
const state = { const state = {
count: ref(0), count: ref(0),
name: ref('World') name: ref(&apos;World&apos;)
} }
const stateActions = { const stateActions = {
'count/increase' (countRef) { &apos;count/increase&apos; (countRef) {
countRef.value++ countRef.value++
}, },
'count/decrease' (countRef) { &apos;count/decrease&apos; (countRef) {
countRef.value-- countRef.value--
}, },
'name/change' (nameRef, newName) { &apos;name/change&apos; (nameRef, newName) {
nameRef.value = newName nameRef.value = newName
} }
@ -202,11 +208,11 @@ const stateActions = {
function useState (prop) { /* ... */ } function useState (prop) { /* ... */ }
</code></pre> </code></pre>
<p>Now <code>useState('count')</code> would return the reference state.count and an object with the actions increase and decrease:</p><pre><code class="js">import { useState } from '@/state' <p>Now <code>useState(&apos;count&apos;)</code> would return the reference state.count and an object with the actions increase and decrease:</p><pre><code class="js">import { useState } from &apos;@/state&apos;
defineComponent({ defineComponent({
setup () { setup () {
const { collection: count, actions: countActions } = useState('count') const { collection: count, actions: countActions } = useState(&apos;count&apos;)
return { return {
count, count,
countUp: countActions.increase countUp: countActions.increase
@ -216,6 +222,10 @@ defineComponent({
</code></pre> </code></pre>
<p>This works well for me and happened to be very convenient already. Maybe I'll make a package out of it. What are your opinions on this?</p></div> <p>This works well for me and happened to be very convenient already. Maybe I'll make a package out of it. What are your opinions on this?</p></div>
<ol class="posts">
<li></li>
</ol>
</main> </main>
<div id="spacer"></div> <div id="spacer"></div>
@ -223,21 +233,21 @@ defineComponent({
<a href="/"> <a href="/">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 832.4 143.1"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 832.4 143.1">
<path id="header-underscore" <path id="header-underscore"
d="M832.4 131.1q0 5.5-3.1 8.6-3 3.4-8.2 3.3h-75.5q-5.2 0-8.2-3.3-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8 0-5.5 3.1-8.7 1.6-1.7 3.7-2.4 2.2-.8 4.5-.8h75.5q5.2 0 8.2 3.2 3 3.1 3 8.7z" /> d="M832.4 131.1q0 5.5-3.1 8.6-3 3.4-8.2 3.3h-75.5q-5.2 0-8.2-3.3-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8 0-5.5 3.1-8.7 1.6-1.7 3.7-2.4 2.2-.8 4.5-.8h75.5q5.2 0 8.2 3.2 3 3.1 3 8.7z"></path>
<path id="header-bracket" <path id="header-bracket"
d="M731.9 81.4q0 6.7-6.5 10.7l-1 .6-74.3 39.2q-2.5 1.3-5.2 1.2-4.8 0-8.1-3.8-3.2-3.6-3.2-8.4 0-3.3 1.7-6 1.8-2.9 4.6-4.4l55.3-29.1-55.3-29q-2.8-1.6-4.6-4.3-1.7-2.7-1.7-6.2 0-4.7 3.2-8.4 3.3-4 8-3.7 2.7 0 5.3 1.2l74.4 39.2q3.3 1.7 5.3 4.7 2 2.8 2 6.5z" /> d="M731.9 81.4q0 6.7-6.5 10.7l-1 .6-74.3 39.2q-2.5 1.3-5.2 1.2-4.8 0-8.1-3.8-3.2-3.6-3.2-8.4 0-3.3 1.7-6 1.8-2.9 4.6-4.4l55.3-29.1-55.3-29q-2.8-1.6-4.6-4.3-1.7-2.7-1.7-6.2 0-4.7 3.2-8.4 3.3-4 8-3.7 2.7 0 5.3 1.2l74.4 39.2q3.3 1.7 5.3 4.7 2 2.8 2 6.5z"></path>
<path id="header-r" <path id="header-r"
d="M588.7 66.5q0 5-3.5 8.5-3.5 3.4-8.1 3.5-4.4 0-8.3-4.3-10-10.7-20.9-10.6-2.2 0-4.3.3-2.1.3-4 1-1.8.6-3.7 1.6-1.7 1-3.4 2.3-1.7 1.3-3.3 2.9-7.8 8.2-7.6 19.7V131q0 5.5-3.1 8.6-3 3.4-8.3 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V51.6q0-5.4 3-8.6 3-3.4 8.3-3.3 2 0 3.7.6 1.8.6 3.3 1.8 1.4 1 2.2 2.7 1 1.5 1.6 3.3 11.8-8.4 27-8.4 10.6 0 21 5 11.3 5.4 17.2 14.5 2.5 3.7 2.5 7.3z" /> d="M588.7 66.5q0 5-3.5 8.5-3.5 3.4-8.1 3.5-4.4 0-8.3-4.3-10-10.7-20.9-10.6-2.2 0-4.3.3-2.1.3-4 1-1.8.6-3.7 1.6-1.7 1-3.4 2.3-1.7 1.3-3.3 2.9-7.8 8.2-7.6 19.7V131q0 5.5-3.1 8.6-3 3.4-8.3 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V51.6q0-5.4 3-8.6 3-3.4 8.3-3.3 2 0 3.7.6 1.8.6 3.3 1.8 1.4 1 2.2 2.7 1 1.5 1.6 3.3 11.8-8.4 27-8.4 10.6 0 21 5 11.3 5.4 17.2 14.5 2.5 3.7 2.5 7.3z"></path>
<path id="header-h" <path id="header-h"
d="M483.9 131.1q0 5.5-3.1 8.6-3 3.4-8.3 3.3-5.2 0-8.2-3.3-3.2-3.1-3.1-8.6V84.8q0-4.6-1.5-8.2-1.4-3.5-4.4-6.9-2.1-2-4.3-3.4-2.2-1.4-4.7-2-2.4-.7-5.3-.7-4.3 0-7.8 1.5-3.3 1.5-6.4 4.6-5.9 6.3-5.8 15v46.4q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v33q1.5-1 3-1.6l3.2-1.2 3.4-1q1.6-.5 3.3-.8l3.5-.4 3.6-.2q4.4 0 8.5 1 4.1.7 7.9 2.4 3.8 1.6 7.3 4.1 3.5 2.5 6.6 5.8Q484 66 484 84.8z" /> d="M483.9 131.1q0 5.5-3.1 8.6-3 3.4-8.3 3.3-5.2 0-8.2-3.3-3.2-3.1-3.1-8.6V84.8q0-4.6-1.5-8.2-1.4-3.5-4.4-6.9-2.1-2-4.3-3.4-2.2-1.4-4.7-2-2.4-.7-5.3-.7-4.3 0-7.8 1.5-3.3 1.5-6.4 4.6-5.9 6.3-5.8 15v46.4q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v33q1.5-1 3-1.6l3.2-1.2 3.4-1q1.6-.5 3.3-.8l3.5-.4 3.6-.2q4.4 0 8.5 1 4.1.7 7.9 2.4 3.8 1.6 7.3 4.1 3.5 2.5 6.6 5.8Q484 66 484 84.8z"></path>
<path id="header-e" <path id="header-e"
d="M387.5 111.1q0 1.2-.3 2.3-.1 1-.5 2l-.9 2q-6.6 12-19.4 19-12 6.6-25.4 6.6-20.8 0-35.8-14.6-15.9-15-15.9-37 0-22.1 15.9-37.1 15-14.6 35.8-14.6 3.9 0 7.8.7 4 .7 8 2.2 9.2 3.1 18.2 10 6 4.6 9.1 9.3 3.3 4.7 3.3 10 0 1.3-.3 2.5-.2 1.3-.7 2.4-1.5 3.4-5 5.3l-56.9 32.2q7.2 4.9 16.5 4.9 7.2 0 12.6-2.5 5.5-2.5 9.7-7.4l.7-1 .8-1 .9-1.3 1-1.5q3.3-4.2 7.4-5.1l1.8-.2q4.4 0 8 3.4 3.6 3.5 3.6 8.5zm-29.9-42.7q-7.2-4.8-16.6-4.8-6 0-11 2-4.9 1.8-9.3 6-4.5 4-6.7 9-2 4.8-2 10.8l.1 2.9z" /> d="M387.5 111.1q0 1.2-.3 2.3-.1 1-.5 2l-.9 2q-6.6 12-19.4 19-12 6.6-25.4 6.6-20.8 0-35.8-14.6-15.9-15-15.9-37 0-22.1 15.9-37.1 15-14.6 35.8-14.6 3.9 0 7.8.7 4 .7 8 2.2 9.2 3.1 18.2 10 6 4.6 9.1 9.3 3.3 4.7 3.3 10 0 1.3-.3 2.5-.2 1.3-.7 2.4-1.5 3.4-5 5.3l-56.9 32.2q7.2 4.9 16.5 4.9 7.2 0 12.6-2.5 5.5-2.5 9.7-7.4l.7-1 .8-1 .9-1.3 1-1.5q3.3-4.2 7.4-5.1l1.8-.2q4.4 0 8 3.4 3.6 3.5 3.6 8.5zm-29.9-42.7q-7.2-4.8-16.6-4.8-6 0-11 2-4.9 1.8-9.3 6-4.5 4-6.7 9-2 4.8-2 10.8l.1 2.9z"></path>
<path id="header-o" <path id="header-o"
d="M286.8 91.4q0 4.2-.6 8.3-.6 4-1.8 7.7-1.1 3.8-2.9 7.4-1.7 3.5-4 6.9-2.4 3.3-5.2 6.1Q258 143 237.7 143T203 128q-14.3-15.2-14.3-36.6 0-21.5 14.3-36.6 14.4-15 34.7-15 4 0 7.8.5 3.9.7 7.5 1.9t7 3q3.3 1.9 6.4 4.3 3.2 2.4 5.9 5.4 14.4 15 14.5 36.5zm-22.6 0q0-2.4-.4-4.5-.2-2.2-.9-4.2-.6-2-1.5-3.9-1-2-2.2-3.7-1.2-1.7-2.8-3.4-4-4.2-8.6-6.1-4.5-2-10-2-11 0-18.7 8.2-7.8 8-7.8 19.6 0 11.4 7.8 19.7 7.8 8 18.6 8 5.6 0 10.1-1.9 4.6-2 8.6-6.1 4-4.3 5.8-9 2-4.9 2-10.7z" /> d="M286.8 91.4q0 4.2-.6 8.3-.6 4-1.8 7.7-1.1 3.8-2.9 7.4-1.7 3.5-4 6.9-2.4 3.3-5.2 6.1Q258 143 237.7 143T203 128q-14.3-15.2-14.3-36.6 0-21.5 14.3-36.6 14.4-15 34.7-15 4 0 7.8.5 3.9.7 7.5 1.9t7 3q3.3 1.9 6.4 4.3 3.2 2.4 5.9 5.4 14.4 15 14.5 36.5zm-22.6 0q0-2.4-.4-4.5-.2-2.2-.9-4.2-.6-2-1.5-3.9-1-2-2.2-3.7-1.2-1.7-2.8-3.4-4-4.2-8.6-6.1-4.5-2-10-2-11 0-18.7 8.2-7.8 8-7.8 19.6 0 11.4 7.8 19.7 7.8 8 18.6 8 5.6 0 10.1-1.9 4.6-2 8.6-6.1 4-4.3 5.8-9 2-4.9 2-10.7z"></path>
<path id="header-k" <path id="header-k"
d="M186.3 131q0 4.7-3.3 8.3-1.5 1.8-3.7 2.7-2 1.1-4.3 1.1-3.5 0-6.6-2L119.2 105v26q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v65.9l49.2-36.1q3.2-2 6.6-2 4.7 0 8 3.7t3.3 8.4q-.2 6-5 9.6l-41 30 41 29.9q2.3 1.7 3.6 4.2 1.4 2.5 1.4 5.4z" /> d="M186.3 131q0 4.7-3.3 8.3-1.5 1.8-3.7 2.7-2 1.1-4.3 1.1-3.5 0-6.6-2L119.2 105v26q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v65.9l49.2-36.1q3.2-2 6.6-2 4.7 0 8 3.7t3.3 8.4q-.2 6-5 9.6l-41 30 41 29.9q2.3 1.7 3.6 4.2 1.4 2.5 1.4 5.4z"></path>
<path id="header-tilde" <path id="header-tilde"
d="M73.1 91q0 2-.6 3.9T71 98.6q-3.2 5.7-8.9 8.5-5.6 2.8-12.9 2.8-8.8 0-18-7.8-2.4-2.3-4.5-3.7-2.1-1.5-3-1.7-1.5 0-2.1.3l-.8 1.3q-.3.7-.8 1.2l-1 1-.9.8q-2.7 2-6.4 2-1.7 0-3.2-.3-1.4-.3-3-1.1-1.5-.8-2.6-2.1-2.8-3.1-2.8-8v-1.3q0-.7.2-1.2l.2-1 .4-1 .4-1q.1-.6.5-1.1l.5-1q3.2-5.7 8.8-8.5 5.7-2.9 13-2.9 3.2 0 6.2 1 3 .9 6 2.7 2.9 1.6 5.7 4.2 5.2 4.6 7.6 5.4 1 0 1.6-.2l.7-.4q.3-.1.5-.4 3.6-5.6 9.2-5.6 5.7 0 8.8 3.5 2.8 3 2.8 8z" /> d="M73.1 91q0 2-.6 3.9T71 98.6q-3.2 5.7-8.9 8.5-5.6 2.8-12.9 2.8-8.8 0-18-7.8-2.4-2.3-4.5-3.7-2.1-1.5-3-1.7-1.5 0-2.1.3l-.8 1.3q-.3.7-.8 1.2l-1 1-.9.8q-2.7 2-6.4 2-1.7 0-3.2-.3-1.4-.3-3-1.1-1.5-.8-2.6-2.1-2.8-3.1-2.8-8v-1.3q0-.7.2-1.2l.2-1 .4-1 .4-1q.1-.6.5-1.1l.5-1q3.2-5.7 8.8-8.5 5.7-2.9 13-2.9 3.2 0 6.2 1 3 .9 6 2.7 2.9 1.6 5.7 4.2 5.2 4.6 7.6 5.4 1 0 1.6-.2l.7-.4q.3-.1.5-.4 3.6-5.6 9.2-5.6 5.7 0 8.8 3.5 2.8 3 2.8 8z"></path>
</svg> </svg>
Homepage of Homepage of
<div class=p-name> <div class=p-name>

View file

@ -3,7 +3,7 @@
<head id="head"> <head id="head">
<meta charset=utf-8> <meta charset=utf-8>
<title id=title >the codeartist — programmer and engineer based in BerlinBlog</title> <title id="title " var="the codeartist — programmer and engineer based in Berlin">Blog</title>
<meta name=description content="The personal page and weblog of Norman Köhring"> <meta name=description content="The personal page and weblog of Norman Köhring">
<meta name=author content="Norman Köhring"> <meta name=author content="Norman Köhring">
<meta name=DC.title content="the codeartist — programmer and engineer based in Berlin"> <meta name=DC.title content="the codeartist — programmer and engineer based in Berlin">
@ -15,8 +15,8 @@
<meta name="og:title" content="Blog // the codeartist"> <meta name="og:title" content="Blog // the codeartist">
<meta property="og:type" content="website"> <meta property="og:type" content="website">
<meta http-equiv="x-ua-compatible" content="ie=edge"/> <meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"/> <meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no">
<meta name=ICBM content="52.4595, 13.5335"> <meta name=ICBM content="52.4595, 13.5335">
<meta name=geo.position content="52.4595; 13.5335"> <meta name=geo.position content="52.4595; 13.5335">
@ -26,7 +26,7 @@
<link rel=me href=https://k0r.in> <link rel=me href=https://k0r.in>
<link rel=me href=https://koehr.ing> <link rel=me href=https://koehr.ing>
<link rel=me href=@Koehr@mstdn.io> <link rel=me href=@Koehr@mstdn.io>
<link rel=me href=https://sr.ht/~koehr/> <link rel=me href=https://sr.ht/~koehr>
<link rel=me href=https://git.k0r.in> <link rel=me href=https://git.k0r.in>
<link rel=me href=https://threads.net/@coffee_n_code> <link rel=me href=https://threads.net/@coffee_n_code>
<link rel=me href=https://instagram.com/@coffee_n_code> <link rel=me href=https://instagram.com/@coffee_n_code>
@ -60,15 +60,15 @@
<li> <li>
<time datetime="Mon, 29 Jun 2020 00:00:00 +0000">June 29, 2020</time> <time datetime="Mon, 29 Jun 2020 00:00:00 +0000">June 29, 2020</time>
<div> <div>
<a href="/blog/2020-06-29-a-store-implementation-for-vue3-composition-api/" >A store implementation from scratch using Vue3's Composition API</a> <a href="/blog/2020-06-29-a-store-implementation-for-vue3-composition-api/">A store implementation from scratch using Vue3&apos;s Composition API</a>
(<span class="reading-time">~<span >6</span> mins</span>) (<span class="reading-time">~<span>7</span> mins</span>)
</div> </div>
<p>Sometimes, I write long-form articles about a topic that I find interesting. I use this as a way to dive deeper into a topic, while often create an example project on the side.</p> <p>Sometimes, I write long-form articles about a topic that I find interesting. I use this as a way to dive deeper into a topic, while often create an example project on the side.</p>
<time datetime="Fri, 03 May 2019 00:00:00 +0000">May 03, 2019</time> <time datetime="Fri, 03 May 2019 00:00:00 +0000">May 03, 2019</time>
<div> <div>
<a href="/blog/2019-05-03-freddy-vs-json/">Freddy vs JSON: how to make a top-down shooter</a> <a href="/blog/2019-05-03-freddy-vs-json/">Freddy vs JSON: how to make a top-down shooter</a>
(<span class="reading-time">~<span >26</span> mins</span>) (<span class="reading-time">~<span>31</span> mins</span>)
</div> </div>
<p>Sometimes, I write long-form articles about a topic that I find interesting. I use this as a way to dive deeper into a topic, while often create an example project on the side.</p> <p>Sometimes, I write long-form articles about a topic that I find interesting. I use this as a way to dive deeper into a topic, while often create an example project on the side.</p>
@ -82,28 +82,28 @@
<time datetime="Thu, 10 Jan 2019 00:00:00 +0000">January 10, 2019</time> <time datetime="Thu, 10 Jan 2019 00:00:00 +0000">January 10, 2019</time>
<div> <div>
<a href="/blog/2019-01-10-running-write-freely-on-arm/">Running writefreely 0.7 on Arm</a> <a href="/blog/2019-01-10-running-write-freely-on-arm/">Running writefreely 0.7 on Arm</a>
(<span class="reading-time">~<span >4</span> mins</span>) (<span class="reading-time">~<span>5</span> mins</span>)
</div> </div>
<p>Sometimes, I write long-form articles about a topic that I find interesting. I use this as a way to dive deeper into a topic, while often create an example project on the side.</p> <p>Sometimes, I write long-form articles about a topic that I find interesting. I use this as a way to dive deeper into a topic, while often create an example project on the side.</p>
<time datetime="Thu, 17 Aug 2017 00:00:00 +0000">August 17, 2017</time> <time datetime="Thu, 17 Aug 2017 00:00:00 +0000">August 17, 2017</time>
<div> <div>
<a href="/blog/2017-08-17-vuejs-reactivity-from-scratch/">Vuejs Reactivity From Scratch</a> <a href="/blog/2017-08-17-vuejs-reactivity-from-scratch/">Vuejs Reactivity From Scratch</a>
(<span class="reading-time">~<span >9</span> mins</span>) (<span class="reading-time">~<span>10</span> mins</span>)
</div> </div>
<p>Sometimes, I write long-form articles about a topic that I find interesting. I use this as a way to dive deeper into a topic, while often create an example project on the side.</p> <p>Sometimes, I write long-form articles about a topic that I find interesting. I use this as a way to dive deeper into a topic, while often create an example project on the side.</p>
<time datetime="Sun, 09 Apr 2017 00:00:00 +0000">April 09, 2017</time> <time datetime="Sun, 09 Apr 2017 00:00:00 +0000">April 09, 2017</time>
<div> <div>
<a href="/blog/2017-04-09-the-magic-0xc2/">The Magic 0xC2</a> <a href="/blog/2017-04-09-the-magic-0xc2/">The Magic 0xC2</a>
(<span class="reading-time">~<span >1</span> mins</span>) (<span class="reading-time">~<span>2</span> mins</span>)
</div> </div>
<p>Sometimes, I write long-form articles about a topic that I find interesting. I use this as a way to dive deeper into a topic, while often create an example project on the side.</p> <p>Sometimes, I write long-form articles about a topic that I find interesting. I use this as a way to dive deeper into a topic, while often create an example project on the side.</p>
<time datetime="Sun, 04 Dec 2016 00:00:00 +0000">December 04, 2016</time> <time datetime="Sun, 04 Dec 2016 00:00:00 +0000">December 04, 2016</time>
<div> <div>
<a href="/blog/2016-12-04-the-price-to-crack-your-password/">The price to crack your password</a> <a href="/blog/2016-12-04-the-price-to-crack-your-password/">The price to crack your password</a>
(<span class="reading-time">~<span >5</span> mins</span>) (<span class="reading-time">~<span>7</span> mins</span>)
</div> </div>
<p>Sometimes, I write long-form articles about a topic that I find interesting. I use this as a way to dive deeper into a topic, while often create an example project on the side.</p> <p>Sometimes, I write long-form articles about a topic that I find interesting. I use this as a way to dive deeper into a topic, while often create an example project on the side.</p>
</li> </li>
@ -116,21 +116,21 @@
<a href="/"> <a href="/">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 832.4 143.1"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 832.4 143.1">
<path id="header-underscore" <path id="header-underscore"
d="M832.4 131.1q0 5.5-3.1 8.6-3 3.4-8.2 3.3h-75.5q-5.2 0-8.2-3.3-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8 0-5.5 3.1-8.7 1.6-1.7 3.7-2.4 2.2-.8 4.5-.8h75.5q5.2 0 8.2 3.2 3 3.1 3 8.7z" /> d="M832.4 131.1q0 5.5-3.1 8.6-3 3.4-8.2 3.3h-75.5q-5.2 0-8.2-3.3-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8 0-5.5 3.1-8.7 1.6-1.7 3.7-2.4 2.2-.8 4.5-.8h75.5q5.2 0 8.2 3.2 3 3.1 3 8.7z"></path>
<path id="header-bracket" <path id="header-bracket"
d="M731.9 81.4q0 6.7-6.5 10.7l-1 .6-74.3 39.2q-2.5 1.3-5.2 1.2-4.8 0-8.1-3.8-3.2-3.6-3.2-8.4 0-3.3 1.7-6 1.8-2.9 4.6-4.4l55.3-29.1-55.3-29q-2.8-1.6-4.6-4.3-1.7-2.7-1.7-6.2 0-4.7 3.2-8.4 3.3-4 8-3.7 2.7 0 5.3 1.2l74.4 39.2q3.3 1.7 5.3 4.7 2 2.8 2 6.5z" /> d="M731.9 81.4q0 6.7-6.5 10.7l-1 .6-74.3 39.2q-2.5 1.3-5.2 1.2-4.8 0-8.1-3.8-3.2-3.6-3.2-8.4 0-3.3 1.7-6 1.8-2.9 4.6-4.4l55.3-29.1-55.3-29q-2.8-1.6-4.6-4.3-1.7-2.7-1.7-6.2 0-4.7 3.2-8.4 3.3-4 8-3.7 2.7 0 5.3 1.2l74.4 39.2q3.3 1.7 5.3 4.7 2 2.8 2 6.5z"></path>
<path id="header-r" <path id="header-r"
d="M588.7 66.5q0 5-3.5 8.5-3.5 3.4-8.1 3.5-4.4 0-8.3-4.3-10-10.7-20.9-10.6-2.2 0-4.3.3-2.1.3-4 1-1.8.6-3.7 1.6-1.7 1-3.4 2.3-1.7 1.3-3.3 2.9-7.8 8.2-7.6 19.7V131q0 5.5-3.1 8.6-3 3.4-8.3 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V51.6q0-5.4 3-8.6 3-3.4 8.3-3.3 2 0 3.7.6 1.8.6 3.3 1.8 1.4 1 2.2 2.7 1 1.5 1.6 3.3 11.8-8.4 27-8.4 10.6 0 21 5 11.3 5.4 17.2 14.5 2.5 3.7 2.5 7.3z" /> d="M588.7 66.5q0 5-3.5 8.5-3.5 3.4-8.1 3.5-4.4 0-8.3-4.3-10-10.7-20.9-10.6-2.2 0-4.3.3-2.1.3-4 1-1.8.6-3.7 1.6-1.7 1-3.4 2.3-1.7 1.3-3.3 2.9-7.8 8.2-7.6 19.7V131q0 5.5-3.1 8.6-3 3.4-8.3 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V51.6q0-5.4 3-8.6 3-3.4 8.3-3.3 2 0 3.7.6 1.8.6 3.3 1.8 1.4 1 2.2 2.7 1 1.5 1.6 3.3 11.8-8.4 27-8.4 10.6 0 21 5 11.3 5.4 17.2 14.5 2.5 3.7 2.5 7.3z"></path>
<path id="header-h" <path id="header-h"
d="M483.9 131.1q0 5.5-3.1 8.6-3 3.4-8.3 3.3-5.2 0-8.2-3.3-3.2-3.1-3.1-8.6V84.8q0-4.6-1.5-8.2-1.4-3.5-4.4-6.9-2.1-2-4.3-3.4-2.2-1.4-4.7-2-2.4-.7-5.3-.7-4.3 0-7.8 1.5-3.3 1.5-6.4 4.6-5.9 6.3-5.8 15v46.4q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v33q1.5-1 3-1.6l3.2-1.2 3.4-1q1.6-.5 3.3-.8l3.5-.4 3.6-.2q4.4 0 8.5 1 4.1.7 7.9 2.4 3.8 1.6 7.3 4.1 3.5 2.5 6.6 5.8Q484 66 484 84.8z" /> d="M483.9 131.1q0 5.5-3.1 8.6-3 3.4-8.3 3.3-5.2 0-8.2-3.3-3.2-3.1-3.1-8.6V84.8q0-4.6-1.5-8.2-1.4-3.5-4.4-6.9-2.1-2-4.3-3.4-2.2-1.4-4.7-2-2.4-.7-5.3-.7-4.3 0-7.8 1.5-3.3 1.5-6.4 4.6-5.9 6.3-5.8 15v46.4q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v33q1.5-1 3-1.6l3.2-1.2 3.4-1q1.6-.5 3.3-.8l3.5-.4 3.6-.2q4.4 0 8.5 1 4.1.7 7.9 2.4 3.8 1.6 7.3 4.1 3.5 2.5 6.6 5.8Q484 66 484 84.8z"></path>
<path id="header-e" <path id="header-e"
d="M387.5 111.1q0 1.2-.3 2.3-.1 1-.5 2l-.9 2q-6.6 12-19.4 19-12 6.6-25.4 6.6-20.8 0-35.8-14.6-15.9-15-15.9-37 0-22.1 15.9-37.1 15-14.6 35.8-14.6 3.9 0 7.8.7 4 .7 8 2.2 9.2 3.1 18.2 10 6 4.6 9.1 9.3 3.3 4.7 3.3 10 0 1.3-.3 2.5-.2 1.3-.7 2.4-1.5 3.4-5 5.3l-56.9 32.2q7.2 4.9 16.5 4.9 7.2 0 12.6-2.5 5.5-2.5 9.7-7.4l.7-1 .8-1 .9-1.3 1-1.5q3.3-4.2 7.4-5.1l1.8-.2q4.4 0 8 3.4 3.6 3.5 3.6 8.5zm-29.9-42.7q-7.2-4.8-16.6-4.8-6 0-11 2-4.9 1.8-9.3 6-4.5 4-6.7 9-2 4.8-2 10.8l.1 2.9z" /> d="M387.5 111.1q0 1.2-.3 2.3-.1 1-.5 2l-.9 2q-6.6 12-19.4 19-12 6.6-25.4 6.6-20.8 0-35.8-14.6-15.9-15-15.9-37 0-22.1 15.9-37.1 15-14.6 35.8-14.6 3.9 0 7.8.7 4 .7 8 2.2 9.2 3.1 18.2 10 6 4.6 9.1 9.3 3.3 4.7 3.3 10 0 1.3-.3 2.5-.2 1.3-.7 2.4-1.5 3.4-5 5.3l-56.9 32.2q7.2 4.9 16.5 4.9 7.2 0 12.6-2.5 5.5-2.5 9.7-7.4l.7-1 .8-1 .9-1.3 1-1.5q3.3-4.2 7.4-5.1l1.8-.2q4.4 0 8 3.4 3.6 3.5 3.6 8.5zm-29.9-42.7q-7.2-4.8-16.6-4.8-6 0-11 2-4.9 1.8-9.3 6-4.5 4-6.7 9-2 4.8-2 10.8l.1 2.9z"></path>
<path id="header-o" <path id="header-o"
d="M286.8 91.4q0 4.2-.6 8.3-.6 4-1.8 7.7-1.1 3.8-2.9 7.4-1.7 3.5-4 6.9-2.4 3.3-5.2 6.1Q258 143 237.7 143T203 128q-14.3-15.2-14.3-36.6 0-21.5 14.3-36.6 14.4-15 34.7-15 4 0 7.8.5 3.9.7 7.5 1.9t7 3q3.3 1.9 6.4 4.3 3.2 2.4 5.9 5.4 14.4 15 14.5 36.5zm-22.6 0q0-2.4-.4-4.5-.2-2.2-.9-4.2-.6-2-1.5-3.9-1-2-2.2-3.7-1.2-1.7-2.8-3.4-4-4.2-8.6-6.1-4.5-2-10-2-11 0-18.7 8.2-7.8 8-7.8 19.6 0 11.4 7.8 19.7 7.8 8 18.6 8 5.6 0 10.1-1.9 4.6-2 8.6-6.1 4-4.3 5.8-9 2-4.9 2-10.7z" /> d="M286.8 91.4q0 4.2-.6 8.3-.6 4-1.8 7.7-1.1 3.8-2.9 7.4-1.7 3.5-4 6.9-2.4 3.3-5.2 6.1Q258 143 237.7 143T203 128q-14.3-15.2-14.3-36.6 0-21.5 14.3-36.6 14.4-15 34.7-15 4 0 7.8.5 3.9.7 7.5 1.9t7 3q3.3 1.9 6.4 4.3 3.2 2.4 5.9 5.4 14.4 15 14.5 36.5zm-22.6 0q0-2.4-.4-4.5-.2-2.2-.9-4.2-.6-2-1.5-3.9-1-2-2.2-3.7-1.2-1.7-2.8-3.4-4-4.2-8.6-6.1-4.5-2-10-2-11 0-18.7 8.2-7.8 8-7.8 19.6 0 11.4 7.8 19.7 7.8 8 18.6 8 5.6 0 10.1-1.9 4.6-2 8.6-6.1 4-4.3 5.8-9 2-4.9 2-10.7z"></path>
<path id="header-k" <path id="header-k"
d="M186.3 131q0 4.7-3.3 8.3-1.5 1.8-3.7 2.7-2 1.1-4.3 1.1-3.5 0-6.6-2L119.2 105v26q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v65.9l49.2-36.1q3.2-2 6.6-2 4.7 0 8 3.7t3.3 8.4q-.2 6-5 9.6l-41 30 41 29.9q2.3 1.7 3.6 4.2 1.4 2.5 1.4 5.4z" /> d="M186.3 131q0 4.7-3.3 8.3-1.5 1.8-3.7 2.7-2 1.1-4.3 1.1-3.5 0-6.6-2L119.2 105v26q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v65.9l49.2-36.1q3.2-2 6.6-2 4.7 0 8 3.7t3.3 8.4q-.2 6-5 9.6l-41 30 41 29.9q2.3 1.7 3.6 4.2 1.4 2.5 1.4 5.4z"></path>
<path id="header-tilde" <path id="header-tilde"
d="M73.1 91q0 2-.6 3.9T71 98.6q-3.2 5.7-8.9 8.5-5.6 2.8-12.9 2.8-8.8 0-18-7.8-2.4-2.3-4.5-3.7-2.1-1.5-3-1.7-1.5 0-2.1.3l-.8 1.3q-.3.7-.8 1.2l-1 1-.9.8q-2.7 2-6.4 2-1.7 0-3.2-.3-1.4-.3-3-1.1-1.5-.8-2.6-2.1-2.8-3.1-2.8-8v-1.3q0-.7.2-1.2l.2-1 .4-1 .4-1q.1-.6.5-1.1l.5-1q3.2-5.7 8.8-8.5 5.7-2.9 13-2.9 3.2 0 6.2 1 3 .9 6 2.7 2.9 1.6 5.7 4.2 5.2 4.6 7.6 5.4 1 0 1.6-.2l.7-.4q.3-.1.5-.4 3.6-5.6 9.2-5.6 5.7 0 8.8 3.5 2.8 3 2.8 8z" /> d="M73.1 91q0 2-.6 3.9T71 98.6q-3.2 5.7-8.9 8.5-5.6 2.8-12.9 2.8-8.8 0-18-7.8-2.4-2.3-4.5-3.7-2.1-1.5-3-1.7-1.5 0-2.1.3l-.8 1.3q-.3.7-.8 1.2l-1 1-.9.8q-2.7 2-6.4 2-1.7 0-3.2-.3-1.4-.3-3-1.1-1.5-.8-2.6-2.1-2.8-3.1-2.8-8v-1.3q0-.7.2-1.2l.2-1 .4-1 .4-1q.1-.6.5-1.1l.5-1q3.2-5.7 8.8-8.5 5.7-2.9 13-2.9 3.2 0 6.2 1 3 .9 6 2.7 2.9 1.6 5.7 4.2 5.2 4.6 7.6 5.4 1 0 1.6-.2l.7-.4q.3-.1.5-.4 3.6-5.6 9.2-5.6 5.7 0 8.8 3.5 2.8 3 2.8 8z"></path>
</svg> </svg>
Homepage of Homepage of
<div class=p-name> <div class=p-name>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -3,7 +3,7 @@
<head id="head"> <head id="head">
<meta charset=utf-8> <meta charset=utf-8>
<title id=title >the codeartist — programmer and engineer based in BerlinWelcome</title> <title id="title " var="the codeartist — programmer and engineer based in Berlin">Welcome</title>
<meta name=description content="The personal page and weblog of Norman Köhring"> <meta name=description content="The personal page and weblog of Norman Köhring">
<meta name=author content="Norman Köhring"> <meta name=author content="Norman Köhring">
<meta name=DC.title content="the codeartist — programmer and engineer based in Berlin"> <meta name=DC.title content="the codeartist — programmer and engineer based in Berlin">
@ -15,8 +15,8 @@
<meta name="og:title" content="Welcome // the codeartist"> <meta name="og:title" content="Welcome // the codeartist">
<meta property="og:type" content="website"> <meta property="og:type" content="website">
<meta http-equiv="x-ua-compatible" content="ie=edge"/> <meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"/> <meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no">
<meta name=ICBM content="52.4595, 13.5335"> <meta name=ICBM content="52.4595, 13.5335">
<meta name=geo.position content="52.4595; 13.5335"> <meta name=geo.position content="52.4595; 13.5335">
@ -26,7 +26,7 @@
<link rel=me href=https://k0r.in> <link rel=me href=https://k0r.in>
<link rel=me href=https://koehr.ing> <link rel=me href=https://koehr.ing>
<link rel=me href=@Koehr@mstdn.io> <link rel=me href=@Koehr@mstdn.io>
<link rel=me href=https://sr.ht/~koehr/> <link rel=me href=https://sr.ht/~koehr>
<link rel=me href=https://git.k0r.in> <link rel=me href=https://git.k0r.in>
<link rel=me href=https://threads.net/@coffee_n_code> <link rel=me href=https://threads.net/@coffee_n_code>
<link rel=me href=https://instagram.com/@coffee_n_code> <link rel=me href=https://instagram.com/@coffee_n_code>
@ -84,10 +84,22 @@
</div> </div>
</div> </div>
<div id=content ><h1>experience</h1><blockquote><p>Thirteen years of professional experience in a couple of tweets</p></blockquote><p>Pretty early in my life I realized that I work best on my own terms. That does not mean that I prefer to work alone. Working with clients, team mates, designers and managers is a crucial part of any development process.</p><p>Some time in the year 2009 I decided to not only live up to my way of working but also share my experience even more. I decided to become a freelancing programmer and consultant. Since then many different places benefited from my work. Start-Ups in their first months as well as well known companies like HERE and Deutsche Telekom Labs.</p><p>Together with entrepreneurs, UI/UX experts and engineers of many fields I created novel and beautiful applications that still influence the live of thousands of people.</p><p>Please see my CV for a more detailed list.</p><h1>coaching</h1><blockquote><p>Whenever possible, I try to help others to learn</p></blockquote><p>Im the organizer of Vuejs // Berlin, a monthly meetup group around Vue and web technologies in general.</p><p>Many people want to learn and grow. Whenever I can I try to help those people by sharing my experience and knowledge. I already voluntarily coached at Code Curious, Frauenloop and Jugend Hackt. I also helped children with their first steps into the world of programming at the Berlin CoderDojo.</p><h1>contact</h1><blockquote><p>You can find me all over the interwebs</p></blockquote><div id="contact" class="contacts"> <div id="content"><h1>experience</h1><blockquote><p>Thirteen years of professional experience in a couple of tweets</p></blockquote><p>Pretty early in my life I realized that I work best on my own terms. That does not mean that I prefer to work alone. Working with clients, team mates, designers and managers is a crucial part of any development process.</p><p>Some time in the year 2009 I decided to not only live up to my way of working but also share my experience even more. I decided to become a freelancing programmer and consultant. Since then many different places benefited from my work. Start-Ups in their first months as well as well known companies like HERE and Deutsche Telekom Labs.</p><p>Together with entrepreneurs, UI/UX experts and engineers of many fields I created novel and beautiful applications that still influence the live of thousands of people.</p><p>Please see my CV for a more detailed list.</p><h1>coaching</h1><blockquote><p>Whenever possible, I try to help others to learn</p></blockquote><p>Im the organizer of Vuejs // Berlin, a monthly meetup group around Vue and web technologies in general.</p><p>Many people want to learn and grow. Whenever I can I try to help those people by sharing my experience and knowledge. I already voluntarily coached at Code Curious, Frauenloop and Jugend Hackt. I also helped children with their first steps into the world of programming at the Berlin CoderDojo.</p></div>
<p><img title="Mail" src="/mail.svg" /> n@[thisdomain]</p><p><img title="Fediverse / Mastodon" src="/fediverse.svg" /> <a href="https://mstdn.io/@Koehr/">@Koehr@mstdn.io</a></p><p><img title="Gitforge" src="/gitforge.svg" /> <a href="https://git.k0r.in/">git.k0r.in</a></p><p><img title="LinkedIn" src="/linkedin.svg" /> <a href="https://linkedin.com/in/norman-köhring-950448109/">Norman Köhring</a></p><p><img title="Instagram" src="/instagram.svg" /> <a href="https://instagram.com/coffee_n_code/">coffee_n_code</a></p><p><img title="Threads" src="/threads.svg" /> <a href="https://threads.net/@coffee_n_code/">coffee_n_code</a></p><p><img title="Reddit" src="/reddit.svg" /> <a href="https://www.reddit.com/user/koehr/">/u/koehr</a></p><p><img title="Github" src="/github.svg" /> <a href="https://github.com/nkoehring/">nkoehring</a></p><p><img title="Twitter" src="/twitter.svg" /> <a href="https://twitter.com/koehr_in/">koehr_in</a></p></div>
</div>
<div id="contact">
<header><h1>contact</h1></header>
<ul class="contacts">
<li><img title="Mail" src="/mail.svg"> n@[thisdomain]</li>
<li><img title="Fediverse / Mastodon" src="/fediverse.svg"> <a href="https://mstdn.io/@Koehr/">@Koehr\@mstdn.io</a></li>
<li><img title="Gitforge" src="/gitforge.svg"> <a href="https://git.k0r.in/">git.k0r.in</a></li>
<li><img title="LinkedIn" src="/linkedin.svg"> <a href="https://linkedin.com/in/norman-köhring-950448109/">Norman Köhring</a></li>
<li><img title="Instagram" src="/instagram.svg"> <a href="https://instagram.com/coffee_n_code/">coffee_n_code</a></li>
<li><img title="Threads" src="/threads.svg"> <a href="https://threads.net/@coffee_n_code/">coffee_n_code</a></li>
<li><img title="Reddit" src="/reddit.svg"> <a href="https://www.reddit.com/user/koehr/">/u/koehr</a></li>
<li><img title="Github" src="/github.svg"> <a href="https://github.com/nkoehring/">nkoehring</a></li>
<li><img title="Twitter" src="/twitter.svg"> <a href="https://twitter.com/koehr_in/">koehr_in</a></li>
</ul>
</div>
<footer> <footer>
<a href="#intro">back to top</a> <a href="#intro">back to top</a>
</footer> </footer>
@ -99,21 +111,21 @@
<a href="/"> <a href="/">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 832.4 143.1"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 832.4 143.1">
<path id="header-underscore" <path id="header-underscore"
d="M832.4 131.1q0 5.5-3.1 8.6-3 3.4-8.2 3.3h-75.5q-5.2 0-8.2-3.3-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8 0-5.5 3.1-8.7 1.6-1.7 3.7-2.4 2.2-.8 4.5-.8h75.5q5.2 0 8.2 3.2 3 3.1 3 8.7z" /> d="M832.4 131.1q0 5.5-3.1 8.6-3 3.4-8.2 3.3h-75.5q-5.2 0-8.2-3.3-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8 0-5.5 3.1-8.7 1.6-1.7 3.7-2.4 2.2-.8 4.5-.8h75.5q5.2 0 8.2 3.2 3 3.1 3 8.7z"></path>
<path id="header-bracket" <path id="header-bracket"
d="M731.9 81.4q0 6.7-6.5 10.7l-1 .6-74.3 39.2q-2.5 1.3-5.2 1.2-4.8 0-8.1-3.8-3.2-3.6-3.2-8.4 0-3.3 1.7-6 1.8-2.9 4.6-4.4l55.3-29.1-55.3-29q-2.8-1.6-4.6-4.3-1.7-2.7-1.7-6.2 0-4.7 3.2-8.4 3.3-4 8-3.7 2.7 0 5.3 1.2l74.4 39.2q3.3 1.7 5.3 4.7 2 2.8 2 6.5z" /> d="M731.9 81.4q0 6.7-6.5 10.7l-1 .6-74.3 39.2q-2.5 1.3-5.2 1.2-4.8 0-8.1-3.8-3.2-3.6-3.2-8.4 0-3.3 1.7-6 1.8-2.9 4.6-4.4l55.3-29.1-55.3-29q-2.8-1.6-4.6-4.3-1.7-2.7-1.7-6.2 0-4.7 3.2-8.4 3.3-4 8-3.7 2.7 0 5.3 1.2l74.4 39.2q3.3 1.7 5.3 4.7 2 2.8 2 6.5z"></path>
<path id="header-r" <path id="header-r"
d="M588.7 66.5q0 5-3.5 8.5-3.5 3.4-8.1 3.5-4.4 0-8.3-4.3-10-10.7-20.9-10.6-2.2 0-4.3.3-2.1.3-4 1-1.8.6-3.7 1.6-1.7 1-3.4 2.3-1.7 1.3-3.3 2.9-7.8 8.2-7.6 19.7V131q0 5.5-3.1 8.6-3 3.4-8.3 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V51.6q0-5.4 3-8.6 3-3.4 8.3-3.3 2 0 3.7.6 1.8.6 3.3 1.8 1.4 1 2.2 2.7 1 1.5 1.6 3.3 11.8-8.4 27-8.4 10.6 0 21 5 11.3 5.4 17.2 14.5 2.5 3.7 2.5 7.3z" /> d="M588.7 66.5q0 5-3.5 8.5-3.5 3.4-8.1 3.5-4.4 0-8.3-4.3-10-10.7-20.9-10.6-2.2 0-4.3.3-2.1.3-4 1-1.8.6-3.7 1.6-1.7 1-3.4 2.3-1.7 1.3-3.3 2.9-7.8 8.2-7.6 19.7V131q0 5.5-3.1 8.6-3 3.4-8.3 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V51.6q0-5.4 3-8.6 3-3.4 8.3-3.3 2 0 3.7.6 1.8.6 3.3 1.8 1.4 1 2.2 2.7 1 1.5 1.6 3.3 11.8-8.4 27-8.4 10.6 0 21 5 11.3 5.4 17.2 14.5 2.5 3.7 2.5 7.3z"></path>
<path id="header-h" <path id="header-h"
d="M483.9 131.1q0 5.5-3.1 8.6-3 3.4-8.3 3.3-5.2 0-8.2-3.3-3.2-3.1-3.1-8.6V84.8q0-4.6-1.5-8.2-1.4-3.5-4.4-6.9-2.1-2-4.3-3.4-2.2-1.4-4.7-2-2.4-.7-5.3-.7-4.3 0-7.8 1.5-3.3 1.5-6.4 4.6-5.9 6.3-5.8 15v46.4q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v33q1.5-1 3-1.6l3.2-1.2 3.4-1q1.6-.5 3.3-.8l3.5-.4 3.6-.2q4.4 0 8.5 1 4.1.7 7.9 2.4 3.8 1.6 7.3 4.1 3.5 2.5 6.6 5.8Q484 66 484 84.8z" /> d="M483.9 131.1q0 5.5-3.1 8.6-3 3.4-8.3 3.3-5.2 0-8.2-3.3-3.2-3.1-3.1-8.6V84.8q0-4.6-1.5-8.2-1.4-3.5-4.4-6.9-2.1-2-4.3-3.4-2.2-1.4-4.7-2-2.4-.7-5.3-.7-4.3 0-7.8 1.5-3.3 1.5-6.4 4.6-5.9 6.3-5.8 15v46.4q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v33q1.5-1 3-1.6l3.2-1.2 3.4-1q1.6-.5 3.3-.8l3.5-.4 3.6-.2q4.4 0 8.5 1 4.1.7 7.9 2.4 3.8 1.6 7.3 4.1 3.5 2.5 6.6 5.8Q484 66 484 84.8z"></path>
<path id="header-e" <path id="header-e"
d="M387.5 111.1q0 1.2-.3 2.3-.1 1-.5 2l-.9 2q-6.6 12-19.4 19-12 6.6-25.4 6.6-20.8 0-35.8-14.6-15.9-15-15.9-37 0-22.1 15.9-37.1 15-14.6 35.8-14.6 3.9 0 7.8.7 4 .7 8 2.2 9.2 3.1 18.2 10 6 4.6 9.1 9.3 3.3 4.7 3.3 10 0 1.3-.3 2.5-.2 1.3-.7 2.4-1.5 3.4-5 5.3l-56.9 32.2q7.2 4.9 16.5 4.9 7.2 0 12.6-2.5 5.5-2.5 9.7-7.4l.7-1 .8-1 .9-1.3 1-1.5q3.3-4.2 7.4-5.1l1.8-.2q4.4 0 8 3.4 3.6 3.5 3.6 8.5zm-29.9-42.7q-7.2-4.8-16.6-4.8-6 0-11 2-4.9 1.8-9.3 6-4.5 4-6.7 9-2 4.8-2 10.8l.1 2.9z" /> d="M387.5 111.1q0 1.2-.3 2.3-.1 1-.5 2l-.9 2q-6.6 12-19.4 19-12 6.6-25.4 6.6-20.8 0-35.8-14.6-15.9-15-15.9-37 0-22.1 15.9-37.1 15-14.6 35.8-14.6 3.9 0 7.8.7 4 .7 8 2.2 9.2 3.1 18.2 10 6 4.6 9.1 9.3 3.3 4.7 3.3 10 0 1.3-.3 2.5-.2 1.3-.7 2.4-1.5 3.4-5 5.3l-56.9 32.2q7.2 4.9 16.5 4.9 7.2 0 12.6-2.5 5.5-2.5 9.7-7.4l.7-1 .8-1 .9-1.3 1-1.5q3.3-4.2 7.4-5.1l1.8-.2q4.4 0 8 3.4 3.6 3.5 3.6 8.5zm-29.9-42.7q-7.2-4.8-16.6-4.8-6 0-11 2-4.9 1.8-9.3 6-4.5 4-6.7 9-2 4.8-2 10.8l.1 2.9z"></path>
<path id="header-o" <path id="header-o"
d="M286.8 91.4q0 4.2-.6 8.3-.6 4-1.8 7.7-1.1 3.8-2.9 7.4-1.7 3.5-4 6.9-2.4 3.3-5.2 6.1Q258 143 237.7 143T203 128q-14.3-15.2-14.3-36.6 0-21.5 14.3-36.6 14.4-15 34.7-15 4 0 7.8.5 3.9.7 7.5 1.9t7 3q3.3 1.9 6.4 4.3 3.2 2.4 5.9 5.4 14.4 15 14.5 36.5zm-22.6 0q0-2.4-.4-4.5-.2-2.2-.9-4.2-.6-2-1.5-3.9-1-2-2.2-3.7-1.2-1.7-2.8-3.4-4-4.2-8.6-6.1-4.5-2-10-2-11 0-18.7 8.2-7.8 8-7.8 19.6 0 11.4 7.8 19.7 7.8 8 18.6 8 5.6 0 10.1-1.9 4.6-2 8.6-6.1 4-4.3 5.8-9 2-4.9 2-10.7z" /> d="M286.8 91.4q0 4.2-.6 8.3-.6 4-1.8 7.7-1.1 3.8-2.9 7.4-1.7 3.5-4 6.9-2.4 3.3-5.2 6.1Q258 143 237.7 143T203 128q-14.3-15.2-14.3-36.6 0-21.5 14.3-36.6 14.4-15 34.7-15 4 0 7.8.5 3.9.7 7.5 1.9t7 3q3.3 1.9 6.4 4.3 3.2 2.4 5.9 5.4 14.4 15 14.5 36.5zm-22.6 0q0-2.4-.4-4.5-.2-2.2-.9-4.2-.6-2-1.5-3.9-1-2-2.2-3.7-1.2-1.7-2.8-3.4-4-4.2-8.6-6.1-4.5-2-10-2-11 0-18.7 8.2-7.8 8-7.8 19.6 0 11.4 7.8 19.7 7.8 8 18.6 8 5.6 0 10.1-1.9 4.6-2 8.6-6.1 4-4.3 5.8-9 2-4.9 2-10.7z"></path>
<path id="header-k" <path id="header-k"
d="M186.3 131q0 4.7-3.3 8.3-1.5 1.8-3.7 2.7-2 1.1-4.3 1.1-3.5 0-6.6-2L119.2 105v26q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v65.9l49.2-36.1q3.2-2 6.6-2 4.7 0 8 3.7t3.3 8.4q-.2 6-5 9.6l-41 30 41 29.9q2.3 1.7 3.6 4.2 1.4 2.5 1.4 5.4z" /> d="M186.3 131q0 4.7-3.3 8.3-1.5 1.8-3.7 2.7-2 1.1-4.3 1.1-3.5 0-6.6-2L119.2 105v26q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v65.9l49.2-36.1q3.2-2 6.6-2 4.7 0 8 3.7t3.3 8.4q-.2 6-5 9.6l-41 30 41 29.9q2.3 1.7 3.6 4.2 1.4 2.5 1.4 5.4z"></path>
<path id="header-tilde" <path id="header-tilde"
d="M73.1 91q0 2-.6 3.9T71 98.6q-3.2 5.7-8.9 8.5-5.6 2.8-12.9 2.8-8.8 0-18-7.8-2.4-2.3-4.5-3.7-2.1-1.5-3-1.7-1.5 0-2.1.3l-.8 1.3q-.3.7-.8 1.2l-1 1-.9.8q-2.7 2-6.4 2-1.7 0-3.2-.3-1.4-.3-3-1.1-1.5-.8-2.6-2.1-2.8-3.1-2.8-8v-1.3q0-.7.2-1.2l.2-1 .4-1 .4-1q.1-.6.5-1.1l.5-1q3.2-5.7 8.8-8.5 5.7-2.9 13-2.9 3.2 0 6.2 1 3 .9 6 2.7 2.9 1.6 5.7 4.2 5.2 4.6 7.6 5.4 1 0 1.6-.2l.7-.4q.3-.1.5-.4 3.6-5.6 9.2-5.6 5.7 0 8.8 3.5 2.8 3 2.8 8z" /> d="M73.1 91q0 2-.6 3.9T71 98.6q-3.2 5.7-8.9 8.5-5.6 2.8-12.9 2.8-8.8 0-18-7.8-2.4-2.3-4.5-3.7-2.1-1.5-3-1.7-1.5 0-2.1.3l-.8 1.3q-.3.7-.8 1.2l-1 1-.9.8q-2.7 2-6.4 2-1.7 0-3.2-.3-1.4-.3-3-1.1-1.5-.8-2.6-2.1-2.8-3.1-2.8-8v-1.3q0-.7.2-1.2l.2-1 .4-1 .4-1q.1-.6.5-1.1l.5-1q3.2-5.7 8.8-8.5 5.7-2.9 13-2.9 3.2 0 6.2 1 3 .9 6 2.7 2.9 1.6 5.7 4.2 5.2 4.6 7.6 5.4 1 0 1.6-.2l.7-.4q.3-.1.5-.4 3.6-5.6 9.2-5.6 5.7 0 8.8 3.5 2.8 3 2.8 8z"></path>
</svg> </svg>
Homepage of Homepage of
<div class=p-name> <div class=p-name>

View file

@ -3,7 +3,7 @@
<head id="head"> <head id="head">
<meta charset=utf-8> <meta charset=utf-8>
<title id=title >the codeartist — programmer and engineer based in BerlinNow</title> <title id="title " var="the codeartist — programmer and engineer based in Berlin">Now</title>
<meta name=description content="The personal page and weblog of Norman Köhring"> <meta name=description content="The personal page and weblog of Norman Köhring">
<meta name=author content="Norman Köhring"> <meta name=author content="Norman Köhring">
<meta name=DC.title content="the codeartist — programmer and engineer based in Berlin"> <meta name=DC.title content="the codeartist — programmer and engineer based in Berlin">
@ -15,8 +15,8 @@
<meta name="og:title" content="Now // the codeartist"> <meta name="og:title" content="Now // the codeartist">
<meta property="og:type" content="website"> <meta property="og:type" content="website">
<meta http-equiv="x-ua-compatible" content="ie=edge"/> <meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"/> <meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no">
<meta name=ICBM content="52.4595, 13.5335"> <meta name=ICBM content="52.4595, 13.5335">
<meta name=geo.position content="52.4595; 13.5335"> <meta name=geo.position content="52.4595; 13.5335">
@ -26,7 +26,7 @@
<link rel=me href=https://k0r.in> <link rel=me href=https://k0r.in>
<link rel=me href=https://koehr.ing> <link rel=me href=https://koehr.ing>
<link rel=me href=@Koehr@mstdn.io> <link rel=me href=@Koehr@mstdn.io>
<link rel=me href=https://sr.ht/~koehr/> <link rel=me href=https://sr.ht/~koehr>
<link rel=me href=https://git.k0r.in> <link rel=me href=https://git.k0r.in>
<link rel=me href=https://threads.net/@coffee_n_code> <link rel=me href=https://threads.net/@coffee_n_code>
<link rel=me href=https://instagram.com/@coffee_n_code> <link rel=me href=https://instagram.com/@coffee_n_code>
@ -43,12 +43,12 @@
<header> <header>
<h1>Now</h1> <h1>Now</h1>
<em >This page shows what I'm up to at the moment, following the idea of Derek Sivers.</em> <em>This page shows what I&apos;m up to at the moment, following the idea of Derek Sivers.</em>
<br/> <br>
Last updated: <time datetime="Sun, 18 Aug 2024 00:00:00 +0000">August 18, 2024</time> Last updated: <time datetime="Sun, 18 Aug 2024 00:00:00 +0000">August 18, 2024</time>
</header> </header>
<div ><hr><p>You can find more now pages on <a href="https://nownownow.com/">nownownow</a>.</p><hr><p>Still live in Berlin where I am working fully remote. I'm approaching the second anniversary at <a href="https://codegaia.io">Code Gaia</a> now and have no plans to change any of it.</p><h2>Priorities</h2><blockquote><p>I do a lot of things all the time and have a hard time to focus. Most of my energy right now hopefully flows into the following things:</p></blockquote><ul><li><p>Keeping up the pace professionally by taking up more management responsibilities.</p></li><li><p>Ramping up my side-project game (mainly by doing smaller freelancing jobs).</p></li></ul><h2>Nice to haves</h2><blockquote><p>Realisticly there is more I want to do, but will I actually find the energy for it?</p></blockquote><ul><li><p>Fleshing out a long form D&D campaign ("Out Of The Cold Shadow").</p></li><li><p>Writing down more short adventures and one-shots and publish them on <a href="https://tiskifer.dk">tiskifer.dk</a>.</p></li></ul><h2>Book(s)</h2><blockquote><p>I'm not really good with taking time for reading, but when I do, I read:</p></blockquote><p><a href="https://openlibrary.org/works/OL2465670W/Accelerando">Accelerando</a> by <a href="https://openlibrary.org/authors/OL343157A/Charles_Stross">Charles Stross</a></p><p><a href="https://openlibrary.org/works/OL19860807W/The_Manager%27s_Path">The Manager's Path</a> by <a href="https://openlibrary.org/authors/OL7564045A/Camille_Fournier">Camille Fournier</a></p></div> <div><hr><p>You can find more now pages on <a href="https://nownownow.com/" target="_blank">nownownow</a>.</p><hr><p>Still live in Berlin where I am working fully remote. I'm approaching the second anniversary at <a href="https://codegaia.io" target="_blank">Code Gaia</a> now and have no plans to change any of it.</p><h2>Priorities</h2><blockquote><p>I do a lot of things all the time and have a hard time to focus. Most of my energy right now hopefully flows into the following things:</p></blockquote><ul><li>Keeping up the pace professionally by taking up more management responsibilities.</li><li>Ramping up my side-project game (mainly by doing smaller freelancing jobs).</li></ul><h2>Nice to haves</h2><blockquote><p>Realisticly there is more I want to do, but will I actually find the energy for it?</p></blockquote><ul><li>Fleshing out a long form D&D campaign ("Out Of The Cold Shadow").</li><li>Writing down more short adventures and one-shots and publish them on <a href="https://tiskifer.dk" target="_blank">tiskifer.dk</a>.</li></ul><h2>Book(s)</h2><blockquote><p>I'm not really good with taking time for reading, but when I do, I read:</p></blockquote><p><a href="https://openlibrary.org/works/OL2465670W/Accelerando" target="_blank">Accelerando</a> by <a href="https://openlibrary.org/authors/OL343157A/Charles_Stross" target="_blank">Charles Stross</a></p><p><a href="https://openlibrary.org/works/OL19860807W/The_Manager%27s_Path" target="_blank">The Manager's Path</a> by <a href="https://openlibrary.org/authors/OL7564045A/Camille_Fournier" target="_blank">Camille Fournier</a></p></div>
</main> </main>
@ -57,21 +57,21 @@
<a href="/"> <a href="/">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 832.4 143.1"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 832.4 143.1">
<path id="header-underscore" <path id="header-underscore"
d="M832.4 131.1q0 5.5-3.1 8.6-3 3.4-8.2 3.3h-75.5q-5.2 0-8.2-3.3-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8 0-5.5 3.1-8.7 1.6-1.7 3.7-2.4 2.2-.8 4.5-.8h75.5q5.2 0 8.2 3.2 3 3.1 3 8.7z" /> d="M832.4 131.1q0 5.5-3.1 8.6-3 3.4-8.2 3.3h-75.5q-5.2 0-8.2-3.3-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8 0-5.5 3.1-8.7 1.6-1.7 3.7-2.4 2.2-.8 4.5-.8h75.5q5.2 0 8.2 3.2 3 3.1 3 8.7z"></path>
<path id="header-bracket" <path id="header-bracket"
d="M731.9 81.4q0 6.7-6.5 10.7l-1 .6-74.3 39.2q-2.5 1.3-5.2 1.2-4.8 0-8.1-3.8-3.2-3.6-3.2-8.4 0-3.3 1.7-6 1.8-2.9 4.6-4.4l55.3-29.1-55.3-29q-2.8-1.6-4.6-4.3-1.7-2.7-1.7-6.2 0-4.7 3.2-8.4 3.3-4 8-3.7 2.7 0 5.3 1.2l74.4 39.2q3.3 1.7 5.3 4.7 2 2.8 2 6.5z" /> d="M731.9 81.4q0 6.7-6.5 10.7l-1 .6-74.3 39.2q-2.5 1.3-5.2 1.2-4.8 0-8.1-3.8-3.2-3.6-3.2-8.4 0-3.3 1.7-6 1.8-2.9 4.6-4.4l55.3-29.1-55.3-29q-2.8-1.6-4.6-4.3-1.7-2.7-1.7-6.2 0-4.7 3.2-8.4 3.3-4 8-3.7 2.7 0 5.3 1.2l74.4 39.2q3.3 1.7 5.3 4.7 2 2.8 2 6.5z"></path>
<path id="header-r" <path id="header-r"
d="M588.7 66.5q0 5-3.5 8.5-3.5 3.4-8.1 3.5-4.4 0-8.3-4.3-10-10.7-20.9-10.6-2.2 0-4.3.3-2.1.3-4 1-1.8.6-3.7 1.6-1.7 1-3.4 2.3-1.7 1.3-3.3 2.9-7.8 8.2-7.6 19.7V131q0 5.5-3.1 8.6-3 3.4-8.3 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V51.6q0-5.4 3-8.6 3-3.4 8.3-3.3 2 0 3.7.6 1.8.6 3.3 1.8 1.4 1 2.2 2.7 1 1.5 1.6 3.3 11.8-8.4 27-8.4 10.6 0 21 5 11.3 5.4 17.2 14.5 2.5 3.7 2.5 7.3z" /> d="M588.7 66.5q0 5-3.5 8.5-3.5 3.4-8.1 3.5-4.4 0-8.3-4.3-10-10.7-20.9-10.6-2.2 0-4.3.3-2.1.3-4 1-1.8.6-3.7 1.6-1.7 1-3.4 2.3-1.7 1.3-3.3 2.9-7.8 8.2-7.6 19.7V131q0 5.5-3.1 8.6-3 3.4-8.3 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V51.6q0-5.4 3-8.6 3-3.4 8.3-3.3 2 0 3.7.6 1.8.6 3.3 1.8 1.4 1 2.2 2.7 1 1.5 1.6 3.3 11.8-8.4 27-8.4 10.6 0 21 5 11.3 5.4 17.2 14.5 2.5 3.7 2.5 7.3z"></path>
<path id="header-h" <path id="header-h"
d="M483.9 131.1q0 5.5-3.1 8.6-3 3.4-8.3 3.3-5.2 0-8.2-3.3-3.2-3.1-3.1-8.6V84.8q0-4.6-1.5-8.2-1.4-3.5-4.4-6.9-2.1-2-4.3-3.4-2.2-1.4-4.7-2-2.4-.7-5.3-.7-4.3 0-7.8 1.5-3.3 1.5-6.4 4.6-5.9 6.3-5.8 15v46.4q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v33q1.5-1 3-1.6l3.2-1.2 3.4-1q1.6-.5 3.3-.8l3.5-.4 3.6-.2q4.4 0 8.5 1 4.1.7 7.9 2.4 3.8 1.6 7.3 4.1 3.5 2.5 6.6 5.8Q484 66 484 84.8z" /> d="M483.9 131.1q0 5.5-3.1 8.6-3 3.4-8.3 3.3-5.2 0-8.2-3.3-3.2-3.1-3.1-8.6V84.8q0-4.6-1.5-8.2-1.4-3.5-4.4-6.9-2.1-2-4.3-3.4-2.2-1.4-4.7-2-2.4-.7-5.3-.7-4.3 0-7.8 1.5-3.3 1.5-6.4 4.6-5.9 6.3-5.8 15v46.4q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v33q1.5-1 3-1.6l3.2-1.2 3.4-1q1.6-.5 3.3-.8l3.5-.4 3.6-.2q4.4 0 8.5 1 4.1.7 7.9 2.4 3.8 1.6 7.3 4.1 3.5 2.5 6.6 5.8Q484 66 484 84.8z"></path>
<path id="header-e" <path id="header-e"
d="M387.5 111.1q0 1.2-.3 2.3-.1 1-.5 2l-.9 2q-6.6 12-19.4 19-12 6.6-25.4 6.6-20.8 0-35.8-14.6-15.9-15-15.9-37 0-22.1 15.9-37.1 15-14.6 35.8-14.6 3.9 0 7.8.7 4 .7 8 2.2 9.2 3.1 18.2 10 6 4.6 9.1 9.3 3.3 4.7 3.3 10 0 1.3-.3 2.5-.2 1.3-.7 2.4-1.5 3.4-5 5.3l-56.9 32.2q7.2 4.9 16.5 4.9 7.2 0 12.6-2.5 5.5-2.5 9.7-7.4l.7-1 .8-1 .9-1.3 1-1.5q3.3-4.2 7.4-5.1l1.8-.2q4.4 0 8 3.4 3.6 3.5 3.6 8.5zm-29.9-42.7q-7.2-4.8-16.6-4.8-6 0-11 2-4.9 1.8-9.3 6-4.5 4-6.7 9-2 4.8-2 10.8l.1 2.9z" /> d="M387.5 111.1q0 1.2-.3 2.3-.1 1-.5 2l-.9 2q-6.6 12-19.4 19-12 6.6-25.4 6.6-20.8 0-35.8-14.6-15.9-15-15.9-37 0-22.1 15.9-37.1 15-14.6 35.8-14.6 3.9 0 7.8.7 4 .7 8 2.2 9.2 3.1 18.2 10 6 4.6 9.1 9.3 3.3 4.7 3.3 10 0 1.3-.3 2.5-.2 1.3-.7 2.4-1.5 3.4-5 5.3l-56.9 32.2q7.2 4.9 16.5 4.9 7.2 0 12.6-2.5 5.5-2.5 9.7-7.4l.7-1 .8-1 .9-1.3 1-1.5q3.3-4.2 7.4-5.1l1.8-.2q4.4 0 8 3.4 3.6 3.5 3.6 8.5zm-29.9-42.7q-7.2-4.8-16.6-4.8-6 0-11 2-4.9 1.8-9.3 6-4.5 4-6.7 9-2 4.8-2 10.8l.1 2.9z"></path>
<path id="header-o" <path id="header-o"
d="M286.8 91.4q0 4.2-.6 8.3-.6 4-1.8 7.7-1.1 3.8-2.9 7.4-1.7 3.5-4 6.9-2.4 3.3-5.2 6.1Q258 143 237.7 143T203 128q-14.3-15.2-14.3-36.6 0-21.5 14.3-36.6 14.4-15 34.7-15 4 0 7.8.5 3.9.7 7.5 1.9t7 3q3.3 1.9 6.4 4.3 3.2 2.4 5.9 5.4 14.4 15 14.5 36.5zm-22.6 0q0-2.4-.4-4.5-.2-2.2-.9-4.2-.6-2-1.5-3.9-1-2-2.2-3.7-1.2-1.7-2.8-3.4-4-4.2-8.6-6.1-4.5-2-10-2-11 0-18.7 8.2-7.8 8-7.8 19.6 0 11.4 7.8 19.7 7.8 8 18.6 8 5.6 0 10.1-1.9 4.6-2 8.6-6.1 4-4.3 5.8-9 2-4.9 2-10.7z" /> d="M286.8 91.4q0 4.2-.6 8.3-.6 4-1.8 7.7-1.1 3.8-2.9 7.4-1.7 3.5-4 6.9-2.4 3.3-5.2 6.1Q258 143 237.7 143T203 128q-14.3-15.2-14.3-36.6 0-21.5 14.3-36.6 14.4-15 34.7-15 4 0 7.8.5 3.9.7 7.5 1.9t7 3q3.3 1.9 6.4 4.3 3.2 2.4 5.9 5.4 14.4 15 14.5 36.5zm-22.6 0q0-2.4-.4-4.5-.2-2.2-.9-4.2-.6-2-1.5-3.9-1-2-2.2-3.7-1.2-1.7-2.8-3.4-4-4.2-8.6-6.1-4.5-2-10-2-11 0-18.7 8.2-7.8 8-7.8 19.6 0 11.4 7.8 19.7 7.8 8 18.6 8 5.6 0 10.1-1.9 4.6-2 8.6-6.1 4-4.3 5.8-9 2-4.9 2-10.7z"></path>
<path id="header-k" <path id="header-k"
d="M186.3 131q0 4.7-3.3 8.3-1.5 1.8-3.7 2.7-2 1.1-4.3 1.1-3.5 0-6.6-2L119.2 105v26q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v65.9l49.2-36.1q3.2-2 6.6-2 4.7 0 8 3.7t3.3 8.4q-.2 6-5 9.6l-41 30 41 29.9q2.3 1.7 3.6 4.2 1.4 2.5 1.4 5.4z" /> d="M186.3 131q0 4.7-3.3 8.3-1.5 1.8-3.7 2.7-2 1.1-4.3 1.1-3.5 0-6.6-2L119.2 105v26q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v65.9l49.2-36.1q3.2-2 6.6-2 4.7 0 8 3.7t3.3 8.4q-.2 6-5 9.6l-41 30 41 29.9q2.3 1.7 3.6 4.2 1.4 2.5 1.4 5.4z"></path>
<path id="header-tilde" <path id="header-tilde"
d="M73.1 91q0 2-.6 3.9T71 98.6q-3.2 5.7-8.9 8.5-5.6 2.8-12.9 2.8-8.8 0-18-7.8-2.4-2.3-4.5-3.7-2.1-1.5-3-1.7-1.5 0-2.1.3l-.8 1.3q-.3.7-.8 1.2l-1 1-.9.8q-2.7 2-6.4 2-1.7 0-3.2-.3-1.4-.3-3-1.1-1.5-.8-2.6-2.1-2.8-3.1-2.8-8v-1.3q0-.7.2-1.2l.2-1 .4-1 .4-1q.1-.6.5-1.1l.5-1q3.2-5.7 8.8-8.5 5.7-2.9 13-2.9 3.2 0 6.2 1 3 .9 6 2.7 2.9 1.6 5.7 4.2 5.2 4.6 7.6 5.4 1 0 1.6-.2l.7-.4q.3-.1.5-.4 3.6-5.6 9.2-5.6 5.7 0 8.8 3.5 2.8 3 2.8 8z" /> d="M73.1 91q0 2-.6 3.9T71 98.6q-3.2 5.7-8.9 8.5-5.6 2.8-12.9 2.8-8.8 0-18-7.8-2.4-2.3-4.5-3.7-2.1-1.5-3-1.7-1.5 0-2.1.3l-.8 1.3q-.3.7-.8 1.2l-1 1-.9.8q-2.7 2-6.4 2-1.7 0-3.2-.3-1.4-.3-3-1.1-1.5-.8-2.6-2.1-2.8-3.1-2.8-8v-1.3q0-.7.2-1.2l.2-1 .4-1 .4-1q.1-.6.5-1.1l.5-1q3.2-5.7 8.8-8.5 5.7-2.9 13-2.9 3.2 0 6.2 1 3 .9 6 2.7 2.9 1.6 5.7 4.2 5.2 4.6 7.6 5.4 1 0 1.6-.2l.7-.4q.3-.1.5-.4 3.6-5.6 9.2-5.6 5.7 0 8.8 3.5 2.8 3 2.8 8z"></path>
</svg> </svg>
Homepage of Homepage of
<div class=p-name> <div class=p-name>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

View file

@ -3,7 +3,7 @@
<head id="head"> <head id="head">
<meta charset=utf-8> <meta charset=utf-8>
<title id=title >the codeartist — programmer and engineer based in BerlinProjects</title> <title id="title " var="the codeartist — programmer and engineer based in Berlin">Projects</title>
<meta name=description content="The personal page and weblog of Norman Köhring"> <meta name=description content="The personal page and weblog of Norman Köhring">
<meta name=author content="Norman Köhring"> <meta name=author content="Norman Köhring">
<meta name=DC.title content="the codeartist — programmer and engineer based in Berlin"> <meta name=DC.title content="the codeartist — programmer and engineer based in Berlin">
@ -15,8 +15,8 @@
<meta name="og:title" content="Projects // the codeartist"> <meta name="og:title" content="Projects // the codeartist">
<meta property="og:type" content="website"> <meta property="og:type" content="website">
<meta http-equiv="x-ua-compatible" content="ie=edge"/> <meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"/> <meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no">
<meta name=ICBM content="52.4595, 13.5335"> <meta name=ICBM content="52.4595, 13.5335">
<meta name=geo.position content="52.4595; 13.5335"> <meta name=geo.position content="52.4595; 13.5335">
@ -26,7 +26,7 @@
<link rel=me href=https://k0r.in> <link rel=me href=https://k0r.in>
<link rel=me href=https://koehr.ing> <link rel=me href=https://koehr.ing>
<link rel=me href=@Koehr@mstdn.io> <link rel=me href=@Koehr@mstdn.io>
<link rel=me href=https://sr.ht/~koehr/> <link rel=me href=https://sr.ht/~koehr>
<link rel=me href=https://git.k0r.in> <link rel=me href=https://git.k0r.in>
<link rel=me href=https://threads.net/@coffee_n_code> <link rel=me href=https://threads.net/@coffee_n_code>
<link rel=me href=https://instagram.com/@coffee_n_code> <link rel=me href=https://instagram.com/@coffee_n_code>
@ -44,15 +44,14 @@
<header> <header>
<h1>Projects</h1> <h1>Projects</h1>
<em>Stuff I made. This is mostly about software, but might also include some TTRPG related things, from time to time.</em> <em>Stuff I made. This is mostly about software, but might also include some TTRPG related things, from time to time.</em>
<br/> <br>
Last updated: <time datetime="Mon, 15 Jul 2024 00:00:00 +0000">July 15, 2024</time> Last updated: <time datetime="Mon, 15 Jul 2024 00:00:00 +0000">July 15, 2024</time>
</header> </header>
<div ><p>I tend to host my code on multiple places, typically <a href="https://sr.ht">Sourcehut</a> and <a href="https://git.k0r.in">my Forgejo server</a>. Usually, if it involves a community, it is hosted or mirrored on Github as well, for visibility.</p><h2>250kB Club <a href="https://250kb.club">🔗</a></h2><img src="250kb.jpg" title="250kB Club Screenshot" alt="250kB Club Screenshot" /> <div><p>I tend to host my code on multiple places, typically <a href="https://sr.ht" target="_blank">Sourcehut</a> and <a href="https://git.k0r.in" target="_blank">my Forgejo server</a>. Usually, if it involves a community, it is hosted or mirrored on Github as well, for visibility.</p><h2>250kB Club <a href="https://250kb.club" target="_blank">🔗</a></h2><p>[250kB Club Screenshot]($image.asset('250kb.jpg').title('250kB Club'))</p><p>I am the creator of 250kB Club, which should actually be called 256kb.club, but that thought reached me only after I got the domain.</p><p>Already in 2016, we crossed the line, where the typical website is bigger than the game Doom. I think, we can do better! The 250kB Club is a collection of web pages that focus on performance, efficiency and accessibility. Originally inspired by <a href="https://1mb.club" target="_blank">1mb.club</a>, I created the 250kB Club, because I don't think 1MB is small enough. Not long ago, we would have waited 10 or more minutes to load this amount of data and not everyone in the world is a lucky high-speed internet user.</p><p>Source code: <a href="https://github.com/nkoehring/250kb-club" target="_blank">github</a>, <a href="https://git.sr.ht/~koehr/the-250kb-club" target="_blank">sourcehut</a>, <a href="https://git.k0r.in/n/250kb-Club" target="_blank">selfhosted</a></p><h2>Starsy <a href="https://starsy.netlify.app" target="_blank">🔗</a></h2><p><figure><img title="Starsy" src="/projects/starsy.jpg">
<p>I am the creator of 250kB Club, which should actually be called 256kb.club, but that thought reached me only after I got the domain.</p><p>Already in 2016, we crossed the line, where the typical website is bigger than the game Doom. I think, we can do better! The 250kB Club is a collection of web pages that focus on performance, efficiency and accessibility. Originally inspired by <a href="https://1mb.club">1mb.club</a>, I created the 250kB Club, because I don't think 1MB is small enough. Not long ago, we would have waited 10 or more minutes to load this amount of data and not everyone in the world is a lucky high-speed internet user.</p><p>Source code: <a href="https://github.com/nkoehring/250kb-club">github</a>, <a href="https://git.sr.ht/~koehr/the-250kb-club">sourcehut</a>, <a href="https://git.k0r.in/n/250kb-Club">selfhosted</a></p><h2>Starsy <a href="https://starsy.netlify.app">🔗</a></h2><img src="starsy.jpg" title="Starsy Screenshot" alt="Starsy Screenshot" /> <figcaption>Starsy Screenshot</figcaption></figure></p><p>For a hard sci-fi campaign setting, I once planned, I created this star system generator. I wanted to recreate the style of some image I found on reddit, a while ago.</p><p>Source code: <a href="https://github.com/nkoehring/starsy" target="_blank">github</a>, <a href="https://git.k0r.in/n/starsy" target="_blank">selfhosted</a></p><h2>RPG-Cards-ng <a href="https://rpg-cards-ng.netlify.app" target="_blank">🔗</a></h2><p><figure><img title="RPG-Cards-ng" src="/projects/rpgcards.jpg">
<p>For a hard sci-fi campaign setting, I once planned, I created this star system generator. I wanted to recreate the style of some image I found on reddit, a while ago.</p><p>Source code: <a href="https://github.com/nkoehring/starsy">github</a>, <a href="https://git.k0r.in/n/starsy">selfhosted</a></p><h2>RPG-Cards-ng <a href="https://rpg-cards-ng.netlify.app">🔗</a></h2><img src="rpgcards.jpg" title="RPG-Cards-ng Screenshot" alt="RPG-Cards-ng Screenshot" /> <figcaption>RPG-Cards-ng Screenshot</figcaption></figure></p><p>I wanted to be able to create good looking cards for RPG sessions but didn't find a good tool that makes designing them simple and intuitive. So I created my own tool.</p><p>Source code: <a href="https://github.com/nkoehring/rpg-cards-ng" target="_blank">github</a>, <a href="https://git.k0r.in/n/rpg-cards-ng" target="_blank">selfhosted</a></p><h2>Vuejs//Berlin <a href="https://vuejs.berlin" target="_blank">🔗</a></h2><p><figure><img title="Vuejs//Berlin" src="/projects/vuejsberlin.jpg">
<p>I wanted to be able to create good looking cards for RPG sessions but didn't find a good tool that makes designing them simple and intuitive. So I created my own tool.</p><p>Source code: <a href="https://github.com/nkoehring/rpg-cards-ng">github</a>, <a href="https://git.k0r.in/n/rpg-cards-ng">selfhosted</a></p><h2>Vuejs//Berlin <a href="https://vuejs.berlin">🔗</a></h2><img src="vuejsberlin.jpg" title="Vuejs Berlin Screenshot" alt="Vuejs Berlin Screenshot" /> <figcaption>Vue.js Berlin Screenshot</figcaption></figure></p><p>I host the monthly Vuejs//Berlin meetup and created this homepage to publish details about the upcoming and former meetups. It also hosts a newsletter archive.</p><p>The Vuejs//Berlin meetup is Berlins community around the <a href="https://vuejs.org" target="_blank">Vue Framework</a> and its ecosystem. We meet monthly every second Tuesday. Doors open at 19:00, talks usually start around 19:30. Subscribe to <a href="https://lu.ma/vuejs_berlin" target="_blank">the event calendar</a> to never miss an update!</p><p>Source code: <a href="https://github.com/VuejsBerlin/new.vuejs.berlin" target="_blank">github</a></p><h2>Projects for myself</h2><p>Just for the sake of completeness and to motivate myself to keep track of it, here are some private projects around my own setup.</p><h3>Homepage Overhaul</h3><blockquote><p>With lots of work comes lots of opportunity for productive procrastination</p></blockquote><p><strong>tl;dr:</strong></p><p>I use <a href="https://zine-ssg.io" target="_blank">zine-ssg</a> to statically build my homepage after every change. I intend to extend it with automated fetching of <a href="/bookmarks/">bookmarks</a>.</p><p><strong>The long version:</strong></p><p>Not too long ago, .ing <span title="Top Level Domain">TLDs</span> became available, that allowed me to finally have my full name as a "cool" domain name: <code>koehr.ing</code>. Other domains I have are <code>nkoehring.de</code> (boring), <code>koehr.in</code> (confusing) and <code>k0r.in</code> (nerdy). <code>koehri.ng</code> wouldn't be possible due to domain registars policies or pricing (Nigeria used to have the british model, like allowing only net.ng, com.ng, and so on. Later they allowed more, but the price would be pretty high).</p><p>Why am I writing all this? Because the new domain name made me think about my homepage as a professional. I wanted to have something, that showcases my skills while not being the usual boring homepage. This is how <a href="https://cli.koehr.ing" target="_blank">the interactive homepage experiment</a> began; a terminal like website, written from scratch. Having this, I now also needed to change my old homepage to somehow feature my new shiny experiment. But my old homepage is white and not very responsive; two very good reasons (for me), to change it. So I also started writing a completely new homepage, using <a href="https://github.com/vssio/vss" target="_blank">vss</a>. Pretty soon I realised, it is by far not mature enough for my needs, so I started building workarounds to suit my needs, so I don't get stuck in the rabbit hole of choosing frameworks over finishing the page. My plan was, to finish the page and its content and then, when there is time, move it on top of something more sophisticated, like good ol' <a href="https://www.getzola.org/" target="_blank">Zola</a>. Eventually I found <a href="https://zine-ssg.io" target="_blank">zine-ssg</a>, which now builds my homepage for me.</p><h3>New Server</h3><p>I found a pretty cheap dedicated server with tons of space and quite some CPU power, compared to cheap virtual servers. Now I need to move everything I hosted on a VServer before. That is not a simple task, unfortunately, as I tend to overthink and want to use the change to make everything better (or just different, maybe). This move includes a switch from <a href="https://www.docker.com/" target="_blank">Docker</a> and <a href="https://blog.container-solutions.com/running-docker-containers-with-systemd" target="_blank">systemd services</a> to <a href="https://podman.io/" target="_blank">podman</a> and <a href="https://wiki.archlinux.org/title/Systemd/User#Automatic_start-up_of_systemd_user_instances" target="_blank">lingering users</a>. This way, no root enabled service is involved in running any outside-facing services. This website and everything under the koehr.ing domain runs already on the new server.</p><h3>learned.today</h3><p>Quite a while (aka way too long) ago, I bought the domain <code>learned.today</code> and thought about some idea around a Today I learned page or service, where people just share short snippets of things they just learned, similar to <a href="/til/">my TIL page</a>. I never got to implementing it though. I wrote it down here as a motivation for myself, to finally work on it.</p></div>
<p>I host the monthly Vuejs//Berlin meetup and created this homepage to publish details about the upcoming and former meetups. It also hosts a newsletter archive.</p><p>The Vuejs//Berlin meetup is Berlins community around the <a href="https://vuejs.org">Vue Framework</a> and its ecosystem. We meet monthly every second Tuesday. Doors open at 19:00, talks usually start around 19:30. Subscribe to <a href="https://lu.ma/vuejs_berlin">the event calendar</a> to never miss an update!</p><p>Source code: <a href="https://github.com/VuejsBerlin/new.vuejs.berlin">github</a></p><h2>Projects for myself</h2><p>Just for the sake of completeness and to motivate myself to keep track of it, here are some private projects around my own setup.</p><h3>Homepage Overhaul</h3><blockquote><p>With lots of work comes lots of opportunity for productive procrastination</p></blockquote><p><strong>tl;dr:</strong></p><p>I use <a href="https://zine-ssg.io">zine-ssg</a> to statically build my homepage after every change. I intend to extend it with automated fetching of <a href="/bookmarks">bookmarks</a>.</p><p><strong>The long version:</strong></p><p>Not too long ago, .ing <span title="Top Level Domain">TLDs</span> became available, that allowed me to finally have my full name as a "cool" domain name: <code>koehr.ing</code>. Other domains I have are <code>nkoehring.de</code> (boring), <code>koehr.in</code> (confusing) and <code>k0r.in</code> (nerdy). <code>koehri.ng</code> wouldn't be possible due to domain registars policies or pricing (Nigeria used to have the british model, like allowing only net.ng, com.ng, and so on. Later they allowed more, but the price would be pretty high).</p><p>Why am I writing all this? Because the new domain name made me think about my homepage as a professional. I wanted to have something, that showcases my skills while not being the usual boring homepage. This is how <a href="https://cli.koehr.ing">the interactive homepage experiment</a> began; a terminal like website, written from scratch. Having this, I now also needed to change my old homepage to somehow feature my new shiny experiment. But my old homepage is white and not very responsive; two very good reasons (for me), to change it. So I also started writing a completely new homepage, using <a href="https://github.com/vssio/vss">vss</a>. Pretty soon I realised, it is by far not mature enough for my needs, so I started building workarounds to suit my needs, so I don't get stuck in the rabbit hole of choosing frameworks over finishing the page. My plan was, to finish the page and its content and then, when there is time, move it on top of something more sophisticated, like good ol' <a href="https://www.getzola.org/">Zola</a>. Eventually I found <a href="https://zine-ssg.io">zine-ssg</a>, which now builds my homepage for me.</p><h3>New Server</h3><p>I found a pretty cheap dedicated server with tons of space and quite some CPU power, compared to cheap virtual servers. Now I need to move everything I hosted on a VServer before. That is not a simple task, unfortunately, as I tend to overthink and want to use the change to make everything better (or just different, maybe). This move includes a switch from <a href="https://www.docker.com/">Docker</a> and <a href="https://blog.container-solutions.com/running-docker-containers-with-systemd">systemd services</a> to <a href="https://podman.io/">podman</a> and <a href="https://wiki.archlinux.org/title/Systemd/User#Automatic_start-up_of_systemd_user_instances">lingering users</a>. This way, no root enabled service is involved in running any outside-facing services. This website and everything under the koehr.ing domain runs already on the new server.</p><h3>learned.today</h3><p>Quite a while (aka way too long) ago, I bought the domain <code>learned.today</code> and thought about some idea around a Today I learned page or service, where people just share short snippets of things they just learned, similar to <a href="/til">my TIL page</a>. I never got to implementing it though. I wrote it down here as a motivation for myself, to finally work on it.</p></div>
</main> </main>
@ -61,21 +60,21 @@
<a href="/"> <a href="/">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 832.4 143.1"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 832.4 143.1">
<path id="header-underscore" <path id="header-underscore"
d="M832.4 131.1q0 5.5-3.1 8.6-3 3.4-8.2 3.3h-75.5q-5.2 0-8.2-3.3-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8 0-5.5 3.1-8.7 1.6-1.7 3.7-2.4 2.2-.8 4.5-.8h75.5q5.2 0 8.2 3.2 3 3.1 3 8.7z" /> d="M832.4 131.1q0 5.5-3.1 8.6-3 3.4-8.2 3.3h-75.5q-5.2 0-8.2-3.3-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8 0-5.5 3.1-8.7 1.6-1.7 3.7-2.4 2.2-.8 4.5-.8h75.5q5.2 0 8.2 3.2 3 3.1 3 8.7z"></path>
<path id="header-bracket" <path id="header-bracket"
d="M731.9 81.4q0 6.7-6.5 10.7l-1 .6-74.3 39.2q-2.5 1.3-5.2 1.2-4.8 0-8.1-3.8-3.2-3.6-3.2-8.4 0-3.3 1.7-6 1.8-2.9 4.6-4.4l55.3-29.1-55.3-29q-2.8-1.6-4.6-4.3-1.7-2.7-1.7-6.2 0-4.7 3.2-8.4 3.3-4 8-3.7 2.7 0 5.3 1.2l74.4 39.2q3.3 1.7 5.3 4.7 2 2.8 2 6.5z" /> d="M731.9 81.4q0 6.7-6.5 10.7l-1 .6-74.3 39.2q-2.5 1.3-5.2 1.2-4.8 0-8.1-3.8-3.2-3.6-3.2-8.4 0-3.3 1.7-6 1.8-2.9 4.6-4.4l55.3-29.1-55.3-29q-2.8-1.6-4.6-4.3-1.7-2.7-1.7-6.2 0-4.7 3.2-8.4 3.3-4 8-3.7 2.7 0 5.3 1.2l74.4 39.2q3.3 1.7 5.3 4.7 2 2.8 2 6.5z"></path>
<path id="header-r" <path id="header-r"
d="M588.7 66.5q0 5-3.5 8.5-3.5 3.4-8.1 3.5-4.4 0-8.3-4.3-10-10.7-20.9-10.6-2.2 0-4.3.3-2.1.3-4 1-1.8.6-3.7 1.6-1.7 1-3.4 2.3-1.7 1.3-3.3 2.9-7.8 8.2-7.6 19.7V131q0 5.5-3.1 8.6-3 3.4-8.3 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V51.6q0-5.4 3-8.6 3-3.4 8.3-3.3 2 0 3.7.6 1.8.6 3.3 1.8 1.4 1 2.2 2.7 1 1.5 1.6 3.3 11.8-8.4 27-8.4 10.6 0 21 5 11.3 5.4 17.2 14.5 2.5 3.7 2.5 7.3z" /> d="M588.7 66.5q0 5-3.5 8.5-3.5 3.4-8.1 3.5-4.4 0-8.3-4.3-10-10.7-20.9-10.6-2.2 0-4.3.3-2.1.3-4 1-1.8.6-3.7 1.6-1.7 1-3.4 2.3-1.7 1.3-3.3 2.9-7.8 8.2-7.6 19.7V131q0 5.5-3.1 8.6-3 3.4-8.3 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V51.6q0-5.4 3-8.6 3-3.4 8.3-3.3 2 0 3.7.6 1.8.6 3.3 1.8 1.4 1 2.2 2.7 1 1.5 1.6 3.3 11.8-8.4 27-8.4 10.6 0 21 5 11.3 5.4 17.2 14.5 2.5 3.7 2.5 7.3z"></path>
<path id="header-h" <path id="header-h"
d="M483.9 131.1q0 5.5-3.1 8.6-3 3.4-8.3 3.3-5.2 0-8.2-3.3-3.2-3.1-3.1-8.6V84.8q0-4.6-1.5-8.2-1.4-3.5-4.4-6.9-2.1-2-4.3-3.4-2.2-1.4-4.7-2-2.4-.7-5.3-.7-4.3 0-7.8 1.5-3.3 1.5-6.4 4.6-5.9 6.3-5.8 15v46.4q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v33q1.5-1 3-1.6l3.2-1.2 3.4-1q1.6-.5 3.3-.8l3.5-.4 3.6-.2q4.4 0 8.5 1 4.1.7 7.9 2.4 3.8 1.6 7.3 4.1 3.5 2.5 6.6 5.8Q484 66 484 84.8z" /> d="M483.9 131.1q0 5.5-3.1 8.6-3 3.4-8.3 3.3-5.2 0-8.2-3.3-3.2-3.1-3.1-8.6V84.8q0-4.6-1.5-8.2-1.4-3.5-4.4-6.9-2.1-2-4.3-3.4-2.2-1.4-4.7-2-2.4-.7-5.3-.7-4.3 0-7.8 1.5-3.3 1.5-6.4 4.6-5.9 6.3-5.8 15v46.4q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v33q1.5-1 3-1.6l3.2-1.2 3.4-1q1.6-.5 3.3-.8l3.5-.4 3.6-.2q4.4 0 8.5 1 4.1.7 7.9 2.4 3.8 1.6 7.3 4.1 3.5 2.5 6.6 5.8Q484 66 484 84.8z"></path>
<path id="header-e" <path id="header-e"
d="M387.5 111.1q0 1.2-.3 2.3-.1 1-.5 2l-.9 2q-6.6 12-19.4 19-12 6.6-25.4 6.6-20.8 0-35.8-14.6-15.9-15-15.9-37 0-22.1 15.9-37.1 15-14.6 35.8-14.6 3.9 0 7.8.7 4 .7 8 2.2 9.2 3.1 18.2 10 6 4.6 9.1 9.3 3.3 4.7 3.3 10 0 1.3-.3 2.5-.2 1.3-.7 2.4-1.5 3.4-5 5.3l-56.9 32.2q7.2 4.9 16.5 4.9 7.2 0 12.6-2.5 5.5-2.5 9.7-7.4l.7-1 .8-1 .9-1.3 1-1.5q3.3-4.2 7.4-5.1l1.8-.2q4.4 0 8 3.4 3.6 3.5 3.6 8.5zm-29.9-42.7q-7.2-4.8-16.6-4.8-6 0-11 2-4.9 1.8-9.3 6-4.5 4-6.7 9-2 4.8-2 10.8l.1 2.9z" /> d="M387.5 111.1q0 1.2-.3 2.3-.1 1-.5 2l-.9 2q-6.6 12-19.4 19-12 6.6-25.4 6.6-20.8 0-35.8-14.6-15.9-15-15.9-37 0-22.1 15.9-37.1 15-14.6 35.8-14.6 3.9 0 7.8.7 4 .7 8 2.2 9.2 3.1 18.2 10 6 4.6 9.1 9.3 3.3 4.7 3.3 10 0 1.3-.3 2.5-.2 1.3-.7 2.4-1.5 3.4-5 5.3l-56.9 32.2q7.2 4.9 16.5 4.9 7.2 0 12.6-2.5 5.5-2.5 9.7-7.4l.7-1 .8-1 .9-1.3 1-1.5q3.3-4.2 7.4-5.1l1.8-.2q4.4 0 8 3.4 3.6 3.5 3.6 8.5zm-29.9-42.7q-7.2-4.8-16.6-4.8-6 0-11 2-4.9 1.8-9.3 6-4.5 4-6.7 9-2 4.8-2 10.8l.1 2.9z"></path>
<path id="header-o" <path id="header-o"
d="M286.8 91.4q0 4.2-.6 8.3-.6 4-1.8 7.7-1.1 3.8-2.9 7.4-1.7 3.5-4 6.9-2.4 3.3-5.2 6.1Q258 143 237.7 143T203 128q-14.3-15.2-14.3-36.6 0-21.5 14.3-36.6 14.4-15 34.7-15 4 0 7.8.5 3.9.7 7.5 1.9t7 3q3.3 1.9 6.4 4.3 3.2 2.4 5.9 5.4 14.4 15 14.5 36.5zm-22.6 0q0-2.4-.4-4.5-.2-2.2-.9-4.2-.6-2-1.5-3.9-1-2-2.2-3.7-1.2-1.7-2.8-3.4-4-4.2-8.6-6.1-4.5-2-10-2-11 0-18.7 8.2-7.8 8-7.8 19.6 0 11.4 7.8 19.7 7.8 8 18.6 8 5.6 0 10.1-1.9 4.6-2 8.6-6.1 4-4.3 5.8-9 2-4.9 2-10.7z" /> d="M286.8 91.4q0 4.2-.6 8.3-.6 4-1.8 7.7-1.1 3.8-2.9 7.4-1.7 3.5-4 6.9-2.4 3.3-5.2 6.1Q258 143 237.7 143T203 128q-14.3-15.2-14.3-36.6 0-21.5 14.3-36.6 14.4-15 34.7-15 4 0 7.8.5 3.9.7 7.5 1.9t7 3q3.3 1.9 6.4 4.3 3.2 2.4 5.9 5.4 14.4 15 14.5 36.5zm-22.6 0q0-2.4-.4-4.5-.2-2.2-.9-4.2-.6-2-1.5-3.9-1-2-2.2-3.7-1.2-1.7-2.8-3.4-4-4.2-8.6-6.1-4.5-2-10-2-11 0-18.7 8.2-7.8 8-7.8 19.6 0 11.4 7.8 19.7 7.8 8 18.6 8 5.6 0 10.1-1.9 4.6-2 8.6-6.1 4-4.3 5.8-9 2-4.9 2-10.7z"></path>
<path id="header-k" <path id="header-k"
d="M186.3 131q0 4.7-3.3 8.3-1.5 1.8-3.7 2.7-2 1.1-4.3 1.1-3.5 0-6.6-2L119.2 105v26q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v65.9l49.2-36.1q3.2-2 6.6-2 4.7 0 8 3.7t3.3 8.4q-.2 6-5 9.6l-41 30 41 29.9q2.3 1.7 3.6 4.2 1.4 2.5 1.4 5.4z" /> d="M186.3 131q0 4.7-3.3 8.3-1.5 1.8-3.7 2.7-2 1.1-4.3 1.1-3.5 0-6.6-2L119.2 105v26q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v65.9l49.2-36.1q3.2-2 6.6-2 4.7 0 8 3.7t3.3 8.4q-.2 6-5 9.6l-41 30 41 29.9q2.3 1.7 3.6 4.2 1.4 2.5 1.4 5.4z"></path>
<path id="header-tilde" <path id="header-tilde"
d="M73.1 91q0 2-.6 3.9T71 98.6q-3.2 5.7-8.9 8.5-5.6 2.8-12.9 2.8-8.8 0-18-7.8-2.4-2.3-4.5-3.7-2.1-1.5-3-1.7-1.5 0-2.1.3l-.8 1.3q-.3.7-.8 1.2l-1 1-.9.8q-2.7 2-6.4 2-1.7 0-3.2-.3-1.4-.3-3-1.1-1.5-.8-2.6-2.1-2.8-3.1-2.8-8v-1.3q0-.7.2-1.2l.2-1 .4-1 .4-1q.1-.6.5-1.1l.5-1q3.2-5.7 8.8-8.5 5.7-2.9 13-2.9 3.2 0 6.2 1 3 .9 6 2.7 2.9 1.6 5.7 4.2 5.2 4.6 7.6 5.4 1 0 1.6-.2l.7-.4q.3-.1.5-.4 3.6-5.6 9.2-5.6 5.7 0 8.8 3.5 2.8 3 2.8 8z" /> d="M73.1 91q0 2-.6 3.9T71 98.6q-3.2 5.7-8.9 8.5-5.6 2.8-12.9 2.8-8.8 0-18-7.8-2.4-2.3-4.5-3.7-2.1-1.5-3-1.7-1.5 0-2.1.3l-.8 1.3q-.3.7-.8 1.2l-1 1-.9.8q-2.7 2-6.4 2-1.7 0-3.2-.3-1.4-.3-3-1.1-1.5-.8-2.6-2.1-2.8-3.1-2.8-8v-1.3q0-.7.2-1.2l.2-1 .4-1 .4-1q.1-.6.5-1.1l.5-1q3.2-5.7 8.8-8.5 5.7-2.9 13-2.9 3.2 0 6.2 1 3 .9 6 2.7 2.9 1.6 5.7 4.2 5.2 4.6 7.6 5.4 1 0 1.6-.2l.7-.4q.3-.1.5-.4 3.6-5.6 9.2-5.6 5.7 0 8.8 3.5 2.8 3 2.8 8z"></path>
</svg> </svg>
Homepage of Homepage of
<div class=p-name> <div class=p-name>

View file

@ -3,7 +3,7 @@
<head id="head"> <head id="head">
<meta charset=utf-8> <meta charset=utf-8>
<title id=title >the codeartist — programmer and engineer based in BerlinSetup</title> <title id="title " var="the codeartist — programmer and engineer based in Berlin">Setup</title>
<meta name=description content="The personal page and weblog of Norman Köhring"> <meta name=description content="The personal page and weblog of Norman Köhring">
<meta name=author content="Norman Köhring"> <meta name=author content="Norman Köhring">
<meta name=DC.title content="the codeartist — programmer and engineer based in Berlin"> <meta name=DC.title content="the codeartist — programmer and engineer based in Berlin">
@ -15,8 +15,8 @@
<meta name="og:title" content="Setup // the codeartist"> <meta name="og:title" content="Setup // the codeartist">
<meta property="og:type" content="website"> <meta property="og:type" content="website">
<meta http-equiv="x-ua-compatible" content="ie=edge"/> <meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"/> <meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no">
<meta name=ICBM content="52.4595, 13.5335"> <meta name=ICBM content="52.4595, 13.5335">
<meta name=geo.position content="52.4595; 13.5335"> <meta name=geo.position content="52.4595; 13.5335">
@ -26,7 +26,7 @@
<link rel=me href=https://k0r.in> <link rel=me href=https://k0r.in>
<link rel=me href=https://koehr.ing> <link rel=me href=https://koehr.ing>
<link rel=me href=@Koehr@mstdn.io> <link rel=me href=@Koehr@mstdn.io>
<link rel=me href=https://sr.ht/~koehr/> <link rel=me href=https://sr.ht/~koehr>
<link rel=me href=https://git.k0r.in> <link rel=me href=https://git.k0r.in>
<link rel=me href=https://threads.net/@coffee_n_code> <link rel=me href=https://threads.net/@coffee_n_code>
<link rel=me href=https://instagram.com/@coffee_n_code> <link rel=me href=https://instagram.com/@coffee_n_code>
@ -44,11 +44,11 @@
<header> <header>
<h1>Setup</h1> <h1>Setup</h1>
<em>As a software engineer, the tools I use define how I work and I find it inspiring to see which tools other people use.</em> <em>As a software engineer, the tools I use define how I work and I find it inspiring to see which tools other people use.</em>
<br/> <br>
Last updated: <time datetime="Mon, 20 May 2024 00:00:00 +0000">May 20, 2024</time> Last updated: <time datetime="Mon, 20 May 2024 00:00:00 +0000">May 20, 2024</time>
</header> </header>
<div ><hr><p>This page focusses on Hardware. For Software, check <a href="/stack">/stack</a>.</p><hr><p>I used to work on laptops without any extras, but over the years ergonomics got more and more important. Now I have a second screen, a standing desk and an ergonomic chair. My main keyboard is split in half and my pointer device is a big red ball.</p><h2>Work Computer: Thinkpad T14s</h2><blockquote><p>Decent CPU, good amount of RAM, very lightweight, great battery life</p></blockquote><p>Thinkpads are my go-to laptops for work. They are robust and performant.</p><h2>Private Computer: ASUS Zenbook Pro Duo</h2><blockquote><p>Fantastic screen, a second display, decent hardware</p></blockquote><p>My private laptop is a bit more experimental. It features a dual screen setup with a 16:10 OLED screen and an additional 16:5(-ish) LCD above the keyboard.</p><h2>Keyboard: Sofle 2 split-keyboard</h2><p>I use the <a href="https://josefadamcik.github.io/SofleKeyboard/">Sofle 2</a> keyboard. I adapted it to my needs. It features two rotary encoders and a customized <a href="https://qmk.fm">qmk firmware</a> configuration. The source code can be found <a href="https://github.com/nkoehring/qmk_firmware/tree/master">on github</a>.</p><h2><span title="a.k.a. mouse">Pointer</span>: Kensington Orbit</h2><p>The <a href="https://www.kensington.com/p/products/electronic-control-solutions/trackball-products/orbit-wireless-trackball-with-scroll-ring/">Kensington Orbit</a> is a trackball and a treat for every wrist.</p><h2>Desk: ergonomic</h2><p>My desk is height adjustable, so that I can sit or stand at it. Its not a fancy branded one; it does it job well, though.</p><h2>Chair: ergonomic</h2><p>My chair is an ergonomic office chair with 4D arm rests and extra back support. I can sit on it all day without issues.</p></div> <div><hr><p>This page focusses on Hardware. For Software, check <a href="/stack/">/stack</a>.</p><hr><p>I used to work on laptops without any extras, but over the years ergonomics got more and more important. Now I have a second screen, a standing desk and an ergonomic chair. My main keyboard is split in half and my pointer device is a big red ball.</p><h2>Work Computer: Thinkpad T14s</h2><blockquote><p>Decent CPU, good amount of RAM, very lightweight, great battery life</p></blockquote><p>Thinkpads are my go-to laptops for work. They are robust and performant.</p><h2>Private Computer: ASUS Zenbook Pro Duo</h2><blockquote><p>Fantastic screen, a second display, decent hardware</p></blockquote><p>My private laptop is a bit more experimental. It features a dual screen setup with a 16:10 OLED screen and an additional 16:5(-ish) LCD above the keyboard.</p><h2>Keyboard: Sofle 2 split-keyboard</h2><p>I use the <a href="https://josefadamcik.github.io/SofleKeyboard/" target="_blank">Sofle 2</a> keyboard. I adapted it to my needs. It features two rotary encoders and a customized <a href="https://qmk.fm" target="_blank">qmk firmware</a> configuration. The source code can be found <a href="https://github.com/nkoehring/qmk_firmware/tree/master" target="_blank">on github</a>.</p><h2><span title="a.k.a. mouse">Pointer</span>: Kensington Orbit</h2><p>The <a href="https://www.kensington.com/p/products/electronic-control-solutions/trackball-products/orbit-wireless-trackball-with-scroll-ring/" target="_blank">Kensington Orbit</a> is a trackball and a treat for every wrist.</p><h2>Desk: ergonomic</h2><p>My desk is height adjustable, so that I can sit or stand at it. Its not a fancy branded one; it does it job well, though.</p><h2>Chair: ergonomic</h2><p>My chair is an ergonomic office chair with 4D arm rests and extra back support. I can sit on it all day without issues.</p></div>
</main> </main>
@ -57,21 +57,21 @@
<a href="/"> <a href="/">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 832.4 143.1"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 832.4 143.1">
<path id="header-underscore" <path id="header-underscore"
d="M832.4 131.1q0 5.5-3.1 8.6-3 3.4-8.2 3.3h-75.5q-5.2 0-8.2-3.3-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8 0-5.5 3.1-8.7 1.6-1.7 3.7-2.4 2.2-.8 4.5-.8h75.5q5.2 0 8.2 3.2 3 3.1 3 8.7z" /> d="M832.4 131.1q0 5.5-3.1 8.6-3 3.4-8.2 3.3h-75.5q-5.2 0-8.2-3.3-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8 0-5.5 3.1-8.7 1.6-1.7 3.7-2.4 2.2-.8 4.5-.8h75.5q5.2 0 8.2 3.2 3 3.1 3 8.7z"></path>
<path id="header-bracket" <path id="header-bracket"
d="M731.9 81.4q0 6.7-6.5 10.7l-1 .6-74.3 39.2q-2.5 1.3-5.2 1.2-4.8 0-8.1-3.8-3.2-3.6-3.2-8.4 0-3.3 1.7-6 1.8-2.9 4.6-4.4l55.3-29.1-55.3-29q-2.8-1.6-4.6-4.3-1.7-2.7-1.7-6.2 0-4.7 3.2-8.4 3.3-4 8-3.7 2.7 0 5.3 1.2l74.4 39.2q3.3 1.7 5.3 4.7 2 2.8 2 6.5z" /> d="M731.9 81.4q0 6.7-6.5 10.7l-1 .6-74.3 39.2q-2.5 1.3-5.2 1.2-4.8 0-8.1-3.8-3.2-3.6-3.2-8.4 0-3.3 1.7-6 1.8-2.9 4.6-4.4l55.3-29.1-55.3-29q-2.8-1.6-4.6-4.3-1.7-2.7-1.7-6.2 0-4.7 3.2-8.4 3.3-4 8-3.7 2.7 0 5.3 1.2l74.4 39.2q3.3 1.7 5.3 4.7 2 2.8 2 6.5z"></path>
<path id="header-r" <path id="header-r"
d="M588.7 66.5q0 5-3.5 8.5-3.5 3.4-8.1 3.5-4.4 0-8.3-4.3-10-10.7-20.9-10.6-2.2 0-4.3.3-2.1.3-4 1-1.8.6-3.7 1.6-1.7 1-3.4 2.3-1.7 1.3-3.3 2.9-7.8 8.2-7.6 19.7V131q0 5.5-3.1 8.6-3 3.4-8.3 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V51.6q0-5.4 3-8.6 3-3.4 8.3-3.3 2 0 3.7.6 1.8.6 3.3 1.8 1.4 1 2.2 2.7 1 1.5 1.6 3.3 11.8-8.4 27-8.4 10.6 0 21 5 11.3 5.4 17.2 14.5 2.5 3.7 2.5 7.3z" /> d="M588.7 66.5q0 5-3.5 8.5-3.5 3.4-8.1 3.5-4.4 0-8.3-4.3-10-10.7-20.9-10.6-2.2 0-4.3.3-2.1.3-4 1-1.8.6-3.7 1.6-1.7 1-3.4 2.3-1.7 1.3-3.3 2.9-7.8 8.2-7.6 19.7V131q0 5.5-3.1 8.6-3 3.4-8.3 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V51.6q0-5.4 3-8.6 3-3.4 8.3-3.3 2 0 3.7.6 1.8.6 3.3 1.8 1.4 1 2.2 2.7 1 1.5 1.6 3.3 11.8-8.4 27-8.4 10.6 0 21 5 11.3 5.4 17.2 14.5 2.5 3.7 2.5 7.3z"></path>
<path id="header-h" <path id="header-h"
d="M483.9 131.1q0 5.5-3.1 8.6-3 3.4-8.3 3.3-5.2 0-8.2-3.3-3.2-3.1-3.1-8.6V84.8q0-4.6-1.5-8.2-1.4-3.5-4.4-6.9-2.1-2-4.3-3.4-2.2-1.4-4.7-2-2.4-.7-5.3-.7-4.3 0-7.8 1.5-3.3 1.5-6.4 4.6-5.9 6.3-5.8 15v46.4q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v33q1.5-1 3-1.6l3.2-1.2 3.4-1q1.6-.5 3.3-.8l3.5-.4 3.6-.2q4.4 0 8.5 1 4.1.7 7.9 2.4 3.8 1.6 7.3 4.1 3.5 2.5 6.6 5.8Q484 66 484 84.8z" /> d="M483.9 131.1q0 5.5-3.1 8.6-3 3.4-8.3 3.3-5.2 0-8.2-3.3-3.2-3.1-3.1-8.6V84.8q0-4.6-1.5-8.2-1.4-3.5-4.4-6.9-2.1-2-4.3-3.4-2.2-1.4-4.7-2-2.4-.7-5.3-.7-4.3 0-7.8 1.5-3.3 1.5-6.4 4.6-5.9 6.3-5.8 15v46.4q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v33q1.5-1 3-1.6l3.2-1.2 3.4-1q1.6-.5 3.3-.8l3.5-.4 3.6-.2q4.4 0 8.5 1 4.1.7 7.9 2.4 3.8 1.6 7.3 4.1 3.5 2.5 6.6 5.8Q484 66 484 84.8z"></path>
<path id="header-e" <path id="header-e"
d="M387.5 111.1q0 1.2-.3 2.3-.1 1-.5 2l-.9 2q-6.6 12-19.4 19-12 6.6-25.4 6.6-20.8 0-35.8-14.6-15.9-15-15.9-37 0-22.1 15.9-37.1 15-14.6 35.8-14.6 3.9 0 7.8.7 4 .7 8 2.2 9.2 3.1 18.2 10 6 4.6 9.1 9.3 3.3 4.7 3.3 10 0 1.3-.3 2.5-.2 1.3-.7 2.4-1.5 3.4-5 5.3l-56.9 32.2q7.2 4.9 16.5 4.9 7.2 0 12.6-2.5 5.5-2.5 9.7-7.4l.7-1 .8-1 .9-1.3 1-1.5q3.3-4.2 7.4-5.1l1.8-.2q4.4 0 8 3.4 3.6 3.5 3.6 8.5zm-29.9-42.7q-7.2-4.8-16.6-4.8-6 0-11 2-4.9 1.8-9.3 6-4.5 4-6.7 9-2 4.8-2 10.8l.1 2.9z" /> d="M387.5 111.1q0 1.2-.3 2.3-.1 1-.5 2l-.9 2q-6.6 12-19.4 19-12 6.6-25.4 6.6-20.8 0-35.8-14.6-15.9-15-15.9-37 0-22.1 15.9-37.1 15-14.6 35.8-14.6 3.9 0 7.8.7 4 .7 8 2.2 9.2 3.1 18.2 10 6 4.6 9.1 9.3 3.3 4.7 3.3 10 0 1.3-.3 2.5-.2 1.3-.7 2.4-1.5 3.4-5 5.3l-56.9 32.2q7.2 4.9 16.5 4.9 7.2 0 12.6-2.5 5.5-2.5 9.7-7.4l.7-1 .8-1 .9-1.3 1-1.5q3.3-4.2 7.4-5.1l1.8-.2q4.4 0 8 3.4 3.6 3.5 3.6 8.5zm-29.9-42.7q-7.2-4.8-16.6-4.8-6 0-11 2-4.9 1.8-9.3 6-4.5 4-6.7 9-2 4.8-2 10.8l.1 2.9z"></path>
<path id="header-o" <path id="header-o"
d="M286.8 91.4q0 4.2-.6 8.3-.6 4-1.8 7.7-1.1 3.8-2.9 7.4-1.7 3.5-4 6.9-2.4 3.3-5.2 6.1Q258 143 237.7 143T203 128q-14.3-15.2-14.3-36.6 0-21.5 14.3-36.6 14.4-15 34.7-15 4 0 7.8.5 3.9.7 7.5 1.9t7 3q3.3 1.9 6.4 4.3 3.2 2.4 5.9 5.4 14.4 15 14.5 36.5zm-22.6 0q0-2.4-.4-4.5-.2-2.2-.9-4.2-.6-2-1.5-3.9-1-2-2.2-3.7-1.2-1.7-2.8-3.4-4-4.2-8.6-6.1-4.5-2-10-2-11 0-18.7 8.2-7.8 8-7.8 19.6 0 11.4 7.8 19.7 7.8 8 18.6 8 5.6 0 10.1-1.9 4.6-2 8.6-6.1 4-4.3 5.8-9 2-4.9 2-10.7z" /> d="M286.8 91.4q0 4.2-.6 8.3-.6 4-1.8 7.7-1.1 3.8-2.9 7.4-1.7 3.5-4 6.9-2.4 3.3-5.2 6.1Q258 143 237.7 143T203 128q-14.3-15.2-14.3-36.6 0-21.5 14.3-36.6 14.4-15 34.7-15 4 0 7.8.5 3.9.7 7.5 1.9t7 3q3.3 1.9 6.4 4.3 3.2 2.4 5.9 5.4 14.4 15 14.5 36.5zm-22.6 0q0-2.4-.4-4.5-.2-2.2-.9-4.2-.6-2-1.5-3.9-1-2-2.2-3.7-1.2-1.7-2.8-3.4-4-4.2-8.6-6.1-4.5-2-10-2-11 0-18.7 8.2-7.8 8-7.8 19.6 0 11.4 7.8 19.7 7.8 8 18.6 8 5.6 0 10.1-1.9 4.6-2 8.6-6.1 4-4.3 5.8-9 2-4.9 2-10.7z"></path>
<path id="header-k" <path id="header-k"
d="M186.3 131q0 4.7-3.3 8.3-1.5 1.8-3.7 2.7-2 1.1-4.3 1.1-3.5 0-6.6-2L119.2 105v26q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v65.9l49.2-36.1q3.2-2 6.6-2 4.7 0 8 3.7t3.3 8.4q-.2 6-5 9.6l-41 30 41 29.9q2.3 1.7 3.6 4.2 1.4 2.5 1.4 5.4z" /> d="M186.3 131q0 4.7-3.3 8.3-1.5 1.8-3.7 2.7-2 1.1-4.3 1.1-3.5 0-6.6-2L119.2 105v26q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v65.9l49.2-36.1q3.2-2 6.6-2 4.7 0 8 3.7t3.3 8.4q-.2 6-5 9.6l-41 30 41 29.9q2.3 1.7 3.6 4.2 1.4 2.5 1.4 5.4z"></path>
<path id="header-tilde" <path id="header-tilde"
d="M73.1 91q0 2-.6 3.9T71 98.6q-3.2 5.7-8.9 8.5-5.6 2.8-12.9 2.8-8.8 0-18-7.8-2.4-2.3-4.5-3.7-2.1-1.5-3-1.7-1.5 0-2.1.3l-.8 1.3q-.3.7-.8 1.2l-1 1-.9.8q-2.7 2-6.4 2-1.7 0-3.2-.3-1.4-.3-3-1.1-1.5-.8-2.6-2.1-2.8-3.1-2.8-8v-1.3q0-.7.2-1.2l.2-1 .4-1 .4-1q.1-.6.5-1.1l.5-1q3.2-5.7 8.8-8.5 5.7-2.9 13-2.9 3.2 0 6.2 1 3 .9 6 2.7 2.9 1.6 5.7 4.2 5.2 4.6 7.6 5.4 1 0 1.6-.2l.7-.4q.3-.1.5-.4 3.6-5.6 9.2-5.6 5.7 0 8.8 3.5 2.8 3 2.8 8z" /> d="M73.1 91q0 2-.6 3.9T71 98.6q-3.2 5.7-8.9 8.5-5.6 2.8-12.9 2.8-8.8 0-18-7.8-2.4-2.3-4.5-3.7-2.1-1.5-3-1.7-1.5 0-2.1.3l-.8 1.3q-.3.7-.8 1.2l-1 1-.9.8q-2.7 2-6.4 2-1.7 0-3.2-.3-1.4-.3-3-1.1-1.5-.8-2.6-2.1-2.8-3.1-2.8-8v-1.3q0-.7.2-1.2l.2-1 .4-1 .4-1q.1-.6.5-1.1l.5-1q3.2-5.7 8.8-8.5 5.7-2.9 13-2.9 3.2 0 6.2 1 3 .9 6 2.7 2.9 1.6 5.7 4.2 5.2 4.6 7.6 5.4 1 0 1.6-.2l.7-.4q.3-.1.5-.4 3.6-5.6 9.2-5.6 5.7 0 8.8 3.5 2.8 3 2.8 8z"></path>
</svg> </svg>
Homepage of Homepage of
<div class=p-name> <div class=p-name>

File diff suppressed because one or more lines are too long

View file

@ -161,6 +161,7 @@ code {
padding-top: 2rem; padding-top: 2rem;
} }
#content>h1, #content>h1,
#contact h1,
main > header > h1 { main > header > h1 {
margin: 0 0 .25em; margin: 0 0 .25em;
font-size: 2rem; font-size: 2rem;
@ -168,7 +169,8 @@ main > header > h1 {
text-shadow: 1px 1px 0 var(--emboss-color); text-shadow: 1px 1px 0 var(--emboss-color);
color: var(--header-fg-color); color: var(--header-fg-color);
} }
#content>h1 { #content>h1,
#contact h1 {
padding-top: 2em; padding-top: 2em;
} }
h2 { h2 {
@ -221,7 +223,8 @@ h2 {
column-fill: balance; column-fill: balance;
} }
.contacts p {
.contacts>li {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 1rem; gap: 1rem;
@ -322,3 +325,4 @@ span[title] {
columns: 1; columns: 1;
} }
} }
iframe{width:640px;max-width:100%;height:30em;}

View file

@ -3,7 +3,7 @@
<head id="head"> <head id="head">
<meta charset=utf-8> <meta charset=utf-8>
<title id=title >the codeartist — programmer and engineer based in BerlinThere is a HTML tag for "Word Break Opportunity"</title> <title id="title " var="the codeartist — programmer and engineer based in Berlin"></title>
<meta name=description content="The personal page and weblog of Norman Köhring"> <meta name=description content="The personal page and weblog of Norman Köhring">
<meta name=author content="Norman Köhring"> <meta name=author content="Norman Köhring">
<meta name=DC.title content="the codeartist — programmer and engineer based in Berlin"> <meta name=DC.title content="the codeartist — programmer and engineer based in Berlin">
@ -11,12 +11,12 @@
<meta name="twitter:site" content="@koehr_in"> <meta name="twitter:site" content="@koehr_in">
<meta name="twitter:author" content="@koehr_in"> <meta name="twitter:author" content="@koehr_in">
<meta name=twitter:description content="The personal page and weblog of the codeartist Norman Köhring"> <meta name=twitter:description content="The personal page and weblog of the codeartist Norman Köhring">
<meta name="twitter:title" content="There is a HTML tag for "Word Break Opportunity" // the codeartist"> <meta name="twitter:title" content="There is a HTML tag for &quot;Word Break Opportunity&quot; // the codeartist">
<meta name="og:title" content="There is a HTML tag for "Word Break Opportunity" // the codeartist"> <meta name="og:title" content="There is a HTML tag for &quot;Word Break Opportunity&quot; // the codeartist">
<meta property="og:type" content="website"> <meta property="og:type" content="website">
<meta http-equiv="x-ua-compatible" content="ie=edge"/> <meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"/> <meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no">
<meta name=ICBM content="52.4595, 13.5335"> <meta name=ICBM content="52.4595, 13.5335">
<meta name=geo.position content="52.4595; 13.5335"> <meta name=geo.position content="52.4595; 13.5335">
@ -26,7 +26,7 @@
<link rel=me href=https://k0r.in> <link rel=me href=https://k0r.in>
<link rel=me href=https://koehr.ing> <link rel=me href=https://koehr.ing>
<link rel=me href=@Koehr@mstdn.io> <link rel=me href=@Koehr@mstdn.io>
<link rel=me href=https://sr.ht/~koehr/> <link rel=me href=https://sr.ht/~koehr>
<link rel=me href=https://git.k0r.in> <link rel=me href=https://git.k0r.in>
<link rel=me href=https://threads.net/@coffee_n_code> <link rel=me href=https://threads.net/@coffee_n_code>
<link rel=me href=https://instagram.com/@coffee_n_code> <link rel=me href=https://instagram.com/@coffee_n_code>
@ -49,10 +49,10 @@
<main id="main"> <main id="main">
<header> <header>
<h1 >There is a HTML tag for "Word Break Opportunity"</h1> <h1 :title="There is a HTML tag for &quot;Word Break Opportunity&quot;"></h1>
<em ></em> <em :title=""></em>
<br/> <br>
Last updated: <time datetime="Tue, 31 Aug 2021 00:00:00 +0000" >August 31, 2021</time> Last updated: <time datetime="Tue, 31 Aug 2021 00:00:00 +0000" :title="August 31, 2021"></time>
</header> </header>
<div><p>For example: <code>Kauf&lt;wbr/&gt;haus</code>.</p></div> <div><p>For example: <code>Kauf&lt;wbr/&gt;haus</code>.</p></div>
@ -68,21 +68,21 @@
<a href="/"> <a href="/">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 832.4 143.1"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 832.4 143.1">
<path id="header-underscore" <path id="header-underscore"
d="M832.4 131.1q0 5.5-3.1 8.6-3 3.4-8.2 3.3h-75.5q-5.2 0-8.2-3.3-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8 0-5.5 3.1-8.7 1.6-1.7 3.7-2.4 2.2-.8 4.5-.8h75.5q5.2 0 8.2 3.2 3 3.1 3 8.7z" /> d="M832.4 131.1q0 5.5-3.1 8.6-3 3.4-8.2 3.3h-75.5q-5.2 0-8.2-3.3-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8 0-5.5 3.1-8.7 1.6-1.7 3.7-2.4 2.2-.8 4.5-.8h75.5q5.2 0 8.2 3.2 3 3.1 3 8.7z"></path>
<path id="header-bracket" <path id="header-bracket"
d="M731.9 81.4q0 6.7-6.5 10.7l-1 .6-74.3 39.2q-2.5 1.3-5.2 1.2-4.8 0-8.1-3.8-3.2-3.6-3.2-8.4 0-3.3 1.7-6 1.8-2.9 4.6-4.4l55.3-29.1-55.3-29q-2.8-1.6-4.6-4.3-1.7-2.7-1.7-6.2 0-4.7 3.2-8.4 3.3-4 8-3.7 2.7 0 5.3 1.2l74.4 39.2q3.3 1.7 5.3 4.7 2 2.8 2 6.5z" /> d="M731.9 81.4q0 6.7-6.5 10.7l-1 .6-74.3 39.2q-2.5 1.3-5.2 1.2-4.8 0-8.1-3.8-3.2-3.6-3.2-8.4 0-3.3 1.7-6 1.8-2.9 4.6-4.4l55.3-29.1-55.3-29q-2.8-1.6-4.6-4.3-1.7-2.7-1.7-6.2 0-4.7 3.2-8.4 3.3-4 8-3.7 2.7 0 5.3 1.2l74.4 39.2q3.3 1.7 5.3 4.7 2 2.8 2 6.5z"></path>
<path id="header-r" <path id="header-r"
d="M588.7 66.5q0 5-3.5 8.5-3.5 3.4-8.1 3.5-4.4 0-8.3-4.3-10-10.7-20.9-10.6-2.2 0-4.3.3-2.1.3-4 1-1.8.6-3.7 1.6-1.7 1-3.4 2.3-1.7 1.3-3.3 2.9-7.8 8.2-7.6 19.7V131q0 5.5-3.1 8.6-3 3.4-8.3 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V51.6q0-5.4 3-8.6 3-3.4 8.3-3.3 2 0 3.7.6 1.8.6 3.3 1.8 1.4 1 2.2 2.7 1 1.5 1.6 3.3 11.8-8.4 27-8.4 10.6 0 21 5 11.3 5.4 17.2 14.5 2.5 3.7 2.5 7.3z" /> d="M588.7 66.5q0 5-3.5 8.5-3.5 3.4-8.1 3.5-4.4 0-8.3-4.3-10-10.7-20.9-10.6-2.2 0-4.3.3-2.1.3-4 1-1.8.6-3.7 1.6-1.7 1-3.4 2.3-1.7 1.3-3.3 2.9-7.8 8.2-7.6 19.7V131q0 5.5-3.1 8.6-3 3.4-8.3 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V51.6q0-5.4 3-8.6 3-3.4 8.3-3.3 2 0 3.7.6 1.8.6 3.3 1.8 1.4 1 2.2 2.7 1 1.5 1.6 3.3 11.8-8.4 27-8.4 10.6 0 21 5 11.3 5.4 17.2 14.5 2.5 3.7 2.5 7.3z"></path>
<path id="header-h" <path id="header-h"
d="M483.9 131.1q0 5.5-3.1 8.6-3 3.4-8.3 3.3-5.2 0-8.2-3.3-3.2-3.1-3.1-8.6V84.8q0-4.6-1.5-8.2-1.4-3.5-4.4-6.9-2.1-2-4.3-3.4-2.2-1.4-4.7-2-2.4-.7-5.3-.7-4.3 0-7.8 1.5-3.3 1.5-6.4 4.6-5.9 6.3-5.8 15v46.4q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v33q1.5-1 3-1.6l3.2-1.2 3.4-1q1.6-.5 3.3-.8l3.5-.4 3.6-.2q4.4 0 8.5 1 4.1.7 7.9 2.4 3.8 1.6 7.3 4.1 3.5 2.5 6.6 5.8Q484 66 484 84.8z" /> d="M483.9 131.1q0 5.5-3.1 8.6-3 3.4-8.3 3.3-5.2 0-8.2-3.3-3.2-3.1-3.1-8.6V84.8q0-4.6-1.5-8.2-1.4-3.5-4.4-6.9-2.1-2-4.3-3.4-2.2-1.4-4.7-2-2.4-.7-5.3-.7-4.3 0-7.8 1.5-3.3 1.5-6.4 4.6-5.9 6.3-5.8 15v46.4q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v33q1.5-1 3-1.6l3.2-1.2 3.4-1q1.6-.5 3.3-.8l3.5-.4 3.6-.2q4.4 0 8.5 1 4.1.7 7.9 2.4 3.8 1.6 7.3 4.1 3.5 2.5 6.6 5.8Q484 66 484 84.8z"></path>
<path id="header-e" <path id="header-e"
d="M387.5 111.1q0 1.2-.3 2.3-.1 1-.5 2l-.9 2q-6.6 12-19.4 19-12 6.6-25.4 6.6-20.8 0-35.8-14.6-15.9-15-15.9-37 0-22.1 15.9-37.1 15-14.6 35.8-14.6 3.9 0 7.8.7 4 .7 8 2.2 9.2 3.1 18.2 10 6 4.6 9.1 9.3 3.3 4.7 3.3 10 0 1.3-.3 2.5-.2 1.3-.7 2.4-1.5 3.4-5 5.3l-56.9 32.2q7.2 4.9 16.5 4.9 7.2 0 12.6-2.5 5.5-2.5 9.7-7.4l.7-1 .8-1 .9-1.3 1-1.5q3.3-4.2 7.4-5.1l1.8-.2q4.4 0 8 3.4 3.6 3.5 3.6 8.5zm-29.9-42.7q-7.2-4.8-16.6-4.8-6 0-11 2-4.9 1.8-9.3 6-4.5 4-6.7 9-2 4.8-2 10.8l.1 2.9z" /> d="M387.5 111.1q0 1.2-.3 2.3-.1 1-.5 2l-.9 2q-6.6 12-19.4 19-12 6.6-25.4 6.6-20.8 0-35.8-14.6-15.9-15-15.9-37 0-22.1 15.9-37.1 15-14.6 35.8-14.6 3.9 0 7.8.7 4 .7 8 2.2 9.2 3.1 18.2 10 6 4.6 9.1 9.3 3.3 4.7 3.3 10 0 1.3-.3 2.5-.2 1.3-.7 2.4-1.5 3.4-5 5.3l-56.9 32.2q7.2 4.9 16.5 4.9 7.2 0 12.6-2.5 5.5-2.5 9.7-7.4l.7-1 .8-1 .9-1.3 1-1.5q3.3-4.2 7.4-5.1l1.8-.2q4.4 0 8 3.4 3.6 3.5 3.6 8.5zm-29.9-42.7q-7.2-4.8-16.6-4.8-6 0-11 2-4.9 1.8-9.3 6-4.5 4-6.7 9-2 4.8-2 10.8l.1 2.9z"></path>
<path id="header-o" <path id="header-o"
d="M286.8 91.4q0 4.2-.6 8.3-.6 4-1.8 7.7-1.1 3.8-2.9 7.4-1.7 3.5-4 6.9-2.4 3.3-5.2 6.1Q258 143 237.7 143T203 128q-14.3-15.2-14.3-36.6 0-21.5 14.3-36.6 14.4-15 34.7-15 4 0 7.8.5 3.9.7 7.5 1.9t7 3q3.3 1.9 6.4 4.3 3.2 2.4 5.9 5.4 14.4 15 14.5 36.5zm-22.6 0q0-2.4-.4-4.5-.2-2.2-.9-4.2-.6-2-1.5-3.9-1-2-2.2-3.7-1.2-1.7-2.8-3.4-4-4.2-8.6-6.1-4.5-2-10-2-11 0-18.7 8.2-7.8 8-7.8 19.6 0 11.4 7.8 19.7 7.8 8 18.6 8 5.6 0 10.1-1.9 4.6-2 8.6-6.1 4-4.3 5.8-9 2-4.9 2-10.7z" /> d="M286.8 91.4q0 4.2-.6 8.3-.6 4-1.8 7.7-1.1 3.8-2.9 7.4-1.7 3.5-4 6.9-2.4 3.3-5.2 6.1Q258 143 237.7 143T203 128q-14.3-15.2-14.3-36.6 0-21.5 14.3-36.6 14.4-15 34.7-15 4 0 7.8.5 3.9.7 7.5 1.9t7 3q3.3 1.9 6.4 4.3 3.2 2.4 5.9 5.4 14.4 15 14.5 36.5zm-22.6 0q0-2.4-.4-4.5-.2-2.2-.9-4.2-.6-2-1.5-3.9-1-2-2.2-3.7-1.2-1.7-2.8-3.4-4-4.2-8.6-6.1-4.5-2-10-2-11 0-18.7 8.2-7.8 8-7.8 19.6 0 11.4 7.8 19.7 7.8 8 18.6 8 5.6 0 10.1-1.9 4.6-2 8.6-6.1 4-4.3 5.8-9 2-4.9 2-10.7z"></path>
<path id="header-k" <path id="header-k"
d="M186.3 131q0 4.7-3.3 8.3-1.5 1.8-3.7 2.7-2 1.1-4.3 1.1-3.5 0-6.6-2L119.2 105v26q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v65.9l49.2-36.1q3.2-2 6.6-2 4.7 0 8 3.7t3.3 8.4q-.2 6-5 9.6l-41 30 41 29.9q2.3 1.7 3.6 4.2 1.4 2.5 1.4 5.4z" /> d="M186.3 131q0 4.7-3.3 8.3-1.5 1.8-3.7 2.7-2 1.1-4.3 1.1-3.5 0-6.6-2L119.2 105v26q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v65.9l49.2-36.1q3.2-2 6.6-2 4.7 0 8 3.7t3.3 8.4q-.2 6-5 9.6l-41 30 41 29.9q2.3 1.7 3.6 4.2 1.4 2.5 1.4 5.4z"></path>
<path id="header-tilde" <path id="header-tilde"
d="M73.1 91q0 2-.6 3.9T71 98.6q-3.2 5.7-8.9 8.5-5.6 2.8-12.9 2.8-8.8 0-18-7.8-2.4-2.3-4.5-3.7-2.1-1.5-3-1.7-1.5 0-2.1.3l-.8 1.3q-.3.7-.8 1.2l-1 1-.9.8q-2.7 2-6.4 2-1.7 0-3.2-.3-1.4-.3-3-1.1-1.5-.8-2.6-2.1-2.8-3.1-2.8-8v-1.3q0-.7.2-1.2l.2-1 .4-1 .4-1q.1-.6.5-1.1l.5-1q3.2-5.7 8.8-8.5 5.7-2.9 13-2.9 3.2 0 6.2 1 3 .9 6 2.7 2.9 1.6 5.7 4.2 5.2 4.6 7.6 5.4 1 0 1.6-.2l.7-.4q.3-.1.5-.4 3.6-5.6 9.2-5.6 5.7 0 8.8 3.5 2.8 3 2.8 8z" /> d="M73.1 91q0 2-.6 3.9T71 98.6q-3.2 5.7-8.9 8.5-5.6 2.8-12.9 2.8-8.8 0-18-7.8-2.4-2.3-4.5-3.7-2.1-1.5-3-1.7-1.5 0-2.1.3l-.8 1.3q-.3.7-.8 1.2l-1 1-.9.8q-2.7 2-6.4 2-1.7 0-3.2-.3-1.4-.3-3-1.1-1.5-.8-2.6-2.1-2.8-3.1-2.8-8v-1.3q0-.7.2-1.2l.2-1 .4-1 .4-1q.1-.6.5-1.1l.5-1q3.2-5.7 8.8-8.5 5.7-2.9 13-2.9 3.2 0 6.2 1 3 .9 6 2.7 2.9 1.6 5.7 4.2 5.2 4.6 7.6 5.4 1 0 1.6-.2l.7-.4q.3-.1.5-.4 3.6-5.6 9.2-5.6 5.7 0 8.8 3.5 2.8 3 2.8 8z"></path>
</svg> </svg>
Homepage of Homepage of
<div class=p-name> <div class=p-name>

View file

@ -3,7 +3,7 @@
<head id="head"> <head id="head">
<meta charset=utf-8> <meta charset=utf-8>
<title id=title >the codeartist — programmer and engineer based in BerlinBush refused offer to discuss Osama Bin Laden handover</title> <title id="title " var="the codeartist — programmer and engineer based in Berlin"></title>
<meta name=description content="The personal page and weblog of Norman Köhring"> <meta name=description content="The personal page and weblog of Norman Köhring">
<meta name=author content="Norman Köhring"> <meta name=author content="Norman Köhring">
<meta name=DC.title content="the codeartist — programmer and engineer based in Berlin"> <meta name=DC.title content="the codeartist — programmer and engineer based in Berlin">
@ -15,8 +15,8 @@
<meta name="og:title" content="Bush refused offer to discuss Osama Bin Laden handover // the codeartist"> <meta name="og:title" content="Bush refused offer to discuss Osama Bin Laden handover // the codeartist">
<meta property="og:type" content="website"> <meta property="og:type" content="website">
<meta http-equiv="x-ua-compatible" content="ie=edge"/> <meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"/> <meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no">
<meta name=ICBM content="52.4595, 13.5335"> <meta name=ICBM content="52.4595, 13.5335">
<meta name=geo.position content="52.4595; 13.5335"> <meta name=geo.position content="52.4595; 13.5335">
@ -26,7 +26,7 @@
<link rel=me href=https://k0r.in> <link rel=me href=https://k0r.in>
<link rel=me href=https://koehr.ing> <link rel=me href=https://koehr.ing>
<link rel=me href=@Koehr@mstdn.io> <link rel=me href=@Koehr@mstdn.io>
<link rel=me href=https://sr.ht/~koehr/> <link rel=me href=https://sr.ht/~koehr>
<link rel=me href=https://git.k0r.in> <link rel=me href=https://git.k0r.in>
<link rel=me href=https://threads.net/@coffee_n_code> <link rel=me href=https://threads.net/@coffee_n_code>
<link rel=me href=https://instagram.com/@coffee_n_code> <link rel=me href=https://instagram.com/@coffee_n_code>
@ -49,10 +49,10 @@
<main id="main"> <main id="main">
<header> <header>
<h1 >Bush refused offer to discuss Osama Bin Laden handover</h1> <h1 :title="Bush refused offer to discuss Osama Bin Laden handover"></h1>
<em ></em> <em :title=""></em>
<br/> <br>
Last updated: <time datetime="Fri, 03 Sep 2021 00:00:00 +0000" >September 03, 2021</time> Last updated: <time datetime="Fri, 03 Sep 2021 00:00:00 +0000" :title="September 03, 2021"></time>
</header> </header>
<div></div> <div></div>
@ -68,21 +68,21 @@
<a href="/"> <a href="/">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 832.4 143.1"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 832.4 143.1">
<path id="header-underscore" <path id="header-underscore"
d="M832.4 131.1q0 5.5-3.1 8.6-3 3.4-8.2 3.3h-75.5q-5.2 0-8.2-3.3-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8 0-5.5 3.1-8.7 1.6-1.7 3.7-2.4 2.2-.8 4.5-.8h75.5q5.2 0 8.2 3.2 3 3.1 3 8.7z" /> d="M832.4 131.1q0 5.5-3.1 8.6-3 3.4-8.2 3.3h-75.5q-5.2 0-8.2-3.3-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8 0-5.5 3.1-8.7 1.6-1.7 3.7-2.4 2.2-.8 4.5-.8h75.5q5.2 0 8.2 3.2 3 3.1 3 8.7z"></path>
<path id="header-bracket" <path id="header-bracket"
d="M731.9 81.4q0 6.7-6.5 10.7l-1 .6-74.3 39.2q-2.5 1.3-5.2 1.2-4.8 0-8.1-3.8-3.2-3.6-3.2-8.4 0-3.3 1.7-6 1.8-2.9 4.6-4.4l55.3-29.1-55.3-29q-2.8-1.6-4.6-4.3-1.7-2.7-1.7-6.2 0-4.7 3.2-8.4 3.3-4 8-3.7 2.7 0 5.3 1.2l74.4 39.2q3.3 1.7 5.3 4.7 2 2.8 2 6.5z" /> d="M731.9 81.4q0 6.7-6.5 10.7l-1 .6-74.3 39.2q-2.5 1.3-5.2 1.2-4.8 0-8.1-3.8-3.2-3.6-3.2-8.4 0-3.3 1.7-6 1.8-2.9 4.6-4.4l55.3-29.1-55.3-29q-2.8-1.6-4.6-4.3-1.7-2.7-1.7-6.2 0-4.7 3.2-8.4 3.3-4 8-3.7 2.7 0 5.3 1.2l74.4 39.2q3.3 1.7 5.3 4.7 2 2.8 2 6.5z"></path>
<path id="header-r" <path id="header-r"
d="M588.7 66.5q0 5-3.5 8.5-3.5 3.4-8.1 3.5-4.4 0-8.3-4.3-10-10.7-20.9-10.6-2.2 0-4.3.3-2.1.3-4 1-1.8.6-3.7 1.6-1.7 1-3.4 2.3-1.7 1.3-3.3 2.9-7.8 8.2-7.6 19.7V131q0 5.5-3.1 8.6-3 3.4-8.3 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V51.6q0-5.4 3-8.6 3-3.4 8.3-3.3 2 0 3.7.6 1.8.6 3.3 1.8 1.4 1 2.2 2.7 1 1.5 1.6 3.3 11.8-8.4 27-8.4 10.6 0 21 5 11.3 5.4 17.2 14.5 2.5 3.7 2.5 7.3z" /> d="M588.7 66.5q0 5-3.5 8.5-3.5 3.4-8.1 3.5-4.4 0-8.3-4.3-10-10.7-20.9-10.6-2.2 0-4.3.3-2.1.3-4 1-1.8.6-3.7 1.6-1.7 1-3.4 2.3-1.7 1.3-3.3 2.9-7.8 8.2-7.6 19.7V131q0 5.5-3.1 8.6-3 3.4-8.3 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V51.6q0-5.4 3-8.6 3-3.4 8.3-3.3 2 0 3.7.6 1.8.6 3.3 1.8 1.4 1 2.2 2.7 1 1.5 1.6 3.3 11.8-8.4 27-8.4 10.6 0 21 5 11.3 5.4 17.2 14.5 2.5 3.7 2.5 7.3z"></path>
<path id="header-h" <path id="header-h"
d="M483.9 131.1q0 5.5-3.1 8.6-3 3.4-8.3 3.3-5.2 0-8.2-3.3-3.2-3.1-3.1-8.6V84.8q0-4.6-1.5-8.2-1.4-3.5-4.4-6.9-2.1-2-4.3-3.4-2.2-1.4-4.7-2-2.4-.7-5.3-.7-4.3 0-7.8 1.5-3.3 1.5-6.4 4.6-5.9 6.3-5.8 15v46.4q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v33q1.5-1 3-1.6l3.2-1.2 3.4-1q1.6-.5 3.3-.8l3.5-.4 3.6-.2q4.4 0 8.5 1 4.1.7 7.9 2.4 3.8 1.6 7.3 4.1 3.5 2.5 6.6 5.8Q484 66 484 84.8z" /> d="M483.9 131.1q0 5.5-3.1 8.6-3 3.4-8.3 3.3-5.2 0-8.2-3.3-3.2-3.1-3.1-8.6V84.8q0-4.6-1.5-8.2-1.4-3.5-4.4-6.9-2.1-2-4.3-3.4-2.2-1.4-4.7-2-2.4-.7-5.3-.7-4.3 0-7.8 1.5-3.3 1.5-6.4 4.6-5.9 6.3-5.8 15v46.4q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v33q1.5-1 3-1.6l3.2-1.2 3.4-1q1.6-.5 3.3-.8l3.5-.4 3.6-.2q4.4 0 8.5 1 4.1.7 7.9 2.4 3.8 1.6 7.3 4.1 3.5 2.5 6.6 5.8Q484 66 484 84.8z"></path>
<path id="header-e" <path id="header-e"
d="M387.5 111.1q0 1.2-.3 2.3-.1 1-.5 2l-.9 2q-6.6 12-19.4 19-12 6.6-25.4 6.6-20.8 0-35.8-14.6-15.9-15-15.9-37 0-22.1 15.9-37.1 15-14.6 35.8-14.6 3.9 0 7.8.7 4 .7 8 2.2 9.2 3.1 18.2 10 6 4.6 9.1 9.3 3.3 4.7 3.3 10 0 1.3-.3 2.5-.2 1.3-.7 2.4-1.5 3.4-5 5.3l-56.9 32.2q7.2 4.9 16.5 4.9 7.2 0 12.6-2.5 5.5-2.5 9.7-7.4l.7-1 .8-1 .9-1.3 1-1.5q3.3-4.2 7.4-5.1l1.8-.2q4.4 0 8 3.4 3.6 3.5 3.6 8.5zm-29.9-42.7q-7.2-4.8-16.6-4.8-6 0-11 2-4.9 1.8-9.3 6-4.5 4-6.7 9-2 4.8-2 10.8l.1 2.9z" /> d="M387.5 111.1q0 1.2-.3 2.3-.1 1-.5 2l-.9 2q-6.6 12-19.4 19-12 6.6-25.4 6.6-20.8 0-35.8-14.6-15.9-15-15.9-37 0-22.1 15.9-37.1 15-14.6 35.8-14.6 3.9 0 7.8.7 4 .7 8 2.2 9.2 3.1 18.2 10 6 4.6 9.1 9.3 3.3 4.7 3.3 10 0 1.3-.3 2.5-.2 1.3-.7 2.4-1.5 3.4-5 5.3l-56.9 32.2q7.2 4.9 16.5 4.9 7.2 0 12.6-2.5 5.5-2.5 9.7-7.4l.7-1 .8-1 .9-1.3 1-1.5q3.3-4.2 7.4-5.1l1.8-.2q4.4 0 8 3.4 3.6 3.5 3.6 8.5zm-29.9-42.7q-7.2-4.8-16.6-4.8-6 0-11 2-4.9 1.8-9.3 6-4.5 4-6.7 9-2 4.8-2 10.8l.1 2.9z"></path>
<path id="header-o" <path id="header-o"
d="M286.8 91.4q0 4.2-.6 8.3-.6 4-1.8 7.7-1.1 3.8-2.9 7.4-1.7 3.5-4 6.9-2.4 3.3-5.2 6.1Q258 143 237.7 143T203 128q-14.3-15.2-14.3-36.6 0-21.5 14.3-36.6 14.4-15 34.7-15 4 0 7.8.5 3.9.7 7.5 1.9t7 3q3.3 1.9 6.4 4.3 3.2 2.4 5.9 5.4 14.4 15 14.5 36.5zm-22.6 0q0-2.4-.4-4.5-.2-2.2-.9-4.2-.6-2-1.5-3.9-1-2-2.2-3.7-1.2-1.7-2.8-3.4-4-4.2-8.6-6.1-4.5-2-10-2-11 0-18.7 8.2-7.8 8-7.8 19.6 0 11.4 7.8 19.7 7.8 8 18.6 8 5.6 0 10.1-1.9 4.6-2 8.6-6.1 4-4.3 5.8-9 2-4.9 2-10.7z" /> d="M286.8 91.4q0 4.2-.6 8.3-.6 4-1.8 7.7-1.1 3.8-2.9 7.4-1.7 3.5-4 6.9-2.4 3.3-5.2 6.1Q258 143 237.7 143T203 128q-14.3-15.2-14.3-36.6 0-21.5 14.3-36.6 14.4-15 34.7-15 4 0 7.8.5 3.9.7 7.5 1.9t7 3q3.3 1.9 6.4 4.3 3.2 2.4 5.9 5.4 14.4 15 14.5 36.5zm-22.6 0q0-2.4-.4-4.5-.2-2.2-.9-4.2-.6-2-1.5-3.9-1-2-2.2-3.7-1.2-1.7-2.8-3.4-4-4.2-8.6-6.1-4.5-2-10-2-11 0-18.7 8.2-7.8 8-7.8 19.6 0 11.4 7.8 19.7 7.8 8 18.6 8 5.6 0 10.1-1.9 4.6-2 8.6-6.1 4-4.3 5.8-9 2-4.9 2-10.7z"></path>
<path id="header-k" <path id="header-k"
d="M186.3 131q0 4.7-3.3 8.3-1.5 1.8-3.7 2.7-2 1.1-4.3 1.1-3.5 0-6.6-2L119.2 105v26q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v65.9l49.2-36.1q3.2-2 6.6-2 4.7 0 8 3.7t3.3 8.4q-.2 6-5 9.6l-41 30 41 29.9q2.3 1.7 3.6 4.2 1.4 2.5 1.4 5.4z" /> d="M186.3 131q0 4.7-3.3 8.3-1.5 1.8-3.7 2.7-2 1.1-4.3 1.1-3.5 0-6.6-2L119.2 105v26q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v65.9l49.2-36.1q3.2-2 6.6-2 4.7 0 8 3.7t3.3 8.4q-.2 6-5 9.6l-41 30 41 29.9q2.3 1.7 3.6 4.2 1.4 2.5 1.4 5.4z"></path>
<path id="header-tilde" <path id="header-tilde"
d="M73.1 91q0 2-.6 3.9T71 98.6q-3.2 5.7-8.9 8.5-5.6 2.8-12.9 2.8-8.8 0-18-7.8-2.4-2.3-4.5-3.7-2.1-1.5-3-1.7-1.5 0-2.1.3l-.8 1.3q-.3.7-.8 1.2l-1 1-.9.8q-2.7 2-6.4 2-1.7 0-3.2-.3-1.4-.3-3-1.1-1.5-.8-2.6-2.1-2.8-3.1-2.8-8v-1.3q0-.7.2-1.2l.2-1 .4-1 .4-1q.1-.6.5-1.1l.5-1q3.2-5.7 8.8-8.5 5.7-2.9 13-2.9 3.2 0 6.2 1 3 .9 6 2.7 2.9 1.6 5.7 4.2 5.2 4.6 7.6 5.4 1 0 1.6-.2l.7-.4q.3-.1.5-.4 3.6-5.6 9.2-5.6 5.7 0 8.8 3.5 2.8 3 2.8 8z" /> d="M73.1 91q0 2-.6 3.9T71 98.6q-3.2 5.7-8.9 8.5-5.6 2.8-12.9 2.8-8.8 0-18-7.8-2.4-2.3-4.5-3.7-2.1-1.5-3-1.7-1.5 0-2.1.3l-.8 1.3q-.3.7-.8 1.2l-1 1-.9.8q-2.7 2-6.4 2-1.7 0-3.2-.3-1.4-.3-3-1.1-1.5-.8-2.6-2.1-2.8-3.1-2.8-8v-1.3q0-.7.2-1.2l.2-1 .4-1 .4-1q.1-.6.5-1.1l.5-1q3.2-5.7 8.8-8.5 5.7-2.9 13-2.9 3.2 0 6.2 1 3 .9 6 2.7 2.9 1.6 5.7 4.2 5.2 4.6 7.6 5.4 1 0 1.6-.2l.7-.4q.3-.1.5-.4 3.6-5.6 9.2-5.6 5.7 0 8.8 3.5 2.8 3 2.8 8z"></path>
</svg> </svg>
Homepage of Homepage of
<div class=p-name> <div class=p-name>

View file

@ -3,7 +3,7 @@
<head id="head"> <head id="head">
<meta charset=utf-8> <meta charset=utf-8>
<title id=title >the codeartist — programmer and engineer based in Berlingit fetch repo_url remote_branch:new_local_branch</title> <title id="title " var="the codeartist — programmer and engineer based in Berlin"></title>
<meta name=description content="The personal page and weblog of Norman Köhring"> <meta name=description content="The personal page and weblog of Norman Köhring">
<meta name=author content="Norman Köhring"> <meta name=author content="Norman Köhring">
<meta name=DC.title content="the codeartist — programmer and engineer based in Berlin"> <meta name=DC.title content="the codeartist — programmer and engineer based in Berlin">
@ -15,8 +15,8 @@
<meta name="og:title" content="git fetch repo_url remote_branch:new_local_branch // the codeartist"> <meta name="og:title" content="git fetch repo_url remote_branch:new_local_branch // the codeartist">
<meta property="og:type" content="website"> <meta property="og:type" content="website">
<meta http-equiv="x-ua-compatible" content="ie=edge"/> <meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"/> <meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no">
<meta name=ICBM content="52.4595, 13.5335"> <meta name=ICBM content="52.4595, 13.5335">
<meta name=geo.position content="52.4595; 13.5335"> <meta name=geo.position content="52.4595; 13.5335">
@ -26,7 +26,7 @@
<link rel=me href=https://k0r.in> <link rel=me href=https://k0r.in>
<link rel=me href=https://koehr.ing> <link rel=me href=https://koehr.ing>
<link rel=me href=@Koehr@mstdn.io> <link rel=me href=@Koehr@mstdn.io>
<link rel=me href=https://sr.ht/~koehr/> <link rel=me href=https://sr.ht/~koehr>
<link rel=me href=https://git.k0r.in> <link rel=me href=https://git.k0r.in>
<link rel=me href=https://threads.net/@coffee_n_code> <link rel=me href=https://threads.net/@coffee_n_code>
<link rel=me href=https://instagram.com/@coffee_n_code> <link rel=me href=https://instagram.com/@coffee_n_code>
@ -49,10 +49,10 @@
<main id="main"> <main id="main">
<header> <header>
<h1 >git fetch repo_url remote_branch:new_local_branch</h1> <h1 :title="git fetch repo_url remote_branch:new_local_branch"></h1>
<em ></em> <em :title=""></em>
<br/> <br>
Last updated: <time datetime="Sat, 04 Sep 2021 00:00:00 +0000" >September 04, 2021</time> Last updated: <time datetime="Sat, 04 Sep 2021 00:00:00 +0000" :title="September 04, 2021"></time>
</header> </header>
<div><p><code>git fetch $repo_url $remote_branch:$new_local_branch</code></p></div> <div><p><code>git fetch $repo_url $remote_branch:$new_local_branch</code></p></div>
@ -68,21 +68,21 @@
<a href="/"> <a href="/">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 832.4 143.1"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 832.4 143.1">
<path id="header-underscore" <path id="header-underscore"
d="M832.4 131.1q0 5.5-3.1 8.6-3 3.4-8.2 3.3h-75.5q-5.2 0-8.2-3.3-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8 0-5.5 3.1-8.7 1.6-1.7 3.7-2.4 2.2-.8 4.5-.8h75.5q5.2 0 8.2 3.2 3 3.1 3 8.7z" /> d="M832.4 131.1q0 5.5-3.1 8.6-3 3.4-8.2 3.3h-75.5q-5.2 0-8.2-3.3-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8 0-5.5 3.1-8.7 1.6-1.7 3.7-2.4 2.2-.8 4.5-.8h75.5q5.2 0 8.2 3.2 3 3.1 3 8.7z"></path>
<path id="header-bracket" <path id="header-bracket"
d="M731.9 81.4q0 6.7-6.5 10.7l-1 .6-74.3 39.2q-2.5 1.3-5.2 1.2-4.8 0-8.1-3.8-3.2-3.6-3.2-8.4 0-3.3 1.7-6 1.8-2.9 4.6-4.4l55.3-29.1-55.3-29q-2.8-1.6-4.6-4.3-1.7-2.7-1.7-6.2 0-4.7 3.2-8.4 3.3-4 8-3.7 2.7 0 5.3 1.2l74.4 39.2q3.3 1.7 5.3 4.7 2 2.8 2 6.5z" /> d="M731.9 81.4q0 6.7-6.5 10.7l-1 .6-74.3 39.2q-2.5 1.3-5.2 1.2-4.8 0-8.1-3.8-3.2-3.6-3.2-8.4 0-3.3 1.7-6 1.8-2.9 4.6-4.4l55.3-29.1-55.3-29q-2.8-1.6-4.6-4.3-1.7-2.7-1.7-6.2 0-4.7 3.2-8.4 3.3-4 8-3.7 2.7 0 5.3 1.2l74.4 39.2q3.3 1.7 5.3 4.7 2 2.8 2 6.5z"></path>
<path id="header-r" <path id="header-r"
d="M588.7 66.5q0 5-3.5 8.5-3.5 3.4-8.1 3.5-4.4 0-8.3-4.3-10-10.7-20.9-10.6-2.2 0-4.3.3-2.1.3-4 1-1.8.6-3.7 1.6-1.7 1-3.4 2.3-1.7 1.3-3.3 2.9-7.8 8.2-7.6 19.7V131q0 5.5-3.1 8.6-3 3.4-8.3 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V51.6q0-5.4 3-8.6 3-3.4 8.3-3.3 2 0 3.7.6 1.8.6 3.3 1.8 1.4 1 2.2 2.7 1 1.5 1.6 3.3 11.8-8.4 27-8.4 10.6 0 21 5 11.3 5.4 17.2 14.5 2.5 3.7 2.5 7.3z" /> d="M588.7 66.5q0 5-3.5 8.5-3.5 3.4-8.1 3.5-4.4 0-8.3-4.3-10-10.7-20.9-10.6-2.2 0-4.3.3-2.1.3-4 1-1.8.6-3.7 1.6-1.7 1-3.4 2.3-1.7 1.3-3.3 2.9-7.8 8.2-7.6 19.7V131q0 5.5-3.1 8.6-3 3.4-8.3 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V51.6q0-5.4 3-8.6 3-3.4 8.3-3.3 2 0 3.7.6 1.8.6 3.3 1.8 1.4 1 2.2 2.7 1 1.5 1.6 3.3 11.8-8.4 27-8.4 10.6 0 21 5 11.3 5.4 17.2 14.5 2.5 3.7 2.5 7.3z"></path>
<path id="header-h" <path id="header-h"
d="M483.9 131.1q0 5.5-3.1 8.6-3 3.4-8.3 3.3-5.2 0-8.2-3.3-3.2-3.1-3.1-8.6V84.8q0-4.6-1.5-8.2-1.4-3.5-4.4-6.9-2.1-2-4.3-3.4-2.2-1.4-4.7-2-2.4-.7-5.3-.7-4.3 0-7.8 1.5-3.3 1.5-6.4 4.6-5.9 6.3-5.8 15v46.4q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v33q1.5-1 3-1.6l3.2-1.2 3.4-1q1.6-.5 3.3-.8l3.5-.4 3.6-.2q4.4 0 8.5 1 4.1.7 7.9 2.4 3.8 1.6 7.3 4.1 3.5 2.5 6.6 5.8Q484 66 484 84.8z" /> d="M483.9 131.1q0 5.5-3.1 8.6-3 3.4-8.3 3.3-5.2 0-8.2-3.3-3.2-3.1-3.1-8.6V84.8q0-4.6-1.5-8.2-1.4-3.5-4.4-6.9-2.1-2-4.3-3.4-2.2-1.4-4.7-2-2.4-.7-5.3-.7-4.3 0-7.8 1.5-3.3 1.5-6.4 4.6-5.9 6.3-5.8 15v46.4q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v33q1.5-1 3-1.6l3.2-1.2 3.4-1q1.6-.5 3.3-.8l3.5-.4 3.6-.2q4.4 0 8.5 1 4.1.7 7.9 2.4 3.8 1.6 7.3 4.1 3.5 2.5 6.6 5.8Q484 66 484 84.8z"></path>
<path id="header-e" <path id="header-e"
d="M387.5 111.1q0 1.2-.3 2.3-.1 1-.5 2l-.9 2q-6.6 12-19.4 19-12 6.6-25.4 6.6-20.8 0-35.8-14.6-15.9-15-15.9-37 0-22.1 15.9-37.1 15-14.6 35.8-14.6 3.9 0 7.8.7 4 .7 8 2.2 9.2 3.1 18.2 10 6 4.6 9.1 9.3 3.3 4.7 3.3 10 0 1.3-.3 2.5-.2 1.3-.7 2.4-1.5 3.4-5 5.3l-56.9 32.2q7.2 4.9 16.5 4.9 7.2 0 12.6-2.5 5.5-2.5 9.7-7.4l.7-1 .8-1 .9-1.3 1-1.5q3.3-4.2 7.4-5.1l1.8-.2q4.4 0 8 3.4 3.6 3.5 3.6 8.5zm-29.9-42.7q-7.2-4.8-16.6-4.8-6 0-11 2-4.9 1.8-9.3 6-4.5 4-6.7 9-2 4.8-2 10.8l.1 2.9z" /> d="M387.5 111.1q0 1.2-.3 2.3-.1 1-.5 2l-.9 2q-6.6 12-19.4 19-12 6.6-25.4 6.6-20.8 0-35.8-14.6-15.9-15-15.9-37 0-22.1 15.9-37.1 15-14.6 35.8-14.6 3.9 0 7.8.7 4 .7 8 2.2 9.2 3.1 18.2 10 6 4.6 9.1 9.3 3.3 4.7 3.3 10 0 1.3-.3 2.5-.2 1.3-.7 2.4-1.5 3.4-5 5.3l-56.9 32.2q7.2 4.9 16.5 4.9 7.2 0 12.6-2.5 5.5-2.5 9.7-7.4l.7-1 .8-1 .9-1.3 1-1.5q3.3-4.2 7.4-5.1l1.8-.2q4.4 0 8 3.4 3.6 3.5 3.6 8.5zm-29.9-42.7q-7.2-4.8-16.6-4.8-6 0-11 2-4.9 1.8-9.3 6-4.5 4-6.7 9-2 4.8-2 10.8l.1 2.9z"></path>
<path id="header-o" <path id="header-o"
d="M286.8 91.4q0 4.2-.6 8.3-.6 4-1.8 7.7-1.1 3.8-2.9 7.4-1.7 3.5-4 6.9-2.4 3.3-5.2 6.1Q258 143 237.7 143T203 128q-14.3-15.2-14.3-36.6 0-21.5 14.3-36.6 14.4-15 34.7-15 4 0 7.8.5 3.9.7 7.5 1.9t7 3q3.3 1.9 6.4 4.3 3.2 2.4 5.9 5.4 14.4 15 14.5 36.5zm-22.6 0q0-2.4-.4-4.5-.2-2.2-.9-4.2-.6-2-1.5-3.9-1-2-2.2-3.7-1.2-1.7-2.8-3.4-4-4.2-8.6-6.1-4.5-2-10-2-11 0-18.7 8.2-7.8 8-7.8 19.6 0 11.4 7.8 19.7 7.8 8 18.6 8 5.6 0 10.1-1.9 4.6-2 8.6-6.1 4-4.3 5.8-9 2-4.9 2-10.7z" /> d="M286.8 91.4q0 4.2-.6 8.3-.6 4-1.8 7.7-1.1 3.8-2.9 7.4-1.7 3.5-4 6.9-2.4 3.3-5.2 6.1Q258 143 237.7 143T203 128q-14.3-15.2-14.3-36.6 0-21.5 14.3-36.6 14.4-15 34.7-15 4 0 7.8.5 3.9.7 7.5 1.9t7 3q3.3 1.9 6.4 4.3 3.2 2.4 5.9 5.4 14.4 15 14.5 36.5zm-22.6 0q0-2.4-.4-4.5-.2-2.2-.9-4.2-.6-2-1.5-3.9-1-2-2.2-3.7-1.2-1.7-2.8-3.4-4-4.2-8.6-6.1-4.5-2-10-2-11 0-18.7 8.2-7.8 8-7.8 19.6 0 11.4 7.8 19.7 7.8 8 18.6 8 5.6 0 10.1-1.9 4.6-2 8.6-6.1 4-4.3 5.8-9 2-4.9 2-10.7z"></path>
<path id="header-k" <path id="header-k"
d="M186.3 131q0 4.7-3.3 8.3-1.5 1.8-3.7 2.7-2 1.1-4.3 1.1-3.5 0-6.6-2L119.2 105v26q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v65.9l49.2-36.1q3.2-2 6.6-2 4.7 0 8 3.7t3.3 8.4q-.2 6-5 9.6l-41 30 41 29.9q2.3 1.7 3.6 4.2 1.4 2.5 1.4 5.4z" /> d="M186.3 131q0 4.7-3.3 8.3-1.5 1.8-3.7 2.7-2 1.1-4.3 1.1-3.5 0-6.6-2L119.2 105v26q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v65.9l49.2-36.1q3.2-2 6.6-2 4.7 0 8 3.7t3.3 8.4q-.2 6-5 9.6l-41 30 41 29.9q2.3 1.7 3.6 4.2 1.4 2.5 1.4 5.4z"></path>
<path id="header-tilde" <path id="header-tilde"
d="M73.1 91q0 2-.6 3.9T71 98.6q-3.2 5.7-8.9 8.5-5.6 2.8-12.9 2.8-8.8 0-18-7.8-2.4-2.3-4.5-3.7-2.1-1.5-3-1.7-1.5 0-2.1.3l-.8 1.3q-.3.7-.8 1.2l-1 1-.9.8q-2.7 2-6.4 2-1.7 0-3.2-.3-1.4-.3-3-1.1-1.5-.8-2.6-2.1-2.8-3.1-2.8-8v-1.3q0-.7.2-1.2l.2-1 .4-1 .4-1q.1-.6.5-1.1l.5-1q3.2-5.7 8.8-8.5 5.7-2.9 13-2.9 3.2 0 6.2 1 3 .9 6 2.7 2.9 1.6 5.7 4.2 5.2 4.6 7.6 5.4 1 0 1.6-.2l.7-.4q.3-.1.5-.4 3.6-5.6 9.2-5.6 5.7 0 8.8 3.5 2.8 3 2.8 8z" /> d="M73.1 91q0 2-.6 3.9T71 98.6q-3.2 5.7-8.9 8.5-5.6 2.8-12.9 2.8-8.8 0-18-7.8-2.4-2.3-4.5-3.7-2.1-1.5-3-1.7-1.5 0-2.1.3l-.8 1.3q-.3.7-.8 1.2l-1 1-.9.8q-2.7 2-6.4 2-1.7 0-3.2-.3-1.4-.3-3-1.1-1.5-.8-2.6-2.1-2.8-3.1-2.8-8v-1.3q0-.7.2-1.2l.2-1 .4-1 .4-1q.1-.6.5-1.1l.5-1q3.2-5.7 8.8-8.5 5.7-2.9 13-2.9 3.2 0 6.2 1 3 .9 6 2.7 2.9 1.6 5.7 4.2 5.2 4.6 7.6 5.4 1 0 1.6-.2l.7-.4q.3-.1.5-.4 3.6-5.6 9.2-5.6 5.7 0 8.8 3.5 2.8 3 2.8 8z"></path>
</svg> </svg>
Homepage of Homepage of
<div class=p-name> <div class=p-name>

View file

@ -3,7 +3,7 @@
<head id="head"> <head id="head">
<meta charset=utf-8> <meta charset=utf-8>
<title id=title >the codeartist — programmer and engineer based in BerlinE-Mail that isn't spam is called ham!</title> <title id="title " var="the codeartist — programmer and engineer based in Berlin"></title>
<meta name=description content="The personal page and weblog of Norman Köhring"> <meta name=description content="The personal page and weblog of Norman Köhring">
<meta name=author content="Norman Köhring"> <meta name=author content="Norman Köhring">
<meta name=DC.title content="the codeartist — programmer and engineer based in Berlin"> <meta name=DC.title content="the codeartist — programmer and engineer based in Berlin">
@ -11,12 +11,12 @@
<meta name="twitter:site" content="@koehr_in"> <meta name="twitter:site" content="@koehr_in">
<meta name="twitter:author" content="@koehr_in"> <meta name="twitter:author" content="@koehr_in">
<meta name=twitter:description content="The personal page and weblog of the codeartist Norman Köhring"> <meta name=twitter:description content="The personal page and weblog of the codeartist Norman Köhring">
<meta name="twitter:title" content="E-Mail that isn't spam is called ham! // the codeartist"> <meta name="twitter:title" content="E-Mail that isn&apos;t spam is called ham! // the codeartist">
<meta name="og:title" content="E-Mail that isn't spam is called ham! // the codeartist"> <meta name="og:title" content="E-Mail that isn&apos;t spam is called ham! // the codeartist">
<meta property="og:type" content="website"> <meta property="og:type" content="website">
<meta http-equiv="x-ua-compatible" content="ie=edge"/> <meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"/> <meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no">
<meta name=ICBM content="52.4595, 13.5335"> <meta name=ICBM content="52.4595, 13.5335">
<meta name=geo.position content="52.4595; 13.5335"> <meta name=geo.position content="52.4595; 13.5335">
@ -26,7 +26,7 @@
<link rel=me href=https://k0r.in> <link rel=me href=https://k0r.in>
<link rel=me href=https://koehr.ing> <link rel=me href=https://koehr.ing>
<link rel=me href=@Koehr@mstdn.io> <link rel=me href=@Koehr@mstdn.io>
<link rel=me href=https://sr.ht/~koehr/> <link rel=me href=https://sr.ht/~koehr>
<link rel=me href=https://git.k0r.in> <link rel=me href=https://git.k0r.in>
<link rel=me href=https://threads.net/@coffee_n_code> <link rel=me href=https://threads.net/@coffee_n_code>
<link rel=me href=https://instagram.com/@coffee_n_code> <link rel=me href=https://instagram.com/@coffee_n_code>
@ -49,10 +49,10 @@
<main id="main"> <main id="main">
<header> <header>
<h1 >E-Mail that isn't spam is called ham!</h1> <h1 :title="E-Mail that isn&apos;t spam is called ham!"></h1>
<em ></em> <em :title=""></em>
<br/> <br>
Last updated: <time datetime="Sun, 05 Sep 2021 00:00:00 +0000" >September 05, 2021</time> Last updated: <time datetime="Sun, 05 Sep 2021 00:00:00 +0000" :title="September 05, 2021"></time>
</header> </header>
<div></div> <div></div>
@ -68,21 +68,21 @@
<a href="/"> <a href="/">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 832.4 143.1"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 832.4 143.1">
<path id="header-underscore" <path id="header-underscore"
d="M832.4 131.1q0 5.5-3.1 8.6-3 3.4-8.2 3.3h-75.5q-5.2 0-8.2-3.3-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8 0-5.5 3.1-8.7 1.6-1.7 3.7-2.4 2.2-.8 4.5-.8h75.5q5.2 0 8.2 3.2 3 3.1 3 8.7z" /> d="M832.4 131.1q0 5.5-3.1 8.6-3 3.4-8.2 3.3h-75.5q-5.2 0-8.2-3.3-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8 0-5.5 3.1-8.7 1.6-1.7 3.7-2.4 2.2-.8 4.5-.8h75.5q5.2 0 8.2 3.2 3 3.1 3 8.7z"></path>
<path id="header-bracket" <path id="header-bracket"
d="M731.9 81.4q0 6.7-6.5 10.7l-1 .6-74.3 39.2q-2.5 1.3-5.2 1.2-4.8 0-8.1-3.8-3.2-3.6-3.2-8.4 0-3.3 1.7-6 1.8-2.9 4.6-4.4l55.3-29.1-55.3-29q-2.8-1.6-4.6-4.3-1.7-2.7-1.7-6.2 0-4.7 3.2-8.4 3.3-4 8-3.7 2.7 0 5.3 1.2l74.4 39.2q3.3 1.7 5.3 4.7 2 2.8 2 6.5z" /> d="M731.9 81.4q0 6.7-6.5 10.7l-1 .6-74.3 39.2q-2.5 1.3-5.2 1.2-4.8 0-8.1-3.8-3.2-3.6-3.2-8.4 0-3.3 1.7-6 1.8-2.9 4.6-4.4l55.3-29.1-55.3-29q-2.8-1.6-4.6-4.3-1.7-2.7-1.7-6.2 0-4.7 3.2-8.4 3.3-4 8-3.7 2.7 0 5.3 1.2l74.4 39.2q3.3 1.7 5.3 4.7 2 2.8 2 6.5z"></path>
<path id="header-r" <path id="header-r"
d="M588.7 66.5q0 5-3.5 8.5-3.5 3.4-8.1 3.5-4.4 0-8.3-4.3-10-10.7-20.9-10.6-2.2 0-4.3.3-2.1.3-4 1-1.8.6-3.7 1.6-1.7 1-3.4 2.3-1.7 1.3-3.3 2.9-7.8 8.2-7.6 19.7V131q0 5.5-3.1 8.6-3 3.4-8.3 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V51.6q0-5.4 3-8.6 3-3.4 8.3-3.3 2 0 3.7.6 1.8.6 3.3 1.8 1.4 1 2.2 2.7 1 1.5 1.6 3.3 11.8-8.4 27-8.4 10.6 0 21 5 11.3 5.4 17.2 14.5 2.5 3.7 2.5 7.3z" /> d="M588.7 66.5q0 5-3.5 8.5-3.5 3.4-8.1 3.5-4.4 0-8.3-4.3-10-10.7-20.9-10.6-2.2 0-4.3.3-2.1.3-4 1-1.8.6-3.7 1.6-1.7 1-3.4 2.3-1.7 1.3-3.3 2.9-7.8 8.2-7.6 19.7V131q0 5.5-3.1 8.6-3 3.4-8.3 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V51.6q0-5.4 3-8.6 3-3.4 8.3-3.3 2 0 3.7.6 1.8.6 3.3 1.8 1.4 1 2.2 2.7 1 1.5 1.6 3.3 11.8-8.4 27-8.4 10.6 0 21 5 11.3 5.4 17.2 14.5 2.5 3.7 2.5 7.3z"></path>
<path id="header-h" <path id="header-h"
d="M483.9 131.1q0 5.5-3.1 8.6-3 3.4-8.3 3.3-5.2 0-8.2-3.3-3.2-3.1-3.1-8.6V84.8q0-4.6-1.5-8.2-1.4-3.5-4.4-6.9-2.1-2-4.3-3.4-2.2-1.4-4.7-2-2.4-.7-5.3-.7-4.3 0-7.8 1.5-3.3 1.5-6.4 4.6-5.9 6.3-5.8 15v46.4q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v33q1.5-1 3-1.6l3.2-1.2 3.4-1q1.6-.5 3.3-.8l3.5-.4 3.6-.2q4.4 0 8.5 1 4.1.7 7.9 2.4 3.8 1.6 7.3 4.1 3.5 2.5 6.6 5.8Q484 66 484 84.8z" /> d="M483.9 131.1q0 5.5-3.1 8.6-3 3.4-8.3 3.3-5.2 0-8.2-3.3-3.2-3.1-3.1-8.6V84.8q0-4.6-1.5-8.2-1.4-3.5-4.4-6.9-2.1-2-4.3-3.4-2.2-1.4-4.7-2-2.4-.7-5.3-.7-4.3 0-7.8 1.5-3.3 1.5-6.4 4.6-5.9 6.3-5.8 15v46.4q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v33q1.5-1 3-1.6l3.2-1.2 3.4-1q1.6-.5 3.3-.8l3.5-.4 3.6-.2q4.4 0 8.5 1 4.1.7 7.9 2.4 3.8 1.6 7.3 4.1 3.5 2.5 6.6 5.8Q484 66 484 84.8z"></path>
<path id="header-e" <path id="header-e"
d="M387.5 111.1q0 1.2-.3 2.3-.1 1-.5 2l-.9 2q-6.6 12-19.4 19-12 6.6-25.4 6.6-20.8 0-35.8-14.6-15.9-15-15.9-37 0-22.1 15.9-37.1 15-14.6 35.8-14.6 3.9 0 7.8.7 4 .7 8 2.2 9.2 3.1 18.2 10 6 4.6 9.1 9.3 3.3 4.7 3.3 10 0 1.3-.3 2.5-.2 1.3-.7 2.4-1.5 3.4-5 5.3l-56.9 32.2q7.2 4.9 16.5 4.9 7.2 0 12.6-2.5 5.5-2.5 9.7-7.4l.7-1 .8-1 .9-1.3 1-1.5q3.3-4.2 7.4-5.1l1.8-.2q4.4 0 8 3.4 3.6 3.5 3.6 8.5zm-29.9-42.7q-7.2-4.8-16.6-4.8-6 0-11 2-4.9 1.8-9.3 6-4.5 4-6.7 9-2 4.8-2 10.8l.1 2.9z" /> d="M387.5 111.1q0 1.2-.3 2.3-.1 1-.5 2l-.9 2q-6.6 12-19.4 19-12 6.6-25.4 6.6-20.8 0-35.8-14.6-15.9-15-15.9-37 0-22.1 15.9-37.1 15-14.6 35.8-14.6 3.9 0 7.8.7 4 .7 8 2.2 9.2 3.1 18.2 10 6 4.6 9.1 9.3 3.3 4.7 3.3 10 0 1.3-.3 2.5-.2 1.3-.7 2.4-1.5 3.4-5 5.3l-56.9 32.2q7.2 4.9 16.5 4.9 7.2 0 12.6-2.5 5.5-2.5 9.7-7.4l.7-1 .8-1 .9-1.3 1-1.5q3.3-4.2 7.4-5.1l1.8-.2q4.4 0 8 3.4 3.6 3.5 3.6 8.5zm-29.9-42.7q-7.2-4.8-16.6-4.8-6 0-11 2-4.9 1.8-9.3 6-4.5 4-6.7 9-2 4.8-2 10.8l.1 2.9z"></path>
<path id="header-o" <path id="header-o"
d="M286.8 91.4q0 4.2-.6 8.3-.6 4-1.8 7.7-1.1 3.8-2.9 7.4-1.7 3.5-4 6.9-2.4 3.3-5.2 6.1Q258 143 237.7 143T203 128q-14.3-15.2-14.3-36.6 0-21.5 14.3-36.6 14.4-15 34.7-15 4 0 7.8.5 3.9.7 7.5 1.9t7 3q3.3 1.9 6.4 4.3 3.2 2.4 5.9 5.4 14.4 15 14.5 36.5zm-22.6 0q0-2.4-.4-4.5-.2-2.2-.9-4.2-.6-2-1.5-3.9-1-2-2.2-3.7-1.2-1.7-2.8-3.4-4-4.2-8.6-6.1-4.5-2-10-2-11 0-18.7 8.2-7.8 8-7.8 19.6 0 11.4 7.8 19.7 7.8 8 18.6 8 5.6 0 10.1-1.9 4.6-2 8.6-6.1 4-4.3 5.8-9 2-4.9 2-10.7z" /> d="M286.8 91.4q0 4.2-.6 8.3-.6 4-1.8 7.7-1.1 3.8-2.9 7.4-1.7 3.5-4 6.9-2.4 3.3-5.2 6.1Q258 143 237.7 143T203 128q-14.3-15.2-14.3-36.6 0-21.5 14.3-36.6 14.4-15 34.7-15 4 0 7.8.5 3.9.7 7.5 1.9t7 3q3.3 1.9 6.4 4.3 3.2 2.4 5.9 5.4 14.4 15 14.5 36.5zm-22.6 0q0-2.4-.4-4.5-.2-2.2-.9-4.2-.6-2-1.5-3.9-1-2-2.2-3.7-1.2-1.7-2.8-3.4-4-4.2-8.6-6.1-4.5-2-10-2-11 0-18.7 8.2-7.8 8-7.8 19.6 0 11.4 7.8 19.7 7.8 8 18.6 8 5.6 0 10.1-1.9 4.6-2 8.6-6.1 4-4.3 5.8-9 2-4.9 2-10.7z"></path>
<path id="header-k" <path id="header-k"
d="M186.3 131q0 4.7-3.3 8.3-1.5 1.8-3.7 2.7-2 1.1-4.3 1.1-3.5 0-6.6-2L119.2 105v26q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v65.9l49.2-36.1q3.2-2 6.6-2 4.7 0 8 3.7t3.3 8.4q-.2 6-5 9.6l-41 30 41 29.9q2.3 1.7 3.6 4.2 1.4 2.5 1.4 5.4z" /> d="M186.3 131q0 4.7-3.3 8.3-1.5 1.8-3.7 2.7-2 1.1-4.3 1.1-3.5 0-6.6-2L119.2 105v26q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v65.9l49.2-36.1q3.2-2 6.6-2 4.7 0 8 3.7t3.3 8.4q-.2 6-5 9.6l-41 30 41 29.9q2.3 1.7 3.6 4.2 1.4 2.5 1.4 5.4z"></path>
<path id="header-tilde" <path id="header-tilde"
d="M73.1 91q0 2-.6 3.9T71 98.6q-3.2 5.7-8.9 8.5-5.6 2.8-12.9 2.8-8.8 0-18-7.8-2.4-2.3-4.5-3.7-2.1-1.5-3-1.7-1.5 0-2.1.3l-.8 1.3q-.3.7-.8 1.2l-1 1-.9.8q-2.7 2-6.4 2-1.7 0-3.2-.3-1.4-.3-3-1.1-1.5-.8-2.6-2.1-2.8-3.1-2.8-8v-1.3q0-.7.2-1.2l.2-1 .4-1 .4-1q.1-.6.5-1.1l.5-1q3.2-5.7 8.8-8.5 5.7-2.9 13-2.9 3.2 0 6.2 1 3 .9 6 2.7 2.9 1.6 5.7 4.2 5.2 4.6 7.6 5.4 1 0 1.6-.2l.7-.4q.3-.1.5-.4 3.6-5.6 9.2-5.6 5.7 0 8.8 3.5 2.8 3 2.8 8z" /> d="M73.1 91q0 2-.6 3.9T71 98.6q-3.2 5.7-8.9 8.5-5.6 2.8-12.9 2.8-8.8 0-18-7.8-2.4-2.3-4.5-3.7-2.1-1.5-3-1.7-1.5 0-2.1.3l-.8 1.3q-.3.7-.8 1.2l-1 1-.9.8q-2.7 2-6.4 2-1.7 0-3.2-.3-1.4-.3-3-1.1-1.5-.8-2.6-2.1-2.8-3.1-2.8-8v-1.3q0-.7.2-1.2l.2-1 .4-1 .4-1q.1-.6.5-1.1l.5-1q3.2-5.7 8.8-8.5 5.7-2.9 13-2.9 3.2 0 6.2 1 3 .9 6 2.7 2.9 1.6 5.7 4.2 5.2 4.6 7.6 5.4 1 0 1.6-.2l.7-.4q.3-.1.5-.4 3.6-5.6 9.2-5.6 5.7 0 8.8 3.5 2.8 3 2.8 8z"></path>
</svg> </svg>
Homepage of Homepage of
<div class=p-name> <div class=p-name>

View file

@ -3,7 +3,7 @@
<head id="head"> <head id="head">
<meta charset=utf-8> <meta charset=utf-8>
<title id=title >the codeartist — programmer and engineer based in BerlinAdding aliases in vite with typescript needs the same alias in tsconfig</title> <title id="title " var="the codeartist — programmer and engineer based in Berlin"></title>
<meta name=description content="The personal page and weblog of Norman Köhring"> <meta name=description content="The personal page and weblog of Norman Köhring">
<meta name=author content="Norman Köhring"> <meta name=author content="Norman Köhring">
<meta name=DC.title content="the codeartist — programmer and engineer based in Berlin"> <meta name=DC.title content="the codeartist — programmer and engineer based in Berlin">
@ -15,8 +15,8 @@
<meta name="og:title" content="Adding aliases in vite with typescript needs the same alias in tsconfig // the codeartist"> <meta name="og:title" content="Adding aliases in vite with typescript needs the same alias in tsconfig // the codeartist">
<meta property="og:type" content="website"> <meta property="og:type" content="website">
<meta http-equiv="x-ua-compatible" content="ie=edge"/> <meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"/> <meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no">
<meta name=ICBM content="52.4595, 13.5335"> <meta name=ICBM content="52.4595, 13.5335">
<meta name=geo.position content="52.4595; 13.5335"> <meta name=geo.position content="52.4595; 13.5335">
@ -26,7 +26,7 @@
<link rel=me href=https://k0r.in> <link rel=me href=https://k0r.in>
<link rel=me href=https://koehr.ing> <link rel=me href=https://koehr.ing>
<link rel=me href=@Koehr@mstdn.io> <link rel=me href=@Koehr@mstdn.io>
<link rel=me href=https://sr.ht/~koehr/> <link rel=me href=https://sr.ht/~koehr>
<link rel=me href=https://git.k0r.in> <link rel=me href=https://git.k0r.in>
<link rel=me href=https://threads.net/@coffee_n_code> <link rel=me href=https://threads.net/@coffee_n_code>
<link rel=me href=https://instagram.com/@coffee_n_code> <link rel=me href=https://instagram.com/@coffee_n_code>
@ -49,36 +49,36 @@
<main id="main"> <main id="main">
<header> <header>
<h1 >Adding aliases in vite with typescript needs the same alias in tsconfig</h1> <h1 :title="Adding aliases in vite with typescript needs the same alias in tsconfig"></h1>
<em ></em> <em :title=""></em>
<br/> <br>
Last updated: <time datetime="Tue, 22 Feb 2022 00:00:00 +0000" >February 22, 2022</time> Last updated: <time datetime="Tue, 22 Feb 2022 00:00:00 +0000" :title="February 22, 2022"></time>
</header> </header>
<div ><p>For example:</p><p>The following vite.config.ts:</p><pre><code class="ts">import { fileURLToPath, URL } from "url" <div><p>For example:</p><p>The following vite.config.ts:</p><pre><code class="ts">import { fileURLToPath, URL } from &quot;url&quot;
import { defineConfig } from 'vite' import { defineConfig } from &apos;vite&apos;
import vue from '@vitejs/plugin-vue' import vue from &apos;@vitejs/plugin-vue&apos;
// https://vitejs.dev/config/ // https://vitejs.dev/config/
export default defineConfig({ export default defineConfig({
plugins: [vue()], plugins: [vue()],
resolve: { resolve: {
alias: { alias: {
"~": fileURLToPath(new URL("./src", import.meta.url)), &quot;~&quot;: fileURLToPath(new URL(&quot;./src&quot;, import.meta.url)),
"~component": fileURLToPath(new URL("./src/components", import.meta.url)), &quot;~component&quot;: fileURLToPath(new URL(&quot;./src/components&quot;, import.meta.url)),
"~composable": fileURLToPath(new URL("./src/composables", import.meta.url)), &quot;~composable&quot;: fileURLToPath(new URL(&quot;./src/composables&quot;, import.meta.url)),
"~lib": fileURLToPath(new URL("./src/lib", import.meta.url)), &quot;~lib&quot;: fileURLToPath(new URL(&quot;./src/lib&quot;, import.meta.url)),
} }
} }
}) })
</code></pre> </code></pre>
<p>will need this in tsconfig.json:</p><pre><code class="json">{ <p>will need this in tsconfig.json:</p><pre><code class="json">{
<span class="string special key">"compilerOptions"</span>: { <span class="string special key">&quot;compilerOptions&quot;</span>: {
<span class="string special key">"paths"</span>: { <span class="string special key">&quot;paths&quot;</span>: {
<span class="string special key">"~/*"</span>: [ <span class="string">"./src/*"</span> ], <span class="string special key">&quot;~/*&quot;</span>: [ <span class="string">&quot;./src/*&quot;</span> ],
<span class="string special key">"~component/*"</span>: [ <span class="string">"./src/components/*"</span> ], <span class="string special key">&quot;~component/*&quot;</span>: [ <span class="string">&quot;./src/components/*&quot;</span> ],
<span class="string special key">"~composable/*"</span>: [ <span class="string">"./src/composables/*"</span> ], <span class="string special key">&quot;~composable/*&quot;</span>: [ <span class="string">&quot;./src/composables/*&quot;</span> ],
<span class="string special key">"~lib/*"</span>: [ <span class="string">"./src/lib/*"</span> ] <span class="string special key">&quot;~lib/*&quot;</span>: [ <span class="string">&quot;./src/lib/*&quot;</span> ]
} }
} }
} }
@ -96,21 +96,21 @@ export default defineConfig({
<a href="/"> <a href="/">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 832.4 143.1"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 832.4 143.1">
<path id="header-underscore" <path id="header-underscore"
d="M832.4 131.1q0 5.5-3.1 8.6-3 3.4-8.2 3.3h-75.5q-5.2 0-8.2-3.3-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8 0-5.5 3.1-8.7 1.6-1.7 3.7-2.4 2.2-.8 4.5-.8h75.5q5.2 0 8.2 3.2 3 3.1 3 8.7z" /> d="M832.4 131.1q0 5.5-3.1 8.6-3 3.4-8.2 3.3h-75.5q-5.2 0-8.2-3.3-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8 0-5.5 3.1-8.7 1.6-1.7 3.7-2.4 2.2-.8 4.5-.8h75.5q5.2 0 8.2 3.2 3 3.1 3 8.7z"></path>
<path id="header-bracket" <path id="header-bracket"
d="M731.9 81.4q0 6.7-6.5 10.7l-1 .6-74.3 39.2q-2.5 1.3-5.2 1.2-4.8 0-8.1-3.8-3.2-3.6-3.2-8.4 0-3.3 1.7-6 1.8-2.9 4.6-4.4l55.3-29.1-55.3-29q-2.8-1.6-4.6-4.3-1.7-2.7-1.7-6.2 0-4.7 3.2-8.4 3.3-4 8-3.7 2.7 0 5.3 1.2l74.4 39.2q3.3 1.7 5.3 4.7 2 2.8 2 6.5z" /> d="M731.9 81.4q0 6.7-6.5 10.7l-1 .6-74.3 39.2q-2.5 1.3-5.2 1.2-4.8 0-8.1-3.8-3.2-3.6-3.2-8.4 0-3.3 1.7-6 1.8-2.9 4.6-4.4l55.3-29.1-55.3-29q-2.8-1.6-4.6-4.3-1.7-2.7-1.7-6.2 0-4.7 3.2-8.4 3.3-4 8-3.7 2.7 0 5.3 1.2l74.4 39.2q3.3 1.7 5.3 4.7 2 2.8 2 6.5z"></path>
<path id="header-r" <path id="header-r"
d="M588.7 66.5q0 5-3.5 8.5-3.5 3.4-8.1 3.5-4.4 0-8.3-4.3-10-10.7-20.9-10.6-2.2 0-4.3.3-2.1.3-4 1-1.8.6-3.7 1.6-1.7 1-3.4 2.3-1.7 1.3-3.3 2.9-7.8 8.2-7.6 19.7V131q0 5.5-3.1 8.6-3 3.4-8.3 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V51.6q0-5.4 3-8.6 3-3.4 8.3-3.3 2 0 3.7.6 1.8.6 3.3 1.8 1.4 1 2.2 2.7 1 1.5 1.6 3.3 11.8-8.4 27-8.4 10.6 0 21 5 11.3 5.4 17.2 14.5 2.5 3.7 2.5 7.3z" /> d="M588.7 66.5q0 5-3.5 8.5-3.5 3.4-8.1 3.5-4.4 0-8.3-4.3-10-10.7-20.9-10.6-2.2 0-4.3.3-2.1.3-4 1-1.8.6-3.7 1.6-1.7 1-3.4 2.3-1.7 1.3-3.3 2.9-7.8 8.2-7.6 19.7V131q0 5.5-3.1 8.6-3 3.4-8.3 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V51.6q0-5.4 3-8.6 3-3.4 8.3-3.3 2 0 3.7.6 1.8.6 3.3 1.8 1.4 1 2.2 2.7 1 1.5 1.6 3.3 11.8-8.4 27-8.4 10.6 0 21 5 11.3 5.4 17.2 14.5 2.5 3.7 2.5 7.3z"></path>
<path id="header-h" <path id="header-h"
d="M483.9 131.1q0 5.5-3.1 8.6-3 3.4-8.3 3.3-5.2 0-8.2-3.3-3.2-3.1-3.1-8.6V84.8q0-4.6-1.5-8.2-1.4-3.5-4.4-6.9-2.1-2-4.3-3.4-2.2-1.4-4.7-2-2.4-.7-5.3-.7-4.3 0-7.8 1.5-3.3 1.5-6.4 4.6-5.9 6.3-5.8 15v46.4q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v33q1.5-1 3-1.6l3.2-1.2 3.4-1q1.6-.5 3.3-.8l3.5-.4 3.6-.2q4.4 0 8.5 1 4.1.7 7.9 2.4 3.8 1.6 7.3 4.1 3.5 2.5 6.6 5.8Q484 66 484 84.8z" /> d="M483.9 131.1q0 5.5-3.1 8.6-3 3.4-8.3 3.3-5.2 0-8.2-3.3-3.2-3.1-3.1-8.6V84.8q0-4.6-1.5-8.2-1.4-3.5-4.4-6.9-2.1-2-4.3-3.4-2.2-1.4-4.7-2-2.4-.7-5.3-.7-4.3 0-7.8 1.5-3.3 1.5-6.4 4.6-5.9 6.3-5.8 15v46.4q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v33q1.5-1 3-1.6l3.2-1.2 3.4-1q1.6-.5 3.3-.8l3.5-.4 3.6-.2q4.4 0 8.5 1 4.1.7 7.9 2.4 3.8 1.6 7.3 4.1 3.5 2.5 6.6 5.8Q484 66 484 84.8z"></path>
<path id="header-e" <path id="header-e"
d="M387.5 111.1q0 1.2-.3 2.3-.1 1-.5 2l-.9 2q-6.6 12-19.4 19-12 6.6-25.4 6.6-20.8 0-35.8-14.6-15.9-15-15.9-37 0-22.1 15.9-37.1 15-14.6 35.8-14.6 3.9 0 7.8.7 4 .7 8 2.2 9.2 3.1 18.2 10 6 4.6 9.1 9.3 3.3 4.7 3.3 10 0 1.3-.3 2.5-.2 1.3-.7 2.4-1.5 3.4-5 5.3l-56.9 32.2q7.2 4.9 16.5 4.9 7.2 0 12.6-2.5 5.5-2.5 9.7-7.4l.7-1 .8-1 .9-1.3 1-1.5q3.3-4.2 7.4-5.1l1.8-.2q4.4 0 8 3.4 3.6 3.5 3.6 8.5zm-29.9-42.7q-7.2-4.8-16.6-4.8-6 0-11 2-4.9 1.8-9.3 6-4.5 4-6.7 9-2 4.8-2 10.8l.1 2.9z" /> d="M387.5 111.1q0 1.2-.3 2.3-.1 1-.5 2l-.9 2q-6.6 12-19.4 19-12 6.6-25.4 6.6-20.8 0-35.8-14.6-15.9-15-15.9-37 0-22.1 15.9-37.1 15-14.6 35.8-14.6 3.9 0 7.8.7 4 .7 8 2.2 9.2 3.1 18.2 10 6 4.6 9.1 9.3 3.3 4.7 3.3 10 0 1.3-.3 2.5-.2 1.3-.7 2.4-1.5 3.4-5 5.3l-56.9 32.2q7.2 4.9 16.5 4.9 7.2 0 12.6-2.5 5.5-2.5 9.7-7.4l.7-1 .8-1 .9-1.3 1-1.5q3.3-4.2 7.4-5.1l1.8-.2q4.4 0 8 3.4 3.6 3.5 3.6 8.5zm-29.9-42.7q-7.2-4.8-16.6-4.8-6 0-11 2-4.9 1.8-9.3 6-4.5 4-6.7 9-2 4.8-2 10.8l.1 2.9z"></path>
<path id="header-o" <path id="header-o"
d="M286.8 91.4q0 4.2-.6 8.3-.6 4-1.8 7.7-1.1 3.8-2.9 7.4-1.7 3.5-4 6.9-2.4 3.3-5.2 6.1Q258 143 237.7 143T203 128q-14.3-15.2-14.3-36.6 0-21.5 14.3-36.6 14.4-15 34.7-15 4 0 7.8.5 3.9.7 7.5 1.9t7 3q3.3 1.9 6.4 4.3 3.2 2.4 5.9 5.4 14.4 15 14.5 36.5zm-22.6 0q0-2.4-.4-4.5-.2-2.2-.9-4.2-.6-2-1.5-3.9-1-2-2.2-3.7-1.2-1.7-2.8-3.4-4-4.2-8.6-6.1-4.5-2-10-2-11 0-18.7 8.2-7.8 8-7.8 19.6 0 11.4 7.8 19.7 7.8 8 18.6 8 5.6 0 10.1-1.9 4.6-2 8.6-6.1 4-4.3 5.8-9 2-4.9 2-10.7z" /> d="M286.8 91.4q0 4.2-.6 8.3-.6 4-1.8 7.7-1.1 3.8-2.9 7.4-1.7 3.5-4 6.9-2.4 3.3-5.2 6.1Q258 143 237.7 143T203 128q-14.3-15.2-14.3-36.6 0-21.5 14.3-36.6 14.4-15 34.7-15 4 0 7.8.5 3.9.7 7.5 1.9t7 3q3.3 1.9 6.4 4.3 3.2 2.4 5.9 5.4 14.4 15 14.5 36.5zm-22.6 0q0-2.4-.4-4.5-.2-2.2-.9-4.2-.6-2-1.5-3.9-1-2-2.2-3.7-1.2-1.7-2.8-3.4-4-4.2-8.6-6.1-4.5-2-10-2-11 0-18.7 8.2-7.8 8-7.8 19.6 0 11.4 7.8 19.7 7.8 8 18.6 8 5.6 0 10.1-1.9 4.6-2 8.6-6.1 4-4.3 5.8-9 2-4.9 2-10.7z"></path>
<path id="header-k" <path id="header-k"
d="M186.3 131q0 4.7-3.3 8.3-1.5 1.8-3.7 2.7-2 1.1-4.3 1.1-3.5 0-6.6-2L119.2 105v26q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v65.9l49.2-36.1q3.2-2 6.6-2 4.7 0 8 3.7t3.3 8.4q-.2 6-5 9.6l-41 30 41 29.9q2.3 1.7 3.6 4.2 1.4 2.5 1.4 5.4z" /> d="M186.3 131q0 4.7-3.3 8.3-1.5 1.8-3.7 2.7-2 1.1-4.3 1.1-3.5 0-6.6-2L119.2 105v26q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v65.9l49.2-36.1q3.2-2 6.6-2 4.7 0 8 3.7t3.3 8.4q-.2 6-5 9.6l-41 30 41 29.9q2.3 1.7 3.6 4.2 1.4 2.5 1.4 5.4z"></path>
<path id="header-tilde" <path id="header-tilde"
d="M73.1 91q0 2-.6 3.9T71 98.6q-3.2 5.7-8.9 8.5-5.6 2.8-12.9 2.8-8.8 0-18-7.8-2.4-2.3-4.5-3.7-2.1-1.5-3-1.7-1.5 0-2.1.3l-.8 1.3q-.3.7-.8 1.2l-1 1-.9.8q-2.7 2-6.4 2-1.7 0-3.2-.3-1.4-.3-3-1.1-1.5-.8-2.6-2.1-2.8-3.1-2.8-8v-1.3q0-.7.2-1.2l.2-1 .4-1 .4-1q.1-.6.5-1.1l.5-1q3.2-5.7 8.8-8.5 5.7-2.9 13-2.9 3.2 0 6.2 1 3 .9 6 2.7 2.9 1.6 5.7 4.2 5.2 4.6 7.6 5.4 1 0 1.6-.2l.7-.4q.3-.1.5-.4 3.6-5.6 9.2-5.6 5.7 0 8.8 3.5 2.8 3 2.8 8z" /> d="M73.1 91q0 2-.6 3.9T71 98.6q-3.2 5.7-8.9 8.5-5.6 2.8-12.9 2.8-8.8 0-18-7.8-2.4-2.3-4.5-3.7-2.1-1.5-3-1.7-1.5 0-2.1.3l-.8 1.3q-.3.7-.8 1.2l-1 1-.9.8q-2.7 2-6.4 2-1.7 0-3.2-.3-1.4-.3-3-1.1-1.5-.8-2.6-2.1-2.8-3.1-2.8-8v-1.3q0-.7.2-1.2l.2-1 .4-1 .4-1q.1-.6.5-1.1l.5-1q3.2-5.7 8.8-8.5 5.7-2.9 13-2.9 3.2 0 6.2 1 3 .9 6 2.7 2.9 1.6 5.7 4.2 5.2 4.6 7.6 5.4 1 0 1.6-.2l.7-.4q.3-.1.5-.4 3.6-5.6 9.2-5.6 5.7 0 8.8 3.5 2.8 3 2.8 8z"></path>
</svg> </svg>
Homepage of Homepage of
<div class=p-name> <div class=p-name>

View file

@ -3,7 +3,7 @@
<head id="head"> <head id="head">
<meta charset=utf-8> <meta charset=utf-8>
<title id=title >the codeartist — programmer and engineer based in BerlinThere is a file system for EFI vars now</title> <title id="title " var="the codeartist — programmer and engineer based in Berlin"></title>
<meta name=description content="The personal page and weblog of Norman Köhring"> <meta name=description content="The personal page and weblog of Norman Köhring">
<meta name=author content="Norman Köhring"> <meta name=author content="Norman Köhring">
<meta name=DC.title content="the codeartist — programmer and engineer based in Berlin"> <meta name=DC.title content="the codeartist — programmer and engineer based in Berlin">
@ -15,8 +15,8 @@
<meta name="og:title" content="There is a file system for EFI vars now // the codeartist"> <meta name="og:title" content="There is a file system for EFI vars now // the codeartist">
<meta property="og:type" content="website"> <meta property="og:type" content="website">
<meta http-equiv="x-ua-compatible" content="ie=edge"/> <meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"/> <meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no">
<meta name=ICBM content="52.4595, 13.5335"> <meta name=ICBM content="52.4595, 13.5335">
<meta name=geo.position content="52.4595; 13.5335"> <meta name=geo.position content="52.4595; 13.5335">
@ -26,7 +26,7 @@
<link rel=me href=https://k0r.in> <link rel=me href=https://k0r.in>
<link rel=me href=https://koehr.ing> <link rel=me href=https://koehr.ing>
<link rel=me href=@Koehr@mstdn.io> <link rel=me href=@Koehr@mstdn.io>
<link rel=me href=https://sr.ht/~koehr/> <link rel=me href=https://sr.ht/~koehr>
<link rel=me href=https://git.k0r.in> <link rel=me href=https://git.k0r.in>
<link rel=me href=https://threads.net/@coffee_n_code> <link rel=me href=https://threads.net/@coffee_n_code>
<link rel=me href=https://instagram.com/@coffee_n_code> <link rel=me href=https://instagram.com/@coffee_n_code>
@ -49,10 +49,10 @@
<main id="main"> <main id="main">
<header> <header>
<h1 >There is a file system for EFI vars now</h1> <h1 :title="There is a file system for EFI vars now"></h1>
<em ></em> <em :title=""></em>
<br/> <br>
Last updated: <time datetime="Tue, 22 Mar 2022 00:00:00 +0000" >March 22, 2022</time> Last updated: <time datetime="Tue, 22 Mar 2022 00:00:00 +0000" :title="March 22, 2022"></time>
</header> </header>
<div><p>On kernel updates I saw a recurring "EFI variables are not supported on this system", so I investigated and learned that the new EFI variables are provided via a file system that needs to be mounted first:</p><pre><code class="sh">mount -t efivarfs efivarfs /sys/firmware/efi/efivars <div><p>On kernel updates I saw a recurring "EFI variables are not supported on this system", so I investigated and learned that the new EFI variables are provided via a file system that needs to be mounted first:</p><pre><code class="sh">mount -t efivarfs efivarfs /sys/firmware/efi/efivars
@ -70,21 +70,21 @@
<a href="/"> <a href="/">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 832.4 143.1"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 832.4 143.1">
<path id="header-underscore" <path id="header-underscore"
d="M832.4 131.1q0 5.5-3.1 8.6-3 3.4-8.2 3.3h-75.5q-5.2 0-8.2-3.3-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8 0-5.5 3.1-8.7 1.6-1.7 3.7-2.4 2.2-.8 4.5-.8h75.5q5.2 0 8.2 3.2 3 3.1 3 8.7z" /> d="M832.4 131.1q0 5.5-3.1 8.6-3 3.4-8.2 3.3h-75.5q-5.2 0-8.2-3.3-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8 0-5.5 3.1-8.7 1.6-1.7 3.7-2.4 2.2-.8 4.5-.8h75.5q5.2 0 8.2 3.2 3 3.1 3 8.7z"></path>
<path id="header-bracket" <path id="header-bracket"
d="M731.9 81.4q0 6.7-6.5 10.7l-1 .6-74.3 39.2q-2.5 1.3-5.2 1.2-4.8 0-8.1-3.8-3.2-3.6-3.2-8.4 0-3.3 1.7-6 1.8-2.9 4.6-4.4l55.3-29.1-55.3-29q-2.8-1.6-4.6-4.3-1.7-2.7-1.7-6.2 0-4.7 3.2-8.4 3.3-4 8-3.7 2.7 0 5.3 1.2l74.4 39.2q3.3 1.7 5.3 4.7 2 2.8 2 6.5z" /> d="M731.9 81.4q0 6.7-6.5 10.7l-1 .6-74.3 39.2q-2.5 1.3-5.2 1.2-4.8 0-8.1-3.8-3.2-3.6-3.2-8.4 0-3.3 1.7-6 1.8-2.9 4.6-4.4l55.3-29.1-55.3-29q-2.8-1.6-4.6-4.3-1.7-2.7-1.7-6.2 0-4.7 3.2-8.4 3.3-4 8-3.7 2.7 0 5.3 1.2l74.4 39.2q3.3 1.7 5.3 4.7 2 2.8 2 6.5z"></path>
<path id="header-r" <path id="header-r"
d="M588.7 66.5q0 5-3.5 8.5-3.5 3.4-8.1 3.5-4.4 0-8.3-4.3-10-10.7-20.9-10.6-2.2 0-4.3.3-2.1.3-4 1-1.8.6-3.7 1.6-1.7 1-3.4 2.3-1.7 1.3-3.3 2.9-7.8 8.2-7.6 19.7V131q0 5.5-3.1 8.6-3 3.4-8.3 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V51.6q0-5.4 3-8.6 3-3.4 8.3-3.3 2 0 3.7.6 1.8.6 3.3 1.8 1.4 1 2.2 2.7 1 1.5 1.6 3.3 11.8-8.4 27-8.4 10.6 0 21 5 11.3 5.4 17.2 14.5 2.5 3.7 2.5 7.3z" /> d="M588.7 66.5q0 5-3.5 8.5-3.5 3.4-8.1 3.5-4.4 0-8.3-4.3-10-10.7-20.9-10.6-2.2 0-4.3.3-2.1.3-4 1-1.8.6-3.7 1.6-1.7 1-3.4 2.3-1.7 1.3-3.3 2.9-7.8 8.2-7.6 19.7V131q0 5.5-3.1 8.6-3 3.4-8.3 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V51.6q0-5.4 3-8.6 3-3.4 8.3-3.3 2 0 3.7.6 1.8.6 3.3 1.8 1.4 1 2.2 2.7 1 1.5 1.6 3.3 11.8-8.4 27-8.4 10.6 0 21 5 11.3 5.4 17.2 14.5 2.5 3.7 2.5 7.3z"></path>
<path id="header-h" <path id="header-h"
d="M483.9 131.1q0 5.5-3.1 8.6-3 3.4-8.3 3.3-5.2 0-8.2-3.3-3.2-3.1-3.1-8.6V84.8q0-4.6-1.5-8.2-1.4-3.5-4.4-6.9-2.1-2-4.3-3.4-2.2-1.4-4.7-2-2.4-.7-5.3-.7-4.3 0-7.8 1.5-3.3 1.5-6.4 4.6-5.9 6.3-5.8 15v46.4q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v33q1.5-1 3-1.6l3.2-1.2 3.4-1q1.6-.5 3.3-.8l3.5-.4 3.6-.2q4.4 0 8.5 1 4.1.7 7.9 2.4 3.8 1.6 7.3 4.1 3.5 2.5 6.6 5.8Q484 66 484 84.8z" /> d="M483.9 131.1q0 5.5-3.1 8.6-3 3.4-8.3 3.3-5.2 0-8.2-3.3-3.2-3.1-3.1-8.6V84.8q0-4.6-1.5-8.2-1.4-3.5-4.4-6.9-2.1-2-4.3-3.4-2.2-1.4-4.7-2-2.4-.7-5.3-.7-4.3 0-7.8 1.5-3.3 1.5-6.4 4.6-5.9 6.3-5.8 15v46.4q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v33q1.5-1 3-1.6l3.2-1.2 3.4-1q1.6-.5 3.3-.8l3.5-.4 3.6-.2q4.4 0 8.5 1 4.1.7 7.9 2.4 3.8 1.6 7.3 4.1 3.5 2.5 6.6 5.8Q484 66 484 84.8z"></path>
<path id="header-e" <path id="header-e"
d="M387.5 111.1q0 1.2-.3 2.3-.1 1-.5 2l-.9 2q-6.6 12-19.4 19-12 6.6-25.4 6.6-20.8 0-35.8-14.6-15.9-15-15.9-37 0-22.1 15.9-37.1 15-14.6 35.8-14.6 3.9 0 7.8.7 4 .7 8 2.2 9.2 3.1 18.2 10 6 4.6 9.1 9.3 3.3 4.7 3.3 10 0 1.3-.3 2.5-.2 1.3-.7 2.4-1.5 3.4-5 5.3l-56.9 32.2q7.2 4.9 16.5 4.9 7.2 0 12.6-2.5 5.5-2.5 9.7-7.4l.7-1 .8-1 .9-1.3 1-1.5q3.3-4.2 7.4-5.1l1.8-.2q4.4 0 8 3.4 3.6 3.5 3.6 8.5zm-29.9-42.7q-7.2-4.8-16.6-4.8-6 0-11 2-4.9 1.8-9.3 6-4.5 4-6.7 9-2 4.8-2 10.8l.1 2.9z" /> d="M387.5 111.1q0 1.2-.3 2.3-.1 1-.5 2l-.9 2q-6.6 12-19.4 19-12 6.6-25.4 6.6-20.8 0-35.8-14.6-15.9-15-15.9-37 0-22.1 15.9-37.1 15-14.6 35.8-14.6 3.9 0 7.8.7 4 .7 8 2.2 9.2 3.1 18.2 10 6 4.6 9.1 9.3 3.3 4.7 3.3 10 0 1.3-.3 2.5-.2 1.3-.7 2.4-1.5 3.4-5 5.3l-56.9 32.2q7.2 4.9 16.5 4.9 7.2 0 12.6-2.5 5.5-2.5 9.7-7.4l.7-1 .8-1 .9-1.3 1-1.5q3.3-4.2 7.4-5.1l1.8-.2q4.4 0 8 3.4 3.6 3.5 3.6 8.5zm-29.9-42.7q-7.2-4.8-16.6-4.8-6 0-11 2-4.9 1.8-9.3 6-4.5 4-6.7 9-2 4.8-2 10.8l.1 2.9z"></path>
<path id="header-o" <path id="header-o"
d="M286.8 91.4q0 4.2-.6 8.3-.6 4-1.8 7.7-1.1 3.8-2.9 7.4-1.7 3.5-4 6.9-2.4 3.3-5.2 6.1Q258 143 237.7 143T203 128q-14.3-15.2-14.3-36.6 0-21.5 14.3-36.6 14.4-15 34.7-15 4 0 7.8.5 3.9.7 7.5 1.9t7 3q3.3 1.9 6.4 4.3 3.2 2.4 5.9 5.4 14.4 15 14.5 36.5zm-22.6 0q0-2.4-.4-4.5-.2-2.2-.9-4.2-.6-2-1.5-3.9-1-2-2.2-3.7-1.2-1.7-2.8-3.4-4-4.2-8.6-6.1-4.5-2-10-2-11 0-18.7 8.2-7.8 8-7.8 19.6 0 11.4 7.8 19.7 7.8 8 18.6 8 5.6 0 10.1-1.9 4.6-2 8.6-6.1 4-4.3 5.8-9 2-4.9 2-10.7z" /> d="M286.8 91.4q0 4.2-.6 8.3-.6 4-1.8 7.7-1.1 3.8-2.9 7.4-1.7 3.5-4 6.9-2.4 3.3-5.2 6.1Q258 143 237.7 143T203 128q-14.3-15.2-14.3-36.6 0-21.5 14.3-36.6 14.4-15 34.7-15 4 0 7.8.5 3.9.7 7.5 1.9t7 3q3.3 1.9 6.4 4.3 3.2 2.4 5.9 5.4 14.4 15 14.5 36.5zm-22.6 0q0-2.4-.4-4.5-.2-2.2-.9-4.2-.6-2-1.5-3.9-1-2-2.2-3.7-1.2-1.7-2.8-3.4-4-4.2-8.6-6.1-4.5-2-10-2-11 0-18.7 8.2-7.8 8-7.8 19.6 0 11.4 7.8 19.7 7.8 8 18.6 8 5.6 0 10.1-1.9 4.6-2 8.6-6.1 4-4.3 5.8-9 2-4.9 2-10.7z"></path>
<path id="header-k" <path id="header-k"
d="M186.3 131q0 4.7-3.3 8.3-1.5 1.8-3.7 2.7-2 1.1-4.3 1.1-3.5 0-6.6-2L119.2 105v26q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v65.9l49.2-36.1q3.2-2 6.6-2 4.7 0 8 3.7t3.3 8.4q-.2 6-5 9.6l-41 30 41 29.9q2.3 1.7 3.6 4.2 1.4 2.5 1.4 5.4z" /> d="M186.3 131q0 4.7-3.3 8.3-1.5 1.8-3.7 2.7-2 1.1-4.3 1.1-3.5 0-6.6-2L119.2 105v26q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v65.9l49.2-36.1q3.2-2 6.6-2 4.7 0 8 3.7t3.3 8.4q-.2 6-5 9.6l-41 30 41 29.9q2.3 1.7 3.6 4.2 1.4 2.5 1.4 5.4z"></path>
<path id="header-tilde" <path id="header-tilde"
d="M73.1 91q0 2-.6 3.9T71 98.6q-3.2 5.7-8.9 8.5-5.6 2.8-12.9 2.8-8.8 0-18-7.8-2.4-2.3-4.5-3.7-2.1-1.5-3-1.7-1.5 0-2.1.3l-.8 1.3q-.3.7-.8 1.2l-1 1-.9.8q-2.7 2-6.4 2-1.7 0-3.2-.3-1.4-.3-3-1.1-1.5-.8-2.6-2.1-2.8-3.1-2.8-8v-1.3q0-.7.2-1.2l.2-1 .4-1 .4-1q.1-.6.5-1.1l.5-1q3.2-5.7 8.8-8.5 5.7-2.9 13-2.9 3.2 0 6.2 1 3 .9 6 2.7 2.9 1.6 5.7 4.2 5.2 4.6 7.6 5.4 1 0 1.6-.2l.7-.4q.3-.1.5-.4 3.6-5.6 9.2-5.6 5.7 0 8.8 3.5 2.8 3 2.8 8z" /> d="M73.1 91q0 2-.6 3.9T71 98.6q-3.2 5.7-8.9 8.5-5.6 2.8-12.9 2.8-8.8 0-18-7.8-2.4-2.3-4.5-3.7-2.1-1.5-3-1.7-1.5 0-2.1.3l-.8 1.3q-.3.7-.8 1.2l-1 1-.9.8q-2.7 2-6.4 2-1.7 0-3.2-.3-1.4-.3-3-1.1-1.5-.8-2.6-2.1-2.8-3.1-2.8-8v-1.3q0-.7.2-1.2l.2-1 .4-1 .4-1q.1-.6.5-1.1l.5-1q3.2-5.7 8.8-8.5 5.7-2.9 13-2.9 3.2 0 6.2 1 3 .9 6 2.7 2.9 1.6 5.7 4.2 5.2 4.6 7.6 5.4 1 0 1.6-.2l.7-.4q.3-.1.5-.4 3.6-5.6 9.2-5.6 5.7 0 8.8 3.5 2.8 3 2.8 8z"></path>
</svg> </svg>
Homepage of Homepage of
<div class=p-name> <div class=p-name>

View file

@ -3,7 +3,7 @@
<head id="head"> <head id="head">
<meta charset=utf-8> <meta charset=utf-8>
<title id=title >the codeartist — programmer and engineer based in Berlinpwdx command shows the working path of a process</title> <title id="title " var="the codeartist — programmer and engineer based in Berlin"></title>
<meta name=description content="The personal page and weblog of Norman Köhring"> <meta name=description content="The personal page and weblog of Norman Köhring">
<meta name=author content="Norman Köhring"> <meta name=author content="Norman Köhring">
<meta name=DC.title content="the codeartist — programmer and engineer based in Berlin"> <meta name=DC.title content="the codeartist — programmer and engineer based in Berlin">
@ -15,8 +15,8 @@
<meta name="og:title" content="pwdx command shows the working path of a process // the codeartist"> <meta name="og:title" content="pwdx command shows the working path of a process // the codeartist">
<meta property="og:type" content="website"> <meta property="og:type" content="website">
<meta http-equiv="x-ua-compatible" content="ie=edge"/> <meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"/> <meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no">
<meta name=ICBM content="52.4595, 13.5335"> <meta name=ICBM content="52.4595, 13.5335">
<meta name=geo.position content="52.4595; 13.5335"> <meta name=geo.position content="52.4595; 13.5335">
@ -26,7 +26,7 @@
<link rel=me href=https://k0r.in> <link rel=me href=https://k0r.in>
<link rel=me href=https://koehr.ing> <link rel=me href=https://koehr.ing>
<link rel=me href=@Koehr@mstdn.io> <link rel=me href=@Koehr@mstdn.io>
<link rel=me href=https://sr.ht/~koehr/> <link rel=me href=https://sr.ht/~koehr>
<link rel=me href=https://git.k0r.in> <link rel=me href=https://git.k0r.in>
<link rel=me href=https://threads.net/@coffee_n_code> <link rel=me href=https://threads.net/@coffee_n_code>
<link rel=me href=https://instagram.com/@coffee_n_code> <link rel=me href=https://instagram.com/@coffee_n_code>
@ -49,10 +49,10 @@
<main id="main"> <main id="main">
<header> <header>
<h1 >pwdx command shows the working path of a process</h1> <h1 :title="pwdx command shows the working path of a process"></h1>
<em ></em> <em :title=""></em>
<br/> <br>
Last updated: <time datetime="Mon, 28 Mar 2022 00:00:00 +0000" >March 28, 2022</time> Last updated: <time datetime="Mon, 28 Mar 2022 00:00:00 +0000" :title="March 28, 2022"></time>
</header> </header>
<div><p>For example:</p><pre><code class="sh">% pwdx 1984 <div><p>For example:</p><pre><code class="sh">% pwdx 1984
@ -71,21 +71,21 @@
<a href="/"> <a href="/">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 832.4 143.1"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 832.4 143.1">
<path id="header-underscore" <path id="header-underscore"
d="M832.4 131.1q0 5.5-3.1 8.6-3 3.4-8.2 3.3h-75.5q-5.2 0-8.2-3.3-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8 0-5.5 3.1-8.7 1.6-1.7 3.7-2.4 2.2-.8 4.5-.8h75.5q5.2 0 8.2 3.2 3 3.1 3 8.7z" /> d="M832.4 131.1q0 5.5-3.1 8.6-3 3.4-8.2 3.3h-75.5q-5.2 0-8.2-3.3-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8 0-5.5 3.1-8.7 1.6-1.7 3.7-2.4 2.2-.8 4.5-.8h75.5q5.2 0 8.2 3.2 3 3.1 3 8.7z"></path>
<path id="header-bracket" <path id="header-bracket"
d="M731.9 81.4q0 6.7-6.5 10.7l-1 .6-74.3 39.2q-2.5 1.3-5.2 1.2-4.8 0-8.1-3.8-3.2-3.6-3.2-8.4 0-3.3 1.7-6 1.8-2.9 4.6-4.4l55.3-29.1-55.3-29q-2.8-1.6-4.6-4.3-1.7-2.7-1.7-6.2 0-4.7 3.2-8.4 3.3-4 8-3.7 2.7 0 5.3 1.2l74.4 39.2q3.3 1.7 5.3 4.7 2 2.8 2 6.5z" /> d="M731.9 81.4q0 6.7-6.5 10.7l-1 .6-74.3 39.2q-2.5 1.3-5.2 1.2-4.8 0-8.1-3.8-3.2-3.6-3.2-8.4 0-3.3 1.7-6 1.8-2.9 4.6-4.4l55.3-29.1-55.3-29q-2.8-1.6-4.6-4.3-1.7-2.7-1.7-6.2 0-4.7 3.2-8.4 3.3-4 8-3.7 2.7 0 5.3 1.2l74.4 39.2q3.3 1.7 5.3 4.7 2 2.8 2 6.5z"></path>
<path id="header-r" <path id="header-r"
d="M588.7 66.5q0 5-3.5 8.5-3.5 3.4-8.1 3.5-4.4 0-8.3-4.3-10-10.7-20.9-10.6-2.2 0-4.3.3-2.1.3-4 1-1.8.6-3.7 1.6-1.7 1-3.4 2.3-1.7 1.3-3.3 2.9-7.8 8.2-7.6 19.7V131q0 5.5-3.1 8.6-3 3.4-8.3 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V51.6q0-5.4 3-8.6 3-3.4 8.3-3.3 2 0 3.7.6 1.8.6 3.3 1.8 1.4 1 2.2 2.7 1 1.5 1.6 3.3 11.8-8.4 27-8.4 10.6 0 21 5 11.3 5.4 17.2 14.5 2.5 3.7 2.5 7.3z" /> d="M588.7 66.5q0 5-3.5 8.5-3.5 3.4-8.1 3.5-4.4 0-8.3-4.3-10-10.7-20.9-10.6-2.2 0-4.3.3-2.1.3-4 1-1.8.6-3.7 1.6-1.7 1-3.4 2.3-1.7 1.3-3.3 2.9-7.8 8.2-7.6 19.7V131q0 5.5-3.1 8.6-3 3.4-8.3 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V51.6q0-5.4 3-8.6 3-3.4 8.3-3.3 2 0 3.7.6 1.8.6 3.3 1.8 1.4 1 2.2 2.7 1 1.5 1.6 3.3 11.8-8.4 27-8.4 10.6 0 21 5 11.3 5.4 17.2 14.5 2.5 3.7 2.5 7.3z"></path>
<path id="header-h" <path id="header-h"
d="M483.9 131.1q0 5.5-3.1 8.6-3 3.4-8.3 3.3-5.2 0-8.2-3.3-3.2-3.1-3.1-8.6V84.8q0-4.6-1.5-8.2-1.4-3.5-4.4-6.9-2.1-2-4.3-3.4-2.2-1.4-4.7-2-2.4-.7-5.3-.7-4.3 0-7.8 1.5-3.3 1.5-6.4 4.6-5.9 6.3-5.8 15v46.4q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v33q1.5-1 3-1.6l3.2-1.2 3.4-1q1.6-.5 3.3-.8l3.5-.4 3.6-.2q4.4 0 8.5 1 4.1.7 7.9 2.4 3.8 1.6 7.3 4.1 3.5 2.5 6.6 5.8Q484 66 484 84.8z" /> d="M483.9 131.1q0 5.5-3.1 8.6-3 3.4-8.3 3.3-5.2 0-8.2-3.3-3.2-3.1-3.1-8.6V84.8q0-4.6-1.5-8.2-1.4-3.5-4.4-6.9-2.1-2-4.3-3.4-2.2-1.4-4.7-2-2.4-.7-5.3-.7-4.3 0-7.8 1.5-3.3 1.5-6.4 4.6-5.9 6.3-5.8 15v46.4q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v33q1.5-1 3-1.6l3.2-1.2 3.4-1q1.6-.5 3.3-.8l3.5-.4 3.6-.2q4.4 0 8.5 1 4.1.7 7.9 2.4 3.8 1.6 7.3 4.1 3.5 2.5 6.6 5.8Q484 66 484 84.8z"></path>
<path id="header-e" <path id="header-e"
d="M387.5 111.1q0 1.2-.3 2.3-.1 1-.5 2l-.9 2q-6.6 12-19.4 19-12 6.6-25.4 6.6-20.8 0-35.8-14.6-15.9-15-15.9-37 0-22.1 15.9-37.1 15-14.6 35.8-14.6 3.9 0 7.8.7 4 .7 8 2.2 9.2 3.1 18.2 10 6 4.6 9.1 9.3 3.3 4.7 3.3 10 0 1.3-.3 2.5-.2 1.3-.7 2.4-1.5 3.4-5 5.3l-56.9 32.2q7.2 4.9 16.5 4.9 7.2 0 12.6-2.5 5.5-2.5 9.7-7.4l.7-1 .8-1 .9-1.3 1-1.5q3.3-4.2 7.4-5.1l1.8-.2q4.4 0 8 3.4 3.6 3.5 3.6 8.5zm-29.9-42.7q-7.2-4.8-16.6-4.8-6 0-11 2-4.9 1.8-9.3 6-4.5 4-6.7 9-2 4.8-2 10.8l.1 2.9z" /> d="M387.5 111.1q0 1.2-.3 2.3-.1 1-.5 2l-.9 2q-6.6 12-19.4 19-12 6.6-25.4 6.6-20.8 0-35.8-14.6-15.9-15-15.9-37 0-22.1 15.9-37.1 15-14.6 35.8-14.6 3.9 0 7.8.7 4 .7 8 2.2 9.2 3.1 18.2 10 6 4.6 9.1 9.3 3.3 4.7 3.3 10 0 1.3-.3 2.5-.2 1.3-.7 2.4-1.5 3.4-5 5.3l-56.9 32.2q7.2 4.9 16.5 4.9 7.2 0 12.6-2.5 5.5-2.5 9.7-7.4l.7-1 .8-1 .9-1.3 1-1.5q3.3-4.2 7.4-5.1l1.8-.2q4.4 0 8 3.4 3.6 3.5 3.6 8.5zm-29.9-42.7q-7.2-4.8-16.6-4.8-6 0-11 2-4.9 1.8-9.3 6-4.5 4-6.7 9-2 4.8-2 10.8l.1 2.9z"></path>
<path id="header-o" <path id="header-o"
d="M286.8 91.4q0 4.2-.6 8.3-.6 4-1.8 7.7-1.1 3.8-2.9 7.4-1.7 3.5-4 6.9-2.4 3.3-5.2 6.1Q258 143 237.7 143T203 128q-14.3-15.2-14.3-36.6 0-21.5 14.3-36.6 14.4-15 34.7-15 4 0 7.8.5 3.9.7 7.5 1.9t7 3q3.3 1.9 6.4 4.3 3.2 2.4 5.9 5.4 14.4 15 14.5 36.5zm-22.6 0q0-2.4-.4-4.5-.2-2.2-.9-4.2-.6-2-1.5-3.9-1-2-2.2-3.7-1.2-1.7-2.8-3.4-4-4.2-8.6-6.1-4.5-2-10-2-11 0-18.7 8.2-7.8 8-7.8 19.6 0 11.4 7.8 19.7 7.8 8 18.6 8 5.6 0 10.1-1.9 4.6-2 8.6-6.1 4-4.3 5.8-9 2-4.9 2-10.7z" /> d="M286.8 91.4q0 4.2-.6 8.3-.6 4-1.8 7.7-1.1 3.8-2.9 7.4-1.7 3.5-4 6.9-2.4 3.3-5.2 6.1Q258 143 237.7 143T203 128q-14.3-15.2-14.3-36.6 0-21.5 14.3-36.6 14.4-15 34.7-15 4 0 7.8.5 3.9.7 7.5 1.9t7 3q3.3 1.9 6.4 4.3 3.2 2.4 5.9 5.4 14.4 15 14.5 36.5zm-22.6 0q0-2.4-.4-4.5-.2-2.2-.9-4.2-.6-2-1.5-3.9-1-2-2.2-3.7-1.2-1.7-2.8-3.4-4-4.2-8.6-6.1-4.5-2-10-2-11 0-18.7 8.2-7.8 8-7.8 19.6 0 11.4 7.8 19.7 7.8 8 18.6 8 5.6 0 10.1-1.9 4.6-2 8.6-6.1 4-4.3 5.8-9 2-4.9 2-10.7z"></path>
<path id="header-k" <path id="header-k"
d="M186.3 131q0 4.7-3.3 8.3-1.5 1.8-3.7 2.7-2 1.1-4.3 1.1-3.5 0-6.6-2L119.2 105v26q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v65.9l49.2-36.1q3.2-2 6.6-2 4.7 0 8 3.7t3.3 8.4q-.2 6-5 9.6l-41 30 41 29.9q2.3 1.7 3.6 4.2 1.4 2.5 1.4 5.4z" /> d="M186.3 131q0 4.7-3.3 8.3-1.5 1.8-3.7 2.7-2 1.1-4.3 1.1-3.5 0-6.6-2L119.2 105v26q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v65.9l49.2-36.1q3.2-2 6.6-2 4.7 0 8 3.7t3.3 8.4q-.2 6-5 9.6l-41 30 41 29.9q2.3 1.7 3.6 4.2 1.4 2.5 1.4 5.4z"></path>
<path id="header-tilde" <path id="header-tilde"
d="M73.1 91q0 2-.6 3.9T71 98.6q-3.2 5.7-8.9 8.5-5.6 2.8-12.9 2.8-8.8 0-18-7.8-2.4-2.3-4.5-3.7-2.1-1.5-3-1.7-1.5 0-2.1.3l-.8 1.3q-.3.7-.8 1.2l-1 1-.9.8q-2.7 2-6.4 2-1.7 0-3.2-.3-1.4-.3-3-1.1-1.5-.8-2.6-2.1-2.8-3.1-2.8-8v-1.3q0-.7.2-1.2l.2-1 .4-1 .4-1q.1-.6.5-1.1l.5-1q3.2-5.7 8.8-8.5 5.7-2.9 13-2.9 3.2 0 6.2 1 3 .9 6 2.7 2.9 1.6 5.7 4.2 5.2 4.6 7.6 5.4 1 0 1.6-.2l.7-.4q.3-.1.5-.4 3.6-5.6 9.2-5.6 5.7 0 8.8 3.5 2.8 3 2.8 8z" /> d="M73.1 91q0 2-.6 3.9T71 98.6q-3.2 5.7-8.9 8.5-5.6 2.8-12.9 2.8-8.8 0-18-7.8-2.4-2.3-4.5-3.7-2.1-1.5-3-1.7-1.5 0-2.1.3l-.8 1.3q-.3.7-.8 1.2l-1 1-.9.8q-2.7 2-6.4 2-1.7 0-3.2-.3-1.4-.3-3-1.1-1.5-.8-2.6-2.1-2.8-3.1-2.8-8v-1.3q0-.7.2-1.2l.2-1 .4-1 .4-1q.1-.6.5-1.1l.5-1q3.2-5.7 8.8-8.5 5.7-2.9 13-2.9 3.2 0 6.2 1 3 .9 6 2.7 2.9 1.6 5.7 4.2 5.2 4.6 7.6 5.4 1 0 1.6-.2l.7-.4q.3-.1.5-.4 3.6-5.6 9.2-5.6 5.7 0 8.8 3.5 2.8 3 2.8 8z"></path>
</svg> </svg>
Homepage of Homepage of
<div class=p-name> <div class=p-name>

View file

@ -3,7 +3,7 @@
<head id="head"> <head id="head">
<meta charset=utf-8> <meta charset=utf-8>
<title id=title >the codeartist — programmer and engineer based in BerlinJest mocks are ...different</title> <title id="title " var="the codeartist — programmer and engineer based in Berlin"></title>
<meta name=description content="The personal page and weblog of Norman Köhring"> <meta name=description content="The personal page and weblog of Norman Köhring">
<meta name=author content="Norman Köhring"> <meta name=author content="Norman Köhring">
<meta name=DC.title content="the codeartist — programmer and engineer based in Berlin"> <meta name=DC.title content="the codeartist — programmer and engineer based in Berlin">
@ -15,8 +15,8 @@
<meta name="og:title" content="Jest mocks are ...different // the codeartist"> <meta name="og:title" content="Jest mocks are ...different // the codeartist">
<meta property="og:type" content="website"> <meta property="og:type" content="website">
<meta http-equiv="x-ua-compatible" content="ie=edge"/> <meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"/> <meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no">
<meta name=ICBM content="52.4595, 13.5335"> <meta name=ICBM content="52.4595, 13.5335">
<meta name=geo.position content="52.4595; 13.5335"> <meta name=geo.position content="52.4595; 13.5335">
@ -26,7 +26,7 @@
<link rel=me href=https://k0r.in> <link rel=me href=https://k0r.in>
<link rel=me href=https://koehr.ing> <link rel=me href=https://koehr.ing>
<link rel=me href=@Koehr@mstdn.io> <link rel=me href=@Koehr@mstdn.io>
<link rel=me href=https://sr.ht/~koehr/> <link rel=me href=https://sr.ht/~koehr>
<link rel=me href=https://git.k0r.in> <link rel=me href=https://git.k0r.in>
<link rel=me href=https://threads.net/@coffee_n_code> <link rel=me href=https://threads.net/@coffee_n_code>
<link rel=me href=https://instagram.com/@coffee_n_code> <link rel=me href=https://instagram.com/@coffee_n_code>
@ -49,26 +49,26 @@
<main id="main"> <main id="main">
<header> <header>
<h1 >Jest mocks are ...different</h1> <h1 :title="Jest mocks are ...different"></h1>
<em ></em> <em :title=""></em>
<br/> <br>
Last updated: <time datetime="Mon, 25 Apr 2022 00:00:00 +0000" >April 25, 2022</time> Last updated: <time datetime="Mon, 25 Apr 2022 00:00:00 +0000" :title="April 25, 2022"></time>
</header> </header>
<div><p>If you want to mock an imported function in Jest in a way that allows you to check if it has been called, you can not do the seemingly straighforward:</p><pre><code class="js">// mock prefix necessary btw <div><p>If you want to mock an imported function in Jest in a way that allows you to check if it has been called, you can not do the seemingly straighforward:</p><pre><code class="js">// mock prefix necessary btw
const mockThatFunction = jest.fn(() =&gt; 'stuff') const mockThatFunction = jest.fn(() =&gt; &apos;stuff&apos;)
jest.mock('@/path/to/module', () =&gt; ({ jest.mock(&apos;@/path/to/module&apos;, () =&gt; ({
thatFunction: mockThatFunction, thatFunction: mockThatFunction,
})) }))
// ...in test descriptions // ...in test descriptions
expect(mockThatFunction).toHaveBeenCalled() expect(mockThatFunction).toHaveBeenCalled()
</code></pre> </code></pre>
<p>This way thatFunction will be undefined without anyone telling you why.</p><p>What you need to do instead:</p><pre><code class="js">import { thatFunction } from '@/path/to/module' <p>This way thatFunction will be undefined without anyone telling you why.</p><p>What you need to do instead:</p><pre><code class="js">import { thatFunction } from &apos;@/path/to/module&apos;
jest.mock('@/path/to/module', () =&gt; ({ jest.mock(&apos;@/path/to/module&apos;, () =&gt; ({
thatFunction: jest.fn(() =&gt; 'stuff'), thatFunction: jest.fn(() =&gt; &apos;stuff&apos;),
})) }))
// ...in test descriptions // ...in test descriptions
@ -87,21 +87,21 @@ expect(thatFunction).toHaveBeenCalled()
<a href="/"> <a href="/">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 832.4 143.1"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 832.4 143.1">
<path id="header-underscore" <path id="header-underscore"
d="M832.4 131.1q0 5.5-3.1 8.6-3 3.4-8.2 3.3h-75.5q-5.2 0-8.2-3.3-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8 0-5.5 3.1-8.7 1.6-1.7 3.7-2.4 2.2-.8 4.5-.8h75.5q5.2 0 8.2 3.2 3 3.1 3 8.7z" /> d="M832.4 131.1q0 5.5-3.1 8.6-3 3.4-8.2 3.3h-75.5q-5.2 0-8.2-3.3-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8 0-5.5 3.1-8.7 1.6-1.7 3.7-2.4 2.2-.8 4.5-.8h75.5q5.2 0 8.2 3.2 3 3.1 3 8.7z"></path>
<path id="header-bracket" <path id="header-bracket"
d="M731.9 81.4q0 6.7-6.5 10.7l-1 .6-74.3 39.2q-2.5 1.3-5.2 1.2-4.8 0-8.1-3.8-3.2-3.6-3.2-8.4 0-3.3 1.7-6 1.8-2.9 4.6-4.4l55.3-29.1-55.3-29q-2.8-1.6-4.6-4.3-1.7-2.7-1.7-6.2 0-4.7 3.2-8.4 3.3-4 8-3.7 2.7 0 5.3 1.2l74.4 39.2q3.3 1.7 5.3 4.7 2 2.8 2 6.5z" /> d="M731.9 81.4q0 6.7-6.5 10.7l-1 .6-74.3 39.2q-2.5 1.3-5.2 1.2-4.8 0-8.1-3.8-3.2-3.6-3.2-8.4 0-3.3 1.7-6 1.8-2.9 4.6-4.4l55.3-29.1-55.3-29q-2.8-1.6-4.6-4.3-1.7-2.7-1.7-6.2 0-4.7 3.2-8.4 3.3-4 8-3.7 2.7 0 5.3 1.2l74.4 39.2q3.3 1.7 5.3 4.7 2 2.8 2 6.5z"></path>
<path id="header-r" <path id="header-r"
d="M588.7 66.5q0 5-3.5 8.5-3.5 3.4-8.1 3.5-4.4 0-8.3-4.3-10-10.7-20.9-10.6-2.2 0-4.3.3-2.1.3-4 1-1.8.6-3.7 1.6-1.7 1-3.4 2.3-1.7 1.3-3.3 2.9-7.8 8.2-7.6 19.7V131q0 5.5-3.1 8.6-3 3.4-8.3 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V51.6q0-5.4 3-8.6 3-3.4 8.3-3.3 2 0 3.7.6 1.8.6 3.3 1.8 1.4 1 2.2 2.7 1 1.5 1.6 3.3 11.8-8.4 27-8.4 10.6 0 21 5 11.3 5.4 17.2 14.5 2.5 3.7 2.5 7.3z" /> d="M588.7 66.5q0 5-3.5 8.5-3.5 3.4-8.1 3.5-4.4 0-8.3-4.3-10-10.7-20.9-10.6-2.2 0-4.3.3-2.1.3-4 1-1.8.6-3.7 1.6-1.7 1-3.4 2.3-1.7 1.3-3.3 2.9-7.8 8.2-7.6 19.7V131q0 5.5-3.1 8.6-3 3.4-8.3 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V51.6q0-5.4 3-8.6 3-3.4 8.3-3.3 2 0 3.7.6 1.8.6 3.3 1.8 1.4 1 2.2 2.7 1 1.5 1.6 3.3 11.8-8.4 27-8.4 10.6 0 21 5 11.3 5.4 17.2 14.5 2.5 3.7 2.5 7.3z"></path>
<path id="header-h" <path id="header-h"
d="M483.9 131.1q0 5.5-3.1 8.6-3 3.4-8.3 3.3-5.2 0-8.2-3.3-3.2-3.1-3.1-8.6V84.8q0-4.6-1.5-8.2-1.4-3.5-4.4-6.9-2.1-2-4.3-3.4-2.2-1.4-4.7-2-2.4-.7-5.3-.7-4.3 0-7.8 1.5-3.3 1.5-6.4 4.6-5.9 6.3-5.8 15v46.4q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v33q1.5-1 3-1.6l3.2-1.2 3.4-1q1.6-.5 3.3-.8l3.5-.4 3.6-.2q4.4 0 8.5 1 4.1.7 7.9 2.4 3.8 1.6 7.3 4.1 3.5 2.5 6.6 5.8Q484 66 484 84.8z" /> d="M483.9 131.1q0 5.5-3.1 8.6-3 3.4-8.3 3.3-5.2 0-8.2-3.3-3.2-3.1-3.1-8.6V84.8q0-4.6-1.5-8.2-1.4-3.5-4.4-6.9-2.1-2-4.3-3.4-2.2-1.4-4.7-2-2.4-.7-5.3-.7-4.3 0-7.8 1.5-3.3 1.5-6.4 4.6-5.9 6.3-5.8 15v46.4q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v33q1.5-1 3-1.6l3.2-1.2 3.4-1q1.6-.5 3.3-.8l3.5-.4 3.6-.2q4.4 0 8.5 1 4.1.7 7.9 2.4 3.8 1.6 7.3 4.1 3.5 2.5 6.6 5.8Q484 66 484 84.8z"></path>
<path id="header-e" <path id="header-e"
d="M387.5 111.1q0 1.2-.3 2.3-.1 1-.5 2l-.9 2q-6.6 12-19.4 19-12 6.6-25.4 6.6-20.8 0-35.8-14.6-15.9-15-15.9-37 0-22.1 15.9-37.1 15-14.6 35.8-14.6 3.9 0 7.8.7 4 .7 8 2.2 9.2 3.1 18.2 10 6 4.6 9.1 9.3 3.3 4.7 3.3 10 0 1.3-.3 2.5-.2 1.3-.7 2.4-1.5 3.4-5 5.3l-56.9 32.2q7.2 4.9 16.5 4.9 7.2 0 12.6-2.5 5.5-2.5 9.7-7.4l.7-1 .8-1 .9-1.3 1-1.5q3.3-4.2 7.4-5.1l1.8-.2q4.4 0 8 3.4 3.6 3.5 3.6 8.5zm-29.9-42.7q-7.2-4.8-16.6-4.8-6 0-11 2-4.9 1.8-9.3 6-4.5 4-6.7 9-2 4.8-2 10.8l.1 2.9z" /> d="M387.5 111.1q0 1.2-.3 2.3-.1 1-.5 2l-.9 2q-6.6 12-19.4 19-12 6.6-25.4 6.6-20.8 0-35.8-14.6-15.9-15-15.9-37 0-22.1 15.9-37.1 15-14.6 35.8-14.6 3.9 0 7.8.7 4 .7 8 2.2 9.2 3.1 18.2 10 6 4.6 9.1 9.3 3.3 4.7 3.3 10 0 1.3-.3 2.5-.2 1.3-.7 2.4-1.5 3.4-5 5.3l-56.9 32.2q7.2 4.9 16.5 4.9 7.2 0 12.6-2.5 5.5-2.5 9.7-7.4l.7-1 .8-1 .9-1.3 1-1.5q3.3-4.2 7.4-5.1l1.8-.2q4.4 0 8 3.4 3.6 3.5 3.6 8.5zm-29.9-42.7q-7.2-4.8-16.6-4.8-6 0-11 2-4.9 1.8-9.3 6-4.5 4-6.7 9-2 4.8-2 10.8l.1 2.9z"></path>
<path id="header-o" <path id="header-o"
d="M286.8 91.4q0 4.2-.6 8.3-.6 4-1.8 7.7-1.1 3.8-2.9 7.4-1.7 3.5-4 6.9-2.4 3.3-5.2 6.1Q258 143 237.7 143T203 128q-14.3-15.2-14.3-36.6 0-21.5 14.3-36.6 14.4-15 34.7-15 4 0 7.8.5 3.9.7 7.5 1.9t7 3q3.3 1.9 6.4 4.3 3.2 2.4 5.9 5.4 14.4 15 14.5 36.5zm-22.6 0q0-2.4-.4-4.5-.2-2.2-.9-4.2-.6-2-1.5-3.9-1-2-2.2-3.7-1.2-1.7-2.8-3.4-4-4.2-8.6-6.1-4.5-2-10-2-11 0-18.7 8.2-7.8 8-7.8 19.6 0 11.4 7.8 19.7 7.8 8 18.6 8 5.6 0 10.1-1.9 4.6-2 8.6-6.1 4-4.3 5.8-9 2-4.9 2-10.7z" /> d="M286.8 91.4q0 4.2-.6 8.3-.6 4-1.8 7.7-1.1 3.8-2.9 7.4-1.7 3.5-4 6.9-2.4 3.3-5.2 6.1Q258 143 237.7 143T203 128q-14.3-15.2-14.3-36.6 0-21.5 14.3-36.6 14.4-15 34.7-15 4 0 7.8.5 3.9.7 7.5 1.9t7 3q3.3 1.9 6.4 4.3 3.2 2.4 5.9 5.4 14.4 15 14.5 36.5zm-22.6 0q0-2.4-.4-4.5-.2-2.2-.9-4.2-.6-2-1.5-3.9-1-2-2.2-3.7-1.2-1.7-2.8-3.4-4-4.2-8.6-6.1-4.5-2-10-2-11 0-18.7 8.2-7.8 8-7.8 19.6 0 11.4 7.8 19.7 7.8 8 18.6 8 5.6 0 10.1-1.9 4.6-2 8.6-6.1 4-4.3 5.8-9 2-4.9 2-10.7z"></path>
<path id="header-k" <path id="header-k"
d="M186.3 131q0 4.7-3.3 8.3-1.5 1.8-3.7 2.7-2 1.1-4.3 1.1-3.5 0-6.6-2L119.2 105v26q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v65.9l49.2-36.1q3.2-2 6.6-2 4.7 0 8 3.7t3.3 8.4q-.2 6-5 9.6l-41 30 41 29.9q2.3 1.7 3.6 4.2 1.4 2.5 1.4 5.4z" /> d="M186.3 131q0 4.7-3.3 8.3-1.5 1.8-3.7 2.7-2 1.1-4.3 1.1-3.5 0-6.6-2L119.2 105v26q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v65.9l49.2-36.1q3.2-2 6.6-2 4.7 0 8 3.7t3.3 8.4q-.2 6-5 9.6l-41 30 41 29.9q2.3 1.7 3.6 4.2 1.4 2.5 1.4 5.4z"></path>
<path id="header-tilde" <path id="header-tilde"
d="M73.1 91q0 2-.6 3.9T71 98.6q-3.2 5.7-8.9 8.5-5.6 2.8-12.9 2.8-8.8 0-18-7.8-2.4-2.3-4.5-3.7-2.1-1.5-3-1.7-1.5 0-2.1.3l-.8 1.3q-.3.7-.8 1.2l-1 1-.9.8q-2.7 2-6.4 2-1.7 0-3.2-.3-1.4-.3-3-1.1-1.5-.8-2.6-2.1-2.8-3.1-2.8-8v-1.3q0-.7.2-1.2l.2-1 .4-1 .4-1q.1-.6.5-1.1l.5-1q3.2-5.7 8.8-8.5 5.7-2.9 13-2.9 3.2 0 6.2 1 3 .9 6 2.7 2.9 1.6 5.7 4.2 5.2 4.6 7.6 5.4 1 0 1.6-.2l.7-.4q.3-.1.5-.4 3.6-5.6 9.2-5.6 5.7 0 8.8 3.5 2.8 3 2.8 8z" /> d="M73.1 91q0 2-.6 3.9T71 98.6q-3.2 5.7-8.9 8.5-5.6 2.8-12.9 2.8-8.8 0-18-7.8-2.4-2.3-4.5-3.7-2.1-1.5-3-1.7-1.5 0-2.1.3l-.8 1.3q-.3.7-.8 1.2l-1 1-.9.8q-2.7 2-6.4 2-1.7 0-3.2-.3-1.4-.3-3-1.1-1.5-.8-2.6-2.1-2.8-3.1-2.8-8v-1.3q0-.7.2-1.2l.2-1 .4-1 .4-1q.1-.6.5-1.1l.5-1q3.2-5.7 8.8-8.5 5.7-2.9 13-2.9 3.2 0 6.2 1 3 .9 6 2.7 2.9 1.6 5.7 4.2 5.2 4.6 7.6 5.4 1 0 1.6-.2l.7-.4q.3-.1.5-.4 3.6-5.6 9.2-5.6 5.7 0 8.8 3.5 2.8 3 2.8 8z"></path>
</svg> </svg>
Homepage of Homepage of
<div class=p-name> <div class=p-name>

View file

@ -3,7 +3,7 @@
<head id="head"> <head id="head">
<meta charset=utf-8> <meta charset=utf-8>
<title id=title >the codeartist — programmer and engineer based in BerlinDisallowed Focussed Tests and how it saved my day</title> <title id="title " var="the codeartist — programmer and engineer based in Berlin"></title>
<meta name=description content="The personal page and weblog of Norman Köhring"> <meta name=description content="The personal page and weblog of Norman Köhring">
<meta name=author content="Norman Köhring"> <meta name=author content="Norman Köhring">
<meta name=DC.title content="the codeartist — programmer and engineer based in Berlin"> <meta name=DC.title content="the codeartist — programmer and engineer based in Berlin">
@ -15,8 +15,8 @@
<meta name="og:title" content="Disallowed Focussed Tests and how it saved my day // the codeartist"> <meta name="og:title" content="Disallowed Focussed Tests and how it saved my day // the codeartist">
<meta property="og:type" content="website"> <meta property="og:type" content="website">
<meta http-equiv="x-ua-compatible" content="ie=edge"/> <meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"/> <meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no">
<meta name=ICBM content="52.4595, 13.5335"> <meta name=ICBM content="52.4595, 13.5335">
<meta name=geo.position content="52.4595; 13.5335"> <meta name=geo.position content="52.4595; 13.5335">
@ -26,7 +26,7 @@
<link rel=me href=https://k0r.in> <link rel=me href=https://k0r.in>
<link rel=me href=https://koehr.ing> <link rel=me href=https://koehr.ing>
<link rel=me href=@Koehr@mstdn.io> <link rel=me href=@Koehr@mstdn.io>
<link rel=me href=https://sr.ht/~koehr/> <link rel=me href=https://sr.ht/~koehr>
<link rel=me href=https://git.k0r.in> <link rel=me href=https://git.k0r.in>
<link rel=me href=https://threads.net/@coffee_n_code> <link rel=me href=https://threads.net/@coffee_n_code>
<link rel=me href=https://instagram.com/@coffee_n_code> <link rel=me href=https://instagram.com/@coffee_n_code>
@ -49,13 +49,13 @@
<main id="main"> <main id="main">
<header> <header>
<h1 >Disallowed Focussed Tests and how it saved my day</h1> <h1 :title="Disallowed Focussed Tests and how it saved my day"></h1>
<em ></em> <em :title=""></em>
<br/> <br>
Last updated: <time datetime="Wed, 15 Jun 2022 00:00:00 +0000" >June 15, 2022</time> Last updated: <time datetime="Wed, 15 Jun 2022 00:00:00 +0000" :title="June 15, 2022"></time>
</header> </header>
<div ><p>Today I was about to push a focussed test. A focussed test, you ask?</p><p>In Jest (and others) one can run only a specific test, by writing <code>it.only(...</code>. Pushing this to production might create some funny or not so funny side effects though. Luckily there is the <code>no-focussed-tests</code> linter rule in <a href="https://github.com/jest-community/eslint-plugin-jest">eslint-plugin-jest</a>.</p></div> <div><p>Today I was about to push a focussed test. A focussed test, you ask?</p><p>In Jest (and others) one can run only a specific test, by writing <code>it.only(...</code>. Pushing this to production might create some funny or not so funny side effects though. Luckily there is the <code>no-focussed-tests</code> linter rule in <a href="https://github.com/jest-community/eslint-plugin-jest" target="_blank">eslint-plugin-jest</a>.</p></div>
<ol class="til"> <ol class="til">
<li></li> <li></li>
@ -68,21 +68,21 @@
<a href="/"> <a href="/">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 832.4 143.1"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 832.4 143.1">
<path id="header-underscore" <path id="header-underscore"
d="M832.4 131.1q0 5.5-3.1 8.6-3 3.4-8.2 3.3h-75.5q-5.2 0-8.2-3.3-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8 0-5.5 3.1-8.7 1.6-1.7 3.7-2.4 2.2-.8 4.5-.8h75.5q5.2 0 8.2 3.2 3 3.1 3 8.7z" /> d="M832.4 131.1q0 5.5-3.1 8.6-3 3.4-8.2 3.3h-75.5q-5.2 0-8.2-3.3-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8 0-5.5 3.1-8.7 1.6-1.7 3.7-2.4 2.2-.8 4.5-.8h75.5q5.2 0 8.2 3.2 3 3.1 3 8.7z"></path>
<path id="header-bracket" <path id="header-bracket"
d="M731.9 81.4q0 6.7-6.5 10.7l-1 .6-74.3 39.2q-2.5 1.3-5.2 1.2-4.8 0-8.1-3.8-3.2-3.6-3.2-8.4 0-3.3 1.7-6 1.8-2.9 4.6-4.4l55.3-29.1-55.3-29q-2.8-1.6-4.6-4.3-1.7-2.7-1.7-6.2 0-4.7 3.2-8.4 3.3-4 8-3.7 2.7 0 5.3 1.2l74.4 39.2q3.3 1.7 5.3 4.7 2 2.8 2 6.5z" /> d="M731.9 81.4q0 6.7-6.5 10.7l-1 .6-74.3 39.2q-2.5 1.3-5.2 1.2-4.8 0-8.1-3.8-3.2-3.6-3.2-8.4 0-3.3 1.7-6 1.8-2.9 4.6-4.4l55.3-29.1-55.3-29q-2.8-1.6-4.6-4.3-1.7-2.7-1.7-6.2 0-4.7 3.2-8.4 3.3-4 8-3.7 2.7 0 5.3 1.2l74.4 39.2q3.3 1.7 5.3 4.7 2 2.8 2 6.5z"></path>
<path id="header-r" <path id="header-r"
d="M588.7 66.5q0 5-3.5 8.5-3.5 3.4-8.1 3.5-4.4 0-8.3-4.3-10-10.7-20.9-10.6-2.2 0-4.3.3-2.1.3-4 1-1.8.6-3.7 1.6-1.7 1-3.4 2.3-1.7 1.3-3.3 2.9-7.8 8.2-7.6 19.7V131q0 5.5-3.1 8.6-3 3.4-8.3 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V51.6q0-5.4 3-8.6 3-3.4 8.3-3.3 2 0 3.7.6 1.8.6 3.3 1.8 1.4 1 2.2 2.7 1 1.5 1.6 3.3 11.8-8.4 27-8.4 10.6 0 21 5 11.3 5.4 17.2 14.5 2.5 3.7 2.5 7.3z" /> d="M588.7 66.5q0 5-3.5 8.5-3.5 3.4-8.1 3.5-4.4 0-8.3-4.3-10-10.7-20.9-10.6-2.2 0-4.3.3-2.1.3-4 1-1.8.6-3.7 1.6-1.7 1-3.4 2.3-1.7 1.3-3.3 2.9-7.8 8.2-7.6 19.7V131q0 5.5-3.1 8.6-3 3.4-8.3 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V51.6q0-5.4 3-8.6 3-3.4 8.3-3.3 2 0 3.7.6 1.8.6 3.3 1.8 1.4 1 2.2 2.7 1 1.5 1.6 3.3 11.8-8.4 27-8.4 10.6 0 21 5 11.3 5.4 17.2 14.5 2.5 3.7 2.5 7.3z"></path>
<path id="header-h" <path id="header-h"
d="M483.9 131.1q0 5.5-3.1 8.6-3 3.4-8.3 3.3-5.2 0-8.2-3.3-3.2-3.1-3.1-8.6V84.8q0-4.6-1.5-8.2-1.4-3.5-4.4-6.9-2.1-2-4.3-3.4-2.2-1.4-4.7-2-2.4-.7-5.3-.7-4.3 0-7.8 1.5-3.3 1.5-6.4 4.6-5.9 6.3-5.8 15v46.4q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v33q1.5-1 3-1.6l3.2-1.2 3.4-1q1.6-.5 3.3-.8l3.5-.4 3.6-.2q4.4 0 8.5 1 4.1.7 7.9 2.4 3.8 1.6 7.3 4.1 3.5 2.5 6.6 5.8Q484 66 484 84.8z" /> d="M483.9 131.1q0 5.5-3.1 8.6-3 3.4-8.3 3.3-5.2 0-8.2-3.3-3.2-3.1-3.1-8.6V84.8q0-4.6-1.5-8.2-1.4-3.5-4.4-6.9-2.1-2-4.3-3.4-2.2-1.4-4.7-2-2.4-.7-5.3-.7-4.3 0-7.8 1.5-3.3 1.5-6.4 4.6-5.9 6.3-5.8 15v46.4q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v33q1.5-1 3-1.6l3.2-1.2 3.4-1q1.6-.5 3.3-.8l3.5-.4 3.6-.2q4.4 0 8.5 1 4.1.7 7.9 2.4 3.8 1.6 7.3 4.1 3.5 2.5 6.6 5.8Q484 66 484 84.8z"></path>
<path id="header-e" <path id="header-e"
d="M387.5 111.1q0 1.2-.3 2.3-.1 1-.5 2l-.9 2q-6.6 12-19.4 19-12 6.6-25.4 6.6-20.8 0-35.8-14.6-15.9-15-15.9-37 0-22.1 15.9-37.1 15-14.6 35.8-14.6 3.9 0 7.8.7 4 .7 8 2.2 9.2 3.1 18.2 10 6 4.6 9.1 9.3 3.3 4.7 3.3 10 0 1.3-.3 2.5-.2 1.3-.7 2.4-1.5 3.4-5 5.3l-56.9 32.2q7.2 4.9 16.5 4.9 7.2 0 12.6-2.5 5.5-2.5 9.7-7.4l.7-1 .8-1 .9-1.3 1-1.5q3.3-4.2 7.4-5.1l1.8-.2q4.4 0 8 3.4 3.6 3.5 3.6 8.5zm-29.9-42.7q-7.2-4.8-16.6-4.8-6 0-11 2-4.9 1.8-9.3 6-4.5 4-6.7 9-2 4.8-2 10.8l.1 2.9z" /> d="M387.5 111.1q0 1.2-.3 2.3-.1 1-.5 2l-.9 2q-6.6 12-19.4 19-12 6.6-25.4 6.6-20.8 0-35.8-14.6-15.9-15-15.9-37 0-22.1 15.9-37.1 15-14.6 35.8-14.6 3.9 0 7.8.7 4 .7 8 2.2 9.2 3.1 18.2 10 6 4.6 9.1 9.3 3.3 4.7 3.3 10 0 1.3-.3 2.5-.2 1.3-.7 2.4-1.5 3.4-5 5.3l-56.9 32.2q7.2 4.9 16.5 4.9 7.2 0 12.6-2.5 5.5-2.5 9.7-7.4l.7-1 .8-1 .9-1.3 1-1.5q3.3-4.2 7.4-5.1l1.8-.2q4.4 0 8 3.4 3.6 3.5 3.6 8.5zm-29.9-42.7q-7.2-4.8-16.6-4.8-6 0-11 2-4.9 1.8-9.3 6-4.5 4-6.7 9-2 4.8-2 10.8l.1 2.9z"></path>
<path id="header-o" <path id="header-o"
d="M286.8 91.4q0 4.2-.6 8.3-.6 4-1.8 7.7-1.1 3.8-2.9 7.4-1.7 3.5-4 6.9-2.4 3.3-5.2 6.1Q258 143 237.7 143T203 128q-14.3-15.2-14.3-36.6 0-21.5 14.3-36.6 14.4-15 34.7-15 4 0 7.8.5 3.9.7 7.5 1.9t7 3q3.3 1.9 6.4 4.3 3.2 2.4 5.9 5.4 14.4 15 14.5 36.5zm-22.6 0q0-2.4-.4-4.5-.2-2.2-.9-4.2-.6-2-1.5-3.9-1-2-2.2-3.7-1.2-1.7-2.8-3.4-4-4.2-8.6-6.1-4.5-2-10-2-11 0-18.7 8.2-7.8 8-7.8 19.6 0 11.4 7.8 19.7 7.8 8 18.6 8 5.6 0 10.1-1.9 4.6-2 8.6-6.1 4-4.3 5.8-9 2-4.9 2-10.7z" /> d="M286.8 91.4q0 4.2-.6 8.3-.6 4-1.8 7.7-1.1 3.8-2.9 7.4-1.7 3.5-4 6.9-2.4 3.3-5.2 6.1Q258 143 237.7 143T203 128q-14.3-15.2-14.3-36.6 0-21.5 14.3-36.6 14.4-15 34.7-15 4 0 7.8.5 3.9.7 7.5 1.9t7 3q3.3 1.9 6.4 4.3 3.2 2.4 5.9 5.4 14.4 15 14.5 36.5zm-22.6 0q0-2.4-.4-4.5-.2-2.2-.9-4.2-.6-2-1.5-3.9-1-2-2.2-3.7-1.2-1.7-2.8-3.4-4-4.2-8.6-6.1-4.5-2-10-2-11 0-18.7 8.2-7.8 8-7.8 19.6 0 11.4 7.8 19.7 7.8 8 18.6 8 5.6 0 10.1-1.9 4.6-2 8.6-6.1 4-4.3 5.8-9 2-4.9 2-10.7z"></path>
<path id="header-k" <path id="header-k"
d="M186.3 131q0 4.7-3.3 8.3-1.5 1.8-3.7 2.7-2 1.1-4.3 1.1-3.5 0-6.6-2L119.2 105v26q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v65.9l49.2-36.1q3.2-2 6.6-2 4.7 0 8 3.7t3.3 8.4q-.2 6-5 9.6l-41 30 41 29.9q2.3 1.7 3.6 4.2 1.4 2.5 1.4 5.4z" /> d="M186.3 131q0 4.7-3.3 8.3-1.5 1.8-3.7 2.7-2 1.1-4.3 1.1-3.5 0-6.6-2L119.2 105v26q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v65.9l49.2-36.1q3.2-2 6.6-2 4.7 0 8 3.7t3.3 8.4q-.2 6-5 9.6l-41 30 41 29.9q2.3 1.7 3.6 4.2 1.4 2.5 1.4 5.4z"></path>
<path id="header-tilde" <path id="header-tilde"
d="M73.1 91q0 2-.6 3.9T71 98.6q-3.2 5.7-8.9 8.5-5.6 2.8-12.9 2.8-8.8 0-18-7.8-2.4-2.3-4.5-3.7-2.1-1.5-3-1.7-1.5 0-2.1.3l-.8 1.3q-.3.7-.8 1.2l-1 1-.9.8q-2.7 2-6.4 2-1.7 0-3.2-.3-1.4-.3-3-1.1-1.5-.8-2.6-2.1-2.8-3.1-2.8-8v-1.3q0-.7.2-1.2l.2-1 .4-1 .4-1q.1-.6.5-1.1l.5-1q3.2-5.7 8.8-8.5 5.7-2.9 13-2.9 3.2 0 6.2 1 3 .9 6 2.7 2.9 1.6 5.7 4.2 5.2 4.6 7.6 5.4 1 0 1.6-.2l.7-.4q.3-.1.5-.4 3.6-5.6 9.2-5.6 5.7 0 8.8 3.5 2.8 3 2.8 8z" /> d="M73.1 91q0 2-.6 3.9T71 98.6q-3.2 5.7-8.9 8.5-5.6 2.8-12.9 2.8-8.8 0-18-7.8-2.4-2.3-4.5-3.7-2.1-1.5-3-1.7-1.5 0-2.1.3l-.8 1.3q-.3.7-.8 1.2l-1 1-.9.8q-2.7 2-6.4 2-1.7 0-3.2-.3-1.4-.3-3-1.1-1.5-.8-2.6-2.1-2.8-3.1-2.8-8v-1.3q0-.7.2-1.2l.2-1 .4-1 .4-1q.1-.6.5-1.1l.5-1q3.2-5.7 8.8-8.5 5.7-2.9 13-2.9 3.2 0 6.2 1 3 .9 6 2.7 2.9 1.6 5.7 4.2 5.2 4.6 7.6 5.4 1 0 1.6-.2l.7-.4q.3-.1.5-.4 3.6-5.6 9.2-5.6 5.7 0 8.8 3.5 2.8 3 2.8 8z"></path>
</svg> </svg>
Homepage of Homepage of
<div class=p-name> <div class=p-name>

View file

@ -3,7 +3,7 @@
<head id="head"> <head id="head">
<meta charset=utf-8> <meta charset=utf-8>
<title id=title >the codeartist — programmer and engineer based in BerlinRob Pike's 5 Rules of Programming</title> <title id="title " var="the codeartist — programmer and engineer based in Berlin"></title>
<meta name=description content="The personal page and weblog of Norman Köhring"> <meta name=description content="The personal page and weblog of Norman Köhring">
<meta name=author content="Norman Köhring"> <meta name=author content="Norman Köhring">
<meta name=DC.title content="the codeartist — programmer and engineer based in Berlin"> <meta name=DC.title content="the codeartist — programmer and engineer based in Berlin">
@ -11,12 +11,12 @@
<meta name="twitter:site" content="@koehr_in"> <meta name="twitter:site" content="@koehr_in">
<meta name="twitter:author" content="@koehr_in"> <meta name="twitter:author" content="@koehr_in">
<meta name=twitter:description content="The personal page and weblog of the codeartist Norman Köhring"> <meta name=twitter:description content="The personal page and weblog of the codeartist Norman Köhring">
<meta name="twitter:title" content="Rob Pike's 5 Rules of Programming // the codeartist"> <meta name="twitter:title" content="Rob Pike&apos;s 5 Rules of Programming // the codeartist">
<meta name="og:title" content="Rob Pike's 5 Rules of Programming // the codeartist"> <meta name="og:title" content="Rob Pike&apos;s 5 Rules of Programming // the codeartist">
<meta property="og:type" content="website"> <meta property="og:type" content="website">
<meta http-equiv="x-ua-compatible" content="ie=edge"/> <meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"/> <meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no">
<meta name=ICBM content="52.4595, 13.5335"> <meta name=ICBM content="52.4595, 13.5335">
<meta name=geo.position content="52.4595; 13.5335"> <meta name=geo.position content="52.4595; 13.5335">
@ -26,7 +26,7 @@
<link rel=me href=https://k0r.in> <link rel=me href=https://k0r.in>
<link rel=me href=https://koehr.ing> <link rel=me href=https://koehr.ing>
<link rel=me href=@Koehr@mstdn.io> <link rel=me href=@Koehr@mstdn.io>
<link rel=me href=https://sr.ht/~koehr/> <link rel=me href=https://sr.ht/~koehr>
<link rel=me href=https://git.k0r.in> <link rel=me href=https://git.k0r.in>
<link rel=me href=https://threads.net/@coffee_n_code> <link rel=me href=https://threads.net/@coffee_n_code>
<link rel=me href=https://instagram.com/@coffee_n_code> <link rel=me href=https://instagram.com/@coffee_n_code>
@ -49,13 +49,13 @@
<main id="main"> <main id="main">
<header> <header>
<h1 >Rob Pike's 5 Rules of Programming</h1> <h1 :title="Rob Pike&apos;s 5 Rules of Programming"></h1>
<em ></em> <em :title=""></em>
<br/> <br>
Last updated: <time datetime="Sat, 11 May 2024 00:00:00 +0000" >May 11, 2024</time> Last updated: <time datetime="Sat, 11 May 2024 00:00:00 +0000" :title="May 11, 2024"></time>
</header> </header>
<div ><ol><li><p>You can't tell where a program is going to spend its time. Bottlenecks occur in surprising places, so don't try to second guess and put in a speed hack until you've proven that's where the bottleneck is.</p></li><li><p>Measure. Don't tune for speed until you've measured, and even then don't unless one part of the code overwhelms the rest.</p></li><li><p>Fancy algorithms are slow when n is small, and n is usually small. Fancy algorithms have big constants. Until you know that n is frequently going to be big, don't get fancy. (Even if n does get big, use Rule 2 first.)</p></li><li><p>Fancy algorithms are buggier than simple ones, and they're much harder to implement. Use simple algorithms as well as simple data structures.</p></li><li><p>Data dominates. If you've chosen the right data structures and organized things well, the algorithms will almost always be self-evident. Data structures, not algorithms, are central to programming.</p></li></ol><p>Pike's rules 1 and 2 restate Tony Hoare's famous maxim "Premature optimization is the root of all evil." Ken Thompson rephrased Pike's rules 3 and 4 as "When in doubt, use brute force.". Rules 3 and 4 are instances of the design philosophy KISS. Rule 5 was previously stated by Fred Brooks in The Mythical Man-Month. Rule 5 is often shortened to "write stupid code that uses smart objects".</p></div> <div><ol><li>You can't tell where a program is going to spend its time. Bottlenecks occur in surprising places, so don't try to second guess and put in a speed hack until you've proven that's where the bottleneck is.</li><li>Measure. Don't tune for speed until you've measured, and even then don't unless one part of the code overwhelms the rest.</li><li>Fancy algorithms are slow when n is small, and n is usually small. Fancy algorithms have big constants. Until you know that n is frequently going to be big, don't get fancy. (Even if n does get big, use Rule 2 first.)</li><li>Fancy algorithms are buggier than simple ones, and they're much harder to implement. Use simple algorithms as well as simple data structures.</li><li>Data dominates. If you've chosen the right data structures and organized things well, the algorithms will almost always be self-evident. Data structures, not algorithms, are central to programming.</li></ol><p>Pike's rules 1 and 2 restate Tony Hoare's famous maxim "Premature optimization is the root of all evil." Ken Thompson rephrased Pike's rules 3 and 4 as "When in doubt, use brute force.". Rules 3 and 4 are instances of the design philosophy KISS. Rule 5 was previously stated by Fred Brooks in The Mythical Man-Month. Rule 5 is often shortened to "write stupid code that uses smart objects".</p></div>
<ol class="til"> <ol class="til">
<li></li> <li></li>
@ -68,21 +68,21 @@
<a href="/"> <a href="/">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 832.4 143.1"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 832.4 143.1">
<path id="header-underscore" <path id="header-underscore"
d="M832.4 131.1q0 5.5-3.1 8.6-3 3.4-8.2 3.3h-75.5q-5.2 0-8.2-3.3-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8 0-5.5 3.1-8.7 1.6-1.7 3.7-2.4 2.2-.8 4.5-.8h75.5q5.2 0 8.2 3.2 3 3.1 3 8.7z" /> d="M832.4 131.1q0 5.5-3.1 8.6-3 3.4-8.2 3.3h-75.5q-5.2 0-8.2-3.3-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8 0-5.5 3.1-8.7 1.6-1.7 3.7-2.4 2.2-.8 4.5-.8h75.5q5.2 0 8.2 3.2 3 3.1 3 8.7z"></path>
<path id="header-bracket" <path id="header-bracket"
d="M731.9 81.4q0 6.7-6.5 10.7l-1 .6-74.3 39.2q-2.5 1.3-5.2 1.2-4.8 0-8.1-3.8-3.2-3.6-3.2-8.4 0-3.3 1.7-6 1.8-2.9 4.6-4.4l55.3-29.1-55.3-29q-2.8-1.6-4.6-4.3-1.7-2.7-1.7-6.2 0-4.7 3.2-8.4 3.3-4 8-3.7 2.7 0 5.3 1.2l74.4 39.2q3.3 1.7 5.3 4.7 2 2.8 2 6.5z" /> d="M731.9 81.4q0 6.7-6.5 10.7l-1 .6-74.3 39.2q-2.5 1.3-5.2 1.2-4.8 0-8.1-3.8-3.2-3.6-3.2-8.4 0-3.3 1.7-6 1.8-2.9 4.6-4.4l55.3-29.1-55.3-29q-2.8-1.6-4.6-4.3-1.7-2.7-1.7-6.2 0-4.7 3.2-8.4 3.3-4 8-3.7 2.7 0 5.3 1.2l74.4 39.2q3.3 1.7 5.3 4.7 2 2.8 2 6.5z"></path>
<path id="header-r" <path id="header-r"
d="M588.7 66.5q0 5-3.5 8.5-3.5 3.4-8.1 3.5-4.4 0-8.3-4.3-10-10.7-20.9-10.6-2.2 0-4.3.3-2.1.3-4 1-1.8.6-3.7 1.6-1.7 1-3.4 2.3-1.7 1.3-3.3 2.9-7.8 8.2-7.6 19.7V131q0 5.5-3.1 8.6-3 3.4-8.3 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V51.6q0-5.4 3-8.6 3-3.4 8.3-3.3 2 0 3.7.6 1.8.6 3.3 1.8 1.4 1 2.2 2.7 1 1.5 1.6 3.3 11.8-8.4 27-8.4 10.6 0 21 5 11.3 5.4 17.2 14.5 2.5 3.7 2.5 7.3z" /> d="M588.7 66.5q0 5-3.5 8.5-3.5 3.4-8.1 3.5-4.4 0-8.3-4.3-10-10.7-20.9-10.6-2.2 0-4.3.3-2.1.3-4 1-1.8.6-3.7 1.6-1.7 1-3.4 2.3-1.7 1.3-3.3 2.9-7.8 8.2-7.6 19.7V131q0 5.5-3.1 8.6-3 3.4-8.3 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V51.6q0-5.4 3-8.6 3-3.4 8.3-3.3 2 0 3.7.6 1.8.6 3.3 1.8 1.4 1 2.2 2.7 1 1.5 1.6 3.3 11.8-8.4 27-8.4 10.6 0 21 5 11.3 5.4 17.2 14.5 2.5 3.7 2.5 7.3z"></path>
<path id="header-h" <path id="header-h"
d="M483.9 131.1q0 5.5-3.1 8.6-3 3.4-8.3 3.3-5.2 0-8.2-3.3-3.2-3.1-3.1-8.6V84.8q0-4.6-1.5-8.2-1.4-3.5-4.4-6.9-2.1-2-4.3-3.4-2.2-1.4-4.7-2-2.4-.7-5.3-.7-4.3 0-7.8 1.5-3.3 1.5-6.4 4.6-5.9 6.3-5.8 15v46.4q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v33q1.5-1 3-1.6l3.2-1.2 3.4-1q1.6-.5 3.3-.8l3.5-.4 3.6-.2q4.4 0 8.5 1 4.1.7 7.9 2.4 3.8 1.6 7.3 4.1 3.5 2.5 6.6 5.8Q484 66 484 84.8z" /> d="M483.9 131.1q0 5.5-3.1 8.6-3 3.4-8.3 3.3-5.2 0-8.2-3.3-3.2-3.1-3.1-8.6V84.8q0-4.6-1.5-8.2-1.4-3.5-4.4-6.9-2.1-2-4.3-3.4-2.2-1.4-4.7-2-2.4-.7-5.3-.7-4.3 0-7.8 1.5-3.3 1.5-6.4 4.6-5.9 6.3-5.8 15v46.4q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v33q1.5-1 3-1.6l3.2-1.2 3.4-1q1.6-.5 3.3-.8l3.5-.4 3.6-.2q4.4 0 8.5 1 4.1.7 7.9 2.4 3.8 1.6 7.3 4.1 3.5 2.5 6.6 5.8Q484 66 484 84.8z"></path>
<path id="header-e" <path id="header-e"
d="M387.5 111.1q0 1.2-.3 2.3-.1 1-.5 2l-.9 2q-6.6 12-19.4 19-12 6.6-25.4 6.6-20.8 0-35.8-14.6-15.9-15-15.9-37 0-22.1 15.9-37.1 15-14.6 35.8-14.6 3.9 0 7.8.7 4 .7 8 2.2 9.2 3.1 18.2 10 6 4.6 9.1 9.3 3.3 4.7 3.3 10 0 1.3-.3 2.5-.2 1.3-.7 2.4-1.5 3.4-5 5.3l-56.9 32.2q7.2 4.9 16.5 4.9 7.2 0 12.6-2.5 5.5-2.5 9.7-7.4l.7-1 .8-1 .9-1.3 1-1.5q3.3-4.2 7.4-5.1l1.8-.2q4.4 0 8 3.4 3.6 3.5 3.6 8.5zm-29.9-42.7q-7.2-4.8-16.6-4.8-6 0-11 2-4.9 1.8-9.3 6-4.5 4-6.7 9-2 4.8-2 10.8l.1 2.9z" /> d="M387.5 111.1q0 1.2-.3 2.3-.1 1-.5 2l-.9 2q-6.6 12-19.4 19-12 6.6-25.4 6.6-20.8 0-35.8-14.6-15.9-15-15.9-37 0-22.1 15.9-37.1 15-14.6 35.8-14.6 3.9 0 7.8.7 4 .7 8 2.2 9.2 3.1 18.2 10 6 4.6 9.1 9.3 3.3 4.7 3.3 10 0 1.3-.3 2.5-.2 1.3-.7 2.4-1.5 3.4-5 5.3l-56.9 32.2q7.2 4.9 16.5 4.9 7.2 0 12.6-2.5 5.5-2.5 9.7-7.4l.7-1 .8-1 .9-1.3 1-1.5q3.3-4.2 7.4-5.1l1.8-.2q4.4 0 8 3.4 3.6 3.5 3.6 8.5zm-29.9-42.7q-7.2-4.8-16.6-4.8-6 0-11 2-4.9 1.8-9.3 6-4.5 4-6.7 9-2 4.8-2 10.8l.1 2.9z"></path>
<path id="header-o" <path id="header-o"
d="M286.8 91.4q0 4.2-.6 8.3-.6 4-1.8 7.7-1.1 3.8-2.9 7.4-1.7 3.5-4 6.9-2.4 3.3-5.2 6.1Q258 143 237.7 143T203 128q-14.3-15.2-14.3-36.6 0-21.5 14.3-36.6 14.4-15 34.7-15 4 0 7.8.5 3.9.7 7.5 1.9t7 3q3.3 1.9 6.4 4.3 3.2 2.4 5.9 5.4 14.4 15 14.5 36.5zm-22.6 0q0-2.4-.4-4.5-.2-2.2-.9-4.2-.6-2-1.5-3.9-1-2-2.2-3.7-1.2-1.7-2.8-3.4-4-4.2-8.6-6.1-4.5-2-10-2-11 0-18.7 8.2-7.8 8-7.8 19.6 0 11.4 7.8 19.7 7.8 8 18.6 8 5.6 0 10.1-1.9 4.6-2 8.6-6.1 4-4.3 5.8-9 2-4.9 2-10.7z" /> d="M286.8 91.4q0 4.2-.6 8.3-.6 4-1.8 7.7-1.1 3.8-2.9 7.4-1.7 3.5-4 6.9-2.4 3.3-5.2 6.1Q258 143 237.7 143T203 128q-14.3-15.2-14.3-36.6 0-21.5 14.3-36.6 14.4-15 34.7-15 4 0 7.8.5 3.9.7 7.5 1.9t7 3q3.3 1.9 6.4 4.3 3.2 2.4 5.9 5.4 14.4 15 14.5 36.5zm-22.6 0q0-2.4-.4-4.5-.2-2.2-.9-4.2-.6-2-1.5-3.9-1-2-2.2-3.7-1.2-1.7-2.8-3.4-4-4.2-8.6-6.1-4.5-2-10-2-11 0-18.7 8.2-7.8 8-7.8 19.6 0 11.4 7.8 19.7 7.8 8 18.6 8 5.6 0 10.1-1.9 4.6-2 8.6-6.1 4-4.3 5.8-9 2-4.9 2-10.7z"></path>
<path id="header-k" <path id="header-k"
d="M186.3 131q0 4.7-3.3 8.3-1.5 1.8-3.7 2.7-2 1.1-4.3 1.1-3.5 0-6.6-2L119.2 105v26q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v65.9l49.2-36.1q3.2-2 6.6-2 4.7 0 8 3.7t3.3 8.4q-.2 6-5 9.6l-41 30 41 29.9q2.3 1.7 3.6 4.2 1.4 2.5 1.4 5.4z" /> d="M186.3 131q0 4.7-3.3 8.3-1.5 1.8-3.7 2.7-2 1.1-4.3 1.1-3.5 0-6.6-2L119.2 105v26q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v65.9l49.2-36.1q3.2-2 6.6-2 4.7 0 8 3.7t3.3 8.4q-.2 6-5 9.6l-41 30 41 29.9q2.3 1.7 3.6 4.2 1.4 2.5 1.4 5.4z"></path>
<path id="header-tilde" <path id="header-tilde"
d="M73.1 91q0 2-.6 3.9T71 98.6q-3.2 5.7-8.9 8.5-5.6 2.8-12.9 2.8-8.8 0-18-7.8-2.4-2.3-4.5-3.7-2.1-1.5-3-1.7-1.5 0-2.1.3l-.8 1.3q-.3.7-.8 1.2l-1 1-.9.8q-2.7 2-6.4 2-1.7 0-3.2-.3-1.4-.3-3-1.1-1.5-.8-2.6-2.1-2.8-3.1-2.8-8v-1.3q0-.7.2-1.2l.2-1 .4-1 .4-1q.1-.6.5-1.1l.5-1q3.2-5.7 8.8-8.5 5.7-2.9 13-2.9 3.2 0 6.2 1 3 .9 6 2.7 2.9 1.6 5.7 4.2 5.2 4.6 7.6 5.4 1 0 1.6-.2l.7-.4q.3-.1.5-.4 3.6-5.6 9.2-5.6 5.7 0 8.8 3.5 2.8 3 2.8 8z" /> d="M73.1 91q0 2-.6 3.9T71 98.6q-3.2 5.7-8.9 8.5-5.6 2.8-12.9 2.8-8.8 0-18-7.8-2.4-2.3-4.5-3.7-2.1-1.5-3-1.7-1.5 0-2.1.3l-.8 1.3q-.3.7-.8 1.2l-1 1-.9.8q-2.7 2-6.4 2-1.7 0-3.2-.3-1.4-.3-3-1.1-1.5-.8-2.6-2.1-2.8-3.1-2.8-8v-1.3q0-.7.2-1.2l.2-1 .4-1 .4-1q.1-.6.5-1.1l.5-1q3.2-5.7 8.8-8.5 5.7-2.9 13-2.9 3.2 0 6.2 1 3 .9 6 2.7 2.9 1.6 5.7 4.2 5.2 4.6 7.6 5.4 1 0 1.6-.2l.7-.4q.3-.1.5-.4 3.6-5.6 9.2-5.6 5.7 0 8.8 3.5 2.8 3 2.8 8z"></path>
</svg> </svg>
Homepage of Homepage of
<div class=p-name> <div class=p-name>

View file

@ -3,7 +3,7 @@
<head id="head"> <head id="head">
<meta charset=utf-8> <meta charset=utf-8>
<title id=title >the codeartist — programmer and engineer based in BerlinSort list of strings in Javascript</title> <title id="title " var="the codeartist — programmer and engineer based in Berlin"></title>
<meta name=description content="The personal page and weblog of Norman Köhring"> <meta name=description content="The personal page and weblog of Norman Köhring">
<meta name=author content="Norman Köhring"> <meta name=author content="Norman Köhring">
<meta name=DC.title content="the codeartist — programmer and engineer based in Berlin"> <meta name=DC.title content="the codeartist — programmer and engineer based in Berlin">
@ -15,8 +15,8 @@
<meta name="og:title" content="Sort list of strings in Javascript // the codeartist"> <meta name="og:title" content="Sort list of strings in Javascript // the codeartist">
<meta property="og:type" content="website"> <meta property="og:type" content="website">
<meta http-equiv="x-ua-compatible" content="ie=edge"/> <meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"/> <meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no">
<meta name=ICBM content="52.4595, 13.5335"> <meta name=ICBM content="52.4595, 13.5335">
<meta name=geo.position content="52.4595; 13.5335"> <meta name=geo.position content="52.4595; 13.5335">
@ -26,7 +26,7 @@
<link rel=me href=https://k0r.in> <link rel=me href=https://k0r.in>
<link rel=me href=https://koehr.ing> <link rel=me href=https://koehr.ing>
<link rel=me href=@Koehr@mstdn.io> <link rel=me href=@Koehr@mstdn.io>
<link rel=me href=https://sr.ht/~koehr/> <link rel=me href=https://sr.ht/~koehr>
<link rel=me href=https://git.k0r.in> <link rel=me href=https://git.k0r.in>
<link rel=me href=https://threads.net/@coffee_n_code> <link rel=me href=https://threads.net/@coffee_n_code>
<link rel=me href=https://instagram.com/@coffee_n_code> <link rel=me href=https://instagram.com/@coffee_n_code>
@ -49,10 +49,10 @@
<main id="main"> <main id="main">
<header> <header>
<h1 >Sort list of strings in Javascript</h1> <h1 :title="Sort list of strings in Javascript"></h1>
<em ></em> <em :title=""></em>
<br/> <br>
Last updated: <time datetime="Sun, 12 May 2024 00:00:00 +0000" >May 12, 2024</time> Last updated: <time datetime="Sun, 12 May 2024 00:00:00 +0000" :title="May 12, 2024"></time>
</header> </header>
<div><pre><code class="ts">users.sort((a, b) =&gt; a.firstname.localeCompare(b.firstname)) <div><pre><code class="ts">users.sort((a, b) =&gt; a.firstname.localeCompare(b.firstname))
@ -72,21 +72,21 @@
<a href="/"> <a href="/">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 832.4 143.1"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 832.4 143.1">
<path id="header-underscore" <path id="header-underscore"
d="M832.4 131.1q0 5.5-3.1 8.6-3 3.4-8.2 3.3h-75.5q-5.2 0-8.2-3.3-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8 0-5.5 3.1-8.7 1.6-1.7 3.7-2.4 2.2-.8 4.5-.8h75.5q5.2 0 8.2 3.2 3 3.1 3 8.7z" /> d="M832.4 131.1q0 5.5-3.1 8.6-3 3.4-8.2 3.3h-75.5q-5.2 0-8.2-3.3-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8 0-5.5 3.1-8.7 1.6-1.7 3.7-2.4 2.2-.8 4.5-.8h75.5q5.2 0 8.2 3.2 3 3.1 3 8.7z"></path>
<path id="header-bracket" <path id="header-bracket"
d="M731.9 81.4q0 6.7-6.5 10.7l-1 .6-74.3 39.2q-2.5 1.3-5.2 1.2-4.8 0-8.1-3.8-3.2-3.6-3.2-8.4 0-3.3 1.7-6 1.8-2.9 4.6-4.4l55.3-29.1-55.3-29q-2.8-1.6-4.6-4.3-1.7-2.7-1.7-6.2 0-4.7 3.2-8.4 3.3-4 8-3.7 2.7 0 5.3 1.2l74.4 39.2q3.3 1.7 5.3 4.7 2 2.8 2 6.5z" /> d="M731.9 81.4q0 6.7-6.5 10.7l-1 .6-74.3 39.2q-2.5 1.3-5.2 1.2-4.8 0-8.1-3.8-3.2-3.6-3.2-8.4 0-3.3 1.7-6 1.8-2.9 4.6-4.4l55.3-29.1-55.3-29q-2.8-1.6-4.6-4.3-1.7-2.7-1.7-6.2 0-4.7 3.2-8.4 3.3-4 8-3.7 2.7 0 5.3 1.2l74.4 39.2q3.3 1.7 5.3 4.7 2 2.8 2 6.5z"></path>
<path id="header-r" <path id="header-r"
d="M588.7 66.5q0 5-3.5 8.5-3.5 3.4-8.1 3.5-4.4 0-8.3-4.3-10-10.7-20.9-10.6-2.2 0-4.3.3-2.1.3-4 1-1.8.6-3.7 1.6-1.7 1-3.4 2.3-1.7 1.3-3.3 2.9-7.8 8.2-7.6 19.7V131q0 5.5-3.1 8.6-3 3.4-8.3 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V51.6q0-5.4 3-8.6 3-3.4 8.3-3.3 2 0 3.7.6 1.8.6 3.3 1.8 1.4 1 2.2 2.7 1 1.5 1.6 3.3 11.8-8.4 27-8.4 10.6 0 21 5 11.3 5.4 17.2 14.5 2.5 3.7 2.5 7.3z" /> d="M588.7 66.5q0 5-3.5 8.5-3.5 3.4-8.1 3.5-4.4 0-8.3-4.3-10-10.7-20.9-10.6-2.2 0-4.3.3-2.1.3-4 1-1.8.6-3.7 1.6-1.7 1-3.4 2.3-1.7 1.3-3.3 2.9-7.8 8.2-7.6 19.7V131q0 5.5-3.1 8.6-3 3.4-8.3 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V51.6q0-5.4 3-8.6 3-3.4 8.3-3.3 2 0 3.7.6 1.8.6 3.3 1.8 1.4 1 2.2 2.7 1 1.5 1.6 3.3 11.8-8.4 27-8.4 10.6 0 21 5 11.3 5.4 17.2 14.5 2.5 3.7 2.5 7.3z"></path>
<path id="header-h" <path id="header-h"
d="M483.9 131.1q0 5.5-3.1 8.6-3 3.4-8.3 3.3-5.2 0-8.2-3.3-3.2-3.1-3.1-8.6V84.8q0-4.6-1.5-8.2-1.4-3.5-4.4-6.9-2.1-2-4.3-3.4-2.2-1.4-4.7-2-2.4-.7-5.3-.7-4.3 0-7.8 1.5-3.3 1.5-6.4 4.6-5.9 6.3-5.8 15v46.4q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v33q1.5-1 3-1.6l3.2-1.2 3.4-1q1.6-.5 3.3-.8l3.5-.4 3.6-.2q4.4 0 8.5 1 4.1.7 7.9 2.4 3.8 1.6 7.3 4.1 3.5 2.5 6.6 5.8Q484 66 484 84.8z" /> d="M483.9 131.1q0 5.5-3.1 8.6-3 3.4-8.3 3.3-5.2 0-8.2-3.3-3.2-3.1-3.1-8.6V84.8q0-4.6-1.5-8.2-1.4-3.5-4.4-6.9-2.1-2-4.3-3.4-2.2-1.4-4.7-2-2.4-.7-5.3-.7-4.3 0-7.8 1.5-3.3 1.5-6.4 4.6-5.9 6.3-5.8 15v46.4q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v33q1.5-1 3-1.6l3.2-1.2 3.4-1q1.6-.5 3.3-.8l3.5-.4 3.6-.2q4.4 0 8.5 1 4.1.7 7.9 2.4 3.8 1.6 7.3 4.1 3.5 2.5 6.6 5.8Q484 66 484 84.8z"></path>
<path id="header-e" <path id="header-e"
d="M387.5 111.1q0 1.2-.3 2.3-.1 1-.5 2l-.9 2q-6.6 12-19.4 19-12 6.6-25.4 6.6-20.8 0-35.8-14.6-15.9-15-15.9-37 0-22.1 15.9-37.1 15-14.6 35.8-14.6 3.9 0 7.8.7 4 .7 8 2.2 9.2 3.1 18.2 10 6 4.6 9.1 9.3 3.3 4.7 3.3 10 0 1.3-.3 2.5-.2 1.3-.7 2.4-1.5 3.4-5 5.3l-56.9 32.2q7.2 4.9 16.5 4.9 7.2 0 12.6-2.5 5.5-2.5 9.7-7.4l.7-1 .8-1 .9-1.3 1-1.5q3.3-4.2 7.4-5.1l1.8-.2q4.4 0 8 3.4 3.6 3.5 3.6 8.5zm-29.9-42.7q-7.2-4.8-16.6-4.8-6 0-11 2-4.9 1.8-9.3 6-4.5 4-6.7 9-2 4.8-2 10.8l.1 2.9z" /> d="M387.5 111.1q0 1.2-.3 2.3-.1 1-.5 2l-.9 2q-6.6 12-19.4 19-12 6.6-25.4 6.6-20.8 0-35.8-14.6-15.9-15-15.9-37 0-22.1 15.9-37.1 15-14.6 35.8-14.6 3.9 0 7.8.7 4 .7 8 2.2 9.2 3.1 18.2 10 6 4.6 9.1 9.3 3.3 4.7 3.3 10 0 1.3-.3 2.5-.2 1.3-.7 2.4-1.5 3.4-5 5.3l-56.9 32.2q7.2 4.9 16.5 4.9 7.2 0 12.6-2.5 5.5-2.5 9.7-7.4l.7-1 .8-1 .9-1.3 1-1.5q3.3-4.2 7.4-5.1l1.8-.2q4.4 0 8 3.4 3.6 3.5 3.6 8.5zm-29.9-42.7q-7.2-4.8-16.6-4.8-6 0-11 2-4.9 1.8-9.3 6-4.5 4-6.7 9-2 4.8-2 10.8l.1 2.9z"></path>
<path id="header-o" <path id="header-o"
d="M286.8 91.4q0 4.2-.6 8.3-.6 4-1.8 7.7-1.1 3.8-2.9 7.4-1.7 3.5-4 6.9-2.4 3.3-5.2 6.1Q258 143 237.7 143T203 128q-14.3-15.2-14.3-36.6 0-21.5 14.3-36.6 14.4-15 34.7-15 4 0 7.8.5 3.9.7 7.5 1.9t7 3q3.3 1.9 6.4 4.3 3.2 2.4 5.9 5.4 14.4 15 14.5 36.5zm-22.6 0q0-2.4-.4-4.5-.2-2.2-.9-4.2-.6-2-1.5-3.9-1-2-2.2-3.7-1.2-1.7-2.8-3.4-4-4.2-8.6-6.1-4.5-2-10-2-11 0-18.7 8.2-7.8 8-7.8 19.6 0 11.4 7.8 19.7 7.8 8 18.6 8 5.6 0 10.1-1.9 4.6-2 8.6-6.1 4-4.3 5.8-9 2-4.9 2-10.7z" /> d="M286.8 91.4q0 4.2-.6 8.3-.6 4-1.8 7.7-1.1 3.8-2.9 7.4-1.7 3.5-4 6.9-2.4 3.3-5.2 6.1Q258 143 237.7 143T203 128q-14.3-15.2-14.3-36.6 0-21.5 14.3-36.6 14.4-15 34.7-15 4 0 7.8.5 3.9.7 7.5 1.9t7 3q3.3 1.9 6.4 4.3 3.2 2.4 5.9 5.4 14.4 15 14.5 36.5zm-22.6 0q0-2.4-.4-4.5-.2-2.2-.9-4.2-.6-2-1.5-3.9-1-2-2.2-3.7-1.2-1.7-2.8-3.4-4-4.2-8.6-6.1-4.5-2-10-2-11 0-18.7 8.2-7.8 8-7.8 19.6 0 11.4 7.8 19.7 7.8 8 18.6 8 5.6 0 10.1-1.9 4.6-2 8.6-6.1 4-4.3 5.8-9 2-4.9 2-10.7z"></path>
<path id="header-k" <path id="header-k"
d="M186.3 131q0 4.7-3.3 8.3-1.5 1.8-3.7 2.7-2 1.1-4.3 1.1-3.5 0-6.6-2L119.2 105v26q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v65.9l49.2-36.1q3.2-2 6.6-2 4.7 0 8 3.7t3.3 8.4q-.2 6-5 9.6l-41 30 41 29.9q2.3 1.7 3.6 4.2 1.4 2.5 1.4 5.4z" /> d="M186.3 131q0 4.7-3.3 8.3-1.5 1.8-3.7 2.7-2 1.1-4.3 1.1-3.5 0-6.6-2L119.2 105v26q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v65.9l49.2-36.1q3.2-2 6.6-2 4.7 0 8 3.7t3.3 8.4q-.2 6-5 9.6l-41 30 41 29.9q2.3 1.7 3.6 4.2 1.4 2.5 1.4 5.4z"></path>
<path id="header-tilde" <path id="header-tilde"
d="M73.1 91q0 2-.6 3.9T71 98.6q-3.2 5.7-8.9 8.5-5.6 2.8-12.9 2.8-8.8 0-18-7.8-2.4-2.3-4.5-3.7-2.1-1.5-3-1.7-1.5 0-2.1.3l-.8 1.3q-.3.7-.8 1.2l-1 1-.9.8q-2.7 2-6.4 2-1.7 0-3.2-.3-1.4-.3-3-1.1-1.5-.8-2.6-2.1-2.8-3.1-2.8-8v-1.3q0-.7.2-1.2l.2-1 .4-1 .4-1q.1-.6.5-1.1l.5-1q3.2-5.7 8.8-8.5 5.7-2.9 13-2.9 3.2 0 6.2 1 3 .9 6 2.7 2.9 1.6 5.7 4.2 5.2 4.6 7.6 5.4 1 0 1.6-.2l.7-.4q.3-.1.5-.4 3.6-5.6 9.2-5.6 5.7 0 8.8 3.5 2.8 3 2.8 8z" /> d="M73.1 91q0 2-.6 3.9T71 98.6q-3.2 5.7-8.9 8.5-5.6 2.8-12.9 2.8-8.8 0-18-7.8-2.4-2.3-4.5-3.7-2.1-1.5-3-1.7-1.5 0-2.1.3l-.8 1.3q-.3.7-.8 1.2l-1 1-.9.8q-2.7 2-6.4 2-1.7 0-3.2-.3-1.4-.3-3-1.1-1.5-.8-2.6-2.1-2.8-3.1-2.8-8v-1.3q0-.7.2-1.2l.2-1 .4-1 .4-1q.1-.6.5-1.1l.5-1q3.2-5.7 8.8-8.5 5.7-2.9 13-2.9 3.2 0 6.2 1 3 .9 6 2.7 2.9 1.6 5.7 4.2 5.2 4.6 7.6 5.4 1 0 1.6-.2l.7-.4q.3-.1.5-.4 3.6-5.6 9.2-5.6 5.7 0 8.8 3.5 2.8 3 2.8 8z"></path>
</svg> </svg>
Homepage of Homepage of
<div class=p-name> <div class=p-name>

View file

@ -3,7 +3,7 @@
<head id="head"> <head id="head">
<meta charset=utf-8> <meta charset=utf-8>
<title id=title >the codeartist — programmer and engineer based in BerlinReading speed is usually from 100 to 260 words per minute</title> <title id="title " var="the codeartist — programmer and engineer based in Berlin"></title>
<meta name=description content="The personal page and weblog of Norman Köhring"> <meta name=description content="The personal page and weblog of Norman Köhring">
<meta name=author content="Norman Köhring"> <meta name=author content="Norman Köhring">
<meta name=DC.title content="the codeartist — programmer and engineer based in Berlin"> <meta name=DC.title content="the codeartist — programmer and engineer based in Berlin">
@ -15,8 +15,8 @@
<meta name="og:title" content="Reading speed is usually from 100 to 260 words per minute // the codeartist"> <meta name="og:title" content="Reading speed is usually from 100 to 260 words per minute // the codeartist">
<meta property="og:type" content="website"> <meta property="og:type" content="website">
<meta http-equiv="x-ua-compatible" content="ie=edge"/> <meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"/> <meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no">
<meta name=ICBM content="52.4595, 13.5335"> <meta name=ICBM content="52.4595, 13.5335">
<meta name=geo.position content="52.4595; 13.5335"> <meta name=geo.position content="52.4595; 13.5335">
@ -26,7 +26,7 @@
<link rel=me href=https://k0r.in> <link rel=me href=https://k0r.in>
<link rel=me href=https://koehr.ing> <link rel=me href=https://koehr.ing>
<link rel=me href=@Koehr@mstdn.io> <link rel=me href=@Koehr@mstdn.io>
<link rel=me href=https://sr.ht/~koehr/> <link rel=me href=https://sr.ht/~koehr>
<link rel=me href=https://git.k0r.in> <link rel=me href=https://git.k0r.in>
<link rel=me href=https://threads.net/@coffee_n_code> <link rel=me href=https://threads.net/@coffee_n_code>
<link rel=me href=https://instagram.com/@coffee_n_code> <link rel=me href=https://instagram.com/@coffee_n_code>
@ -49,10 +49,10 @@
<main id="main"> <main id="main">
<header> <header>
<h1 >Reading speed is usually from 100 to 260 words per minute</h1> <h1 :title="Reading speed is usually from 100 to 260 words per minute"></h1>
<em ></em> <em :title=""></em>
<br/> <br>
Last updated: <time datetime="Mon, 13 May 2024 00:00:00 +0000" >May 13, 2024</time> Last updated: <time datetime="Mon, 13 May 2024 00:00:00 +0000" :title="May 13, 2024"></time>
</header> </header>
<div><p>With an average of 183 wpm.</p></div> <div><p>With an average of 183 wpm.</p></div>
@ -68,21 +68,21 @@
<a href="/"> <a href="/">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 832.4 143.1"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 832.4 143.1">
<path id="header-underscore" <path id="header-underscore"
d="M832.4 131.1q0 5.5-3.1 8.6-3 3.4-8.2 3.3h-75.5q-5.2 0-8.2-3.3-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8 0-5.5 3.1-8.7 1.6-1.7 3.7-2.4 2.2-.8 4.5-.8h75.5q5.2 0 8.2 3.2 3 3.1 3 8.7z" /> d="M832.4 131.1q0 5.5-3.1 8.6-3 3.4-8.2 3.3h-75.5q-5.2 0-8.2-3.3-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8 0-5.5 3.1-8.7 1.6-1.7 3.7-2.4 2.2-.8 4.5-.8h75.5q5.2 0 8.2 3.2 3 3.1 3 8.7z"></path>
<path id="header-bracket" <path id="header-bracket"
d="M731.9 81.4q0 6.7-6.5 10.7l-1 .6-74.3 39.2q-2.5 1.3-5.2 1.2-4.8 0-8.1-3.8-3.2-3.6-3.2-8.4 0-3.3 1.7-6 1.8-2.9 4.6-4.4l55.3-29.1-55.3-29q-2.8-1.6-4.6-4.3-1.7-2.7-1.7-6.2 0-4.7 3.2-8.4 3.3-4 8-3.7 2.7 0 5.3 1.2l74.4 39.2q3.3 1.7 5.3 4.7 2 2.8 2 6.5z" /> d="M731.9 81.4q0 6.7-6.5 10.7l-1 .6-74.3 39.2q-2.5 1.3-5.2 1.2-4.8 0-8.1-3.8-3.2-3.6-3.2-8.4 0-3.3 1.7-6 1.8-2.9 4.6-4.4l55.3-29.1-55.3-29q-2.8-1.6-4.6-4.3-1.7-2.7-1.7-6.2 0-4.7 3.2-8.4 3.3-4 8-3.7 2.7 0 5.3 1.2l74.4 39.2q3.3 1.7 5.3 4.7 2 2.8 2 6.5z"></path>
<path id="header-r" <path id="header-r"
d="M588.7 66.5q0 5-3.5 8.5-3.5 3.4-8.1 3.5-4.4 0-8.3-4.3-10-10.7-20.9-10.6-2.2 0-4.3.3-2.1.3-4 1-1.8.6-3.7 1.6-1.7 1-3.4 2.3-1.7 1.3-3.3 2.9-7.8 8.2-7.6 19.7V131q0 5.5-3.1 8.6-3 3.4-8.3 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V51.6q0-5.4 3-8.6 3-3.4 8.3-3.3 2 0 3.7.6 1.8.6 3.3 1.8 1.4 1 2.2 2.7 1 1.5 1.6 3.3 11.8-8.4 27-8.4 10.6 0 21 5 11.3 5.4 17.2 14.5 2.5 3.7 2.5 7.3z" /> d="M588.7 66.5q0 5-3.5 8.5-3.5 3.4-8.1 3.5-4.4 0-8.3-4.3-10-10.7-20.9-10.6-2.2 0-4.3.3-2.1.3-4 1-1.8.6-3.7 1.6-1.7 1-3.4 2.3-1.7 1.3-3.3 2.9-7.8 8.2-7.6 19.7V131q0 5.5-3.1 8.6-3 3.4-8.3 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V51.6q0-5.4 3-8.6 3-3.4 8.3-3.3 2 0 3.7.6 1.8.6 3.3 1.8 1.4 1 2.2 2.7 1 1.5 1.6 3.3 11.8-8.4 27-8.4 10.6 0 21 5 11.3 5.4 17.2 14.5 2.5 3.7 2.5 7.3z"></path>
<path id="header-h" <path id="header-h"
d="M483.9 131.1q0 5.5-3.1 8.6-3 3.4-8.3 3.3-5.2 0-8.2-3.3-3.2-3.1-3.1-8.6V84.8q0-4.6-1.5-8.2-1.4-3.5-4.4-6.9-2.1-2-4.3-3.4-2.2-1.4-4.7-2-2.4-.7-5.3-.7-4.3 0-7.8 1.5-3.3 1.5-6.4 4.6-5.9 6.3-5.8 15v46.4q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v33q1.5-1 3-1.6l3.2-1.2 3.4-1q1.6-.5 3.3-.8l3.5-.4 3.6-.2q4.4 0 8.5 1 4.1.7 7.9 2.4 3.8 1.6 7.3 4.1 3.5 2.5 6.6 5.8Q484 66 484 84.8z" /> d="M483.9 131.1q0 5.5-3.1 8.6-3 3.4-8.3 3.3-5.2 0-8.2-3.3-3.2-3.1-3.1-8.6V84.8q0-4.6-1.5-8.2-1.4-3.5-4.4-6.9-2.1-2-4.3-3.4-2.2-1.4-4.7-2-2.4-.7-5.3-.7-4.3 0-7.8 1.5-3.3 1.5-6.4 4.6-5.9 6.3-5.8 15v46.4q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v33q1.5-1 3-1.6l3.2-1.2 3.4-1q1.6-.5 3.3-.8l3.5-.4 3.6-.2q4.4 0 8.5 1 4.1.7 7.9 2.4 3.8 1.6 7.3 4.1 3.5 2.5 6.6 5.8Q484 66 484 84.8z"></path>
<path id="header-e" <path id="header-e"
d="M387.5 111.1q0 1.2-.3 2.3-.1 1-.5 2l-.9 2q-6.6 12-19.4 19-12 6.6-25.4 6.6-20.8 0-35.8-14.6-15.9-15-15.9-37 0-22.1 15.9-37.1 15-14.6 35.8-14.6 3.9 0 7.8.7 4 .7 8 2.2 9.2 3.1 18.2 10 6 4.6 9.1 9.3 3.3 4.7 3.3 10 0 1.3-.3 2.5-.2 1.3-.7 2.4-1.5 3.4-5 5.3l-56.9 32.2q7.2 4.9 16.5 4.9 7.2 0 12.6-2.5 5.5-2.5 9.7-7.4l.7-1 .8-1 .9-1.3 1-1.5q3.3-4.2 7.4-5.1l1.8-.2q4.4 0 8 3.4 3.6 3.5 3.6 8.5zm-29.9-42.7q-7.2-4.8-16.6-4.8-6 0-11 2-4.9 1.8-9.3 6-4.5 4-6.7 9-2 4.8-2 10.8l.1 2.9z" /> d="M387.5 111.1q0 1.2-.3 2.3-.1 1-.5 2l-.9 2q-6.6 12-19.4 19-12 6.6-25.4 6.6-20.8 0-35.8-14.6-15.9-15-15.9-37 0-22.1 15.9-37.1 15-14.6 35.8-14.6 3.9 0 7.8.7 4 .7 8 2.2 9.2 3.1 18.2 10 6 4.6 9.1 9.3 3.3 4.7 3.3 10 0 1.3-.3 2.5-.2 1.3-.7 2.4-1.5 3.4-5 5.3l-56.9 32.2q7.2 4.9 16.5 4.9 7.2 0 12.6-2.5 5.5-2.5 9.7-7.4l.7-1 .8-1 .9-1.3 1-1.5q3.3-4.2 7.4-5.1l1.8-.2q4.4 0 8 3.4 3.6 3.5 3.6 8.5zm-29.9-42.7q-7.2-4.8-16.6-4.8-6 0-11 2-4.9 1.8-9.3 6-4.5 4-6.7 9-2 4.8-2 10.8l.1 2.9z"></path>
<path id="header-o" <path id="header-o"
d="M286.8 91.4q0 4.2-.6 8.3-.6 4-1.8 7.7-1.1 3.8-2.9 7.4-1.7 3.5-4 6.9-2.4 3.3-5.2 6.1Q258 143 237.7 143T203 128q-14.3-15.2-14.3-36.6 0-21.5 14.3-36.6 14.4-15 34.7-15 4 0 7.8.5 3.9.7 7.5 1.9t7 3q3.3 1.9 6.4 4.3 3.2 2.4 5.9 5.4 14.4 15 14.5 36.5zm-22.6 0q0-2.4-.4-4.5-.2-2.2-.9-4.2-.6-2-1.5-3.9-1-2-2.2-3.7-1.2-1.7-2.8-3.4-4-4.2-8.6-6.1-4.5-2-10-2-11 0-18.7 8.2-7.8 8-7.8 19.6 0 11.4 7.8 19.7 7.8 8 18.6 8 5.6 0 10.1-1.9 4.6-2 8.6-6.1 4-4.3 5.8-9 2-4.9 2-10.7z" /> d="M286.8 91.4q0 4.2-.6 8.3-.6 4-1.8 7.7-1.1 3.8-2.9 7.4-1.7 3.5-4 6.9-2.4 3.3-5.2 6.1Q258 143 237.7 143T203 128q-14.3-15.2-14.3-36.6 0-21.5 14.3-36.6 14.4-15 34.7-15 4 0 7.8.5 3.9.7 7.5 1.9t7 3q3.3 1.9 6.4 4.3 3.2 2.4 5.9 5.4 14.4 15 14.5 36.5zm-22.6 0q0-2.4-.4-4.5-.2-2.2-.9-4.2-.6-2-1.5-3.9-1-2-2.2-3.7-1.2-1.7-2.8-3.4-4-4.2-8.6-6.1-4.5-2-10-2-11 0-18.7 8.2-7.8 8-7.8 19.6 0 11.4 7.8 19.7 7.8 8 18.6 8 5.6 0 10.1-1.9 4.6-2 8.6-6.1 4-4.3 5.8-9 2-4.9 2-10.7z"></path>
<path id="header-k" <path id="header-k"
d="M186.3 131q0 4.7-3.3 8.3-1.5 1.8-3.7 2.7-2 1.1-4.3 1.1-3.5 0-6.6-2L119.2 105v26q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v65.9l49.2-36.1q3.2-2 6.6-2 4.7 0 8 3.7t3.3 8.4q-.2 6-5 9.6l-41 30 41 29.9q2.3 1.7 3.6 4.2 1.4 2.5 1.4 5.4z" /> d="M186.3 131q0 4.7-3.3 8.3-1.5 1.8-3.7 2.7-2 1.1-4.3 1.1-3.5 0-6.6-2L119.2 105v26q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v65.9l49.2-36.1q3.2-2 6.6-2 4.7 0 8 3.7t3.3 8.4q-.2 6-5 9.6l-41 30 41 29.9q2.3 1.7 3.6 4.2 1.4 2.5 1.4 5.4z"></path>
<path id="header-tilde" <path id="header-tilde"
d="M73.1 91q0 2-.6 3.9T71 98.6q-3.2 5.7-8.9 8.5-5.6 2.8-12.9 2.8-8.8 0-18-7.8-2.4-2.3-4.5-3.7-2.1-1.5-3-1.7-1.5 0-2.1.3l-.8 1.3q-.3.7-.8 1.2l-1 1-.9.8q-2.7 2-6.4 2-1.7 0-3.2-.3-1.4-.3-3-1.1-1.5-.8-2.6-2.1-2.8-3.1-2.8-8v-1.3q0-.7.2-1.2l.2-1 .4-1 .4-1q.1-.6.5-1.1l.5-1q3.2-5.7 8.8-8.5 5.7-2.9 13-2.9 3.2 0 6.2 1 3 .9 6 2.7 2.9 1.6 5.7 4.2 5.2 4.6 7.6 5.4 1 0 1.6-.2l.7-.4q.3-.1.5-.4 3.6-5.6 9.2-5.6 5.7 0 8.8 3.5 2.8 3 2.8 8z" /> d="M73.1 91q0 2-.6 3.9T71 98.6q-3.2 5.7-8.9 8.5-5.6 2.8-12.9 2.8-8.8 0-18-7.8-2.4-2.3-4.5-3.7-2.1-1.5-3-1.7-1.5 0-2.1.3l-.8 1.3q-.3.7-.8 1.2l-1 1-.9.8q-2.7 2-6.4 2-1.7 0-3.2-.3-1.4-.3-3-1.1-1.5-.8-2.6-2.1-2.8-3.1-2.8-8v-1.3q0-.7.2-1.2l.2-1 .4-1 .4-1q.1-.6.5-1.1l.5-1q3.2-5.7 8.8-8.5 5.7-2.9 13-2.9 3.2 0 6.2 1 3 .9 6 2.7 2.9 1.6 5.7 4.2 5.2 4.6 7.6 5.4 1 0 1.6-.2l.7-.4q.3-.1.5-.4 3.6-5.6 9.2-5.6 5.7 0 8.8 3.5 2.8 3 2.8 8z"></path>
</svg> </svg>
Homepage of Homepage of
<div class=p-name> <div class=p-name>

View file

@ -3,7 +3,7 @@
<head id="head"> <head id="head">
<meta charset=utf-8> <meta charset=utf-8>
<title id=title >the codeartist — programmer and engineer based in BerlinJavascript's Array.from is neat!</title> <title id="title " var="the codeartist — programmer and engineer based in Berlin"></title>
<meta name=description content="The personal page and weblog of Norman Köhring"> <meta name=description content="The personal page and weblog of Norman Köhring">
<meta name=author content="Norman Köhring"> <meta name=author content="Norman Köhring">
<meta name=DC.title content="the codeartist — programmer and engineer based in Berlin"> <meta name=DC.title content="the codeartist — programmer and engineer based in Berlin">
@ -11,12 +11,12 @@
<meta name="twitter:site" content="@koehr_in"> <meta name="twitter:site" content="@koehr_in">
<meta name="twitter:author" content="@koehr_in"> <meta name="twitter:author" content="@koehr_in">
<meta name=twitter:description content="The personal page and weblog of the codeartist Norman Köhring"> <meta name=twitter:description content="The personal page and weblog of the codeartist Norman Köhring">
<meta name="twitter:title" content="Javascript's Array.from is neat! // the codeartist"> <meta name="twitter:title" content="Javascript&apos;s Array.from is neat! // the codeartist">
<meta name="og:title" content="Javascript's Array.from is neat! // the codeartist"> <meta name="og:title" content="Javascript&apos;s Array.from is neat! // the codeartist">
<meta property="og:type" content="website"> <meta property="og:type" content="website">
<meta http-equiv="x-ua-compatible" content="ie=edge"/> <meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"/> <meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no">
<meta name=ICBM content="52.4595, 13.5335"> <meta name=ICBM content="52.4595, 13.5335">
<meta name=geo.position content="52.4595; 13.5335"> <meta name=geo.position content="52.4595; 13.5335">
@ -26,7 +26,7 @@
<link rel=me href=https://k0r.in> <link rel=me href=https://k0r.in>
<link rel=me href=https://koehr.ing> <link rel=me href=https://koehr.ing>
<link rel=me href=@Koehr@mstdn.io> <link rel=me href=@Koehr@mstdn.io>
<link rel=me href=https://sr.ht/~koehr/> <link rel=me href=https://sr.ht/~koehr>
<link rel=me href=https://git.k0r.in> <link rel=me href=https://git.k0r.in>
<link rel=me href=https://threads.net/@coffee_n_code> <link rel=me href=https://threads.net/@coffee_n_code>
<link rel=me href=https://instagram.com/@coffee_n_code> <link rel=me href=https://instagram.com/@coffee_n_code>
@ -49,10 +49,10 @@
<main id="main"> <main id="main">
<header> <header>
<h1 >Javascript's Array.from is neat!</h1> <h1 :title="Javascript&apos;s Array.from is neat!"></h1>
<em ></em> <em :title=""></em>
<br/> <br>
Last updated: <time datetime="Fri, 06 Sep 2024 00:00:00 +0000" >September 06, 2024</time> Last updated: <time datetime="Fri, 06 Sep 2024 00:00:00 +0000" :title="September 06, 2024"></time>
</header> </header>
<div><p>Because it simply executes a function arg1.length times, one can do things like:</p><pre><code class="ts">const randomNumbers = Array.from({ length: 75 }, Math.random) <div><p>Because it simply executes a function arg1.length times, one can do things like:</p><pre><code class="ts">const randomNumbers = Array.from({ length: 75 }, Math.random)
@ -70,21 +70,21 @@
<a href="/"> <a href="/">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 832.4 143.1"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 832.4 143.1">
<path id="header-underscore" <path id="header-underscore"
d="M832.4 131.1q0 5.5-3.1 8.6-3 3.4-8.2 3.3h-75.5q-5.2 0-8.2-3.3-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8 0-5.5 3.1-8.7 1.6-1.7 3.7-2.4 2.2-.8 4.5-.8h75.5q5.2 0 8.2 3.2 3 3.1 3 8.7z" /> d="M832.4 131.1q0 5.5-3.1 8.6-3 3.4-8.2 3.3h-75.5q-5.2 0-8.2-3.3-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8 0-5.5 3.1-8.7 1.6-1.7 3.7-2.4 2.2-.8 4.5-.8h75.5q5.2 0 8.2 3.2 3 3.1 3 8.7z"></path>
<path id="header-bracket" <path id="header-bracket"
d="M731.9 81.4q0 6.7-6.5 10.7l-1 .6-74.3 39.2q-2.5 1.3-5.2 1.2-4.8 0-8.1-3.8-3.2-3.6-3.2-8.4 0-3.3 1.7-6 1.8-2.9 4.6-4.4l55.3-29.1-55.3-29q-2.8-1.6-4.6-4.3-1.7-2.7-1.7-6.2 0-4.7 3.2-8.4 3.3-4 8-3.7 2.7 0 5.3 1.2l74.4 39.2q3.3 1.7 5.3 4.7 2 2.8 2 6.5z" /> d="M731.9 81.4q0 6.7-6.5 10.7l-1 .6-74.3 39.2q-2.5 1.3-5.2 1.2-4.8 0-8.1-3.8-3.2-3.6-3.2-8.4 0-3.3 1.7-6 1.8-2.9 4.6-4.4l55.3-29.1-55.3-29q-2.8-1.6-4.6-4.3-1.7-2.7-1.7-6.2 0-4.7 3.2-8.4 3.3-4 8-3.7 2.7 0 5.3 1.2l74.4 39.2q3.3 1.7 5.3 4.7 2 2.8 2 6.5z"></path>
<path id="header-r" <path id="header-r"
d="M588.7 66.5q0 5-3.5 8.5-3.5 3.4-8.1 3.5-4.4 0-8.3-4.3-10-10.7-20.9-10.6-2.2 0-4.3.3-2.1.3-4 1-1.8.6-3.7 1.6-1.7 1-3.4 2.3-1.7 1.3-3.3 2.9-7.8 8.2-7.6 19.7V131q0 5.5-3.1 8.6-3 3.4-8.3 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V51.6q0-5.4 3-8.6 3-3.4 8.3-3.3 2 0 3.7.6 1.8.6 3.3 1.8 1.4 1 2.2 2.7 1 1.5 1.6 3.3 11.8-8.4 27-8.4 10.6 0 21 5 11.3 5.4 17.2 14.5 2.5 3.7 2.5 7.3z" /> d="M588.7 66.5q0 5-3.5 8.5-3.5 3.4-8.1 3.5-4.4 0-8.3-4.3-10-10.7-20.9-10.6-2.2 0-4.3.3-2.1.3-4 1-1.8.6-3.7 1.6-1.7 1-3.4 2.3-1.7 1.3-3.3 2.9-7.8 8.2-7.6 19.7V131q0 5.5-3.1 8.6-3 3.4-8.3 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V51.6q0-5.4 3-8.6 3-3.4 8.3-3.3 2 0 3.7.6 1.8.6 3.3 1.8 1.4 1 2.2 2.7 1 1.5 1.6 3.3 11.8-8.4 27-8.4 10.6 0 21 5 11.3 5.4 17.2 14.5 2.5 3.7 2.5 7.3z"></path>
<path id="header-h" <path id="header-h"
d="M483.9 131.1q0 5.5-3.1 8.6-3 3.4-8.3 3.3-5.2 0-8.2-3.3-3.2-3.1-3.1-8.6V84.8q0-4.6-1.5-8.2-1.4-3.5-4.4-6.9-2.1-2-4.3-3.4-2.2-1.4-4.7-2-2.4-.7-5.3-.7-4.3 0-7.8 1.5-3.3 1.5-6.4 4.6-5.9 6.3-5.8 15v46.4q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v33q1.5-1 3-1.6l3.2-1.2 3.4-1q1.6-.5 3.3-.8l3.5-.4 3.6-.2q4.4 0 8.5 1 4.1.7 7.9 2.4 3.8 1.6 7.3 4.1 3.5 2.5 6.6 5.8Q484 66 484 84.8z" /> d="M483.9 131.1q0 5.5-3.1 8.6-3 3.4-8.3 3.3-5.2 0-8.2-3.3-3.2-3.1-3.1-8.6V84.8q0-4.6-1.5-8.2-1.4-3.5-4.4-6.9-2.1-2-4.3-3.4-2.2-1.4-4.7-2-2.4-.7-5.3-.7-4.3 0-7.8 1.5-3.3 1.5-6.4 4.6-5.9 6.3-5.8 15v46.4q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v33q1.5-1 3-1.6l3.2-1.2 3.4-1q1.6-.5 3.3-.8l3.5-.4 3.6-.2q4.4 0 8.5 1 4.1.7 7.9 2.4 3.8 1.6 7.3 4.1 3.5 2.5 6.6 5.8Q484 66 484 84.8z"></path>
<path id="header-e" <path id="header-e"
d="M387.5 111.1q0 1.2-.3 2.3-.1 1-.5 2l-.9 2q-6.6 12-19.4 19-12 6.6-25.4 6.6-20.8 0-35.8-14.6-15.9-15-15.9-37 0-22.1 15.9-37.1 15-14.6 35.8-14.6 3.9 0 7.8.7 4 .7 8 2.2 9.2 3.1 18.2 10 6 4.6 9.1 9.3 3.3 4.7 3.3 10 0 1.3-.3 2.5-.2 1.3-.7 2.4-1.5 3.4-5 5.3l-56.9 32.2q7.2 4.9 16.5 4.9 7.2 0 12.6-2.5 5.5-2.5 9.7-7.4l.7-1 .8-1 .9-1.3 1-1.5q3.3-4.2 7.4-5.1l1.8-.2q4.4 0 8 3.4 3.6 3.5 3.6 8.5zm-29.9-42.7q-7.2-4.8-16.6-4.8-6 0-11 2-4.9 1.8-9.3 6-4.5 4-6.7 9-2 4.8-2 10.8l.1 2.9z" /> d="M387.5 111.1q0 1.2-.3 2.3-.1 1-.5 2l-.9 2q-6.6 12-19.4 19-12 6.6-25.4 6.6-20.8 0-35.8-14.6-15.9-15-15.9-37 0-22.1 15.9-37.1 15-14.6 35.8-14.6 3.9 0 7.8.7 4 .7 8 2.2 9.2 3.1 18.2 10 6 4.6 9.1 9.3 3.3 4.7 3.3 10 0 1.3-.3 2.5-.2 1.3-.7 2.4-1.5 3.4-5 5.3l-56.9 32.2q7.2 4.9 16.5 4.9 7.2 0 12.6-2.5 5.5-2.5 9.7-7.4l.7-1 .8-1 .9-1.3 1-1.5q3.3-4.2 7.4-5.1l1.8-.2q4.4 0 8 3.4 3.6 3.5 3.6 8.5zm-29.9-42.7q-7.2-4.8-16.6-4.8-6 0-11 2-4.9 1.8-9.3 6-4.5 4-6.7 9-2 4.8-2 10.8l.1 2.9z"></path>
<path id="header-o" <path id="header-o"
d="M286.8 91.4q0 4.2-.6 8.3-.6 4-1.8 7.7-1.1 3.8-2.9 7.4-1.7 3.5-4 6.9-2.4 3.3-5.2 6.1Q258 143 237.7 143T203 128q-14.3-15.2-14.3-36.6 0-21.5 14.3-36.6 14.4-15 34.7-15 4 0 7.8.5 3.9.7 7.5 1.9t7 3q3.3 1.9 6.4 4.3 3.2 2.4 5.9 5.4 14.4 15 14.5 36.5zm-22.6 0q0-2.4-.4-4.5-.2-2.2-.9-4.2-.6-2-1.5-3.9-1-2-2.2-3.7-1.2-1.7-2.8-3.4-4-4.2-8.6-6.1-4.5-2-10-2-11 0-18.7 8.2-7.8 8-7.8 19.6 0 11.4 7.8 19.7 7.8 8 18.6 8 5.6 0 10.1-1.9 4.6-2 8.6-6.1 4-4.3 5.8-9 2-4.9 2-10.7z" /> d="M286.8 91.4q0 4.2-.6 8.3-.6 4-1.8 7.7-1.1 3.8-2.9 7.4-1.7 3.5-4 6.9-2.4 3.3-5.2 6.1Q258 143 237.7 143T203 128q-14.3-15.2-14.3-36.6 0-21.5 14.3-36.6 14.4-15 34.7-15 4 0 7.8.5 3.9.7 7.5 1.9t7 3q3.3 1.9 6.4 4.3 3.2 2.4 5.9 5.4 14.4 15 14.5 36.5zm-22.6 0q0-2.4-.4-4.5-.2-2.2-.9-4.2-.6-2-1.5-3.9-1-2-2.2-3.7-1.2-1.7-2.8-3.4-4-4.2-8.6-6.1-4.5-2-10-2-11 0-18.7 8.2-7.8 8-7.8 19.6 0 11.4 7.8 19.7 7.8 8 18.6 8 5.6 0 10.1-1.9 4.6-2 8.6-6.1 4-4.3 5.8-9 2-4.9 2-10.7z"></path>
<path id="header-k" <path id="header-k"
d="M186.3 131q0 4.7-3.3 8.3-1.5 1.8-3.7 2.7-2 1.1-4.3 1.1-3.5 0-6.6-2L119.2 105v26q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v65.9l49.2-36.1q3.2-2 6.6-2 4.7 0 8 3.7t3.3 8.4q-.2 6-5 9.6l-41 30 41 29.9q2.3 1.7 3.6 4.2 1.4 2.5 1.4 5.4z" /> d="M186.3 131q0 4.7-3.3 8.3-1.5 1.8-3.7 2.7-2 1.1-4.3 1.1-3.5 0-6.6-2L119.2 105v26q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v65.9l49.2-36.1q3.2-2 6.6-2 4.7 0 8 3.7t3.3 8.4q-.2 6-5 9.6l-41 30 41 29.9q2.3 1.7 3.6 4.2 1.4 2.5 1.4 5.4z"></path>
<path id="header-tilde" <path id="header-tilde"
d="M73.1 91q0 2-.6 3.9T71 98.6q-3.2 5.7-8.9 8.5-5.6 2.8-12.9 2.8-8.8 0-18-7.8-2.4-2.3-4.5-3.7-2.1-1.5-3-1.7-1.5 0-2.1.3l-.8 1.3q-.3.7-.8 1.2l-1 1-.9.8q-2.7 2-6.4 2-1.7 0-3.2-.3-1.4-.3-3-1.1-1.5-.8-2.6-2.1-2.8-3.1-2.8-8v-1.3q0-.7.2-1.2l.2-1 .4-1 .4-1q.1-.6.5-1.1l.5-1q3.2-5.7 8.8-8.5 5.7-2.9 13-2.9 3.2 0 6.2 1 3 .9 6 2.7 2.9 1.6 5.7 4.2 5.2 4.6 7.6 5.4 1 0 1.6-.2l.7-.4q.3-.1.5-.4 3.6-5.6 9.2-5.6 5.7 0 8.8 3.5 2.8 3 2.8 8z" /> d="M73.1 91q0 2-.6 3.9T71 98.6q-3.2 5.7-8.9 8.5-5.6 2.8-12.9 2.8-8.8 0-18-7.8-2.4-2.3-4.5-3.7-2.1-1.5-3-1.7-1.5 0-2.1.3l-.8 1.3q-.3.7-.8 1.2l-1 1-.9.8q-2.7 2-6.4 2-1.7 0-3.2-.3-1.4-.3-3-1.1-1.5-.8-2.6-2.1-2.8-3.1-2.8-8v-1.3q0-.7.2-1.2l.2-1 .4-1 .4-1q.1-.6.5-1.1l.5-1q3.2-5.7 8.8-8.5 5.7-2.9 13-2.9 3.2 0 6.2 1 3 .9 6 2.7 2.9 1.6 5.7 4.2 5.2 4.6 7.6 5.4 1 0 1.6-.2l.7-.4q.3-.1.5-.4 3.6-5.6 9.2-5.6 5.7 0 8.8 3.5 2.8 3 2.8 8z"></path>
</svg> </svg>
Homepage of Homepage of
<div class=p-name> <div class=p-name>

View file

@ -3,7 +3,7 @@
<head id="head"> <head id="head">
<meta charset=utf-8> <meta charset=utf-8>
<title id=title >the codeartist — programmer and engineer based in BerlinToday I Learned</title> <title id="title " var="the codeartist — programmer and engineer based in Berlin"></title>
<meta name=description content="The personal page and weblog of Norman Köhring"> <meta name=description content="The personal page and weblog of Norman Köhring">
<meta name=author content="Norman Köhring"> <meta name=author content="Norman Köhring">
<meta name=DC.title content="the codeartist — programmer and engineer based in Berlin"> <meta name=DC.title content="the codeartist — programmer and engineer based in Berlin">
@ -15,8 +15,8 @@
<meta name="og:title" content="Today I Learned // the codeartist"> <meta name="og:title" content="Today I Learned // the codeartist">
<meta property="og:type" content="website"> <meta property="og:type" content="website">
<meta http-equiv="x-ua-compatible" content="ie=edge"/> <meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"/> <meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no">
<meta name=ICBM content="52.4595, 13.5335"> <meta name=ICBM content="52.4595, 13.5335">
<meta name=geo.position content="52.4595; 13.5335"> <meta name=geo.position content="52.4595; 13.5335">
@ -26,7 +26,7 @@
<link rel=me href=https://k0r.in> <link rel=me href=https://k0r.in>
<link rel=me href=https://koehr.ing> <link rel=me href=https://koehr.ing>
<link rel=me href=@Koehr@mstdn.io> <link rel=me href=@Koehr@mstdn.io>
<link rel=me href=https://sr.ht/~koehr/> <link rel=me href=https://sr.ht/~koehr>
<link rel=me href=https://git.k0r.in> <link rel=me href=https://git.k0r.in>
<link rel=me href=https://threads.net/@coffee_n_code> <link rel=me href=https://threads.net/@coffee_n_code>
<link rel=me href=https://instagram.com/@coffee_n_code> <link rel=me href=https://instagram.com/@coffee_n_code>
@ -49,10 +49,10 @@
<main id="main"> <main id="main">
<header> <header>
<h1 >Today I Learned</h1> <h1 :title="Today I Learned"></h1>
<em >This page contains short notes and sometimes code snippets, of interesting things I just found out.</em> <em :title="This page contains short notes and sometimes code snippets, of interesting things I just found out."></em>
<br/> <br>
Last updated: <time datetime="Mon, 13 May 2024 00:00:00 +0000" >May 13, 2024</time> Last updated: <time datetime="Mon, 13 May 2024 00:00:00 +0000" :title="May 13, 2024"></time>
</header> </header>
<div></div> <div></div>
@ -61,80 +61,80 @@
<li> <li>
<time datetime="Fri, 06 Sep 2024 00:00:00 +0000">September 06, 2024</time> <time datetime="Fri, 06 Sep 2024 00:00:00 +0000">September 06, 2024</time>
<div> <div>
<a href="/til/2024-09-06/" >Javascript's Array.from is neat!</a> <a href="/til/2024-09-06/">Javascript&apos;s Array.from is neat!</a>
(<a rel="nofollow noopener" class="external" href="#">source</a>)
</div> </div>
<time datetime="Mon, 13 May 2024 00:00:00 +0000">May 13, 2024</time> <time datetime="Mon, 13 May 2024 00:00:00 +0000">May 13, 2024</time>
<div> <div>
<a href="/til/2024-05-13/">Reading speed is usually from 100 to 260 words per minute</a> <a href="/til/2024-05-13/">Reading speed is usually from 100 to 260 words per minute</a>
(<a rel="nofollow noopener" class="external" href="#">source</a>)
</div> </div>
<time datetime="Sun, 12 May 2024 00:00:00 +0000">May 12, 2024</time> <time datetime="Sun, 12 May 2024 00:00:00 +0000">May 12, 2024</time>
<div> <div>
<a href="/til/2024-05-12/">Sort list of strings in Javascript</a> <a href="/til/2024-05-12/">Sort list of strings in Javascript</a>
(<a rel="nofollow noopener" class="external" href="#">source</a>)
</div> </div>
<time datetime="Sat, 11 May 2024 00:00:00 +0000">May 11, 2024</time> <time datetime="Sat, 11 May 2024 00:00:00 +0000">May 11, 2024</time>
<div> <div>
<a href="/til/2024-05-11/" >Rob Pike's 5 Rules of Programming</a> <a href="/til/2024-05-11/">Rob Pike&apos;s 5 Rules of Programming</a>
(<a rel="nofollow noopener" class="external" href="#">source</a>)
</div> </div>
<time datetime="Wed, 15 Jun 2022 00:00:00 +0000">June 15, 2022</time> <time datetime="Wed, 15 Jun 2022 00:00:00 +0000">June 15, 2022</time>
<div> <div>
<a href="/til/2022-06-15/">Disallowed Focussed Tests and how it saved my day</a> <a href="/til/2022-06-15/">Disallowed Focussed Tests and how it saved my day</a>
(<a rel="nofollow noopener" class="external" href="#">source</a>)
</div> </div>
<time datetime="Mon, 25 Apr 2022 00:00:00 +0000">April 25, 2022</time> <time datetime="Mon, 25 Apr 2022 00:00:00 +0000">April 25, 2022</time>
<div> <div>
<a href="/til/2022-04-25/">Jest mocks are ...different</a> <a href="/til/2022-04-25/">Jest mocks are ...different</a>
(<a rel="nofollow noopener" class="external" href="#">source</a>)
</div> </div>
<time datetime="Mon, 28 Mar 2022 00:00:00 +0000">March 28, 2022</time> <time datetime="Mon, 28 Mar 2022 00:00:00 +0000">March 28, 2022</time>
<div> <div>
<a href="/til/2022-03-28/">pwdx command shows the working path of a process</a> <a href="/til/2022-03-28/">pwdx command shows the working path of a process</a>
(<a rel="nofollow noopener" class="external" href="#">source</a>)
</div> </div>
<time datetime="Tue, 22 Mar 2022 00:00:00 +0000">March 22, 2022</time> <time datetime="Tue, 22 Mar 2022 00:00:00 +0000">March 22, 2022</time>
<div> <div>
<a href="/til/2022-03-22/">There is a file system for EFI vars now</a> <a href="/til/2022-03-22/">There is a file system for EFI vars now</a>
(<a rel="nofollow noopener" class="external" href="#">source</a>)
</div> </div>
<time datetime="Tue, 22 Feb 2022 00:00:00 +0000">February 22, 2022</time> <time datetime="Tue, 22 Feb 2022 00:00:00 +0000">February 22, 2022</time>
<div> <div>
<a href="/til/2022-02-22/">Adding aliases in vite with typescript needs the same alias in tsconfig</a> <a href="/til/2022-02-22/">Adding aliases in vite with typescript needs the same alias in tsconfig</a>
(<a rel="nofollow noopener" class="external" href="#">source</a>)
</div> </div>
<time datetime="Sun, 05 Sep 2021 00:00:00 +0000">September 05, 2021</time> <time datetime="Sun, 05 Sep 2021 00:00:00 +0000">September 05, 2021</time>
<div> <div>
<a href="/til/2021-09-05/" >E-Mail that isn't spam is called ham!</a> <a href="/til/2021-09-05/">E-Mail that isn&apos;t spam is called ham!</a>
(<a rel="nofollow noopener" class="external" href="#">source</a>)
</div> </div>
<time datetime="Sat, 04 Sep 2021 00:00:00 +0000">September 04, 2021</time> <time datetime="Sat, 04 Sep 2021 00:00:00 +0000">September 04, 2021</time>
<div> <div>
<a href="/til/2021-09-04/">git fetch repo_url remote_branch:new_local_branch</a> <a href="/til/2021-09-04/">git fetch repo_url remote_branch:new_local_branch</a>
(<a rel="nofollow noopener" class="external" href="#">source</a>)
</div> </div>
<time datetime="Fri, 03 Sep 2021 00:00:00 +0000">September 03, 2021</time> <time datetime="Fri, 03 Sep 2021 00:00:00 +0000">September 03, 2021</time>
<div> <div>
<a href="/til/2021-09-03/">Bush refused offer to discuss Osama Bin Laden handover</a> <a href="/til/2021-09-03/">Bush refused offer to discuss Osama Bin Laden handover</a>
(<a rel="nofollow noopener" class="external" href="#">source</a>)
</div> </div>
<time datetime="Tue, 31 Aug 2021 00:00:00 +0000">August 31, 2021</time> <time datetime="Tue, 31 Aug 2021 00:00:00 +0000">August 31, 2021</time>
<div> <div>
<a href="/til/2021-08-31/" >There is a HTML tag for "Word Break Opportunity"</a> <a href="/til/2021-08-31/">There is a HTML tag for &quot;Word Break Opportunity&quot;</a>
(<a rel="nofollow noopener" class="external" href="#">source</a>)
</div> </div>
</li> </li>
</ol> </ol>
@ -146,21 +146,21 @@
<a href="/"> <a href="/">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 832.4 143.1"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 832.4 143.1">
<path id="header-underscore" <path id="header-underscore"
d="M832.4 131.1q0 5.5-3.1 8.6-3 3.4-8.2 3.3h-75.5q-5.2 0-8.2-3.3-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8 0-5.5 3.1-8.7 1.6-1.7 3.7-2.4 2.2-.8 4.5-.8h75.5q5.2 0 8.2 3.2 3 3.1 3 8.7z" /> d="M832.4 131.1q0 5.5-3.1 8.6-3 3.4-8.2 3.3h-75.5q-5.2 0-8.2-3.3-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8 0-5.5 3.1-8.7 1.6-1.7 3.7-2.4 2.2-.8 4.5-.8h75.5q5.2 0 8.2 3.2 3 3.1 3 8.7z"></path>
<path id="header-bracket" <path id="header-bracket"
d="M731.9 81.4q0 6.7-6.5 10.7l-1 .6-74.3 39.2q-2.5 1.3-5.2 1.2-4.8 0-8.1-3.8-3.2-3.6-3.2-8.4 0-3.3 1.7-6 1.8-2.9 4.6-4.4l55.3-29.1-55.3-29q-2.8-1.6-4.6-4.3-1.7-2.7-1.7-6.2 0-4.7 3.2-8.4 3.3-4 8-3.7 2.7 0 5.3 1.2l74.4 39.2q3.3 1.7 5.3 4.7 2 2.8 2 6.5z" /> d="M731.9 81.4q0 6.7-6.5 10.7l-1 .6-74.3 39.2q-2.5 1.3-5.2 1.2-4.8 0-8.1-3.8-3.2-3.6-3.2-8.4 0-3.3 1.7-6 1.8-2.9 4.6-4.4l55.3-29.1-55.3-29q-2.8-1.6-4.6-4.3-1.7-2.7-1.7-6.2 0-4.7 3.2-8.4 3.3-4 8-3.7 2.7 0 5.3 1.2l74.4 39.2q3.3 1.7 5.3 4.7 2 2.8 2 6.5z"></path>
<path id="header-r" <path id="header-r"
d="M588.7 66.5q0 5-3.5 8.5-3.5 3.4-8.1 3.5-4.4 0-8.3-4.3-10-10.7-20.9-10.6-2.2 0-4.3.3-2.1.3-4 1-1.8.6-3.7 1.6-1.7 1-3.4 2.3-1.7 1.3-3.3 2.9-7.8 8.2-7.6 19.7V131q0 5.5-3.1 8.6-3 3.4-8.3 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V51.6q0-5.4 3-8.6 3-3.4 8.3-3.3 2 0 3.7.6 1.8.6 3.3 1.8 1.4 1 2.2 2.7 1 1.5 1.6 3.3 11.8-8.4 27-8.4 10.6 0 21 5 11.3 5.4 17.2 14.5 2.5 3.7 2.5 7.3z" /> d="M588.7 66.5q0 5-3.5 8.5-3.5 3.4-8.1 3.5-4.4 0-8.3-4.3-10-10.7-20.9-10.6-2.2 0-4.3.3-2.1.3-4 1-1.8.6-3.7 1.6-1.7 1-3.4 2.3-1.7 1.3-3.3 2.9-7.8 8.2-7.6 19.7V131q0 5.5-3.1 8.6-3 3.4-8.3 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V51.6q0-5.4 3-8.6 3-3.4 8.3-3.3 2 0 3.7.6 1.8.6 3.3 1.8 1.4 1 2.2 2.7 1 1.5 1.6 3.3 11.8-8.4 27-8.4 10.6 0 21 5 11.3 5.4 17.2 14.5 2.5 3.7 2.5 7.3z"></path>
<path id="header-h" <path id="header-h"
d="M483.9 131.1q0 5.5-3.1 8.6-3 3.4-8.3 3.3-5.2 0-8.2-3.3-3.2-3.1-3.1-8.6V84.8q0-4.6-1.5-8.2-1.4-3.5-4.4-6.9-2.1-2-4.3-3.4-2.2-1.4-4.7-2-2.4-.7-5.3-.7-4.3 0-7.8 1.5-3.3 1.5-6.4 4.6-5.9 6.3-5.8 15v46.4q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v33q1.5-1 3-1.6l3.2-1.2 3.4-1q1.6-.5 3.3-.8l3.5-.4 3.6-.2q4.4 0 8.5 1 4.1.7 7.9 2.4 3.8 1.6 7.3 4.1 3.5 2.5 6.6 5.8Q484 66 484 84.8z" /> d="M483.9 131.1q0 5.5-3.1 8.6-3 3.4-8.3 3.3-5.2 0-8.2-3.3-3.2-3.1-3.1-8.6V84.8q0-4.6-1.5-8.2-1.4-3.5-4.4-6.9-2.1-2-4.3-3.4-2.2-1.4-4.7-2-2.4-.7-5.3-.7-4.3 0-7.8 1.5-3.3 1.5-6.4 4.6-5.9 6.3-5.8 15v46.4q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v33q1.5-1 3-1.6l3.2-1.2 3.4-1q1.6-.5 3.3-.8l3.5-.4 3.6-.2q4.4 0 8.5 1 4.1.7 7.9 2.4 3.8 1.6 7.3 4.1 3.5 2.5 6.6 5.8Q484 66 484 84.8z"></path>
<path id="header-e" <path id="header-e"
d="M387.5 111.1q0 1.2-.3 2.3-.1 1-.5 2l-.9 2q-6.6 12-19.4 19-12 6.6-25.4 6.6-20.8 0-35.8-14.6-15.9-15-15.9-37 0-22.1 15.9-37.1 15-14.6 35.8-14.6 3.9 0 7.8.7 4 .7 8 2.2 9.2 3.1 18.2 10 6 4.6 9.1 9.3 3.3 4.7 3.3 10 0 1.3-.3 2.5-.2 1.3-.7 2.4-1.5 3.4-5 5.3l-56.9 32.2q7.2 4.9 16.5 4.9 7.2 0 12.6-2.5 5.5-2.5 9.7-7.4l.7-1 .8-1 .9-1.3 1-1.5q3.3-4.2 7.4-5.1l1.8-.2q4.4 0 8 3.4 3.6 3.5 3.6 8.5zm-29.9-42.7q-7.2-4.8-16.6-4.8-6 0-11 2-4.9 1.8-9.3 6-4.5 4-6.7 9-2 4.8-2 10.8l.1 2.9z" /> d="M387.5 111.1q0 1.2-.3 2.3-.1 1-.5 2l-.9 2q-6.6 12-19.4 19-12 6.6-25.4 6.6-20.8 0-35.8-14.6-15.9-15-15.9-37 0-22.1 15.9-37.1 15-14.6 35.8-14.6 3.9 0 7.8.7 4 .7 8 2.2 9.2 3.1 18.2 10 6 4.6 9.1 9.3 3.3 4.7 3.3 10 0 1.3-.3 2.5-.2 1.3-.7 2.4-1.5 3.4-5 5.3l-56.9 32.2q7.2 4.9 16.5 4.9 7.2 0 12.6-2.5 5.5-2.5 9.7-7.4l.7-1 .8-1 .9-1.3 1-1.5q3.3-4.2 7.4-5.1l1.8-.2q4.4 0 8 3.4 3.6 3.5 3.6 8.5zm-29.9-42.7q-7.2-4.8-16.6-4.8-6 0-11 2-4.9 1.8-9.3 6-4.5 4-6.7 9-2 4.8-2 10.8l.1 2.9z"></path>
<path id="header-o" <path id="header-o"
d="M286.8 91.4q0 4.2-.6 8.3-.6 4-1.8 7.7-1.1 3.8-2.9 7.4-1.7 3.5-4 6.9-2.4 3.3-5.2 6.1Q258 143 237.7 143T203 128q-14.3-15.2-14.3-36.6 0-21.5 14.3-36.6 14.4-15 34.7-15 4 0 7.8.5 3.9.7 7.5 1.9t7 3q3.3 1.9 6.4 4.3 3.2 2.4 5.9 5.4 14.4 15 14.5 36.5zm-22.6 0q0-2.4-.4-4.5-.2-2.2-.9-4.2-.6-2-1.5-3.9-1-2-2.2-3.7-1.2-1.7-2.8-3.4-4-4.2-8.6-6.1-4.5-2-10-2-11 0-18.7 8.2-7.8 8-7.8 19.6 0 11.4 7.8 19.7 7.8 8 18.6 8 5.6 0 10.1-1.9 4.6-2 8.6-6.1 4-4.3 5.8-9 2-4.9 2-10.7z" /> d="M286.8 91.4q0 4.2-.6 8.3-.6 4-1.8 7.7-1.1 3.8-2.9 7.4-1.7 3.5-4 6.9-2.4 3.3-5.2 6.1Q258 143 237.7 143T203 128q-14.3-15.2-14.3-36.6 0-21.5 14.3-36.6 14.4-15 34.7-15 4 0 7.8.5 3.9.7 7.5 1.9t7 3q3.3 1.9 6.4 4.3 3.2 2.4 5.9 5.4 14.4 15 14.5 36.5zm-22.6 0q0-2.4-.4-4.5-.2-2.2-.9-4.2-.6-2-1.5-3.9-1-2-2.2-3.7-1.2-1.7-2.8-3.4-4-4.2-8.6-6.1-4.5-2-10-2-11 0-18.7 8.2-7.8 8-7.8 19.6 0 11.4 7.8 19.7 7.8 8 18.6 8 5.6 0 10.1-1.9 4.6-2 8.6-6.1 4-4.3 5.8-9 2-4.9 2-10.7z"></path>
<path id="header-k" <path id="header-k"
d="M186.3 131q0 4.7-3.3 8.3-1.5 1.8-3.7 2.7-2 1.1-4.3 1.1-3.5 0-6.6-2L119.2 105v26q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v65.9l49.2-36.1q3.2-2 6.6-2 4.7 0 8 3.7t3.3 8.4q-.2 6-5 9.6l-41 30 41 29.9q2.3 1.7 3.6 4.2 1.4 2.5 1.4 5.4z" /> d="M186.3 131q0 4.7-3.3 8.3-1.5 1.8-3.7 2.7-2 1.1-4.3 1.1-3.5 0-6.6-2L119.2 105v26q0 5.5-3 8.6-3.1 3.4-8.4 3.3l-2.2-.2q-1-.1-2.2-.5-1-.3-2-1-1-.6-1.8-1.6-1.7-1.6-2.4-3.8-.7-2.3-.7-4.8V11.9q0-5.5 3-8.6 3-3.4 8.3-3.3 5.2 0 8.2 3.3 3.2 3.1 3.2 8.6v65.9l49.2-36.1q3.2-2 6.6-2 4.7 0 8 3.7t3.3 8.4q-.2 6-5 9.6l-41 30 41 29.9q2.3 1.7 3.6 4.2 1.4 2.5 1.4 5.4z"></path>
<path id="header-tilde" <path id="header-tilde"
d="M73.1 91q0 2-.6 3.9T71 98.6q-3.2 5.7-8.9 8.5-5.6 2.8-12.9 2.8-8.8 0-18-7.8-2.4-2.3-4.5-3.7-2.1-1.5-3-1.7-1.5 0-2.1.3l-.8 1.3q-.3.7-.8 1.2l-1 1-.9.8q-2.7 2-6.4 2-1.7 0-3.2-.3-1.4-.3-3-1.1-1.5-.8-2.6-2.1-2.8-3.1-2.8-8v-1.3q0-.7.2-1.2l.2-1 .4-1 .4-1q.1-.6.5-1.1l.5-1q3.2-5.7 8.8-8.5 5.7-2.9 13-2.9 3.2 0 6.2 1 3 .9 6 2.7 2.9 1.6 5.7 4.2 5.2 4.6 7.6 5.4 1 0 1.6-.2l.7-.4q.3-.1.5-.4 3.6-5.6 9.2-5.6 5.7 0 8.8 3.5 2.8 3 2.8 8z" /> d="M73.1 91q0 2-.6 3.9T71 98.6q-3.2 5.7-8.9 8.5-5.6 2.8-12.9 2.8-8.8 0-18-7.8-2.4-2.3-4.5-3.7-2.1-1.5-3-1.7-1.5 0-2.1.3l-.8 1.3q-.3.7-.8 1.2l-1 1-.9.8q-2.7 2-6.4 2-1.7 0-3.2-.3-1.4-.3-3-1.1-1.5-.8-2.6-2.1-2.8-3.1-2.8-8v-1.3q0-.7.2-1.2l.2-1 .4-1 .4-1q.1-.6.5-1.1l.5-1q3.2-5.7 8.8-8.5 5.7-2.9 13-2.9 3.2 0 6.2 1 3 .9 6 2.7 2.9 1.6 5.7 4.2 5.2 4.6 7.6 5.4 1 0 1.6-.2l.7-.4q.3-.1.5-.4 3.6-5.6 9.2-5.6 5.7 0 8.8 3.5 2.8 3 2.8 8z"></path>
</svg> </svg>
Homepage of Homepage of
<div class=p-name> <div class=p-name>