Homepage setup for schleppe lab blog

This commit is contained in:
2023-05-19 18:08:45 +02:00
commit 445e0eb768
50 changed files with 1756 additions and 0 deletions

6
.gitignore vendored Normal file
View File

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

36
Gemfile Normal file
View File

@@ -0,0 +1,36 @@
source "https://rubygems.org"
# Hello! This is where you manage which Jekyll version is used to run.
# When you want to use a different version, change it below, save the
# file and run `bundle install`. Run Jekyll with `bundle exec`, like so:
#
# bundle exec jekyll serve
#
# This will help ensure the proper Jekyll version is running.
# Happy Jekylling!
gem "jekyll", "~> 4.3.2"
# This is the default theme for new Jekyll sites. You may change this to anything you like.
# gem "minima", "~> 2.5"
# If you want to use GitHub Pages, remove the "gem "jekyll"" above and
# uncomment the line below. To upgrade, run `bundle update github-pages`.
# gem "github-pages", group: :jekyll_plugins
# If you have any plugins, put them here!
group :jekyll_plugins do
gem 'jekyll-tagging'
gem 'jekyll-sitemap'
gem "jekyll-feed", "~> 0.12"
gem "jekyll-seo-tag", "~> 2.8.0"
end
# Windows and JRuby does not include zoneinfo files, so bundle the tzinfo-data gem
# and associated library.
platforms :mingw, :x64_mingw, :mswin, :jruby do
gem "tzinfo", ">= 1", "< 3"
gem "tzinfo-data"
end
# Performance-booster for watching directories on Windows
gem "wdm", "~> 0.1.1", :platforms => [:mingw, :x64_mingw, :mswin]
# Lock `http_parser.rb` gem to `v0.6.x` on JRuby builds since newer versions of the gem
# do not have a Java counterpart.
gem "http_parser.rb", "~> 0.6.0", :platforms => [:jruby]

87
Gemfile.lock Normal file
View File

@@ -0,0 +1,87 @@
GEM
remote: https://rubygems.org/
specs:
addressable (2.8.4)
public_suffix (>= 2.0.2, < 6.0)
colorator (1.1.0)
concurrent-ruby (1.2.2)
em-websocket (0.5.3)
eventmachine (>= 0.12.9)
http_parser.rb (~> 0)
eventmachine (1.2.7)
ffi (1.15.5)
forwardable-extended (2.6.0)
google-protobuf (3.23.1-arm64-darwin)
http_parser.rb (0.8.0)
i18n (1.13.0)
concurrent-ruby (~> 1.0)
jekyll (4.3.2)
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-feed (0.17.0)
jekyll (>= 3.7, < 5.0)
jekyll-sass-converter (3.0.0)
sass-embedded (~> 1.54)
jekyll-seo-tag (2.8.0)
jekyll (>= 3.8, < 5.0)
jekyll-sitemap (1.4.0)
jekyll (>= 3.7, < 5.0)
jekyll-tagging (1.1.0)
nuggets
jekyll-watch (2.2.1)
listen (~> 3.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)
nuggets (1.6.1)
pathutil (0.16.2)
forwardable-extended (~> 2.6)
public_suffix (5.0.1)
rb-fsevent (0.11.2)
rb-inotify (0.10.1)
ffi (~> 1.0)
rexml (3.2.5)
rouge (4.1.1)
safe_yaml (1.0.5)
sass-embedded (1.62.1-arm64-darwin)
google-protobuf (~> 3.21)
terminal-table (3.0.2)
unicode-display_width (>= 1.1.1, < 3)
unicode-display_width (2.4.2)
webrick (1.8.1)
PLATFORMS
arm64-darwin-22
DEPENDENCIES
http_parser.rb (~> 0.6.0)
jekyll (~> 4.3.2)
jekyll-feed (~> 0.12)
jekyll-seo-tag (~> 2.8.0)
jekyll-sitemap
jekyll-tagging
tzinfo (>= 1, < 3)
tzinfo-data
wdm (~> 0.1.1)
BUNDLED WITH
2.4.13

65
_config.yml Normal file
View File

@@ -0,0 +1,65 @@
# 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 }}.
include:
- _pages
title: Schleppe Lab
email: kevin.midboe@gmail.com
description: >- # this means to ignore newlines until "baseurl:"
Write an awesome description for your new site here. You can edit this
line in _config.yml. It will appear in your document head meta (for
Google search results) and in your feed.xml site description.
baseurl: "" # the subpath of your site, e.g. /blog
url: "" # the base hostname & protocol for your site, e.g. http://example.com
twitter_username: kevinmidboe
github_username: kevinmidboe
show_excerpts: true
# permalink: /posts/:year/:slug:output_ext
permalink: /posts/:year/:slug
tag_page_layout: tag_page
tag_page_dir: tag
# Build settings
# theme: minima
plugins:
- jekyll-feed
- jekyll-sitemap
- jekyll-seo-tag
# Exclude from processing.
# The following items will not be processed, by default.
# Any item listed under the `exclude:` key here will be automatically added to
# the internal "default list".
#
# Excluded items can be processed by explicitly listing the directories or
# their entries' file path in the `include:` list.
#
# exclude:
# - .sass-cache/
# - .jekyll-cache/
# - gemfiles/
# - Gemfile
# - Gemfile.lock
# - node_modules/
# - vendor/bundle/
# - vendor/cache/
# - vendor/gems/
# - vendor/ruby/

View File

@@ -0,0 +1,174 @@
{% capture headingsWorkspace %}
{% comment %}
Copyright (c) 2018 Vladimir "allejo" Jimenez
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
{% endcomment %}
{% comment %}
Version 1.0.13
https://github.com/allejo/jekyll-anchor-headings
"Be the pull request you wish to see in the world." ~Ben Balter
Usage:
{% include anchor_headings.html html=content anchorBody="#" %}
Parameters:
* html (string) - the HTML of compiled markdown generated by kramdown in Jekyll
Optional Parameters:
* beforeHeading (bool) : false - Set to true if the anchor should be placed _before_ the heading's content
* headerAttrs (string) : '' - Any custom HTML attributes that will be added to the heading tag; you may NOT use `id`;
the `%heading%` and `%html_id%` placeholders are available
* anchorAttrs (string) : '' - Any custom HTML attributes that will be added to the `<a>` tag; you may NOT use `href`, `class` or `title`;
the `%heading%` and `%html_id%` placeholders are available
* anchorBody (string) : '' - The content that will be placed inside the anchor; the `%heading%` placeholder is available
* anchorClass (string) : '' - The class(es) that will be used for each anchor. Separate multiple classes with a space
* anchorTitle (string) : '' - The `title` attribute that will be used for anchors
* h_min (int) : 1 - The minimum header level to build an anchor for; any header lower than this value will be ignored
* h_max (int) : 6 - The maximum header level to build an anchor for; any header greater than this value will be ignored
* bodyPrefix (string) : '' - Anything that should be inserted inside of the heading tag _before_ its anchor and content
* bodySuffix (string) : '' - Anything that should be inserted inside of the heading tag _after_ its anchor and content
* generateId (true) : false - Set to true if a header without id should generate an id to use.
Output:
The original HTML with the addition of anchors inside of all of the h1-h6 headings.
{% endcomment %}
{% assign minHeader = include.h_min | default: 1 %}
{% assign maxHeader = include.h_max | default: 6 %}
{% assign beforeHeading = include.beforeHeading %}
{% assign headerAttrs = include.headerAttrs %}
{% assign nodes = include.html | split: '<h' %}
{% capture edited_headings %}{% endcapture %}
{% for _node in nodes %}
{% capture node %}{{ _node | strip }}{% endcapture %}
{% if node == "" %}
{% continue %}
{% endif %}
{% assign nextChar = node | replace: '"', '' | strip | slice: 0, 1 %}
{% assign headerLevel = nextChar | times: 1 %}
<!-- If the level is cast to 0, it means it's not a h1-h6 tag, so let's see if we need to fix it -->
{% if headerLevel == 0 %}
<!-- Split up the node based on closing angle brackets and get the first one. -->
{% assign firstChunk = node | split: '>' | first %}
<!-- If the first chunk does NOT contain a '<', that means we've broken another HTML tag that starts with 'h' -->
{% unless firstChunk contains '<' %}
{% capture node %}<h{{ node }}{% endcapture %}
{% endunless %}
{% capture edited_headings %}{{ edited_headings }}{{ node }}{% endcapture %}
{% continue %}
{% endif %}
{% capture _closingTag %}</h{{ headerLevel }}>{% endcapture %}
{% assign _workspace = node | split: _closingTag %}
{% capture _hAttrToStrip %}{{ _workspace[0] | split: '>' | first }}>{% endcapture %}
{% assign header = _workspace[0] | replace: _hAttrToStrip, '' %}
{% assign escaped_header = header | strip_html | strip %}
{% assign _classWorkspace = _workspace[0] | split: 'class="' %}
{% assign _classWorkspace = _classWorkspace[1] | split: '"' %}
{% assign _html_class = _classWorkspace[0] %}
{% if _html_class contains "no_anchor" %}
{% assign skip_anchor = true %}
{% else %}
{% assign skip_anchor = false %}
{% endif %}
{% assign _idWorkspace = _workspace[0] | split: 'id="' %}
{% if _idWorkspace[1] %}
{% assign _idWorkspace = _idWorkspace[1] | split: '"' %}
{% assign html_id = _idWorkspace[0] %}
{% assign h_attrs = headerAttrs %}
{% elsif include.generateId %}
<!-- If the header did not have an id we create one. -->
{% assign html_id = escaped_header | slugify %}
{% if html_id == "" %}
{% assign html_id = false %}
{% endif %}
<!-- Append the generated id to other potential header attributes. -->
{% capture h_attrs %}{{ headerAttrs }} id="%html_id%"{% endcapture %}
{% endif %}
<!-- Build the anchor to inject for our heading -->
{% capture anchor %}{% endcapture %}
{% if skip_anchor == false and html_id and headerLevel >= minHeader and headerLevel <= maxHeader %}
{% if h_attrs %}
{% capture _hAttrToStrip %}{{ _hAttrToStrip | split: '>' | first }} {{ h_attrs | strip | replace: '%heading%', escaped_header | replace: '%html_id%', html_id }}>{% endcapture %}
{% endif %}
{% capture anchor %}href="#{{ html_id }}"{% endcapture %}
{% if include.anchorClass %}
{% capture anchor %}{{ anchor }} class="{{ include.anchorClass }}"{% endcapture %}
{% endif %}
{% if include.anchorTitle %}
{% capture anchor %}{{ anchor }} title="{{ include.anchorTitle | replace: '%heading%', escaped_header }}"{% endcapture %}
{% endif %}
{% if include.anchorAttrs %}
{% capture anchor %}{{ anchor }} {{ include.anchorAttrs | replace: '%heading%', escaped_header | replace: '%html_id%', html_id }}{% endcapture %}
{% endif %}
{% capture anchor %}<a {{ anchor }}>{{ include.anchorBody | replace: '%heading%', escaped_header | default: '' }}</a>{% endcapture %}
<!-- In order to prevent adding extra space after a heading, we'll let the 'anchor' value contain it -->
{% if beforeHeading %}
{% capture anchor %}{{ anchor }} {% endcapture %}
{% else %}
{% capture anchor %} {{ anchor }}{% endcapture %}
{% endif %}
{% endif %}
{% capture new_heading %}
<h{{ _hAttrToStrip }}
{{ include.bodyPrefix }}
{% if beforeHeading %}
{{ anchor }}{{ header }}
{% else %}
{{ header }}{{ anchor }}
{% endif %}
{{ include.bodySuffix }}
</h{{ headerLevel }}>
{% endcapture %}
<!--
If we have content after the `</hX>` tag, then we'll want to append that here so we don't lost any content.
-->
{% assign chunkCount = _workspace | size %}
{% if chunkCount > 1 %}
{% capture new_heading %}{{ new_heading }}{{ _workspace | last }}{% endcapture %}
{% endif %}
{% capture edited_headings %}{{ edited_headings }}{{ new_heading }}{% endcapture %}
{% endfor %}
{% endcapture %}{% assign headingsWorkspace = '' %}{{ edited_headings | strip }}

View File

@@ -0,0 +1,20 @@
{%- if page.comments != false and jekyll.environment == "production" -%}
<div id="disqus_thread"></div>
<script>
var disqus_config = function () {
this.page.url = '{{ page.url | absolute_url }}';
this.page.identifier = '{{ page.url | absolute_url }}';
};
(function() {
var d = document, s = d.createElement('script');
s.src = 'https://{{ site.disqus.shortname }}.disqus.com/embed.js';
s.setAttribute('data-timestamp', +new Date());
(d.head || d.body).appendChild(s);
})();
</script>
<noscript>Please enable JavaScript to view the <a href="https://disqus.com/?ref_noscript" rel="nofollow">comments powered by Disqus.</a></noscript>
{%- endif -%}

28
_includes/footer.html Normal file
View File

@@ -0,0 +1,28 @@
<footer class="site-footer h-card">
<data class="u-url" href="{{ "/" | relative_url }}"></data>
<div class="wrapper">
<div class="footer-col-wrapper">
<div class="footer-col footer-col-1">
<ul class="contact-list">
<li class="p-name">
{%- if site.author -%}
{{ site.author | escape }}
{%- else -%}
{{ site.title | escape }}
{%- endif -%}
</li>
{%- if site.email -%}
<li><a class="u-email" href="mailto:{{ site.email }}">{{ site.email }}</a></li>
{%- endif -%}
</ul>
</div>
<div class="footer-col footer-col-2">
{%- include social.html -%}
</div>
</div>
</div>
</footer>

9
_includes/head.html Normal file
View File

@@ -0,0 +1,9 @@
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
{%- seo -%}
<link rel="stylesheet" href="{{ "/assets/style.css" | relative_url }}">
{%- feed_meta -%}
</head>

30
_includes/header.html Normal file
View File

@@ -0,0 +1,30 @@
<header class="site-header" role="banner">
<div class="wrapper">
{%- assign default_paths = site.pages | map: "path" -%}
{%- assign page_paths = site.header_pages | default: default_paths -%}
<a class="site-title" rel="author" href="{{ "/" | relative_url }}">{{ site.title | escape }}</a>
{%- if page_paths -%}
<nav class="site-nav">
<input type="checkbox" id="nav-trigger" class="nav-trigger" />
<label for="nav-trigger">
<span class="menu-icon">
<svg viewBox="0 0 18 15" width="18px" height="15px">
<path d="M18,1.484c0,0.82-0.665,1.484-1.484,1.484H1.484C0.665,2.969,0,2.304,0,1.484l0,0C0,0.665,0.665,0,1.484,0 h15.032C17.335,0,18,0.665,18,1.484L18,1.484z M18,7.516C18,8.335,17.335,9,16.516,9H1.484C0.665,9,0,8.335,0,7.516l0,0 c0-0.82,0.665-1.484,1.484-1.484h15.032C17.335,6.031,18,6.696,18,7.516L18,7.516z M18,13.516C18,14.335,17.335,15,16.516,15H1.484 C0.665,15,0,14.335,0,13.516l0,0c0-0.82,0.665-1.483,1.484-1.483h15.032C17.335,12.031,18,12.695,18,13.516L18,13.516z"/>
</svg>
</span>
</label>
<div class="trigger">
{%- for path in page_paths -%}
{%- assign my_page = site.pages | where: "path", path | first -%}
{%- if my_page.title -%}
<a class="page-link" href="{{ my_page.url | relative_url }}">{{ my_page.title | escape }}</a>
{%- endif -%}
{%- endfor -%}
</div>
</nav>
{%- endif -%}
</div>
</header>

View File

@@ -0,0 +1 @@
<a href="https://github.com/{{ include.username }}"><span class="icon icon--github">{% include icon-github.svg %}</span><span class="username">{{ include.username }}</span></a>

View File

@@ -0,0 +1 @@
<svg viewBox="0 0 16 16" width="16px" height="16px"><path fill="#828282" d="M7.999,0.431c-4.285,0-7.76,3.474-7.76,7.761 c0,3.428,2.223,6.337,5.307,7.363c0.388,0.071,0.53-0.168,0.53-0.374c0-0.184-0.007-0.672-0.01-1.32 c-2.159,0.469-2.614-1.04-2.614-1.04c-0.353-0.896-0.862-1.135-0.862-1.135c-0.705-0.481,0.053-0.472,0.053-0.472 c0.779,0.055,1.189,0.8,1.189,0.8c0.692,1.186,1.816,0.843,2.258,0.645c0.071-0.502,0.271-0.843,0.493-1.037 C4.86,11.425,3.049,10.76,3.049,7.786c0-0.847,0.302-1.54,0.799-2.082C3.768,5.507,3.501,4.718,3.924,3.65 c0,0,0.652-0.209,2.134,0.796C6.677,4.273,7.34,4.187,8,4.184c0.659,0.003,1.323,0.089,1.943,0.261 c1.482-1.004,2.132-0.796,2.132-0.796c0.423,1.068,0.157,1.857,0.077,2.054c0.497,0.542,0.798,1.235,0.798,2.082 c0,2.981-1.814,3.637-3.543,3.829c0.279,0.24,0.527,0.713,0.527,1.437c0,1.037-0.01,1.874-0.01,2.129 c0,0.208,0.14,0.449,0.534,0.373c3.081-1.028,5.302-3.935,5.302-7.362C15.76,3.906,12.285,0.431,7.999,0.431z"/></svg>

After

Width:  |  Height:  |  Size: 953 B

View File

@@ -0,0 +1 @@
<a href="https://twitter.com/{{ include.username }}"><span class="icon icon--twitter">{% include icon-twitter.svg %}</span><span class="username">{{ include.username }}</span></a>

View File

@@ -0,0 +1 @@
<svg viewBox="0 0 16 16" width="16px" height="16px"><path fill="#828282" d="M15.969,3.058c-0.586,0.26-1.217,0.436-1.878,0.515c0.675-0.405,1.194-1.045,1.438-1.809c-0.632,0.375-1.332,0.647-2.076,0.793c-0.596-0.636-1.446-1.033-2.387-1.033c-1.806,0-3.27,1.464-3.27,3.27 c0,0.256,0.029,0.506,0.085,0.745C5.163,5.404,2.753,4.102,1.14,2.124C0.859,2.607,0.698,3.168,0.698,3.767 c0,1.134,0.577,2.135,1.455,2.722C1.616,6.472,1.112,6.325,0.671,6.08c0,0.014,0,0.027,0,0.041c0,1.584,1.127,2.906,2.623,3.206 C3.02,9.402,2.731,9.442,2.433,9.442c-0.211,0-0.416-0.021-0.615-0.059c0.416,1.299,1.624,2.245,3.055,2.271 c-1.119,0.877-2.529,1.4-4.061,1.4c-0.264,0-0.524-0.015-0.78-0.046c1.447,0.928,3.166,1.469,5.013,1.469 c6.015,0,9.304-4.983,9.304-9.304c0-0.142-0.003-0.283-0.009-0.423C14.976,4.29,15.531,3.714,15.969,3.058z"/></svg>

After

Width:  |  Height:  |  Size: 814 B

23
_includes/image.html Normal file
View File

@@ -0,0 +1,23 @@
<!-- _includes/image.html -->
{% if include.fullwidth %}
<figure class="fullwidth">
{% else %}
<figure>
{% endif %}
{% if include.url %}
<a href="{{ include.url }}">
{% endif %}
<img
{% if include.srcabs %}
src="{{ include.srcabs }}"
{% else %}
src="{{ site.baseurl }}/assets/images/{{ include.src }}"
{% endif %}
alt="{{ include.alt }}">
{% if include.url %}
</a>
{% endif %}
{% if include.caption %}
<figcaption>{{ include.caption }}</figcaption>
{% endif %}
</figure>

25
_includes/social.html Normal file
View File

@@ -0,0 +1,25 @@
<ul class="social-media-list">
{%- if site.github_username -%}
<li>
<a
href="https://github.com/{{ site.github_username| cgi_escape | escape }}"
>
<div class="svg-icon">
{%- include icon-github.svg -%}
</div>
<span class="username">{{ site.github_username| escape }}</span>
</a>
</li>
{%- endif -%} {%- if site.twitter_username -%}
<li>
<a
href="https://www.twitter.com/{{ site.twitter_username| cgi_escape | escape }}"
>
<div class="svg-icon">
{%- include icon-twitter.svg -%}
</div>
<span class="username">{{ site.twitter_username| escape }}</span>
</a>
</li>
{%- endif -%}
</ul>

8
_includes/tags.html Normal file
View File

@@ -0,0 +1,8 @@
{%- if page.tags.size > 0 -%}
<span class="post-tags">
{%- for tag in page.tags -%}
#<a href="/tag/{{ tag }}">{{ tag }}</a>&nbsp;
{%- endfor -%}
</span>
{%- endif -%}

20
_layouts/default.html Normal file
View File

@@ -0,0 +1,20 @@
<!DOCTYPE html>
<html lang="{{ page.lang | default: site.lang | default: "en" }}">
{%- include head.html -%}
<body>
<div class="container">
{%- include header.html -%}
<main class="page-content" aria-label="Content">
{{ content }}
</main>
{%- include footer.html -%}
</div>
</body>
</html>

53
_layouts/home.html Normal file
View File

@@ -0,0 +1,53 @@
---
layout: default
---
<div class="home">
<div class="intro">
<h1 class="page-heading">Welcome home</h1>
<p>Thank you for venturing into my corner of The Internet, to read my stories of engineering and technology, and explore the projects Ive created and am in the process of creating. I primarily focus on home automation, homelab, and virtualization, but also enjoy building and making things. Feel free to browse the blog for regular updates, project pages for long term project descriptions, and my Youtube and Twitch channels for video content and casual relaxation. I hope you enjoy your journey along the way!</p>
</div>
{{ content }}
{%- if site.posts.size > 0 -%}
<ul class="post-list">
{%- for post in site.posts -%}
<li>
<h3>
<a class="post-link" href="{{ post.url | relative_url }}">
{{ post.title | escape }}
</a>
</h3>
{%- assign date_format = site.minima.date_format | default: "%b %-d, %Y" -%}
<span class="post-meta">{{ post.date | date: date_format }}</span>
{%- if post.tags.size > 0 -%}
<div>
<span class="post-tags">
{%- for tag in post.tags -%}
#<a href="/tag/{{ tag }}">{{ tag }}</a>&nbsp;
{%- endfor -%}
</span>
</div>
{%- endif -%}
{%- if site.show_excerpts -%}
<div class="excerpt">
<p>{{ post.excerpt }}</p>
<div>
<a class="read-more" href="{{ post.url | relative_url }}">read more →</a>
</div>
</div>
{%- endif -%}
</li>
{%- endfor -%}
</ul>
<p class="rss-subscribe">subscribe <a href="{{ "/feed.xml" | relative_url }}">via RSS</a></p>
{%- endif -%}
</div>

14
_layouts/page.html Normal file
View File

@@ -0,0 +1,14 @@
---
layout: default
---
<article class="post">
<header class="post-header">
<h1 class="post-title">{{ page.title | escape }}</h1>
</header>
<div class="post-content">
{{ content }}
</div>
</article>

34
_layouts/post.html Normal file
View File

@@ -0,0 +1,34 @@
---
layout: default
---
<article class="post h-entry" itemscope itemtype="http://schema.org/BlogPosting">
<header class="post-header">
<h1 class="post-title p-name" itemprop="name headline">{{ page.title | escape }}</h1>
<p class="post-meta">
<time class="dt-published" datetime="{{ page.date | date_to_xmlschema }}" itemprop="datePublished">
{%- assign date_format = site.minima.date_format | default: "%b %-d, %Y, %H:%M:%S" -%}
Created: {{ page.date | date: date_format }}
</time>
<time class="dt-modified" datetime="{{ page.updated | date_to_xmlschema }}" itemprop="dateModified">
Updated: {{ page.updated | date: date_format }}
</time>
{%- if page.author -%}
<span itemprop="author" itemscope itemtype="http://schema.org/Person"><span class="p-author h-card" itemprop="name">{{ page.author }}</span></span>
{%- endif -%}</p>
{%- include tags.html -%}
</header>
<div class="post-content e-content" itemprop="articleBody">
{% include anchor_headings.html html=content anchorBody="#" %}
</div>
{%- if site.disqus.shortname -%}
{%- include disqus_comments.html -%}
{%- endif -%}
<a class="u-url" href="{{ page.url | relative_url }}" hidden></a>
</article>
<script src="/assets/scripts/copyCode.js"></script>

16
_layouts/tag_page.html Normal file
View File

@@ -0,0 +1,16 @@
---
layout: default
---
<h2>{{ page.tag }}</h2>
<ul>
{% for post in page.posts %}
<li>
<a href="{{ post.url }}">{{ post.title }}</a>
({{ post.date | date_to_string }} | Tags: {{ post | tags }})
</li>
{% endfor %}
</ul>
<div id="tag-cloud">
{{ site | tag_cloud }}
</div>

16
_layouts/tags.html Normal file
View File

@@ -0,0 +1,16 @@
---
layout: default
---
<div class="tags-page">
<h1 class="page-heading">Tags</h1>
<ul>
{% for tag in site.tags %}
<li>
<a href="/tag/{{ tag[0] }}.html">{{ tag[0] }} ({{ tag[1] | size }})</a>
</li>
{% endfor %}
</ul>
</div>

24
_pages/404.html Normal file
View File

@@ -0,0 +1,24 @@
---
permalink: /404.html
layout: default
---
<style type="text/css" media="screen">
.container {
margin: 10px auto;
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>

18
_pages/about.markdown Normal file
View File

@@ -0,0 +1,18 @@
---
layout: page
title: About
permalink: /about/
---
This is the base Jekyll theme. You can find out more info about customizing your Jekyll theme, as well as basic Jekyll usage documentation at [jekyllrb.com](https://jekyllrb.com/)
You can find the source code for Minima at GitHub:
[jekyll][jekyll-organization] /
[minima](https://github.com/jekyll/minima)
You can find the source code for Jekyll at GitHub:
[jekyll][jekyll-organization] /
[jekyll](https://github.com/jekyll/jekyll)
[jekyll-organization]: https://github.com/jekyll

5
_pages/tags.markdown Normal file
View File

@@ -0,0 +1,5 @@
---
layout: tags
title: Tags
permalink: /tags/
---

View File

@@ -0,0 +1,18 @@
---
layout: post
title: E-ink brewpi viewer
date: 2023-05-01 10:46:15 +0200
updated: 2023-05-01 14:52:00 +0200
tags: brewing e-ink
---
Continuing on brewpi refrigerator project we have already created a [regulator]() & [website](), but I also want a way to view the current refrigerator state at a glance.
{% include image.html
src="0001-brewpi.jpeg"
alt="Jekyll's logo"
caption="E-ink display displaying current brew status."
fullwidth="true"
%}

View File

@@ -0,0 +1,90 @@
---
layout: post
title: "Remove Proxmox Server Access over SERIAL! Cheaper Alternative to IPMI or KVMs"
date: 2023-05-18 10:46:15 +0200
updated: 2023-05-19 14:52:00 +0200
tags: virtualization networking
excerpt: Ive gone from “no backups” to “raid is a backup” to “two zfs pools in one box”, and decided its finally time for a proper backup solution. So, I settled on Proxmox Backup Server! And today, I rebuild my HP Microserver Gen8 with 4x10T refurbished SAS drives, a new SAS controller card, and more! With this backup solution, Im feeling a lot better about my data migration to Ceph. Contents Video SAS Drive Formatting ZFS Pool Setup Next Steps Video SAS Drive Formatting Since these drives were refurbished they were formerly formatted for a hardware RAID controller and were giving me lots of protection errors in dmesg - specifically blk_update_request protection error (and failing to read, but not write).
---
I have a rack-mounted KVM now, and its great, but Im working on building out a new Proxmox cluster which might not have a graphics output at all on some of the nodes. So, I need a new remote access solution for them.
The new nodes Im planning on building will all be based on used consumer hardware, so Im limited by what would be available on normal mATX boards. This doesnt include IPMI, and if I go with AMD-based CPUs, doesnt include an iGPU either. So I either need to get cheap GPUs to add to the second PCIe slot (which I then cant use for things like HBAs), or at least put a GPU in for troubleshooting. However, adding a GPU often moves PCIe devices, leading to issues where the network card on enp4 is now enp5 when the GPU is attahed, for example. So trouleshooting for real would be a nightmare with this approach.
But! There is an alternative. Despite being ancient, many boards still have a COM header connected to the chipset, which provides a basic serial port header (COM1 in Windows) and is completely usable. So, my goal is to connect this COM header to a female RJ45 port on the back of the computer, so I can plug in a Cisco-style terminal cable. These sorts of cables (RJ45 serial to USB) are readily available cheaply on the internet, and I can open a terminal emulator on my laptop to diagnose the worst issues that lock up the system.
Since some systems are rumored to not POST without a graphics card, Im testing this approach today.
# Contents
- [Video](#video)
- [Building the Cable](#building-the-cable)
- [Proxmox Setup](#proxmox-setup)
- [Parts](#parts)
# Video
# Building the cable
The Cisco/Juniper style RJ45 pinout is fairly simple if we exclude all of the flow control lines, so we just need 3 wires. I bought a pack of 2x5 IDC headers and a panel mount female RJ45 extension cable (which can be mounted in the case), cut the male end off, and crimped the resulting wires directly in the IDC header. Then I used a cheap USB to RJ45 serial cable and all worked great.
Heres the pinout drawing for reference:
# Proxmox Setup
Setup is really two steps - enabling kernel console via serial, and enabling a tty on that serial port. One of these requires editing the kernel `cmdline` (Which can vary a bit - see Proxmoxs docs for more info), and the other requires using systemd.
First, we need to add a new `console` argument to the kernel cmdline. Default for this is `tty0`, and we can add multiple arguments, so we should make sure both are specified. On my system I am using systemd-boot, so I edit the file `/etc/kernel/cmdline` and add:
```bash
console=tty0 console=ttyS0,115200n8
```
(ttyS0 should be COM1 in Windows, and should be the COM port on the motherboard. You can also use USB Serial here if you need to, or any other serial ports you have available)
Now, we just need to enable getty on our serial port so we have a proper login terminal:
```
systemctl enable serial-getty@ttyS0.service
```
And reboot, watching boot messages on the console happily
![image tooltip here](/assets/images/0001-proxmox.jpg)
*cluster viewed from here*
{% include image.html
src="0001-proxmox.png"
alt="Jekyll's logo"
caption="This is Jekyll's logo, featuring Dr. Jekyll's serum!"
%}
I get that these push clippy things are on the low end because theyre cheap and not really ideal for proper cooler pressure, but god damn why cant all cooler installations be this easy? Some of the shit Ive had to install in my past have been too damn complicated for no obvious reason. Although, after putting this thing on the board, there was very obvious warping happening on the board, so, pointless rant by me, clearly.
I really dont mind warping as much as a lot of people seem to, Ive used a lot of warped PCBs in my day and theyre pretty solid bits of kit. Once I installed the board in the case the motherboard screws seemed to bed it back as it were, so the board was straight.
{% include image.html
src="0002-proxmox.png"
alt="Jekyll's logo"
caption="This is Jekyll's logo, featuring Dr. Jekyll's serum!"
fullwidth="true"
%}
{% include image.html
src="0003-proxmox.png"
alt="Jekyll's logo"
caption="This is Jekyll's logo, featuring Dr. Jekyll's serum!"
fullwidth="true"
%}
Of course, since Proxmox is Debian (with Ubuntu kernels), this should work on any of your other systems also Debian-based, as long as you are aware of the right place for the cmdline config (GRUB or Systemdboot).
# Parts
Some links to products may be affiliate links, which may earn a commission for me.
- [Female 2x5 IDC Connector (50 pack)](https://google.com)
- [RJ45 Panel Mount Female Extension](https://google.com)
- [RJ45 Console Cable to USB-A](https://google.com)
- [RJ45 Console Cable to USB-C](https://google.com)

View File

@@ -0,0 +1,138 @@
---
layout: post
title: Network KVM for ALL of my Servers!
date: 2023-05-19 15:46:15 +0200
updated: 2023-05-19 15:52:00 +0200
tags: networking virtualization
---
Since I use a lot of repurposed computers as servers, I dont have many with IPMI / remote access built in. Usually I can configure them remotely through SSH or their web UI, but sometimes things go wrong and its nice to have remote console access. Enter, PiKVM, a project to build a networked KVM switch with a Raspberry Pi. Unfortunately, I have a more than one server, and building a PiKVM for every one gets expensive, so Im combining it with an 8 port rack mount KVM switch so I can remotely view and control all of the servers in my rack.
The KVM Im using supports network control (but its not a network KVM, it can just switch inputs over the network) and Ive configured that in this video.
# Contents
- [Networking Configuration](#networking-configuration)
- [PiKVM Configuration](#pikvm-configuration)
# Networking Configuration
The network configuration goes in `/etc/systemd/network/eth0.network`. Make sure to run `rw` to make the filesystem writeable before editing it, and `ro` when you are done.
```
[Match]
Name=eth0
[Network]
DHCP=yes
DNSSEC=no
# Use DHCP for primary address
# Add a static address in a /31 for the TESmart KVM
Address=192.168.1.11/31
[DHCP]
# Use same IP by forcing to use MAC address for clientID
ClientIdentifier=mac
# https://github.com/pikvm/pikvm/issues/583
RouteMetric=10
```
# PiKVM Configuration
The PiKVM configuration override goes in `/etc/kvmd/override.yaml`. Make sure to run `rw` to make the filesystem writeable before editing it, and `ro` when you are done. Im using the default IP of the Tesmart and a /31 subnet to avoid changing it, but if you do change the IP youd change it here as well.
```yaml
kvmd:
gpio:
drivers:
tes:
type: tesmart
host: 192.168.1.10
port: 5000
scheme:
server0_led:
driver: tes
pin: 0
mode: input
server0_switch:
driver: tes
pin: 0
mode: output
switch: false
server1_led:
driver: tes
pin: 1
mode: input
server1_switch:
driver: tes
pin: 1
mode: output
switch: false
server2_led:
driver: tes
pin: 2
mode: input
server2_switch:
driver: tes
pin: 2
mode: output
switch: false
server3_led:
driver: tes
pin: 3
mode: input
server3_switch:
driver: tes
pin: 3
mode: output
switch: false
server4_led:
driver: tes
pin: 4
mode: input
server4_switch:
driver: tes
pin: 4
mode: output
switch: false
server5_led:
driver: tes
pin: 5
mode: input
server5_switch:
driver: tes
pin: 5
mode: output
switch: false
server6_led:
driver: tes
pin: 6
mode: input
server6_switch:
driver: tes
pin: 6
mode: output
switch: false
server7_led:
driver: tes
pin: 7
mode: input
server7_switch:
driver: tes
pin: 7
mode: output
switch: false
view:
table:
- ["TESMART Switch"]
- []
- ["#Terra NAS", server0_led, server0_switch|Switch]
- ["#Megalab", server1_led, server1_switch|Switch]
- ["#PVE1", server2_led, server2_switch|Switch]
- ["#PVE2", server3_led, server3_switch|Switch]
- ["#PVE3", server4_led, server4_switch|Switch]
- ["#Minilab", server5_led, server5_switch|Switch]
- ["#OPNsense", server6_led, server6_switch|Switch]
- ["#Iridium", server7_led, server7_switch|Switch]
```

View File

@@ -0,0 +1,29 @@
---
layout: post
title: "Welcome to Jekyll!"
date: 2023-05-19 00:56:15 +0200
categories: posts jekyll update
---
Youll find this post in your `_posts` directory. Go ahead and edit it and re-build the site to see your changes. You can rebuild the site in many different ways, but the most common way is to run `jekyll serve`, which launches a web server and auto-regenerates your site when a file is updated.
Jekyll requires blog post files to be named according to the following format:
`YEAR-MONTH-DAY-title.MARKUP`
Where `YEAR` is a four-digit number, `MONTH` and `DAY` are both two-digit numbers, and `MARKUP` is the file extension representing the format used in the file. After that, include the necessary front matter. Take a look at the source for this post to get an idea about how it works.
Jekyll also offers powerful support for code snippets:
{% highlight ruby %}
def print_hi(name)
puts "Hi, #{name}"
end
print_hi('Tom')
#=> prints 'Hi, Tom' to STDOUT.
{% endhighlight %}
Check out the [Jekyll docs][jekyll-docs] for more info on how to get the most out of Jekyll. File all bugs/feature requests at [Jekylls GitHub repo][jekyll-gh]. If you have questions, you can ask them on [Jekyll Talk][jekyll-talk].
[jekyll-docs]: https://jekyllrb.com/docs/home
[jekyll-gh]: https://github.com/jekyll/jekyll
[jekyll-talk]: https://talk.jekyllrb.com/

274
_sass/_base.scss Normal file
View File

@@ -0,0 +1,274 @@
/**
* Reset some basic elements
*/
body,
h1,
h2,
h3,
h4,
h5,
h6,
p,
blockquote,
pre,
hr,
dl,
dd,
ol,
ul,
figure {
margin: 0;
padding: 0;
}
* {
box-sizing: border-box;
}
/**
* Basic styling
*/
body {
font: $base-font-weight #{$base-font-size}/#{$base-line-height}
$base-font-family;
color: $text-color;
background-color: $background-color;
-webkit-text-size-adjust: 100%;
-webkit-font-feature-settings: "kern" 1;
-moz-font-feature-settings: "kern" 1;
-o-font-feature-settings: "kern" 1;
font-feature-settings: "kern" 1;
font-kerning: normal;
}
/**
* Set `margin-bottom` to maintain vertical rhythm
*/
h1,
h2,
h3,
h4,
h5,
h6,
p,
blockquote,
pre,
ul,
ol,
dl,
figure,
%vertical-rhythm {
margin-bottom: calc(var(--spacing-unit) / 2);
}
/**
* `main` element
*/
main {
display: block; /* Default value of `display` of `main` element is 'inline' in IE 11. */
}
/**
* Images
*/
img {
max-width: 100%;
vertical-align: middle;
}
/**
* Figures
*/
figure > img {
display: block;
}
figcaption {
font-size: $small-font-size;
}
/**
* Lists
*/
ul,
ol {
margin-left: var(--spacing-unit);
}
li {
> ul,
> ol {
margin-bottom: 0;
}
}
/**
* Headings
*/
h1,
h2,
h3,
h4,
h5,
h6 {
font-weight: $base-font-weight;
font-weight: bold;
}
/**
* Links
*/
a {
color: $brand-color;
text-decoration: none;
&:hover {
text-decoration: underline;
}
.social-media-list &:hover {
text-decoration: none;
.username {
text-decoration: underline;
}
}
}
/**
* Blockquotes
*/
blockquote {
color: $grey-color;
border-left: 4px solid $grey-color-light;
padding-left: calc(var(--spacing-unit) / 2);
@include relative-font-size(1.125);
letter-spacing: -1px;
font-style: italic;
> :last-child {
margin-bottom: 0;
}
}
/**
* Code formatting
*/
pre,
code {
font-size: 0.9375em;
border: 1px solid hsla(0, 0%, 100%, 0.1);
padding: 3em;
// background-color: var(--background-color);
}
code {
padding: 1px 5px;
background-color: rgba(255, 168, 106, 0.2);
color: var(--brand-color);
margin: 0 2px;
padding: 1px 6px;
border: none;
}
pre {
padding: 8px 12px;
padding: 1.25em;
overflow-x: auto;
> code {
background-color: unset;
border: 0;
padding-right: 0;
padding-left: 0;
}
}
.highlight {
position: relative;
}
.highlight > button {
all: unset;
opacity: 0;
position: absolute;
top: 1rem;
right: 1rem;
z-index: 100;
cursor: pointer;
background: hsla(0, 0%, 87.8%, 0.2) !important;
border-radius: 0 !important;
box-shadow: 0 2px 0 0 rgba(0, 0, 0, 0.2) !important;
color: #bbb !important;
font-size: 0.8em !important;
margin: 6px !important;
padding: 10px !important;
transition: opacity 0.5s ease;
}
.highlight:hover > button {
opacity: 1;
}
.highlight > button:active,
.highlight > button:focus {
opacity: 1;
}
/**
* Clearfix
*/
%clearfix:after {
content: "";
display: table;
clear: both;
}
/**
* Icons
*/
.svg-icon {
width: 21px;
height: 16px;
display: inline-block;
fill: #{$grey-color};
padding-right: 5px;
vertical-align: middle;
}
.social-media-list {
li + li {
padding-top: 5px;
}
}
/**
* Tables
*/
table {
margin-bottom: var(--spacing-unit);
width: 100%;
text-align: $table-text-align;
color: lighten($text-color, 18%);
border-collapse: collapse;
border: 1px solid $grey-color-light;
tr {
&:nth-child(even) {
background-color: lighten($grey-color-light, 6%);
}
}
th,
td {
padding: calc(var(--spacing-unit) / 3) calc(var(--spacing-unit) / 2);
}
th {
background-color: lighten($grey-color-light, 3%);
border: 1px solid darken($grey-color-light, 4%);
border-bottom-color: darken($grey-color-light, 12%);
}
td {
border: 1px solid $grey-color-light;
}
}

98
_sass/_header.scss Normal file
View File

@@ -0,0 +1,98 @@
/**
* Site header
*/
.site-header {
border-bottom: 3px dashed $grey-color-light;
border-bottom: 3px dashed rgba(254, 168, 106, 0.6);
min-height: calc(var(--spacing-unit) * 1.865);
// Positioning context for the mobile navigation icon
position: relative;
}
.site-title {
@include relative-font-size(1.625);
font-weight: 300;
line-height: $base-line-height * $base-font-size * 2.25;
letter-spacing: -1px;
margin-bottom: 0;
float: left;
}
.site-nav {
float: right;
line-height: $base-line-height * $base-font-size * 2.25;
.nav-trigger {
display: none;
}
.menu-icon {
display: none;
}
.page-link {
color: $text-color;
line-height: $base-line-height;
// Gaps between nav items, but not on the last one
&:not(:last-child) {
margin-right: 20px;
}
}
@include media-query($on-palm) {
position: absolute;
top: 9px;
right: calc(var(--spacing-unit) / 2);
background-color: $background-color;
border: 1px solid $grey-color-light;
border-radius: 5px;
text-align: right;
label[for="nav-trigger"] {
display: block;
float: right;
width: 36px;
height: 36px;
z-index: 2;
cursor: pointer;
}
.menu-icon {
display: block;
float: right;
width: 36px;
height: 26px;
line-height: 0;
padding-top: 10px;
text-align: center;
> svg {
fill: $grey-color-dark;
}
}
input ~ .trigger {
clear: both;
display: none;
}
input:checked ~ .trigger {
display: block;
padding-bottom: 5px;
}
.page-link {
display: block;
padding: 5px 10px;
&:not(:last-child) {
margin-right: 0;
}
margin-left: 20px;
}
}
}

196
_sass/_layout.scss Normal file
View File

@@ -0,0 +1,196 @@
/**
* Site footer
*/
.site-footer {
border-top: 1px solid $grey-color-light;
padding: var(--spacing-unit) 0;
}
.footer-heading {
@include relative-font-size(1.125);
margin-bottom: calc(var(--spacing-unit) / 2);
}
.contact-list,
.social-media-list {
list-style: none;
margin-left: 0;
}
.footer-col-wrapper {
@include relative-font-size(0.9375);
color: $grey-color;
@extend %clearfix;
display: flex;
justify-content: space-between;
@include media-query($on-palm) {
flex-direction: column;
}
}
.container {
display: flex;
flex-direction: column;
width: 100%;
max-width: 864px;
min-height: 100vh;
margin: 0 auto;
padding: var(--spacing-unit);
@include media-query($on-palm) {
padding: 0.7rem;
}
}
.home .intro {
margin-bottom: 5em;
}
/**
* Page content
*/
.page-heading {
margin-top: 1.75em;
@include relative-font-size(2);
}
.post-list-heading {
@include relative-font-size(1.75);
}
.post-list {
margin-left: 0;
list-style: none;
> li {
border-bottom: 1px solid var(--border-color);
margin-bottom: var(--spacing-unit);
padding-bottom: var(--spacing-unit);
}
h3,
h3 > a {
font-size: 1.4em;
margin: 0;
}
}
.post-tags,
.post-tags a {
color: $grey-color;
}
.post-meta {
font-size: $small-font-size;
opacity: 0.8;
color: var(--brand-color);
}
.post-link {
display: block;
font-size: 1.5em;
}
.excerpt {
margin-top: 2em;
}
.read-more {
background: none;
box-shadow: none;
display: inline-flex;
margin: 0;
max-width: 100%;
padding: 0;
opacity: 0.8;
}
figure.fullwidth {
position: relative;
width: 55vw;
left: 50%;
transform: translateX(-50%);
@include media-query($on-laptop) {
width: 95vw;
}
}
/**
* Posts
*/
.post-header {
margin-bottom: var(--spacing-unit);
}
.post-title {
--border: 3px dotted var(--brand-color);
font-size: 2em;
color: var(--brand-color);
border-bottom: var(--border);
letter-spacing: -1px;
margin: 4rem 0 1rem;
padding-bottom: 1rem;
position: relative;
@include media-query($on-laptop) {
@include relative-font-size(2.25);
}
&::after {
border-bottom: var(--border);
bottom: 2px;
content: "";
display: block;
position: absolute;
width: 100%;
}
}
.post-content {
margin-bottom: var(--spacing-unit);
h1,
h2,
h3,
h4 {
a {
opacity: 0;
transition: opacity 0.15s ease;
}
&:hover > a {
opacity: 1;
}
a:hover {
text-decoration: none;
}
}
h2 {
@include relative-font-size(2);
@include media-query($on-laptop) {
@include relative-font-size(1.75);
}
}
h3 {
@include relative-font-size(1.625);
@include media-query($on-laptop) {
@include relative-font-size(1.375);
}
}
h4 {
@include relative-font-size(1.25);
@include media-query($on-laptop) {
@include relative-font-size(1.125);
}
}
}

View File

@@ -0,0 +1,66 @@
/**
* Syntax highlighting styles
*/
.highlight {
@extend %vertical-rhythm;
.c { color: #998; font-style: italic } // Comment
.err { color: #a61717; background-color: #e3d2d2 } // Error
.k { font-weight: bold } // Keyword
.o { font-weight: bold } // Operator
.cm { color: #998; font-style: italic } // Comment.Multiline
.cp { color: #999; font-weight: bold } // Comment.Preproc
.c1 { color: #998; font-style: italic } // Comment.Single
.cs { color: #999; font-weight: bold; font-style: italic } // Comment.Special
.gd { color: #000; background-color: #fdd } // Generic.Deleted
.gd .x { color: #000; background-color: #faa } // Generic.Deleted.Specific
.ge { font-style: italic } // Generic.Emph
.gr { color: #a00 } // Generic.Error
.gh { color: #999 } // Generic.Heading
.gi { color: #000; background-color: #dfd } // Generic.Inserted
.gi .x { color: #000; background-color: #afa } // Generic.Inserted.Specific
.go { color: #888 } // Generic.Output
.gp { color: #555 } // Generic.Prompt
.gs { font-weight: bold } // Generic.Strong
.gu { color: #aaa } // Generic.Subheading
.gt { color: #a00 } // Generic.Traceback
.kc { font-weight: bold } // Keyword.Constant
.kd { font-weight: bold } // Keyword.Declaration
.kp { font-weight: bold } // Keyword.Pseudo
.kr { font-weight: bold } // Keyword.Reserved
.kt { color: #458; font-weight: bold } // Keyword.Type
.m { color: #099 } // Literal.Number
.s { color: #d14 } // Literal.String
.na { color: #008080 } // Name.Attribute
.nb { color: #0086B3 } // Name.Builtin
.nc { color: #458; font-weight: bold } // Name.Class
.no { color: #008080 } // Name.Constant
.ni { color: #800080 } // Name.Entity
.ne { color: #900; font-weight: bold } // Name.Exception
.nf { color: #900; font-weight: bold } // Name.Function
.nn { color: #555 } // Name.Namespace
.nt { color: #000080 } // Name.Tag
.nv { color: #008080 } // Name.Variable
.ow { font-weight: bold } // Operator.Word
.w { color: #bbb } // Text.Whitespace
.mf { color: #099 } // Literal.Number.Float
.mh { color: #099 } // Literal.Number.Hex
.mi { color: #099 } // Literal.Number.Integer
.mo { color: #099 } // Literal.Number.Oct
.sb { color: #d14 } // Literal.String.Backtick
.sc { color: #d14 } // Literal.String.Char
.sd { color: #d14 } // Literal.String.Doc
.s2 { color: #d14 } // Literal.String.Double
.se { color: #d14 } // Literal.String.Escape
.sh { color: #d14 } // Literal.String.Heredoc
.si { color: #d14 } // Literal.String.Interpol
.sx { color: #d14 } // Literal.String.Other
.sr { color: #009926 } // Literal.String.Regex
.s1 { color: #d14 } // Literal.String.Single
.ss { color: #990073 } // Literal.String.Symbol
.bp { color: #999 } // Name.Builtin.Pseudo
.vc { color: #008080 } // Name.Variable.Class
.vg { color: #008080 } // Name.Variable.Global
.vi { color: #008080 } // Name.Variable.Instance
.il { color: #099 } // Literal.Number.Integer.Long
}

16
_sass/_tags.scss Normal file
View File

@@ -0,0 +1,16 @@
.tags-page {
h1 {
color: var(--brand-color);
}
ul {
margin-left: 1.25em;
color: var(--brand-color);
list-style-type: square;
li a {
color: white;
}
}
}

77
_sass/main.scss Normal file
View File

@@ -0,0 +1,77 @@
@charset "utf-8";
// Define defaults for each variable.
@font-face {
font-family: "Fira Code";
src: url("/assets/fonts/FiraCode-Regular.ttf");
}
@font-face {
font-family: "Fira Code";
font-weight: bold;
src: url("/assets/fonts/FiraCode-Bold.ttf");
}
:root {
--font-family: "Fira Code", Monaco, Consolas, "Ubuntu Mono", monospace;
--font-size: 16px;
--font-weight: 400;
--font-size-small: 14px;
--line-height: 1.5;
--spacing-unit: 2.5em;
--text-color: white;
--background-color: #222129;
--brand-color: #fea86a;
--border-color: hsla(0, 0%, 100%, 0.1);
}
$base-font-family: "Fira Code", Monaco, Consolas, "Ubuntu Mono", monospace !default;
$base-font-size: 16px !default;
$base-font-weight: 400 !default;
$small-font-size: $base-font-size * 0.875 !default;
$base-line-height: 1.5 !default;
$spacing-unit: 2.5em !default;
$text-color: white !default;
$background-color: #222129 !default;
$brand-color: #fea86a !default;
$grey-color: #828282 !default;
$grey-color-light: lighten($grey-color, 40%) !default;
$grey-color-dark: darken($grey-color, 25%) !default;
$table-text-align: left !default;
// Width of the content area
$content-width: 800px !default;
$on-palm: 600px !default;
$on-laptop: 800px !default;
// Use media queries like this:
// @include media-query($on-palm) {
// .wrapper {
// padding-right: $spacing-unit / 2;
// padding-left: $spacing-unit / 2;
// }
// }
@mixin media-query($device) {
@media screen and (max-width: $device) {
@content;
}
}
@mixin relative-font-size($ratio) {
font-size: $base-font-size * $ratio;
}
// Import partials.
// @import "base", "layout", "tags", "syntax-highlighting";
@import "base";
@import "layout";
@import "tags";
@import "syntax-highlighting.scss";
@import "header.scss";

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: 2.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 381 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 168 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 778 KiB

View File

@@ -0,0 +1,26 @@
// This assumes that you're using Rouge; if not, update the selector
// const codeBlocks = document.querySelectorAll('.code-header + .highlighter-rouge');
const codeBlocks = document.querySelectorAll('.highlight');
const copyCodeButtons = document.querySelectorAll('.copy-code-button');
codeBlocks.forEach((codeBlock) => {
const copyButton = document.createElement('button');
copyButton.className = 'copy';
copyButton.type = 'button';
copyButton.ariaLabel = 'Copy code to clipboard';
copyButton.innerText = 'Copy';
codeBlock.append(copyButton);
copyButton.addEventListener('click', function () {
const code = codeBlock.querySelector('code').innerText.trim();
window.navigator.clipboard.writeText(code);
copyButton.innerText = 'Copied';
const fourSeconds = 4000;
setTimeout(function () {
copyButton.innerText = 'Copy';
}, fourSeconds);
});
});

5
assets/style.scss Normal file
View File

@@ -0,0 +1,5 @@
---
---
@import 'main';

8
index.markdown Normal file
View File

@@ -0,0 +1,8 @@
---
# Feel free to add content and custom Front Matter to this file.
# To modify the layout, see https://jekyllrb.com/docs/themes/#overriding-theme-defaults
layout: home
title: "Schleppe Lab"
---