Change fonts, add rust blog post
2
Gemfile
@ -8,7 +8,7 @@ group :jekyll_plugins do
|
||||
gem 'jekyll-feed'
|
||||
gem 'jekyll-redirect-from'
|
||||
gem 'jekyll_flexible_include'
|
||||
gem "kramdown-syntax-coderay", "~> 1.0"
|
||||
# gem "kramdown-syntax-coderay", "~> 1.0"
|
||||
gem "jekyll-last-modified-at"
|
||||
end
|
||||
|
||||
|
@ -22,9 +22,13 @@ collections:
|
||||
output: true
|
||||
|
||||
kramdown:
|
||||
syntax_highlighter: coderay
|
||||
syntax_highlighter: rouge
|
||||
syntax_highlighter_opts:
|
||||
line_numbers: false
|
||||
css_class: 'highlight'
|
||||
span:
|
||||
wrap: span
|
||||
|
||||
|
||||
flexible_include:
|
||||
die_on_flexible_include_error: false
|
||||
@ -36,7 +40,7 @@ plugins:
|
||||
# - jekyll-feed
|
||||
- jekyll-redirect-from
|
||||
- flexible_include
|
||||
- kramdown-syntax-coderay
|
||||
# - kramdown-syntax-coderay
|
||||
- jekyll-last-modified-at
|
||||
|
||||
|
||||
|
@ -26,6 +26,12 @@
|
||||
<!-- Webmentions provided webmention.io -->
|
||||
<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 -->
|
||||
{% if page.excerpt %}
|
||||
<!-- HTML Meta Tag Description -->
|
||||
|
@ -21,7 +21,7 @@
|
||||
</figure>
|
||||
</a>
|
||||
|
||||
<section style="view-transition-name: {{post.slug}}">
|
||||
<section class="transition-container" style="view-transition-name: {{post.slug}}">
|
||||
<section class="title-date-container">
|
||||
<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>
|
||||
|
39
_posts/2025-05-26-PyO3-smart-pointers.md
Normal 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:
|
||||
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}.
|
54
_projects/montys_website.md
Normal 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> -->
|
@ -41,4 +41,32 @@ span.icon {
|
||||
|
||||
span.icon svg {
|
||||
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 {
|
||||
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;
|
||||
}
|
111
_sass/base.scss
@ -13,20 +13,49 @@
|
||||
@import "mastodon_timeline";
|
||||
@import "night_mode_toggle";
|
||||
@import "highlights";
|
||||
@import "tables"; // The syntax highlighting css
|
||||
// generated with rougify style bw > code_style_bw.scss
|
||||
// @import "code_style_bw";
|
||||
@import "code_style_github";
|
||||
@import "tables";
|
||||
|
||||
@import "rouge_theme_github.scss";
|
||||
|
||||
@import "d2";
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
font-family: $font_stack;
|
||||
text-rendering: geometricPrecision;
|
||||
@font-face {
|
||||
font-family: "JetBrains Mono";
|
||||
src: url("/assets/fonts/JetBrainsMono.woff2") format("woff2");
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Inter";
|
||||
src: url("/assets/fonts/Inter.woff2") format("woff2");
|
||||
// font-weight: normal;
|
||||
// font-style: normal;
|
||||
}
|
||||
|
||||
// @font-face {
|
||||
// font-family: "Inter";
|
||||
// src: url("/assets/fonts/Inter.woff2") format("woff2");
|
||||
// font-weight: normal;
|
||||
// font-style: italic;
|
||||
// font-variation-settings: "ital" 1;
|
||||
// font-synthesis: none;
|
||||
// }
|
||||
|
||||
@font-face {
|
||||
font-family: "Space Grotesk";
|
||||
src: url('/assets/fonts/SpaceGrotesk.woff2') format('woff2');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
|
||||
: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-bg-color: #fcfcfc;
|
||||
--theme-model-line-color: #222;
|
||||
@ -34,7 +63,7 @@
|
||||
--theme-subtle-outline: oklch(90% 0 50);
|
||||
--theme-subtle-background: rgba(128, 128, 128, 0.05);
|
||||
--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;
|
||||
|
||||
--night-mode-fade-time: 0.5s;
|
||||
@ -71,9 +100,23 @@
|
||||
--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 {
|
||||
width: 100vw;
|
||||
scroll-behavior: smooth;
|
||||
font-family: var(--body-font);
|
||||
font-size: 0.9em;
|
||||
|
||||
|
||||
}
|
||||
|
||||
body {
|
||||
@ -121,6 +164,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 {
|
||||
width: 100%;
|
||||
@ -164,6 +223,7 @@ section.title-icon-container {
|
||||
|
||||
section.byline-time {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
time {
|
||||
text-align: right;
|
||||
@include time-text;
|
||||
@ -184,7 +244,7 @@ section.byline {
|
||||
p,
|
||||
figcaption {
|
||||
font-size: 1em;
|
||||
line-height: 1.3em;
|
||||
line-height: 1.4em;
|
||||
}
|
||||
|
||||
main :is(p, h1, h2, h3, h4, h5, h6) {
|
||||
@ -293,18 +353,17 @@ figure.multiple {
|
||||
}
|
||||
|
||||
section.note {
|
||||
a {
|
||||
color: purple;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0;
|
||||
}
|
||||
padding: 1em;
|
||||
margin-top: 1em;
|
||||
margin-bottom: 1em;
|
||||
padding-top: 0.5em;
|
||||
padding-bottom: 0.5em;
|
||||
margin-top: 0.5em;
|
||||
margin-bottom: 0.5em;
|
||||
background-color: var(--theme-highlight-color-transparent);
|
||||
border-radius: 10px;
|
||||
color: black;
|
||||
}
|
||||
|
||||
section.center {
|
||||
@ -314,15 +373,19 @@ section.center {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
div.CodeRay {
|
||||
|
||||
|
||||
div.highlighter-rouge {
|
||||
font-family: SFMono-Regular, Menlo, Monaco, Consolas, Liberation Mono,
|
||||
Courier New, Courier, monospace;
|
||||
font-size: 12px;
|
||||
line-height: 1.4;
|
||||
padding: 1em;
|
||||
background-color: var(--theme-subtle-background);
|
||||
border-radius: 5px;
|
||||
|
||||
div.highlight {
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
// Override background colors from the theme.
|
||||
span {
|
||||
background-color: unset !important;
|
||||
@ -388,11 +451,13 @@ body:not(.has-wc) .has-wc {
|
||||
}
|
||||
|
||||
// Make code a bit smaller so it doesn't wrap as much
|
||||
div.CodeRay {
|
||||
pre.highlight code {
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
@ -430,11 +495,15 @@ svg {
|
||||
--button-color: var(--color-dark);
|
||||
--border-color: var(--color-light-alpha);
|
||||
|
||||
|
||||
|
||||
|
||||
body {
|
||||
--theme-text-color: #fcfcfc;
|
||||
--theme-bg-color: #222;
|
||||
--theme-subtle-outline: oklch(50% 0 50);
|
||||
--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
|
||||
@ -463,11 +532,13 @@ svg {
|
||||
|
||||
:root:not([data-user-color-scheme]) {
|
||||
@include night-mode;
|
||||
// @import "rouge_theme_gruvbox.dark.scss";
|
||||
}
|
||||
}
|
||||
|
||||
[data-user-color-scheme="dark"] {
|
||||
@include night-mode;
|
||||
@import "rouge_theme_gruvbox.dark.scss";
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -44,7 +44,7 @@ header {
|
||||
|
||||
h1,
|
||||
h2 {
|
||||
font-family: $title_font_stack;
|
||||
font-family: var(--title-font);
|
||||
}
|
||||
|
||||
a {
|
||||
|
@ -25,3 +25,7 @@ section.highlights {
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
}
|
||||
|
||||
section.transition-container {
|
||||
width: 100%;
|
||||
}
|
@ -31,6 +31,8 @@ article.project {
|
||||
}
|
||||
|
||||
section.header {
|
||||
width: 100%;
|
||||
|
||||
h1 {
|
||||
font-size: clamp(20px, 20px * 100vw / 300px, 25px);
|
||||
}
|
||||
|
233
_sass/rouge_theme_github.scss
Normal 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;
|
||||
}
|
||||
}
|
123
_sass/rouge_theme_gruvbox.dark.scss
Normal 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;
|
||||
}
|
||||
}
|
BIN
assets/blog/pyo3-smart-pointers/thumbnail.png
Normal file
After Width: | Height: | Size: 4.5 KiB |
75
assets/blog/pyo3-smart-pointers/thumbnail.svg
Normal 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<<tspan
|
||||
style="fill:#c87137"
|
||||
id="tspan1809">T</tspan>></tspan></text>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.5 KiB |
BIN
assets/fonts/Inter-Italic-VariableFont_opsz,wght.ttf
Normal file
BIN
assets/fonts/Inter-VariableFont_opsz,wght.ttf
Normal file
BIN
assets/fonts/Inter.woff2
Normal file
BIN
assets/fonts/JetBrainsMono-Italic-VariableFont_wght.ttf
Normal file
BIN
assets/fonts/JetBrainsMono-VariableFont_wght.ttf
Normal file
BIN
assets/fonts/JetBrainsMono.woff2
Normal file
BIN
assets/fonts/SpaceGrotesk-VariableFont_wght.ttf
Normal file
BIN
assets/fonts/SpaceGrotesk.woff2
Normal file
BIN
assets/projects/montys_website/bio_page.png
Normal file
After Width: | Height: | Size: 185 KiB |
BIN
assets/projects/montys_website/bio_pic.png
Normal file
After Width: | Height: | Size: 72 KiB |
BIN
assets/projects/montys_website/map_page.png
Normal file
After Width: | Height: | Size: 2.9 MiB |
BIN
assets/projects/montys_website/music_page.png
Normal file
After Width: | Height: | Size: 2.5 MiB |
BIN
assets/projects/montys_website/test.glb
Normal file
BIN
assets/projects/montys_website/test2.glb
Normal file
BIN
assets/projects/montys_website/test3.glb
Normal file
49
assets/projects/montys_website/thumbnail.svg
Normal 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 |
@ -9,6 +9,8 @@ mathjax: false
|
||||
|
||||
# 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
|
||||
|
||||
* small telegram/whatsapp server that you can forward an audio message to and get a transcription
|
||||
|