Compare commits

...

4 Commits

Author SHA1 Message Date
Tom
365df899c7 Fix alt again 2025-05-26 11:32:19 +01:00
Tom
410ed27830 Add alt text 2025-05-26 11:21:58 +01:00
Tom
d5b8ea7fbb Fix aside arrow 2025-05-26 11:11:22 +01:00
Tom
c2f196a93a Change fonts, add rust blog post 2025-05-26 10:37:43 +01:00
34 changed files with 707 additions and 324 deletions

View File

@ -8,7 +8,7 @@ group :jekyll_plugins do
gem 'jekyll-feed' gem 'jekyll-feed'
gem 'jekyll-redirect-from' gem 'jekyll-redirect-from'
gem 'jekyll_flexible_include' gem 'jekyll_flexible_include'
gem "kramdown-syntax-coderay", "~> 1.0" # gem "kramdown-syntax-coderay", "~> 1.0"
gem "jekyll-last-modified-at" gem "jekyll-last-modified-at"
end end

View File

@ -22,9 +22,13 @@ collections:
output: true output: true
kramdown: kramdown:
syntax_highlighter: coderay syntax_highlighter: rouge
syntax_highlighter_opts: syntax_highlighter_opts:
line_numbers: false line_numbers: false
css_class: 'highlight'
span:
wrap: span
flexible_include: flexible_include:
die_on_flexible_include_error: false die_on_flexible_include_error: false
@ -36,7 +40,7 @@ plugins:
# - jekyll-feed # - jekyll-feed
- jekyll-redirect-from - jekyll-redirect-from
- flexible_include - flexible_include
- kramdown-syntax-coderay # - kramdown-syntax-coderay
- jekyll-last-modified-at - jekyll-last-modified-at

View File

@ -26,6 +26,12 @@
<!-- Webmentions provided webmention.io --> <!-- Webmentions provided webmention.io -->
<link rel="webmention" href="https://webmention.io/thomashodson.com/webmention" /> <link rel="webmention" href="https://webmention.io/thomashodson.com/webmention" />
<!-- Preload fonts -->
<link rel="preload" href="/assets/fonts/JetBrainsMono.woff2" as="font" type="font/woff2">
<link rel="preload" href="/assets/fonts/Inter.woff2" as="font" type="font/woff2">
<link rel="preload" href="/assets/fonts/SpaceGrotesk.woff2" as="font" type="font/woff2">
<!-- Description tags --> <!-- Description tags -->
{% if page.excerpt %} {% if page.excerpt %}
<!-- HTML Meta Tag Description --> <!-- HTML Meta Tag Description -->

View File

@ -21,7 +21,7 @@
</figure> </figure>
</a> </a>
<section style="view-transition-name: {{post.slug}}"> <section class="transition-container" style="view-transition-name: {{post.slug}}">
<section class="title-date-container"> <section class="title-date-container">
<h2 class="p-name blogroll-title"><a class="u-uid u-url" href="{{ post.url }}">{{ post.title }}</a></h2> <h2 class="p-name blogroll-title"><a class="u-uid u-url" href="{{ post.url }}">{{ post.title }}</a></h2>
<time class="dt-published" datetime="{{ post.date | date_to_xmlschema }}">{{ post.date | date: '%b %Y' }}</time> <time class="dt-published" datetime="{{ post.date | date_to_xmlschema }}">{{ post.date | date: '%b %Y' }}</time>

View File

@ -0,0 +1,39 @@
---
title: Bind, Borrow, Deref
layout: post
excerpt: Safely sharing objects between Python and Rust using PyO3
draft: False
assets: /assets/blog/pyo3-smart-pointers
thumbnail: /assets/blog/pyo3-smart-pointers/thumbnail.svg
social_image: /assets/blog/pyo3-smart-pointers/thumbnail.png
alt: An SVG of the text 'Py<T>' with the T in orange.
image_class: invertable
---
<section class="note" markdown=1>
This article works for the rust package PyO3 `v0.25`, check the [migration guide](https://pyo3.rs/latest/migration.html) if you're working with a newer version as the project is changing quickly and I imagine the advent of free-threaded python will lead to some changes.
</section>
If you're doing Rust <-> Python interfaces with PyO3 you'll have to work with PyO3's model of how owning python objects in rust. I'm still on my way to fully getting this but here are my notes on the topic so far.
If `T`{:.language-rust} is a python type (in rust) then `Py<T>`{:.language-rust} is the 'loosest' handle we can have on it. This is the only one you can store in a struct.
The next level up is talking to the python interpreter. To do this you need to 'bind' to the interpreter. In pre-3.13 python, only one thread can get the GIL at a time and so holding the GIL means you have the exclusive right to talk to the Python interpreter. In free-threaded python, multiple threads can talk to the interpreter but they still need to `bind` to it.
<details class="aside" markdown=1>
<summary>Why do we still have to bind in free-threaded python?</summary>
My understanding is that, even in free-threaded python, we still a need a mechanism to keep track of which threads are currently bound to the interpreter because the python garbage collector can only run when no threads are bound to the interpreter. Presumably this means we need to be careful to give the GC a chance to run every now and then but I haven't looked deeply into this aspect.
</details>
Binding requires a `py` which is a token in PyO3 that represents the python interpreter. Calling `let bound = value.bind(py)`{:.language-rust} converts our `Py<T>`{:.language-rust} to a `Bound<'py, T>`{:.language-rust}.
A `Bound<'py, T>`{:.language-rust} is basically a smart pointer like `Rc<T>`{:.language-rust} or `Arc<T>`{:.language-rust} but the reference counting and garbage collection of the value it points to is managed by the Python interpreter instead of Rust. To actually use the value T we need to borrow the `Bound<'py, T>`{:.language-rust} with `bound.borrow()` giving us a `PyRef<'py, T>`{:.language-rust}. This increments the reference count in Python world and gives us a `PyRef<'py, T>`{:.language-rust}. Note that in python there's no distinction between a mutable reference and an immutable one so once we have borrowed we can read or write.
Finally `PyRef<'py, T>`{:.language-rust} implements the `Deref`{:.language-rust} trait so we can use the value as if it were a `T`{:.language-rust} while still having some useful context information about where we borrowed the `T`{:.language-rust} from.
So in summary:
1. Bind a `Py<T>`{:.language-rust} to the GIL to get a `Bound<'py, T>`{:.language-rust}
1. Borrow a `Bound<'py, T>`{:.language-rust} to get a `PyRef<'py, T>`{:.language-rust}
1. Use a `PyRef<'py, T>`{:.language-rust} just like a `T`{:.language-rust}.

View File

@ -0,0 +1,54 @@
---
title: A Portfolio Website
layout: project
excerpt: A portfolio website for a friend of mine who is an artist and musician. He did the art I just added CSS.
permalink: /projects/montys_website
assets: /assets/projects/montys_website
date: 2023-11-12
draft: True
img:
alt:
class: invertable
src: /assets/projects/montys_website/thumbnail.svg
social_image: /assets/projects/montys_website/bio_pic.png
head: |
<script type="module" src="/assets/js/model-viewer.js"></script>
---
<figure>
<img src="{{page.assets}}/bio_page.png">
</figure>
<figure>
<img src="{{page.assets}}/map_page.png">
<figcaption>Click to zoom</figcaption>
</figure>
<model-viewer src = "{{page.assets}}/test.glb" camera-controls></model-viewer>
<model-viewer src = "{{page.assets}}/test2.glb" camera-controls></model-viewer>
<model-viewer src = "{{page.assets}}/test3.glb" camera-controls></model-viewer>
<!-- <outline-model-viewer model = "{{page.assets}}/test.glb" camera='{"type":"perspective","fov":30,"near":10,"far":10000,"position":[364.9,307.2,459.7],"rotation":[-0.5891,0.5833,0.3527],"zoom":250,"target":[0,0,0]}'
ambient-light="6" directional-light="0.8" materials=keep mode=2
>
<img class="outline-model-poster no-wc" src = "{{page.img.src}}">
<p class="has-wc">Loading model...</p>
</outline-model-viewer>
<outline-model-viewer model = "{{page.assets}}/test2.glb" camera='{"type":"perspective","fov":30,"near":10,"far":10000,"position":[364.9,307.2,459.7],"rotation":[-0.5891,0.5833,0.3527],"zoom":250,"target":[0,0,0]}'>
<img class="outline-model-poster no-wc" src = "{{page.img.src}}">
<p class="has-wc">Loading model...</p>
</outline-model-viewer>
<outline-model-viewer model = "{{page.assets}}/test3.glb" camera='{"type":"perspective","fov":30,"near":10,"far":10000,"position":[364.9,307.2,459.7],"rotation":[-0.5891,0.5833,0.3527],"zoom":250,"target":[0,0,0]}' materials=keep mode=2 ambient-light="6" directional-light="0.8">
<img class="outline-model-poster no-wc" src = "{{page.models}}/pots/pots.png">
<p class="has-wc">Loading model...</p>
</outline-model-viewer> -->

View File

@ -41,4 +41,40 @@ span.icon {
span.icon svg { span.icon svg {
width: .75em; width: .75em;
}
// aside details summary element
// <details class="aside" markdown=1>
// <summary>Why do we still have to bind in free-threaded python?</summary>
// My understanding is that, even in free-threaded python, we still a need a mechanism to keep track of which threads are currently bound to the interpreter because the python garbage collector can only run when no threads are bound to the interpreter. Presumably this means we would need to be careful to give the GC a chance to run every now and then but I haven't looked deeply into this aspect.
// </details>
details.aside[open] > summary {
margin-bottom: 0.5em;
}
details.aside[open] > summary::after {
content: "";
}
details.aside > summary::after {
content: "";
color: var(--theme-highlight-color);
}
details.aside {
summary {
display: flex;
justify-content: space-between;
font-weight: 700;
}
p {
margin: 0;
}
padding: 1em;
margin-top: 1em;
margin-bottom: 1em;
background-color: var(--theme-highlight-color-transparent);
border-radius: 10px;
} }

View File

@ -13,20 +13,33 @@
@import "mastodon_timeline"; @import "mastodon_timeline";
@import "night_mode_toggle"; @import "night_mode_toggle";
@import "highlights"; @import "highlights";
@import "tables"; // The syntax highlighting css @import "tables";
// generated with rougify style bw > code_style_bw.scss
// @import "code_style_bw"; @import "rouge_theme_github.scss";
@import "code_style_github";
@import "d2"; @import "d2";
* { @font-face {
box-sizing: border-box; font-family: "JetBrains Mono";
font-family: $font_stack; src: url("/assets/fonts/JetBrainsMono.woff2") format("woff2");
text-rendering: geometricPrecision;
} }
@font-face {
font-family: "Inter";
src: url("/assets/fonts/Inter.woff2") format("woff2");
}
@font-face {
font-family: "Space Grotesk";
src: url('/assets/fonts/SpaceGrotesk.woff2') format('woff2');
}
:root { :root {
--body-font: 'Inter', 'IBM Plex Sans', sans-serif;
--title-font: Impact, Haettenschweiler, "Franklin Gothic Bold", Charcoal, "Helvetica Inserat", "Bitstream Vera Sans Bold", "Arial Black", "sans serif", HelveticaNeue-CondensedBlack;
--mono-font: "JetBrains Mono", "Source Code Pro", Consolas, "Ubuntu Mono", Menlo, "DejaVu Sans Mono", monospace, monospace;
--theme-text-color: #222; --theme-text-color: #222;
--theme-bg-color: #fcfcfc; --theme-bg-color: #fcfcfc;
--theme-model-line-color: #222; --theme-model-line-color: #222;
@ -34,7 +47,7 @@
--theme-subtle-outline: oklch(90% 0 50); --theme-subtle-outline: oklch(90% 0 50);
--theme-subtle-background: rgba(128, 128, 128, 0.05); --theme-subtle-background: rgba(128, 128, 128, 0.05);
--theme-highlight-color: hsl(338, 75%, 60%); --theme-highlight-color: hsl(338, 75%, 60%);
--theme-highlight-color-transparent: hsla(338, 75%, 60%, 33%); --theme-highlight-color-transparent: hsla(338, 75%, 60%, 20%);
--theme-subtle-text-color: #606984; --theme-subtle-text-color: #606984;
--night-mode-fade-time: 0.5s; --night-mode-fade-time: 0.5s;
@ -71,9 +84,23 @@
--border-color: var(--color-dark-alpha); --border-color: var(--color-dark-alpha);
} }
* {
box-sizing: border-box;
text-rendering: geometricPrecision;
}
h2 {
font-family: var(--body-font);
font-variation-settings: "wght" 700;
}
html { html {
width: 100vw; width: 100vw;
scroll-behavior: smooth; scroll-behavior: smooth;
font-family: var(--body-font);
font-size: 0.9em;
} }
body { body {
@ -121,6 +148,22 @@ main {
} }
} }
// All code both inline and block
code {
font-family: var(--mono-font);
font-size: 0.9rem;
}
// Inline blocks
:not(pre) > code {
}
// Block code
pre.highlight code {
}
hr.heading { hr.heading {
width: 100%; width: 100%;
@ -164,6 +207,7 @@ section.title-icon-container {
section.byline-time { section.byline-time {
display: flex; display: flex;
justify-content: space-between;
time { time {
text-align: right; text-align: right;
@include time-text; @include time-text;
@ -184,7 +228,7 @@ section.byline {
p, p,
figcaption { figcaption {
font-size: 1em; font-size: 1em;
line-height: 1.3em; line-height: 1.4em;
} }
main :is(p, h1, h2, h3, h4, h5, h6) { main :is(p, h1, h2, h3, h4, h5, h6) {
@ -293,18 +337,17 @@ figure.multiple {
} }
section.note { section.note {
a {
color: purple;
}
p { p {
margin: 0; margin: 0;
} }
padding: 1em; padding: 1em;
margin-top: 1em; padding-top: 0.5em;
margin-bottom: 1em; padding-bottom: 0.5em;
margin-top: 0.5em;
margin-bottom: 0.5em;
background-color: var(--theme-highlight-color-transparent); background-color: var(--theme-highlight-color-transparent);
border-radius: 10px; border-radius: 10px;
color: black;
} }
section.center { section.center {
@ -314,15 +357,19 @@ section.center {
margin-bottom: 1em; margin-bottom: 1em;
} }
div.CodeRay {
div.highlighter-rouge {
font-family: SFMono-Regular, Menlo, Monaco, Consolas, Liberation Mono, font-family: SFMono-Regular, Menlo, Monaco, Consolas, Liberation Mono,
Courier New, Courier, monospace; Courier New, Courier, monospace;
font-size: 12px; font-size: 12px;
line-height: 1.4; line-height: 1.4;
padding: 1em;
background-color: var(--theme-subtle-background);
border-radius: 5px; border-radius: 5px;
div.highlight {
padding: 1em;
}
// Override background colors from the theme. // Override background colors from the theme.
span { span {
background-color: unset !important; background-color: unset !important;
@ -388,11 +435,13 @@ body:not(.has-wc) .has-wc {
} }
// Make code a bit smaller so it doesn't wrap as much // Make code a bit smaller so it doesn't wrap as much
div.CodeRay { pre.highlight code {
font-size: 0.8rem; font-size: 0.8rem;
} }
} }
.hidden { .hidden {
display: none; display: none;
} }
@ -430,11 +479,15 @@ svg {
--button-color: var(--color-dark); --button-color: var(--color-dark);
--border-color: var(--color-light-alpha); --border-color: var(--color-light-alpha);
body { body {
--theme-text-color: #fcfcfc; --theme-text-color: #fcfcfc;
--theme-bg-color: #222; --theme-bg-color: #222;
--theme-subtle-outline: oklch(50% 0 50); --theme-subtle-outline: oklch(50% 0 50);
--theme-subtle-background: rgba(255, 255, 255, 0.05); --theme-subtle-background: rgba(255, 255, 255, 0.05);
--theme-highlight-color-transparent: hsl(338, 85%, 21%);
} }
// Two main image classes are "invertable" i.e look good inverted // Two main image classes are "invertable" i.e look good inverted
@ -463,11 +516,13 @@ svg {
:root:not([data-user-color-scheme]) { :root:not([data-user-color-scheme]) {
@include night-mode; @include night-mode;
// @import "rouge_theme_gruvbox.dark.scss";
} }
} }
[data-user-color-scheme="dark"] { [data-user-color-scheme="dark"] {
@include night-mode; @include night-mode;
@import "rouge_theme_gruvbox.dark.scss";
} }
@media (prefers-reduced-motion: no-preference) { @media (prefers-reduced-motion: no-preference) {

View File

@ -1,66 +0,0 @@
.highlight table td { padding: 5px; }
.highlight table pre { margin: 0; }
.highlight, .highlight .w {
color: #000000;
background-color: #ffffff;
}
.highlight .c, .highlight .ch, .highlight .cd, .highlight .cm, .highlight .cpf, .highlight .c1, .highlight .cs {
font-style: italic;
}
.highlight .cp {
}
.highlight .k, .highlight .kc, .highlight .kd, .highlight .kn, .highlight .kr, .highlight .kv {
font-weight: bold;
}
.highlight .kp {
}
.highlight .kt {
}
.highlight .o, .highlight .ow {
font-weight: bold;
}
.highlight .nc {
font-weight: bold;
}
.highlight .nn {
font-weight: bold;
}
.highlight .ne {
font-weight: bold;
}
.highlight .ni {
font-weight: bold;
}
.highlight .nt {
font-weight: bold;
}
.highlight .s, .highlight .sb, .highlight .sc, .highlight .dl, .highlight .sd, .highlight .s2, .highlight .sh, .highlight .sx, .highlight .sr, .highlight .s1, .highlight .ss {
font-style: italic;
}
.highlight .sa {
font-weight: bold;
}
.highlight .si {
font-weight: bold;
}
.highlight .se {
font-weight: bold;
}
.highlight .gh {
font-weight: bold;
}
.highlight .gu {
font-weight: bold;
}
.highlight .ge {
font-style: italic;
}
.highlight .gs {
font-weight: bold;
}
.highlight .gp {
font-weight: bold;
}
.highlight .err {
color: #FF0000;
}

View File

@ -1,233 +0,0 @@
.highlight {
font-family: SFMono-Regular, Menlo, Monaco, Consolas, Liberation Mono,
Courier New, Courier, monospace;
font-size: 12px;
line-height: 1.4;
}
.highlight table td {
padding: 5px;
}
.highlight table pre {
margin: 0;
}
.highlight .cm {
color: #999988;
font-style: italic;
}
.highlight .cp {
color: #999999;
font-weight: bold;
}
.highlight .c1 {
color: #999988;
font-style: italic;
}
.highlight .cs {
color: #999999;
font-weight: bold;
font-style: italic;
}
.highlight .c,
.highlight .ch,
.highlight .cd,
.highlight .cpf {
color: #999988;
font-style: italic;
}
.highlight .err {
color: #a61717;
background-color: #e3d2d2;
}
.highlight .gd {
color: #000000;
background-color: #ffdddd;
}
.highlight .ge {
color: #000000;
font-style: italic;
}
.highlight .gr {
color: #aa0000;
}
.highlight .gh {
color: #999999;
}
.highlight .gi {
color: #000000;
background-color: #ddffdd;
}
.highlight .go {
color: #888888;
}
.highlight .gp {
color: #555555;
}
.highlight .gs {
font-weight: bold;
}
.highlight .gu {
color: #aaaaaa;
}
.highlight .gt {
color: #aa0000;
}
.highlight .kc {
color: #000000;
font-weight: bold;
}
.highlight .kd {
color: #000000;
font-weight: bold;
}
.highlight .kn {
color: #000000;
font-weight: bold;
}
.highlight .kp {
color: #000000;
font-weight: bold;
}
.highlight .kr {
color: #000000;
font-weight: bold;
}
.highlight .kt {
color: #445588;
font-weight: bold;
}
.highlight .k,
.highlight .kv {
color: #000000;
font-weight: bold;
}
.highlight .mf {
color: #009999;
}
.highlight .mh {
color: #009999;
}
.highlight .il {
color: #009999;
}
.highlight .mi {
color: #009999;
}
.highlight .mo {
color: #009999;
}
.highlight .m,
.highlight .mb,
.highlight .mx {
color: #009999;
}
.highlight .sa {
color: #000000;
font-weight: bold;
}
.highlight .sb {
color: #d14;
}
.highlight .sc {
color: #d14;
}
.highlight .sd {
color: #d14;
}
.highlight .s2 {
color: #d14;
}
.highlight .se {
color: #d14;
}
.highlight .sh {
color: #d14;
}
.highlight .si {
color: #d14;
}
.highlight .sx {
color: #d14;
}
.highlight .sr {
color: #009926;
}
.highlight .s1 {
color: #d14;
}
.highlight .ss {
color: #990073;
}
.highlight .s,
.highlight .dl {
color: #d14;
}
.highlight .na {
color: #008080;
}
.highlight .bp {
color: #999999;
}
.highlight .nb {
color: #0086b3;
}
.highlight .nc {
color: #445588;
font-weight: bold;
}
.highlight .no {
color: #008080;
}
.highlight .nd {
color: #3c5d5d;
font-weight: bold;
}
.highlight .ni {
color: #800080;
}
.highlight .ne {
color: #990000;
font-weight: bold;
}
.highlight .nf,
.highlight .fm {
color: #990000;
font-weight: bold;
}
.highlight .nl {
color: #990000;
font-weight: bold;
}
.highlight .nn {
color: #555555;
}
.highlight .nt {
color: #000080;
}
.highlight .vc {
color: #008080;
}
.highlight .vg {
color: #008080;
}
.highlight .vi {
color: #008080;
}
.highlight .nv,
.highlight .vm {
color: #008080;
}
.highlight .ow {
color: #000000;
font-weight: bold;
}
.highlight .o {
color: #000000;
font-weight: bold;
}
.highlight .w {
color: #bbbbbb;
}
.highlight {
background-color: #f8f8f8;
}

View File

@ -44,7 +44,7 @@ header {
h1, h1,
h2 { h2 {
font-family: $title_font_stack; font-family: var(--title-font);
} }
a { a {

View File

@ -25,3 +25,7 @@ section.highlights {
font-size: 1.25rem; font-size: 1.25rem;
} }
} }
section.transition-container {
width: 100%;
}

View File

@ -31,6 +31,8 @@ article.project {
} }
section.header { section.header {
width: 100%;
h1 { h1 {
font-size: clamp(20px, 20px * 100vw / 300px, 25px); font-size: clamp(20px, 20px * 100vw / 300px, 25px);
} }

View File

@ -0,0 +1,233 @@
.highlighter-rouge {
background-color: var(--theme-subtle-background);
}
code.highlighter-rouge {
padding-right: 0.3em;
padding-left: 0.3em;
border-radius: 0.3em;
}
.highlight,
.highlighter-rouge {
table td {
padding: 5px;
}
table pre {
margin: 0;
}
.cm {
color: #999988;
font-style: italic;
}
.cp {
color: #999999;
font-weight: bold;
}
.c1 {
color: #999988;
font-style: italic;
}
.cs {
color: #999999;
font-weight: bold;
font-style: italic;
}
.c,
.ch,
.cd,
.cpf {
color: #999988;
font-style: italic;
}
.err {
color: #a61717;
// background-color: unset;
}
.gd {
color: #000000;
background-color: #ffdddd;
}
.ge {
color: #000000;
font-style: italic;
}
.gr {
color: #aa0000;
}
.gh {
color: #999999;
}
.gi {
color: #000000;
background-color: #ddffdd;
}
.go {
color: #888888;
}
.gp {
color: #555555;
}
.gs {
font-weight: bold;
}
.gu {
color: #aaaaaa;
}
.gt {
color: #aa0000;
}
.kc {
color: #000000;
font-weight: bold;
}
.kd {
color: #000000;
font-weight: bold;
}
.kn {
color: #000000;
font-weight: bold;
}
.kp {
color: #000000;
font-weight: bold;
}
.kr {
color: #000000;
font-weight: bold;
}
.kt {
color: #445588;
font-weight: bold;
}
.k,
.kv {
color: #000000;
font-weight: bold;
}
.mf {
color: #009999;
}
.mh {
color: #009999;
}
.il {
color: #009999;
}
.mi {
color: #009999;
}
.mo {
color: #009999;
}
.m,
.mb,
.mx {
color: #009999;
}
.sb {
color: #d14;
}
.sc {
color: #d14;
}
.sd {
color: #d14;
}
.s2 {
color: #d14;
}
.se {
color: #d14;
}
.sh {
color: #d14;
}
.si {
color: #d14;
}
.sx {
color: #d14;
}
.sr {
color: #009926;
}
.s1 {
color: #d14;
}
.ss {
color: #990073;
}
.s,
.sa,
.dl {
color: #d14;
}
.na {
color: #008080;
}
.bp {
color: #999999;
}
.nb {
color: #0086b3;
}
.nc {
color: #445588;
font-weight: bold;
}
.no {
color: #008080;
}
.nd {
color: #3c5d5d;
font-weight: bold;
}
.ni {
color: #800080;
}
.ne {
color: #990000;
font-weight: bold;
}
.nf,
.fm {
color: #990000;
font-weight: bold;
}
.nl {
color: #990000;
font-weight: bold;
}
.nn {
color: #555555;
}
.nt {
color: #000080;
}
.vc {
color: #008080;
}
.vg {
color: #008080;
}
.vi {
color: #008080;
}
.nv,
.vm {
color: #008080;
}
.ow {
color: #000000;
font-weight: bold;
}
.o {
color: #000000;
font-weight: bold;
}
.w {
color: #bbbbbb;
}
}

View File

@ -0,0 +1,123 @@
.highlight,
.highlighter-rouge {
table td {
padding: 5px;
}
table pre {
margin: 0;
}
.highlight,
.w {
color: #fbf1c7;
background-color: unset;
}
.err {
color: #fb4934;
background-color: #282828;
font-weight: bold;
}
.c,
.ch,
.cd,
.cm,
.cpf,
.c1,
.cs {
color: #928374;
font-style: italic;
}
.cp {
color: #8ec07c;
}
.nt {
color: #fb4934;
}
.n {
color: #fbf1c7;
}
.o,
.ow {
color: #fbf1c7;
}
.p,
.pi {
color: #fbf1c7;
}
.gi {
color: #b8bb26;
background-color: #282828;
}
.gd {
color: #fb4934;
background-color: #282828;
}
.gh {
color: #b8bb26;
font-weight: bold;
}
.k,
.kn,
.kp,
.kr,
.kv {
color: #fb4934;
}
.kc {
color: #d3869b;
}
.kt {
color: #fabd2f;
}
.kd {
color: #fe8019;
}
.s,
.sa,
.sb,
.sc,
.dl,
.sd,
.s2,
.sh,
.sx,
.s1 {
color: #b8bb26;
font-style: italic;
}
.si {
color: #b8bb26;
font-style: italic;
}
.sr {
color: #b8bb26;
font-style: italic;
}
.se {
color: #fe8019;
}
.nn {
color: #8ec07c;
}
.nc {
color: #8ec07c;
}
.no {
color: #d3869b;
}
.na {
color: #b8bb26;
}
.m,
.mb,
.mf,
.mh,
.mi,
.il,
.mo,
.mx {
color: #d3869b;
}
.ss {
color: #83a598;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

View File

@ -0,0 +1,75 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="250"
height="250"
viewBox="0 0 66.145832 66.145833"
version="1.1"
id="svg5"
inkscape:version="1.2.2 (b0a84865, 2022-12-01)"
sodipodi:docname="thumbnail.svg"
inkscape:export-filename="thumbnail.png"
inkscape:export-xdpi="150"
inkscape:export-ydpi="150"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview7"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
showgrid="false"
inkscape:zoom="0.58578193"
inkscape:cx="231.31475"
inkscape:cy="133.15535"
inkscape:window-width="1309"
inkscape:window-height="638"
inkscape:window-x="0"
inkscape:window-y="35"
inkscape:window-maximized="0"
inkscape:current-layer="layer1" />
<defs
id="defs2">
<rect
x="34.386857"
y="105.45303"
width="214.38501"
height="38.162215"
id="rect236" />
<rect
x="34.386856"
y="105.45303"
width="175.37297"
height="34.386856"
id="rect236-5" />
<rect
x="34.386856"
y="105.45303"
width="277.30765"
height="48.229837"
id="rect236-7" />
</defs>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<text
xml:space="preserve"
transform="matrix(0.60814846,0,0,0.60814846,-12.261402,-40.379947)"
id="text234-4"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:26.7632px;line-height:1.15;font-family:'Space Grotesk';-inkscape-font-specification:'Space Grotesk, @wght=700';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;font-variation-settings:'wght' 700;white-space:pre;shape-inside:url(#rect236-5);display:inline;fill:#000000;fill-opacity:1;stroke-width:2.592;stroke-miterlimit:4.9"><tspan
x="34.386719"
y="128.09907"
id="tspan1811">Py&lt;<tspan
style="fill:#c87137"
id="tspan1809">T</tspan>&gt;</tspan></text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Binary file not shown.

BIN
assets/fonts/Inter.woff2 Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 185 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 MiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="250mm"
height="250mm"
viewBox="0 0 250 250"
version="1.1"
id="svg5"
xml:space="preserve"
sodipodi:docname="thumbnail.svg"
inkscape:version="1.2.2 (b0a84865, 2022-12-01)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
id="namedview7"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
showgrid="false"
inkscape:zoom="0.33165719"
inkscape:cx="432.67568"
inkscape:cy="107.03824"
inkscape:window-width="1390"
inkscape:window-height="1205"
inkscape:window-x="166"
inkscape:window-y="43"
inkscape:window-maximized="0"
inkscape:current-layer="g2512" /><defs
id="defs2" /><g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-1.8192797,-13.999887)"><g
id="g2512"
transform="matrix(3.1226268,0,0,3.1226268,-3.8616521,-29.716538)"><path
style="fill:none;stroke:none;stroke-width:0.6858;stroke-dasharray:none;stroke-opacity:1"
d="m 2.1621798,54.030288 v -39.6875 H 41.84968 81.53718 v 39.6875 39.6875 H 41.84968 2.1621798 Z"
id="path406" /><path
style="fill:none;stroke:#000000;stroke-width:0.6858;stroke-dasharray:none;stroke-opacity:1"
d="m 30.779229,93.452872 -0.150034,-0.7276 c -0.416208,-2.01845 -0.950344,-5.52016 -0.950344,-6.23032 0,-0.44175 -0.07704,-0.72615 -0.171188,-0.632 -0.372642,0.37264 -1.114263,2.99155 -0.990388,3.49738 0.07242,0.29572 -0.05258,0.89103 -0.277786,1.32292 -0.225204,0.43189 -0.310474,0.99354 -0.311371,1.30906 -0.002,0.685905 -0.115251,0.895165 -0.484417,1.219779 m -6.584299,0.06472 c -0.09701,-0.097 -0.176711,-0.60302 -0.177104,-1.12448 -6.09e-4,-0.82371 -0.130783,-1.01817 -0.992188,-1.48231 -0.857599,-0.46208 -0.978182,-0.64071 -0.893041,-1.32291 0.119249,-0.95551 0.155688,-6.72556 0.07079,-11.20876 -0.05065,-2.67466 -0.159576,-3.46748 -0.593145,-4.31734 -0.518574,-1.01649 -0.521126,-1.12266 -0.108191,-4.50171 0.232599,-1.90337 0.533212,-3.66678 0.668028,-3.91869 0.134816,-0.2519 0.313209,-1.18687 0.39643,-2.07771 0.135857,-1.45429 0.1013,-1.6197 -0.338382,-1.6197 -0.269331,0 -0.720808,-0.1748 -1.003282,-0.38846 -0.282475,-0.21365 -0.846926,-0.39224 -1.254334,-0.39687 -1.78881,-0.0203 -3.456505,-1.69851 -3.765424,-3.78912 -0.144882,-0.9805 -0.09223,-1.37216 0.23276,-1.73127 0.379584,-0.41943 0.578215,-1.41289 1.490067,-7.45261 0.356484,-2.36121 0.831608,-4.00768 1.603371,-5.55625 0.874045,-1.7538 1.2908,-2.14504 3.108757,-2.91842 0.769792,-0.32748 1.507772,-0.79749 1.639956,-1.04448 0.139078,-0.25987 0.998532,-0.65024 2.039961,-0.92657 0.989795,-0.26263 1.948456,-0.5942 2.130357,-0.73683 0.519401,-0.40726 0.382772,-1.23251 -0.551469,-3.33089 -0.777251,-1.74576 -0.847627,-2.10391 -0.684792,-3.48493 0.271566,-2.30318 1.138963,-3.67996 2.871205,-4.55736 1.936786,-0.981 3.164378,-0.93876 5.178077,0.17816 1.225479,0.67972 1.720771,1.14446 2.171907,2.0379 0.851117,1.68558 0.811588,3.95411 -0.107913,6.19314 -0.711722,1.73307 -0.712473,1.74202 -0.22292,2.65107 0.270166,0.50167 0.682504,0.91213 0.916305,0.91213 0.65304,0 3.317029,1.02791 3.413949,1.31729 0.04725,0.14108 0.844319,0.62987 1.771263,1.0862 0.926944,0.45634 1.851867,1.02497 2.055384,1.26362 0.515805,0.60487 1.921687,5.03766 2.403298,7.57768 0.220736,1.16416 0.585779,2.90554 0.811207,3.86972 0.22543,0.96419 0.432626,2.81966 0.460439,4.12328 0.04772,2.23636 0.0067,2.43192 -0.725758,3.46276 -0.993815,1.39862 -1.756153,1.70331 -4.238011,1.69384 l -2.015604,-0.008 0.20455,1.23425 c 0.112503,0.67884 0.230859,1.61109 0.263014,2.07167 0.03215,0.46058 0.245668,1.17496 0.474472,1.5875 0.444765,0.80193 0.807167,1.97646 1.340541,4.34466 0.351599,1.56112 0.197302,3.90875 -0.297072,4.51992 -0.320011,0.39562 -1.276376,13.68669 -1.047745,14.56098 0.215625,0.82455 -0.252669,1.49238 -1.221266,1.74164 -0.660998,0.1701 -0.872694,0.38055 -0.937509,0.93202 l -0.08372,0.7123"
id="path404"
sodipodi:nodetypes="cssssssccsssssssssscsssssssssssssssssscssscccssssssssc" /></g></g></svg>

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

@ -9,6 +9,8 @@ mathjax: false
# Project Ideas # Project Ideas
* Take on board some ideas from https://plainvanillaweb.com/index.html
* get https://www.feather.art/ and try out the line rendering for nice 3D annotations * get https://www.feather.art/ and try out the line rendering for nice 3D annotations
* small telegram/whatsapp server that you can forward an audio message to and get a transcription * small telegram/whatsapp server that you can forward an audio message to and get a transcription