initial commit

This commit is contained in:
Markus Heurung 2024-03-05 17:04:12 +01:00
commit 3be5ee1703
33 changed files with 2121 additions and 0 deletions

5
.gitignore vendored Normal file
View file

@ -0,0 +1,5 @@
_site
.sass-cache
.jekyll-cache
.jekyll-metadata
vendor

25
404.html Normal file
View file

@ -0,0 +1,25 @@
---
permalink: /404.html
layout: default
---
<style type="text/css" media="screen">
.container {
margin: 10px auto;
max-width: 600px;
text-align: center;
}
h1 {
margin: 30px 0;
font-size: 4em;
line-height: 1;
letter-spacing: -1px;
}
</style>
<div class="container">
<h1>404</h1>
<p><strong>Page not found :(</strong></p>
<p>The requested page could not be found.</p>
</div>

14
Gemfile Normal file
View file

@ -0,0 +1,14 @@
source "https://rubygems.org"
gem "jekyll", "~> 4.0"
gem "rss"
gem "rake"
group :jekyll_plugins do
gem "jekyll-compose"
gem "jekyll-deploy"
gem "jekyll-feed", "~> 0.17"
gem "jekyll-redirect-from"
gem "jemoji"
end

119
Gemfile.lock Normal file
View file

@ -0,0 +1,119 @@
GEM
remote: https://rubygems.org/
specs:
activesupport (7.1.3)
base64
bigdecimal
concurrent-ruby (~> 1.0, >= 1.0.2)
connection_pool (>= 2.2.5)
drb
i18n (>= 1.6, < 2)
minitest (>= 5.1)
mutex_m
tzinfo (~> 2.0)
addressable (2.8.6)
public_suffix (>= 2.0.2, < 6.0)
base64 (0.2.0)
bigdecimal (3.1.6)
colorator (1.1.0)
concurrent-ruby (1.2.3)
connection_pool (2.4.1)
drb (2.2.0)
ruby2_keywords
em-websocket (0.5.3)
eventmachine (>= 0.12.9)
http_parser.rb (~> 0)
eventmachine (1.2.7)
ffi (1.16.3)
forwardable-extended (2.6.0)
gemoji (4.1.0)
google-protobuf (3.25.3-x86_64-linux)
html-pipeline (2.14.3)
activesupport (>= 2)
nokogiri (>= 1.4)
http_parser.rb (0.8.0)
i18n (1.14.1)
concurrent-ruby (~> 1.0)
jekyll (4.3.3)
addressable (~> 2.4)
colorator (~> 1.0)
em-websocket (~> 0.5)
i18n (~> 1.0)
jekyll-sass-converter (>= 2.0, < 4.0)
jekyll-watch (~> 2.0)
kramdown (~> 2.3, >= 2.3.1)
kramdown-parser-gfm (~> 1.0)
liquid (~> 4.0)
mercenary (>= 0.3.6, < 0.5)
pathutil (~> 0.9)
rouge (>= 3.0, < 5.0)
safe_yaml (~> 1.0)
terminal-table (>= 1.8, < 4.0)
webrick (~> 1.7)
jekyll-compose (0.12.0)
jekyll (>= 3.7, < 5.0)
jekyll-deploy (0.0.2)
jekyll-feed (0.17.0)
jekyll (>= 3.7, < 5.0)
jekyll-redirect-from (0.16.0)
jekyll (>= 3.3, < 5.0)
jekyll-sass-converter (3.0.0)
sass-embedded (~> 1.54)
jekyll-watch (2.2.1)
listen (~> 3.0)
jemoji (0.13.0)
gemoji (>= 3, < 5)
html-pipeline (~> 2.2)
jekyll (>= 3.0, < 5.0)
kramdown (2.4.0)
rexml
kramdown-parser-gfm (1.1.0)
kramdown (~> 2.0)
liquid (4.0.4)
listen (3.8.0)
rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10)
mercenary (0.4.0)
minitest (5.22.2)
mutex_m (0.2.0)
nokogiri (1.16.2-x86_64-linux)
racc (~> 1.4)
pathutil (0.16.2)
forwardable-extended (~> 2.6)
public_suffix (5.0.4)
racc (1.7.3)
rake (13.1.0)
rb-fsevent (0.11.2)
rb-inotify (0.10.1)
ffi (~> 1.0)
rexml (3.2.6)
rouge (4.2.0)
rss (0.3.0)
rexml
ruby2_keywords (0.0.5)
safe_yaml (1.0.5)
sass-embedded (1.69.5)
google-protobuf (~> 3.23)
rake (>= 13.0.0)
terminal-table (3.0.2)
unicode-display_width (>= 1.1.1, < 3)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
unicode-display_width (2.5.0)
webrick (1.8.1)
PLATFORMS
x86_64-linux
DEPENDENCIES
jekyll (~> 4.0)
jekyll-compose
jekyll-deploy
jekyll-feed (~> 0.17)
jekyll-redirect-from
jemoji
rake
rss
BUNDLED WITH
2.4.22

52
Rakefile Normal file
View file

@ -0,0 +1,52 @@
require "jekyll"
require "time"
desc "create a new note"
task :note do
slug = "#{Date.today}-#{('a'..'z').to_a.repeated_permutation(1).to_a.sample(2).join}"
file = File.join(
File.dirname(__FILE__),
"_notes",
slug + ".md"
)
frontmatter = <<~EONOTE
---
layout: default
title: Note
date: "#{DateTime.now.strftime("%Y-%m-%d %H:%M")}"
---
EONOTE
File.write(file, frontmatter)
system("#{ENV['EDITOR']} #file}")
end
desc "build site"
task :build do
Jekyll::Commands::Build.process({})
end
desc "clean site"
task :clean do
Jekyll::Commands::Clean.process({})
end
desc "serve local site"
task :serve => [:build] do
Jekyll::Commands::Serve.process({
incremental: true,
livereload: true,
skip_initial_build: false,
open_url: true,
})
end
desc "deploy site"
task :deploy => [:build] do
sh "rsync -az --delete ./_site srv.muhh.lol:/var/www/htdocs/muhh.lol/"
end
task :default => [:clean, :build, :serve]

51
_config.yml Normal file
View file

@ -0,0 +1,51 @@
# Welcome to Jekyll!
#
# This config file is meant for settings that affect your whole blog, values
# which you are expected to set up once and rarely edit after that. If you find
# yourself editing this file very often, consider using Jekyll's data files
# feature for the data you need to update frequently.
#
# For technical reasons, this file is *NOT* reloaded automatically when you use
# 'bundle exec jekyll serve'. If you change this file, please restart the server process.
#
# If you need help with YAML syntax, here are some quick references for you:
# https://learn-the-web.algonquindesign.ca/topics/markdown-yaml-cheat-sheet/#yaml
# https://learnxinyminutes.com/docs/yaml/
#
# Site settings
# These are used to personalize your new site. If you look in the HTML files,
# you will see them accessed via {{ site.title }}, {{ site.email }}, and so on.
# You can create any custom variable you would like, and they will be accessible
# in the templates via {{ site.myvariable }}.
title: muhh internet happy place
email: muhh@omg.lol
author: Markus Heurung
mastodon: https://social.lol/@muhh
description: >-
muhh internet happy place.
The personal website of Markus Heurung.
url: https://muhh.lol
baseurl: ""
timezone: Europe/Berlin
permalink: "/posts/:title/"
collections:
notes:
output: true
pages:
output: true
rss_post_limit: 10000
plugins:
- jekyll-redirect-from
- jemoji
exclude:
- Rakefile
- Gemfile
- Gemfile.lock
- .jekyll-cache
- .gitignore

24
_data/blogroll.yml Normal file
View file

@ -0,0 +1,24 @@
- title: Marco
url: https://mb.esamecar.net/
added_at: Tue, 27 Feb 2024 11:24:00 +0100
- title: Sascha Assbach
url: https://assbach.de/
added_at: Tue, 20 Feb 2024 09:54:00 +0100
- title: Greg Morris
url: https://gregmorris.co.uk/
added_at: Tue, 20 Feb 2024 09:54:00 +0100
- title: Amit Gawande
url: https://www.amitgawande.com/
added_at: Mon, 19 Feb 2024 00:00:00 +0100
- title: Alice Bartlett
url: https://alicebartlett.co.uk/
added_at: Mon, 19 Feb 2024 00:00:00 +0100
- title: Benjamin Birkenhake
url: https://anmutunddemut.de/
added_at: Mon, 19 Feb 2024 00:00:00 +0100
- title: Jochen Lillich
url: https://geewiz.dev/
added_at: Mon, 19 Feb 2024 00:00:00 +0100
- title: Markus Spath
url: https://hackr.de/
added_at: Mon, 19 Feb 2024 00:00:00 +0100

188
_layouts/default.html Normal file
View file

@ -0,0 +1,188 @@
<!doctype html>
<html lang="en">
<head>
<meta content="width=device-width, initial-scale=1.0" name="viewport">
<meta content="text/html; charset=utf-8" http-equiv="content-type">
<link rel="me" href="https://micro.blog/muhh">
<link rel="alternate" type="application/rss+xml" href="/feed.xml">
<link rel="alternate" type="application/rss+xml" href="/notes.xml">
<link rel="icon" href="/assets/fav.svg" type="image/svg+xml" sizes="24x24">
<!--link rel="icon" href="/assets/fav.png" type="image/png" sizes="96x96"-->
<!--<link href="https://fonts.googleapis.com/css2?family=Readex+Pro&display=swap" rel="stylesheet">-->
<link href="/assets/new.css" rel="stylesheet" type="text/css">
{% if page.collection == "posts" %}
<link href="/assets/syntax.css" rel="stylesheet" type="text/css">
{% endif %}
{% if page.title %}
<title>{{ page.title }} - {{ site.title }}</title>
<meta content="{{ page.title }} - {{ site.title }}" property="og:title">
<meta content="{{ page.title }} - {{ site.title }}" name="twitter:title">
{% else %}
<title>{{ site.title }}</title>
<meta content="{{ site.title }}" property="og:title">
<meta content="{{ site.title }}" name="twitter:title">
{% endif %}
{% if page.collection == "posts" or page.collection == "notes" or page.collection == "stories" %}
<meta content="{{ site.url }}{{ page.url }}" property="og:url">
<meta content="{{ page.content | strip_html | strip_newlines | truncate: 120 }}" name="description">
{% if page.collection == "posts" %}
<meta content="article" property="og:type">
<meta content="@muhh" property="twitter:site">
<meta name="twitter:card" content="summary_large_image">
{% endif %}
{% if page.image %}
<meta content="https://muhh.lol/images/{{ page.image }}" property="og:image">
<meta content="https://muhh.lol/images/{{ page.image }}" property="twitter:image">
{% elsif page.image_text %}
<meta content="https://muhh-text-image.herokuapp.com/title?v=2&text={{ page.image_text | strip | url_encode }}" property="og:image">
<meta content="https://muhh-text-image.herokuapp.com/title?v=2&text={{ page.image_text | strip | url_encode }}" property="twitter:image">
{% else %}
<meta content="summary" name="twitter:card">
<meta content="https://muhh.lol/assets/logo.png" name="twitter:image">
<meta content="https://muhh.lol/assets/logo.png" property="og:image">
{% endif %}
{% else %}
<meta content="summary" name="twitter:card">
<meta content="https://muhh.lol/assets/logo.png" property="twitter:image">
<meta content="https://muhh.lol/assets/logo.png" property="og:image">
<meta content="{{ site.description }}" name="description">
<meta content="website" property="og:type">
{% endif %}
</head>
<body class="{% if page.root != true %}post-body{% endif %} col-{{ page.collection }}" data-page-type="{{ page.type }}">
<header>
<div class="logo-container">
{% if page.root != true %}
<a href="/{% if page.collection == "notes" %}notes{% endif %}" aria-label="Home" class="back-link">&leftarrow;</a>
{% endif %}
<svg class="logo" viewBox="0 0 196 169" fill="none" xmlns="http://www.w3.org/2000/svg">
<title>~</title>
<path d="M53.3782 160.773C64.4534 151.592 86.0271 133.546 97.4226 133.546C112.866 133.546 113.373 160.773 126.168 160.773C138.963 160.773 150.185 155.479 150.185 155.479" stroke="#cccccc" stroke-width="16" stroke-linecap="round"/>
</svg>
{% if page.root != true %}
<span class="font">{{ site.title }}</span>
{% endif %}
</div>
<h1 class="h1">
<span lang="en">{{ page.title }}</span>
</h1>
{% if page.root == true %}
<div class="desc" lang="en" data-status-loading hidden><span data-status-text></span> <span data-status-datetime></span></div>
{% endif %}
{% if page.collection == "posts" %}<time datetime="{{ page.date | date_to_xmlschema }}">{{ page.date | date: "%B %e, %Y" }}</time>{% endif %}
{% if page.collection == "notes" or page.collection == "stories" %}<time datetime="{{ page.date }}">{{ page.date | date: "%Y/%m/%d %H:%M" }}</time>{% endif %}
<div class="desc">{{ page.header_content }}</div>
</header>
<main>
{% capture content_and_then_some do %}
{% if page.type == "photos" %}
<input type="radio" name="layout" value="y-scroll" id="y-scroll" checked>
<label for="y-scroll">
<svg width="15" height="15" viewBox="0 0 60 60" fill="none" xmlns="http://www.w3.org/2000/svg"><title>vertical scroll</title><path d="M55 0a5 5 0 0 1 5 5v31a5 5 0 0 1-5 5H5a5 5 0 0 1-5-5V5a5 5 0 0 1 5-5h50ZM55 47a5 5 0 0 1 5 5v8H0v-8a5 5 0 0 1 5-5h50Z" fill="#D9D9D9"/></svg>
</label>
<input type="radio" name="layout" value="x-scroll" id="x-scroll">
<label for="x-scroll">
<svg width="15" height="15" viewBox="0 0 60 60" fill="none" xmlns="http://www.w3.org/2000/svg"><title>horizontal scroll</title><path d="M0 5a5 5 0 0 1 5-5h30a5 5 0 0 1 5 5v50a5 5 0 0 1-5 5H5a5 5 0 0 1-5-5V5ZM47 5a5 5 0 0 1 5-5h8v60h-8a5 5 0 0 1-5-5V5Z" fill="#D9D9D9"/></svg>
</label>
<input type="radio" name="layout" value="grid2fr" id="grid2fr">
<label for="grid2fr">
<svg width="15" height="15" viewBox="0 0 60 60" fill="none" xmlns="http://www.w3.org/2000/svg"><title>grid 2 columns</title><path d="M0 37c0-2 2-4 4-4h19c2 0 4 2 4 4v19c0 2-2 4-4 4H4c-2 0-4-2-4-4V37zM0 4c0-2 2-4 4-4h19c2 0 4 2 4 4v19c0 2-2 4-4 4H4c-2 0-4-2-4-4V4zM33 37c0-2 2-4 4-4h19c2 0 4 2 4 4v19c0 2-2 4-4 4H37c-2 0-4-2-4-4V37zM33 4c0-2 2-4 4-4h19c2 0 4 2 4 4v19c0 2-2 4-4 4H37c-2 0-4-2-4-4V4z" fill="#D9D9D9"/></svg>
</label>
</label>
<input type="radio" name="layout" value="grid3fr" id="grid3fr">
<label for="grid3fr">
<svg width="15" height="15" viewBox="0 0 60 60" fill="none" xmlns="http://www.w3.org/2000/svg"><title>grid 3 columns</title><path d="M22 4c0-2 2-4 4-4h8c2 0 4 2 4 4v8c0 2-2 4-4 4h-8c-2 0-4-2-4-4V4zM0 26c0-2 2-4 4-4h8c2 0 4 2 4 4v8c0 2-2 4-4 4H4c-2 0-4-2-4-4v-8zM22 26c0-2 2-4 4-4h8c2 0 4 2 4 4v8c0 2-2 4-4 4h-8c-2 0-4-2-4-4v-8zM0 48c0-2 2-4 4-4h8c2 0 4 2 4 4v8c0 2-2 4-4 4H4c-2 0-4-2-4-4v-8zM44 26c0-2 2-4 4-4h8c2 0 4 2 4 4v8c0 2-2 4-4 4h-8c-2 0-4-2-4-4v-8zM22 48c0-2 2-4 4-4h8c2 0 4 2 4 4v8c0 2-2 4-4 4h-8c-2 0-4-2-4-4v-8zM44 48c0-2 2-4 4-4h8c2 0 4 2 4 4v8c0 2-2 4-4 4h-8c-2 0-4-2-4-4v-8zM0 4c0-2 2-4 4-4h8c2 0 4 2 4 4v8c0 2-2 4-4 4H4c-2 0-4-2-4-4V4zM44 4c0-2 2-4 4-4h8c2 0 4 2 4 4v8c0 2-2 4-4 4h-8c-2 0-4-2-4-4V4z" fill="#D9D9D9"/></svg>
</label>
{% endif %}
{{ content }}
{% endcapture %}
{% if page.collection == "posts" or page.collection == "pages" %}
<article>
{{ content_and_then_some }}
</article>
{% elsif page.collection == "notes" %}
{{ content_and_then_some }}
{% else %}
{{ content_and_then_some }}
{% endif %}
{% if page.feature == 1 or page.open_heart %}
{% if page.enable_heart %}
<hr class="hr">
<div class="smol">
<div class="monospace">
<div id="like-prompt">Like this {% if page.collection == "posts" %}post{% elsif page.collection == "notes" %}note{% else %}page{% endif %}? let me know!</div>
&gt;<open-heart class="text-open-heart" href="https://likes.muhh.lol/?id={{ page.url }}" emoji="❤️" aria-labelledby="like-prompt">
<span class="on">Liked.<br>(Thanks!)</span><span class="off">Sure. <kbd></kbd></span>
</open-heart>
</div>
</div>
{% endif %}
{% endif %}
</main>
<footer>
<hr class="hr">
<nav aria-label="About this site">
<a href="{% link _pages/colophon.md %}">Colophon</a>
<hr class="inline-hr">
<a href="{% link _pages/imprint_gdpr.md %}">Impressum</a>
<hr class="inline-hr">
<a href="{% link _pages/accessibility-statement.md %}">Accessibility statement</a>
<hr class="inline-hr">
<a href="https://code.muhh.lol/muhh/site">View source</a>
</nav>
</footer>
{% if page.root %}
<script type="module" src="/assets/site.js"></script>
<!--<script type="module" src="https://unpkg.com/open-stories-element@latest"></script>-->
{% endif %}
{% comment %}
{% if page.feature == 1 or page.open_heart or page.has_open_heart %}
<script type="module" src="https://unpkg.com/open-heart-element@latest"></script>
<script>
const observer = new IntersectionObserver((entries, observer) => {
entries.forEach(async (entry) => {
await customElements.whenDefined('open-heart')
if (entry.target instanceof OpenHeartElement && entry.isIntersecting) {
entry.target.getCount()
observer.unobserve(entry.target)
}
})
})
for (const oh of document.querySelectorAll('open-heart')) {
observer.observe(oh)
}
</script>
{% endif %}
{% if page.type == "photos" %}
<script>
const photos = document.querySelector('#photos')
const xScroll = document.querySelector('#x-scroll')
// move scroll area into viewport and user focus
document.addEventListener('change', function(event) {
if (xScroll.checked) {
photos.scrollIntoView()
photos.setAttribute('tabindex', '-1')
photos.focus()
photos.addEventListener('blur', function() {
photos.blur()
}, {once: true})
}
})
// return focus
document.addEventListener('keydown', function(event) {
if (event.key === 'Escape' && xScroll.checked && photos.contains(event.target)) {
xScroll.focus()
window.scrollTo(0, 0)
}
})
</script>
{% endif %}
{% endcomment %}
</body>
</html>

7
_notes/2024-02-19-rt.md Normal file
View file

@ -0,0 +1,7 @@
---
layout: default
title: Note
date: "2024-02-19 13:49"
---
Let's get [this](https://muhh.lol) live and add a first note.

7
_notes/2024-02-20-fj.md Normal file
View file

@ -0,0 +1,7 @@
---
layout: default
title: Note
date: "2024-02-20 14:48"
---
Handing down cameras to get the latest is established, no? I might need to sell some lenses as well.

8
_notes/2024-02-20-us.md Normal file
View file

@ -0,0 +1,8 @@
---
layout: default
title: Note
date: "2024-02-20 09:55"
---
I like this new home. It's so easy and clear how I can go on with everything.
Plain text is simply the best.

9
_notes/2024-02-23-pd.md Normal file
View file

@ -0,0 +1,9 @@
---
layout: default
title: Note
date: "2024-02-23 16:34"
---
I might have pulled out all the old laptops and there are now 3 macbooks laying on the table.
including my beloved 11" macbook air (2011) and a black macbook from 2007.
and the spare parts are cheap!

7
_notes/2024-02-26-cl.md Normal file
View file

@ -0,0 +1,7 @@
---
layout: default
title: Note
date: "2024-02-26 17:28"
---
I may have bought two iPods that are almost old enough to vote now.

11
_now/2023-04-15.md Normal file
View file

@ -0,0 +1,11 @@
---
layout: default
date: 2023-04-15 00:00
title: My now page
---
- On the web I'm in a wibblywobblytimeywimey state. With all these great options provided by omg.lol, micro.blog, social.lol and all the other things I can do on my on server or in the fediverse I feel like it gets cluttered more and more. Add to this that I'm feeling a bit limited by micro.blogs hosting and I'm in the middle of a transition where I even think about retiring my almost 20 year old byzero.de domain.
- At work I'm building tooling to juggle a big migration project. We need to automate the careful replacement of old with new servers. This sometimes looks like I'm building some small size orchestration solution like Kubernetes. But bad. {server}
- At home we are preparing the renovation of the whole ground floor. When we bought the house we only did a few renovations and modifications. Now it's time for remodeling and more. {house-chimney}
(This is a [now page](https://nownownow.com/about), and if you have your own site, [you should make one](https://nownownow.com/about), too.)

11
_now/2024-02-19.md Normal file
View file

@ -0,0 +1,11 @@
---
layout: default
date: 2024-02-19 00:00
title: My now page
---
- On the web it's all new. Building [muhh.lol](https://muhh.lol) with Jekyll right now. Fun!
- At work I had a long weekend. {server}
- At home we wanted to start so many projects. But in a family with 3 kids there's always something. Viruses, bacteria and fungi mostly. We are restructuring our planning right now. {house-chimney}
(This is a [now page](https://nownownow.com/about), and if you have your own site, [you should make one](https://nownownow.com/about), too.)

View file

@ -0,0 +1,33 @@
---
layout: default
title: Accessibility Statement for muhh.lol
permalink: /accessibility-statement/
---
This is an accessibility statement from Markus Heurung.
## Measures to support accessibility
Markus Heurung takes the following measures to ensure accessibility of muhh.lol:
- Include accessibility as part of my mission statement.
- Include accessibility throughout my internal policies.
- Provide continual accessibility training for myself.
## Conformance status
The Web Content Accessibility Guidelines (WCAG) defines requirements for designers and developers to improve accessibility for people with disabilities. It defines three levels of conformance: Level A, Level AA, and Level AAA. muhh.lol is partially conformant with WCAG 2.1 level AA. Partially conformant means that some parts of the content do not fully conform to the accessibility standard.
- I am aware that there is one color contrast violation on the front page.
- I constantly experiment things on the site so it might not be fully conformant at all times.
## Feedback
I welcome all feedback on the accessibility of muhh.lol. Please let me know if you encounter accessibility barriers on the site.
To report, [write me an email](mailto:{{ site.email }}) or [message me on Mastodon]({{ site.mastodon }}), and I will try to respond with 2 weeks.
## Date
This statement was created on 19 February 2024 using [the W3C Accessibility Statement Generator Tool](https://www.w3.org/WAI/planning/statements/generator/) and copied fro [Mu-An Chiou's accessibility statement](https://muan.co/accessibility-statement).

32
_pages/banners.md Normal file
View file

@ -0,0 +1,32 @@
---
layout: default
title: Banners
permalink: banners/
---
## People's banners
Make one. Tell me.
## My banners
{% comment %}
<div class="text"><img loading="lazy" src="/images/banner.svg" width="88" height="31" alt="An animated banner with one short line, one medium line, one long line, a symbol resembling the tilde, each being drawn in order."></div><div class="text"><img loading="lazy" src="/images/banner.gif" width="88" height="31" alt="An animated banner with one short line, one medium line, one long line, a symbol resembling the tilde, each being drawn in order."></div><div class="text"><img loading="lazy" src="/images/banner.png" width="88" height="31" alt="An banner with one short line, one medium line, one long line, and then a symbol resembling the tilde."></div>
{% endcomment %}
Not yet.
<hr class="hr">
1. Recommended. SVG. This includes dark and light mode and `prefers-reduced-motion`.
2. Plain old GIF. Actually 176&times;62. Please set the dimensions accordingly.
3. Static PNG. Actually 176&times;62. Please set the dimensions accordingly.
I suggest that you hotlink my banner and keep a copy as backup, so that when I update them you get the latest. That is if you trust me enough.
## References
- [Wikipedia: Link exchange](https://en.wikipedia.org/wiki/Link_exchange).
- [Remembering Powered By and 88×31](https://tekeye.uk/computer_history/powered-by).
- [The 88x31 GIF Collection](http://cyber.dabamos.de/88x31/).

16
_pages/blogroll.md Normal file
View file

@ -0,0 +1,16 @@
---
layout: default
title: Blogroll
permalink: /blogroll/
---
<a href="/blogroll.xml" class="">RSS</a>
This page is under construction and by far not everything I read and enjoy.
The order is randomized on build.
{% assign links = site.data.blogroll | sort: "title" | sample: site.data.blogroll.size %}
{%- for item in links %}
- [{{ item.title }}]({{ item.url }})
{%- endfor %}

12
_pages/colophon.md Normal file
View file

@ -0,0 +1,12 @@
---
layout: default
title: Colophon
permalink: /colophon/
---
This website is run by Jekyll and hosted on an OpenBSD server that I built on Hetzner
cloud so I don't have to maintain that thing all the time. It's still a hobby.
The site is heavily based on [muan's website](https://muan.co), she built a great one. I plan to adapt it more and more to my wants and needs.
There will be more details soon.

7
_pages/defaults.md Normal file
View file

@ -0,0 +1,7 @@
---
layout: default
title: Defaults
permalink: /defaults/
---

44
_pages/imprint_gdpr.md Normal file
View file

@ -0,0 +1,44 @@
---
layout: default
title: Impressum / Datenschutzerklärung
permalink: /imprint_gdpr/
---
This is for all my websites, domains including subdomains and other things:
- byzero.de
- muhh.lol
- hammelblog.de
- heurung.net
- markusheurung.de
## Impressum
Markus Heurung
Persönliche Textsammlung. Impressumfrei nach § 55 RStV.
## Contact
Email: {{ site.email }}
## Datenschutzerklärung (DSGVO)
Auf dieser Webseite werden keine personenbezogenen Daten erhoben, gespeichert oder verarbeitet. Es werden keine Cookies verwendet.
## Data Protection Policy (GDPR)
This website does not collect, store or process Personally Identifiable Information (PII). This website does not require the use of cookies.
## Verweis auf Dritte
Die Websites byzero.de und hammelblog.de wird auf micro.blog ([Datenschutzerklärung](https://help.micro.blog/t/privacy-policy/114)) gehostet und schließen Daten von dort ein.
Die Website omg.muhh.lol, bin.muhh.lol, status.muhh.lol und markusheurung.de werden alle bei omg.lol ([Datenschutzerklärung](https://home.omg.lol/info/legal#privacy-policy)) gehostet.
Die Website muhh.lol wird von mir selbst auf einem gemietetem Server betrieben. Ich halte nur einfache Logfiles ohne PII vor.
## Third Party Inclusion
The websites byzero.de and hammelblog.de are hosted on micro.blog ([privacy policy](https://help.micro.blog/t/privacy-policy/114)) and include data from there.
The websites omg.muhh.lol, bin.muhh.lol, status.muhh.lol and markusheurung.de are all hosted at omg.lol ([privacy policy](https://home.omg.lol/info/legal#privacy-policy)).
The website muhh.lol is hosted by myself on a rented server. I only keep simple log files without PII.

38
_pages/qna.md Normal file
View file

@ -0,0 +1,38 @@
---
layout: default
title: Questions & answers
permalink: /qna/
---
## How do you preferred to be called?
Markus, or muhh (only as a username, _never_ capitalized).
## Why muhh?
My first username was "heure" or "l'Heure", which was an old nickname based on my
surname. But that didn't stick and I used the uncreative thing and used my initials.
Yes, I have three first names. It's a traditional thing where kids get piled on
names of their godparents. I like it.
## How is your name pronounced?
Phonetic spelling: ˈmaʁkʊs
<audio src="/assets/name.m4a" controls></audio>
The muhh sounds like a cows moooo. Go figure.
## What are your pronouns?
He/him.
## Where are you from?
I am from [Hammelburg, Germany](https://www.openstreetmap.org/#map=15/50.1195/9.8850).
{% comment %}
## Are you OK?
[I am tired of my own thoughts.](https://muan.co/notes/2023-09-06-uu)
{% endcomment %}

8
_pages/uses.md Normal file
View file

@ -0,0 +1,8 @@
---
layout: default
title: Uses
permalink: /uses/
---
Jekyll
kitty

130
_plugins/rssgenerator.rb Normal file
View file

@ -0,0 +1,130 @@
# Jekyll plugin for generating an rss 2.0 feed for posts
#
# Based on https://github.com/kikoval/jekyll-rss/ but heavily modified
#
# Usage: place this file in the _plugins directory and set the required configuration
# attributes in the _config.yml file
#
# Uses the following attributes in _config.yml:
# title - the title of the site
# url - the url of the site
# description - (optional) a description for the feed (if not specified will be generated from title)
# author - (optional) the author of the site (if not specified will be left blank)
# copyright - (optional) the copyright of the feed (if not specified will be left blank)
# rss_path - (optional) the path to the feed (if not specified "/" will be used)
# rss_name - (optional) the name of the rss file (if not specified "rss.xml" will be used)
# rss_post_limit - (optional) the number of posts in the feed
#
# Author: Assaf Gelber <assaf.gelber@gmail.com>
# Site: http://agelber.com
# Source: http://github.com/agelber/jekyll-rss
#
# Distributed under the MIT license
# Copyright Assaf Gelber 2013
require "jekyll"
require "rss"
module RssFeed
class Page < Jekyll::Page; end
class Generator < Jekyll::Generator
priority :low
safe true
attr_reader :site, :rss_content
# Generates an rss 2.0 feed
#
# site - the site
#
# Returns nothing
def generate(site)
@site = site
feed_items = []
# collect Data
@rss_content = RSS::Maker.make('2.0') do |maker|
maker.channel.title = @site.config['title']
maker.channel.link = @site.config['url']
maker.channel.description = @site.config['description'] || "RSS feed for #{site.config['title']}"
maker.channel.author = @site.config['author']
maker.channel.updated = @site.posts.docs.map { |p| p.date }.max
maker.channel.copyright = @site.config['copyright']
@site.collections.each do |name, meta|
Jekyll.logger.info "muhh Feed:", "Adding #{name} to global feed"
feed_items
site.posts.docs.reverse[0..post_limit].each do |post|
maker.items.new_item do |item|
item.title = post.data["title"]
item.link = "#{@site.config['url']}#{post.url}"
item.description = post.data["excerpt"]
item.updated = post.date
end
end
end
end
create_file
# Add the feed page to the site pages
site.pages << RssFeed::Page.new(site, site.dest, rss_path, rss_name)
end
private
def rss_path
ensure_slashes(@site.config['rss_path'] || "/")
end
def rss_name
@site.config['rss_name'] || "rss.xml"
end
def create_file
full_path = File.join(@site.dest, rss_path)
ensure_dir(full_path)
File.open("#{full_path}#{rss_name}", "w") { |f| f.write(@rss_content) }
end
# Ensures the given path has leading and trailing slashes
#
# path - the string path
#
# Return the path with leading and trailing slashes
def ensure_slashes(path)
ensure_leading_slash(ensure_trailing_slash(path))
end
# Ensures the given path has a leading slash
#
# path - the string path
#
# Returns the path with a leading slash
def ensure_leading_slash(path)
path[0] == "/" ? path : "/#{path}"
end
# Ensures the given path has a trailing slash
#
# path - the string path
#
# Returns the path with a trailing slash
def ensure_trailing_slash(path)
path[-1] == "/" ? path : "#{path}/"
end
# Ensures the given directory exists
#
# path - the string path of the directory
#
# Returns nothing
def ensure_dir(path)
FileUtils.mkdir_p(path)
end
def post_limit
@site.config['rss_post_limit'] - 1 rescue @site.posts.count
end
end
end

12
_posts/2024-02-19-ha.md Normal file
View file

@ -0,0 +1,12 @@
---
layout: default
title: Ha!
date: 2024-02-19 01:14 +0100
feature: 1
---
This is it, this is the new site. Still heavily under construction, but it's here.
And it's mine. My precious.
Danke, [Mu-An](https://muan.co)! So much of this site is based on hers.

799
assets/new.scss Normal file
View file

@ -0,0 +1,799 @@
---
---
:root {
--backgroundColor: #fdfdfd;
--textColor: #303030;
--secondaryTextColor: #404040;
--mutedTextColor: #707070;
--subtleBackgroundColor: #f5f5f5;
--heartedBackgroundColor: #ffe2e2;
--selectionBackgroundColor: #ffc;
--linkColor: #2357cd;
--borderColor: #ccc;
--hrColor: #888;
--activeColor: #74d274;
--langBackgroundColor: #eeeeee;
--langShadowColor: transparent;
--logoColor: #cccccc;
--photoBackground: #f4f4f4;
}
@media (prefers-color-scheme: dark) {
:root {
--backgroundColor: #151615;
--textColor: #dbdfdf;
--secondaryTextColor: #cfd5d5;
--mutedTextColor: #b4b6b8;
--subtleBackgroundColor: #3a3b3b;
--heartedBackgroundColor: #652222;
--selectionBackgroundColor: #19446b;
--linkColor: #6eb8ff;
--borderColor: #414141;
--hrColor: #888;
--activeColor: #74d274;
--langBackgroundColor: #2c2c2c;
--langShadowColor: #0b0c0b33;
--logoColor: #555555;
--photoBackground: #1a1a1a;
}
}
body {
background: var(--backgroundColor);
color: var(--textColor);
line-height: 1.7em;
padding: 0 2.5em;
margin: 0;
font-size: 18px;
word-wrap: break-word;
}
body, kbd {
font-family: system-ui, sans-serif;
}
a {
color: var(--linkColor);
text-underline-position: under;
}
::selection {
background: var(--selectionBackgroundColor);
}
header {
padding-top: 2.5em;
}
footer {
padding-bottom: 2.5em;
}
header,
main,
footer {
max-width: 36em;
margin: auto;
}
h1, h2, h3, h4, h5, h6, .font {
font-family: 'Readex Pro', sans-serif;
}
.plain {
font-family: system-ui, sans-serif
}
h1, h2, h3, h4, h5, h6 {
margin: 1.4em 0 1em 0;
font-weight: normal;
}
.logo {
width: 2em;
path {
stroke: var(--logoColor);
}
}
.logo-container {
display: flex;
align-items: center;
}
.post-body {
.logo-container {
line-height: 1em;
color: var(--mutedTextColor);
}
.logo {
width: 1em;
margin-left: .8em;
margin-right: .4em;
path {
stroke: var(--mutedTextColor);
stroke-width: 22;
}
}
.h1 {
font-size: 1.5rem;
}
}
.h1 {
font-size: 1.2rem;
font-weight: normal;
margin-bottom: 0;
}
.text {
margin-right: .4rem;
font-size: inherit;
font-weight: normal;
display: inline-block;
margin-top: 0;
}
.terminal .line {
padding: 0;
margin-bottom: 1em;
line-height: 1.6em;
}
.terminal {
list-style: none;
padding-left: 0;
li {
padding: .1rem 0;
}
ul {
margin-top: 0.5rem;
}
}
.hr {
border: 0;
border-left: .7rem solid var(--textColor);
height: .7rem;
margin: 3rem 0;
}
.inline-hr {
border: 0;
border-left: .3rem solid var(--borderColor);
height: .3rem;
display: inline-block;
vertical-align: middle;
align-self: center;
margin: 0;
}
.notes {
list-style: none;
margin: 0;
padding: 0;
.note {
border-bottom: 1px solid var(--borderColor);
padding-bottom: 3em;
margin-top: 3em;
}
}
.note {
scroll-margin: 2em;
main > & {
margin-top: -.6em;
}
& > ul {
margin-top: 1.5em;
list-style: disc;
}
&:last-of-type {
border-bottom: 0;
}
p:first-child, blockquote:first-child { margin-top: 0; }
p:last-child, blockquote:last-child, img:last-child { margin-bottom: 0; }
}
.note-heading {
font-size: .8em;
line-height: 1;
font-weight: normal;
margin: 0;
color: var(--mutedTextColor);
a {
color: inherit;
text-decoration: none;
}
}
blockquote {
color: var(--secondaryTextColor);
margin: 2em 0 2em 1.5em;
&::before {
content: '';
font-size: 2rem;
position: absolute;
margin-left: -.5em;
font-family: sans-serif;
}
}
img {
max-width: 100%;
margin: 1em 0;
&[width] {
margin: 0;
vertical-align: middle;
}
}
hr {
margin: 2em 0;
border: 0;
border-bottom: 1px solid var(--hrColor);
}
.pagination {
margin-top: 4em;
}
article {
font-family: system-ui, sans-serif;
font-size: 16px;
}
.smol {
font-size: .8em;
font-weight: normal;
}
.task-list-item-checkbox {
margin-right: .5em;
vertical-align: middle;
}
.entry-title {
margin: 0;
}
.entry {
margin-bottom: 3em;
}
.lang {
font-size: .8rem;
display: inline-flex;
margin-top: 2em;
white-space: nowrap;
box-shadow: 0 5px 15px var(--langShadowColor);
a[aria-current] {
color: var(--textColor);
&:before {
content: "";
color: var(--activeColor);
}
}
a {
background-color: var(--langBackgroundColor);
border-color: var(--borderColor);
color: var(--mutedTextColor);
padding: 4px 16px;
margin-right: 1px;
text-decoration: none;
&:first-child {
border-top-left-radius: 6px;
border-bottom-left-radius: 6px;
}
&:last-child {
border-top-right-radius: 6px;
border-bottom-right-radius: 6px;
}
&:hover {
background: var(--langBackgroundColor);
}
&:focus {
z-index: 1;
}
&:before {
content: "";
color: var(--borderColor);
padding-right: 10px;
}
}
}
.styled-link {
margin-left: .4rem;
font-size: .7em;
}
time {
font-size: .8em;
color: var(--mutedTextColor);
}
.desc {
color: var(--mutedTextColor);
font-size: 0.8em;
line-height: 1.5;
}
@keyframes flash {
0% {
opacity: 0;
}
50% {
opacity: 1;
}
100% {
opacity: 1;
}
}
.timestamp-colon {
animation-name: flash;
animation-duration: 2s;
animation-timing-function: step-end;
animation-iteration-count: infinite;
}
@media (prefers-reduced-motion: reduce) {
.timestamp-colon {
animation-name: none;
}
}
.offsetthis {
vertical-align: super;
font-size: .6em;
}
.photos {
display: flex;
gap: 1em;
flex-wrap: nowrap;
overflow: auto;
align-items: center;
.image-link {
flex-shrink: 0;
}
img {
background-color: var(--photoBackground);
}
}
figure {
margin: 1em 0 3em;
img {
margin: 0 auto;
max-height: calc(100vh - 6em);
background-color: var(--photoBackground);
display: block;
}
.image-link {
display: block;
width: fit-content;
margin: 0 auto 0.5em;
}
p {
margin-bottom: 0;
}
}
[data-page-type="photos"] {
header, main, footer {
max-width: 100%;
}
input {
position: absolute;
left: -100px;
&:checked + label path {
fill: var(--activeColor);
}
&:focus + label {
outline: auto;
outline-color: var(--activeColor);
}
}
label {
top: -30px;
left: 100px;
padding: .5em;
cursor: pointer;
position: relative;
display: inline-flex;
}
label path {
fill: var(--logoColor);
}
}
.photos-wrapper {
&:focus { outline: none; }
scroll-behavior: smooth;
clear: both;
text-align: center;
}
.back-link {
text-decoration: none;
color: var(--textColor);
background-color: var(--langBackgroundColor);
width: 1.6em;
text-align: center;
line-height: 1.6em;
aspect-ratio: 1/1;
display: inline-block;
border-radius: 4em;
}
[value*="grid"]:checked ~ .photos-wrapper {
display: grid;
column-gap: 2.5em;
grid-template-columns: repeat(2, 1fr);
grid-auto-flow: dense;
.figure-landscape {
grid-column: span 2;
}
figure {
margin-bottom: 0;
align-self: start;
}
img {
max-height: none;
height: auto;
}
}
[value="grid3fr"]:checked ~ .photos-wrapper {
grid-template-columns: repeat(3, 1fr);
.figure-landscape {
grid-column: span 3;
}
}
[value="x-scroll"]:checked ~ .photos-wrapper {
display: flex;
overflow: auto;
gap: 1.5em;
scroll-snap-type: x mandatory;
scroll-snap-align: center;
figure {
scroll-snap-align: center;
margin-bottom: 0;
flex-shrink: 0;
width: min-content;
&:has(.portrait) figcaption {
max-width: calc(100vh * 0.667 - 6em);
margin: auto;
}
&:has(.landscape) figcaption {
max-width: calc(100vw * 0.667 - 2em);
margin: auto;
}
}
img {
max-height: calc(100vh - 6em);
max-width: calc(100vw - 5em);
flex-shrink: 0;
}
}
.photo-metadata {
display: flex;
justify-content: center;
align-items: center;
flex-wrap: wrap;
margin: auto;
gap: 0.5em;
open-heart {
margin-left: 0;
}
}
figcaption {
padding: .5em 1em;
p {
margin: 0;
}
}
[data-status-loading] {
margin: .17em 0 0;
display: block;
opacity: .3;
animation: loading .5s infinite alternate;
[data-status-text]:empty {
display: inline-block;
width: 100px;
height: 1em;
border-radius: .3em;
background: var(--subtleBackgroundColor);
}
}
// This ensures that
// 1. screens that are too short
// 2. screens that are not tall enough to display the full width of a 3:2 image
// at height: (100v - 6em) height
// don't get the option to use horizontal scroll.
// https://github.com/web-platform-tests/wpt/pull/34865
// @media (max-height: 540px), (max-width: calc((100vh - 6em) * 1.5)) {
@media (max-height: 540px), (max-width: calc(100vh * 1.4)) {
body {
padding: 0 2em;
}
.photos-wrapper {
margin-left: -2em;
margin-right: -2em;
img {
max-height: none;
&.landscape {
height: calc(100vw / 1.5);
}
&.portrait {
height: calc(100vw / 0.667);
}
&.square {
height: 100vw;
}
}
}
[name="layout"] {
&, + label { visibility: hidden; }
}
}
.stories {
display: flex;
gap: 1em;
align-items: center;
overflow: auto;
padding: 10px;
margin: -10px;
}
open-stories {
.count {
font-size: 0.8em;
}
&::part(dialog):focus {
outline: none;
}
&:not(:defined),
&::part(button) {
font-family: system-ui, sans-serif;
border: 1px solid var(--borderColor);
box-shadow: inset 0 0 0 2px var(--backgroundColor);
color: var(--textColor);
background: var(--subtleBackgroundColor);
padding: 1em 0;
text-align: center;
height: 76px;
width: 76px;
border-radius: 50%;
font-size: 0.65em;
box-sizing: border-box;
align-items: center;
display: flex;
flex-direction: column;
flex-shrink: 0;
</