Mostly hijack anemone's HTML and my personal site's CSS

This commit is contained in:
asonix 2024-02-10 01:08:15 -06:00
commit 842dc3534d
22 changed files with 2374 additions and 0 deletions

3
.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
.envrc
.direnv
public

68
config.toml Normal file
View file

@ -0,0 +1,68 @@
# The URL the site will be built for
base_url = "https://blog.asonix.dog"
# Whether to automatically compile all Sass files in the sass directory
compile_sass = false
# Whether to build a search index to be used later on by a JavaScript library
build_search_index = false
generate_feed = true
[[taxonomies]]
name = "tags"
feed = true
[markdown]
# Whether to do syntax highlighting
# Theme can be customised by setting the `highlight_theme` variable to a theme supported by Zola
highlight_code = true
highlight_theme = "css"
extra_syntaxes_and_themes = [
"highlight_themes",
]
[[markdown.highlight_themes_css]]
theme = "base16-equilibrium-light"
filename = "syntax-theme-light.css"
[[markdown.highlight_themes_css]]
theme = "base16-eighties"
filename = "syntax-theme-dark.css"
[extra]
display_author = true
author = "asonix"
favicon = "favicon.ico"
[[extra.header_nav]]
url = "https://asonix.dog"
name = "Home"
[[extra.header_nav]]
url = "/"
name = "Blog"
[[extra.header_nav]]
url = "https://git.asonix.dog"
name = "Software"
[[extra.header_nav]]
url = "https://masto.asonix.dog/@asonix"
name = "Mastodon"
[[extra.header_nav]]
url = "https://matrix.to/#/@asonix:matrix.asonix.dog"
name = "Matrix"
[[extra.header_nav]]
url = "https://t.me/asonix"
name = "Telegram"
[[extra.header_nav]]
url = "https://www.furaffinity.net/user/asonix"
name = "Furaffinity"

View file

@ -0,0 +1,287 @@
+++
title = "Ugh Forgejo Actions"
description = "Forgejo Stuff lol idk who knows"
date = 2024-02-10
[taxonomies]
tags = ["admin", "ci", "docker", "forgejo", "actions"]
+++
Over the last few days I've figured out how to use Forgejo Actions. I was excited to try it since
it's integrated directly into Forgejo these days, and compatibility with github Actions means
there's already loads of third party actions to take advantage of. Previously I was using Drone CI.
I still am in a number of projects. But I'm hoping to get everything moved over over the next week
or so.
But that's not why I'm writing this blog post. I'm writing this blog post because I haven't found
very many useful resources for understanding how Actions works, despite the prevalence github
Actions. All the documentation makes it look so simple to use, and in many cases I'm sure it is, but
when you're running it yourself, you'll find the edges.
## Getting Started
Setting up Forgejo Actions isn't a huge deal. I'm running it via docker-compose, but it can be run
natively or in kubernetes or with lxc (etc). The one crucial thing though is it needs access to a
docker daemon in order to operate. Giving it a Docker in Docker container is fine. Here's my DinD
section:
```yaml,linenos
services:
docker-in-docker:
image: docker:dind
privileged: true
command: ["dockerd", "-H", "tcp://0.0.0.0:2375", "--tls=false"]
restart: always
```
Simple enough? Now we're going to get a little more complicated with the Runner configuration. The
runner needs to be brought up in 2 steps. The first step registers the runner with Forgejo and
creates the runner configuration file. The second step launches the runner process. This is
unfortunately not as simple as launching the container, but it isn't too bad.
```yaml,linenos
services:
# docker-in-docker: ...
Forgejo-runner-1-register:
image: code.Forgejo.org/Forgejo/runner:3.3.0
links:
- docker-in-docker
environment:
DOCKER_HOST: tcp://docker-in-docker:2375
volumes:
- /storage/Forgejo-actions/runner-1:/data
user: 0:0
command: >-
bash -ec '
if [ -f config.yml ]; then
exit 0 ;
fi ;
while : ; do
Forgejo-runner register --no-interactive --instance https://git.asonix.dog --name bluestar-runner-1 --token TOKEN && break ;
sleep 1 ;
done ;
Forgejo-runner generate-config > config.yml ;
sed -i -e "s|network: .*|network: host|" config.yml ;
sed -i -e "s|labels: \[\]|labels: \[\"docker:docker://bash:alpine3.19\"\]|" config.yml ;
chown -R 1000:1000 /data
'
```
This is the first step. The script loops attempting to register the runner with Forgejo if there
isn't an existing configuration file, and when it succeeds it writes the configuration file and
updates some values.
This can be more-or-less copied verbatim, with the exception of `TOKEN`, which needs to be copied
from the Forgejo actions admin panel. We'll come back to the config.yml file later. Next up we
actually run the runner.
```yaml,linenos
services:
# docker-in-docker: ...
# Forgejo-runner-1-register: ...
Forgejo-runner-1-daemon:
image: code.Forgejo.org/Forgejo/runner:3.3.0
links:
- docker-in-docker
environment:
DOCKER_HOST: tcp://docker-in-docker:2375
depends_on:
Forgejo-runner-1-register:
condition: service_completed_successfully
volumes:
- /storage/Forgejo-actions/runner-1:/data
command: "Forgejo-runner --config config.yml daemon"
restart: always
```
A lot less going on. We let the Forgejo runner access our Docker-in-Docker daemon and launch it
after the registration container finishes. Off to a great start.
Using my basic "make sure it works" action that I cobbled together after reading some of the
documentation, we can make sure the runner works:
```yaml,linenos
on:
pull_request:
push:
branches:
- main
tags:
- "v*.*.*"
env:
BINARY: example
jobs:
test:
runs-on: docker
strategy:
matrix:
info:
- arch: amd64
- arch: arm64v8
- arch: arm64v7
steps:
# We can run multiple bash commands, and for each item in our matrix!
- run: env
- run: echo "${{ matrix.info.arch }} Good"
test2:
runs-on: docker
container:
# we can override the docker image, how fancy
image: debian:bookworm-slim
steps:
- run : echo "Hello, debian"
test3:
runs-on: docker
container:
image: docker.io/asonix/rust-builder:latest-linux-arm32v7
steps:
# We can even compile rust code! It's amazing!
- run: cargo init --bin --name $BINARY
- run: build
```
This all runs successfully when a branch or a tag matching v\*.\*.\* is pushed. We did it! ~~We're
done!~~
Let's add it to an existing project (say, [pict-rs](https://git.asonix.dog/asonix/pict-rs))
```yaml,linenos
on:
push:
pull_request:
branches:
- main
jobs:
clippy:
runs-on: docker
container:
image: docker.io/asonix/rust-builder:latest-linux-arm32v7
steps:
-
name: Checkout pict-rs
uses: actions/checkout@v4
-
name: Clippy
run: |
cargo clippy --no-default-features -- -D warnings
cargo clippy --no-default-features --features io-uring -- -D warnings
```
And run it!
```
OCI runtime exec failed: exec failed: unable to start container process: exec: "node":
executable file not found in $PATH: unknown
```
Oh.
...what?
Hmm...
## The Problems
So actions/checkout@v4 depends on node to run, but my rust builder container doesn't have node in it
so... I can't checkout my code? Well let't just split this up a bit, then.
```yaml,linenos
on:
push:
pull_request:
branches:
- main
jobs:
clone:
runs-on: docker
container:
image: docker.io/node:20-bookworm
steps:
-
name: Checkout pict-rs
uses: actions/checkout@v4
clippy:
needs: [clone]
runs-on: docker
container:
image: docker.io/asonix/rust-builder:latest-linux-amd64
steps:
-
name: Clippy
run: |
cargo clippy --no-default-features -- -D warnings
cargo clippy --no-default-features --features io-uring -- -D warnings
```
Except that doesn't work. The cloned repo doesn't stick around between jobs. If we had more than one
runner the jobs might not even run on the same one! We could try solving this with artifacts but
wait... `actions/download-artifact@v4` also depends on node, so we can't run it in the rust-builder
container.
So we have Actions but we can't use them. How does github handle this? Well github's answer is to
install anything you could ever need into their default actions containers. Meaning node, go,
python, ruby, docker (oh, docker... we'll need that too) and more are all bundled into a 60GB image.
If you remember when we had a script that ran `sed` on the config earlier...
```bash
sed -i -e "s|labels: \[\]|labels: \[\"docker:docker://bash:alpine3.19\"\]|" config.yml ;
```
We were setting a value in the Forgejo runner's config to provide our runners with default
containers. We started with `bash` on `alpine`. While that particular container is very small and
doesn't take long to download, it doesn't contain the majority of things that actions expect to
exist.
In order to build pict-rs we need rust, and not just any rust but a rust that is capable of
cross-building (I target armv7, aarch64, and x86_64 with musl libc). In order to clone pict-rs, use
the actions cache, use the actions artifacts, and more we need nodejs. In order to build docker
containers we need docker and qemu. The container image we need to have or make to run our CI is now
nontrivial.
As a proof of concept, I first wrote my actions where I installed everything by hand. I started with
the node:20-bookworm image from dockerhub. I had steps to apt-get install docker, download rustup
and install it, add the proper targets, add clippy, add cargo-binstall,
`cargo binstall cargo-zigbuild`, and install zig. While this worked, it took a while just in the
setup phase, which isn't what we want for CI.
> My previous CI for pict-rs used my `rust-builder` image, which doesn't actually use
cargo-zigbuild. I opted to use zig's linker for pict-rs in Forgejo Actions because I knew it
would be easier than manually constructing a cross-compile environment. It would also enable me
to use a single container to build for any platform, rather than my previous CI which had a
unique container for each platform I targeted.
So I wrote a bit of caching. I had used an action to install zig, and that action cached zig on the
runner. I wrote my own caching layer for all the rustup and cargo bits. That sped things up as well,
but it still meant using space in the runner cache, and potentially installing everything again on a
cache miss. In this process, I also hit the github rate limit for downloading cargo-zigbuild via
cargo-binstall, meaning I had to start compiling it from crates.io instead (which doesn't take too
long, but it's still longer than downloading a binary).
> As an aside, I had to set `DOCKER_HOST: tcp://docker-in-docker:2375` as an environment variable in
the runner `config.yml` file so that my use of docker in the actions container would find my
docker-in-docker daemon.
## Giving In
I decided I needed a universal base container image to run my CI the way github does it, because
it's the only way that makes sense for their CI system. If all the actions people write are going to
expect me to have things installed, then I better have them installed. You can find the actions
workflow I use to produce my base image in my
[actions-base-image repository](https://git.asonix.dog/asonix/actions-base-image). I'm sure that in
the future I will encounter more actions that fail to run on this image and I will need to update it
to add more dependencies.
I also wrote another caching action, simpler now than before since all the rust, zig, and docker
bits are baked into the base image. You can find it [here](https://git.asonix.dog/asonix/actions) in
the `cache-rust-dependencies` folder. It's extremely basic but saves me a download from crates.io
for each job pict-rs runs.
## So?
Am I happy with Forgejo Actions? Not really. I think the design of Actions is pretty bad for the
Forgejo Actions case where you control the runners yourself. On github it's fine, since github
manages the 60GB image behind the scenes where you never need to think about it. Outside of github
it's less ideal. I'm still going to migrate all my projects to it now that I have everything
working and a not-too-big base image for myself (it's 1GB).
I hope anyone else struggling with Actions (github, gitea, forgejo, or otherwise) gains some insight
from this post. It's not like I built this blog in the first place to be able to put this online or
anything. Let's hope now that I've written all this that I don't need to update my base image to
publish this to [garage](https://garagehq.deuxfleurs.fr/).

9
content/_index.md Normal file
View file

@ -0,0 +1,9 @@
+++
paginate_by = 15
title = "All blog posts"
sort_by = "date"
template = "index.html"
page_template = "blog-page.html"
+++
> List of all *[tags](/tags)*

61
flake.lock Normal file
View file

@ -0,0 +1,61 @@
{
"nodes": {
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1705309234,
"narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1707268954,
"narHash": "sha256-2en1kvde3cJVc3ZnTy8QeD2oKcseLFjYPLKhIGDanQ0=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "f8e2ebd66d097614d51a56a755450d4ae1632df1",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

28
flake.nix Normal file
View file

@ -0,0 +1,28 @@
{
description = "Blog";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
flake-utils.url = "github:numtide/flake-utils";
};
outputs = { self, nixpkgs, flake-utils }:
flake-utils.lib.eachDefaultSystem (system:
let
pkgs = import nixpkgs {
inherit system;
};
in
{
packages = {
default = pkgs.hello;
};
devShell = with pkgs; mkShell {
nativeBuildInputs = [
zola
taplo
];
};
});
}

View file

@ -0,0 +1,560 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>author</key>
<string>Template: Chris Kempson, Scheme: Chris Kempson (http://chriskempson.com)</string>
<key>name</key>
<string>Base16 Eighties</string>
<key>semanticClass</key>
<string>theme.base16.eighties</string>
<key>colorSpaceName</key>
<string>sRGB</string>
<key>gutterSettings</key>
<dict>
<key>background</key>
<string>#393939</string>
<key>divider</key>
<string>#393939</string>
<key>foreground</key>
<string>#747369</string>
<key>selectionBackground</key>
<string>#515151</string>
<key>selectionForeground</key>
<string>#a09f93</string>
</dict>
<key>settings</key>
<array>
<dict>
<key>settings</key>
<dict>
<key>background</key>
<string>#2d2d2d</string>
<key>caret</key>
<string>#d3d0c8</string>
<key>foreground</key>
<string>#d3d0c8</string>
<key>invisibles</key>
<string>#747369</string>
<key>lineHighlight</key>
<string>#74736955</string>
<key>selection</key>
<string>#515151</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Text</string>
<key>scope</key>
<string>variable.parameter.function</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#d3d0c8</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Comments</string>
<key>scope</key>
<string>comment, punctuation.definition.comment</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#747369</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Punctuation</string>
<key>scope</key>
<string>punctuation.definition.string, punctuation.definition.variable, punctuation.definition.string, punctuation.definition.parameters, punctuation.definition.string, punctuation.definition.array</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#d3d0c8</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Delimiters</string>
<key>scope</key>
<string>none</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#d3d0c8</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Operators</string>
<key>scope</key>
<string>keyword.operator</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#d3d0c8</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Keywords</string>
<key>scope</key>
<string>keyword</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#cc99cc</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Variables</string>
<key>scope</key>
<string>variable</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#f2777a</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Functions</string>
<key>scope</key>
<string>entity.name.function, meta.require, support.function.any-method, variable.function, variable.annotation, support.macro</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#6699cc</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Labels</string>
<key>scope</key>
<string>entity.name.label</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#d27b53</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Classes</string>
<key>scope</key>
<string>support.class, entity.name.class, entity.name.type.class</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#ffcc66</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Classes</string>
<key>scope</key>
<string>meta.class</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#f2f0ec</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Methods</string>
<key>scope</key>
<string>keyword.other.special-method</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#6699cc</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Storage</string>
<key>scope</key>
<string>storage</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#cc99cc</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Support</string>
<key>scope</key>
<string>support.function</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#66cccc</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Strings, Inherited Class</string>
<key>scope</key>
<string>string, constant.other.symbol, entity.other.inherited-class</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#99cc99</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Integers</string>
<key>scope</key>
<string>constant.numeric</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#f99157</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Floats</string>
<key>scope</key>
<string>none</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#f99157</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Boolean</string>
<key>scope</key>
<string>none</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#f99157</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Constants</string>
<key>scope</key>
<string>constant</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#f99157</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Tags</string>
<key>scope</key>
<string>entity.name.tag</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#f2777a</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Attributes</string>
<key>scope</key>
<string>entity.other.attribute-name</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#f99157</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Attribute IDs</string>
<key>scope</key>
<string>entity.other.attribute-name.id, punctuation.definition.entity</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#6699cc</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Selector</string>
<key>scope</key>
<string>meta.selector</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#cc99cc</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Values</string>
<key>scope</key>
<string>none</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#f99157</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Headings</string>
<key>scope</key>
<string>markup.heading punctuation.definition.heading, entity.name.section</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#6699cc</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Units</string>
<key>scope</key>
<string>keyword.other.unit</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#f99157</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Bold</string>
<key>scope</key>
<string>markup.bold, punctuation.definition.bold</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string>bold</string>
<key>foreground</key>
<string>#ffcc66</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Italic</string>
<key>scope</key>
<string>markup.italic, punctuation.definition.italic</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string>italic</string>
<key>foreground</key>
<string>#cc99cc</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Code</string>
<key>scope</key>
<string>markup.raw.inline</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#99cc99</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Link Text</string>
<key>scope</key>
<string>string.other.link, punctuation.definition.string.end.markdown, punctuation.definition.string.begin.markdown</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#f2777a</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Link Url</string>
<key>scope</key>
<string>meta.link</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#f99157</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Lists</string>
<key>scope</key>
<string>markup.list</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#f2777a</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Quotes</string>
<key>scope</key>
<string>markup.quote</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#f99157</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Separator</string>
<key>scope</key>
<string>meta.separator</string>
<key>settings</key>
<dict>
<key>background</key>
<string>#515151</string>
<key>foreground</key>
<string>#d3d0c8</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Inserted</string>
<key>scope</key>
<string>markup.inserted</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#99cc99</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Deleted</string>
<key>scope</key>
<string>markup.deleted</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#f2777a</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Changed</string>
<key>scope</key>
<string>markup.changed</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#cc99cc</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Colors</string>
<key>scope</key>
<string>constant.other.color</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#66cccc</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Regular Expressions</string>
<key>scope</key>
<string>string.regexp</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#66cccc</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Escape Characters</string>
<key>scope</key>
<string>constant.character.escape</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#66cccc</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Embedded</string>
<key>scope</key>
<string>punctuation.section.embedded, variable.interpolation</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#cc99cc</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Illegal</string>
<key>scope</key>
<string>invalid.illegal</string>
<key>settings</key>
<dict>
<key>background</key>
<string>#f2777a</string>
<key>foreground</key>
<string>#f2f0ec</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Broken</string>
<key>scope</key>
<string>invalid.broken</string>
<key>settings</key>
<dict>
<key>background</key>
<string>#f99157</string>
<key>foreground</key>
<string>#2d2d2d</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Deprecated</string>
<key>scope</key>
<string>invalid.deprecated</string>
<key>settings</key>
<dict>
<key>background</key>
<string>#d27b53</string>
<key>foreground</key>
<string>#f2f0ec</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Unimplemented</string>
<key>scope</key>
<string>invalid.unimplemented</string>
<key>settings</key>
<dict>
<key>background</key>
<string>#747369</string>
<key>foreground</key>
<string>#f2f0ec</string>
</dict>
</dict>
</array>
<key>uuid</key>
<string>uuid</string>
</dict>
</plist>

View file

@ -0,0 +1,561 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>author</key>
<string>Carlo Abelli</string>
<key>name</key>
<string>Base16 Equilibrium Light</string>
<key>semanticClass</key>
<string>base16.equilibrium.light</string>
<key>colorSpaceName</key>
<string>sRGB</string>
<key>gutterSettings</key>
<dict>
<key>background</key>
<string>#e7e2d9</string>
<key>divider</key>
<string>#e7e2d9</string>
<key>foreground</key>
<string>#73777f</string>
<key>selectionBackground</key>
<string>#d8d4cb</string>
<key>selectionForeground</key>
<string>#5a5f66</string>
</dict>
<key>settings</key>
<array>
<dict>
<key>settings</key>
<dict>
<key>background</key>
<string>#f5f0e7</string>
<key>caret</key>
<string>#43474e</string>
<key>foreground</key>
<string>#43474e</string>
<key>invisibles</key>
<string>#73777f</string>
<key>lineHighlight</key>
<string>#73777f55</string>
<key>selection</key>
<string>#d8d4cb</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Text</string>
<key>scope</key>
<string>variable.parameter.function</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#43474e</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Comments</string>
<key>scope</key>
<string>comment, punctuation.definition.comment</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#73777f</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Punctuation</string>
<key>scope</key>
<string>punctuation.definition.string, punctuation.definition.variable, punctuation.definition.string, punctuation.definition.parameters, punctuation.definition.string, punctuation.definition.array</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#43474e</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Delimiters</string>
<key>scope</key>
<string>none</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#43474e</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Operators</string>
<key>scope</key>
<string>keyword.operator</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#43474e</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Keywords</string>
<key>scope</key>
<string>keyword</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#4e66b6</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Variables</string>
<key>scope</key>
<string>variable</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#d02023</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Functions</string>
<key>scope</key>
<string>entity.name.function, meta.require, support.function.any-method</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#0073b5</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Labels</string>
<key>scope</key>
<string>entity.name.label</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#c42775</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Classes</string>
<key>scope</key>
<string>support.class, entity.name.class, entity.name.type.class</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#9d6f00</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Classes</string>
<key>scope</key>
<string>meta.class</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#181c22</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Methods</string>
<key>scope</key>
<string>keyword.other.special-method</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#0073b5</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Storage</string>
<key>scope</key>
<string>storage</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#4e66b6</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Support</string>
<key>scope</key>
<string>support.function</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#007a72</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Strings, Inherited Class</string>
<key>scope</key>
<string>string, constant.other.symbol, entity.other.inherited-class</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#637200</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Integers</string>
<key>scope</key>
<string>constant.numeric</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#bf3e05</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Floats</string>
<key>scope</key>
<string>none</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#bf3e05</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Boolean</string>
<key>scope</key>
<string>none</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#bf3e05</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Constants</string>
<key>scope</key>
<string>constant</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#bf3e05</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Tags</string>
<key>scope</key>
<string>entity.name.tag</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#d02023</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Attributes</string>
<key>scope</key>
<string>entity.other.attribute-name</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#bf3e05</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Attribute IDs</string>
<key>scope</key>
<string>entity.other.attribute-name.id, punctuation.definition.entity</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#0073b5</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Selector</string>
<key>scope</key>
<string>meta.selector</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#4e66b6</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Values</string>
<key>scope</key>
<string>none</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#bf3e05</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Headings</string>
<key>scope</key>
<string>markup.heading punctuation.definition.heading, entity.name.section</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#0073b5</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Units</string>
<key>scope</key>
<string>keyword.other.unit</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#bf3e05</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Bold</string>
<key>scope</key>
<string>markup.bold, punctuation.definition.bold</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string>bold</string>
<key>foreground</key>
<string>#9d6f00</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Italic</string>
<key>scope</key>
<string>markup.italic, punctuation.definition.italic</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string>italic</string>
<key>foreground</key>
<string>#4e66b6</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Code</string>
<key>scope</key>
<string>markup.raw.inline</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#637200</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Link Text</string>
<key>scope</key>
<string>string.other.link, punctuation.definition.string.end.markdown</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#d02023</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Link Url</string>
<key>scope</key>
<string>meta.link</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#bf3e05</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Lists</string>
<key>scope</key>
<string>markup.list</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#d02023</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Quotes</string>
<key>scope</key>
<string>markup.quote</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#bf3e05</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Separator</string>
<key>scope</key>
<string>meta.separator</string>
<key>settings</key>
<dict>
<key>background</key>
<string>#d8d4cb</string>
<key>foreground</key>
<string>#43474e</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Inserted</string>
<key>scope</key>
<string>markup.inserted</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#637200</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Deleted</string>
<key>scope</key>
<string>markup.deleted</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#d02023</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Changed</string>
<key>scope</key>
<string>markup.changed</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#4e66b6</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Colors</string>
<key>scope</key>
<string>constant.other.color</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#007a72</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Regular Expressions</string>
<key>scope</key>
<string>string.regexp</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#007a72</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Escape Characters</string>
<key>scope</key>
<string>constant.character.escape</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#007a72</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Embedded</string>
<key>scope</key>
<string>punctuation.section.embedded, variable.interpolation</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#c42775</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Illegal</string>
<key>scope</key>
<string>invalid.illegal</string>
<key>settings</key>
<dict>
<key>background</key>
<string>#d02023</string>
<key>foreground</key>
<string>#181c22</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Broken</string>
<key>scope</key>
<string>invalid.broken</string>
<key>settings</key>
<dict>
<key>background</key>
<string>#bf3e05</string>
<key>foreground</key>
<string>#f5f0e7</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Deprecated</string>
<key>scope</key>
<string>invalid.deprecated</string>
<key>settings</key>
<dict>
<key>background</key>
<string>#c42775</string>
<key>foreground</key>
<string>#181c22</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Unimplemented</string>
<key>scope</key>
<string>invalid.unimplemented</string>
<key>settings</key>
<dict>
<key>background</key>
<string>#73777f</string>
<key>foreground</key>
<string>#181c22</string>
</dict>
</dict>
</array>
<key>uuid</key>
<string>uuid</string>
</dict>
</plist>

BIN
static/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

5
static/icons.svg Normal file
View file

@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg">
<symbol id="rss" viewBox="0 0 24 24"><rect x="0" y="0" fill="none" stroke="none" />
<path fill="currentColor" d="M6.18 15.64a2.18 2.18 0 0 1 2.18 2.18C8.36 19 7.38 20 6.18 20C5 20 4 19 4 17.82a2.18 2.18 0 0 1 2.18-2.18M4 4.44A15.56 15.56 0 0 1 19.56 20h-2.83A12.73 12.73 0 0 0 4 7.27V4.44m0 5.66a9.9 9.9 0 0 1 9.9 9.9h-2.83A7.07 7.07 0 0 0 4 12.93V10.1Z"/>
</symbol>
</svg>

After

Width:  |  Height:  |  Size: 423 B

BIN
static/pinkliom-small2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

209
static/styles.css Normal file
View file

@ -0,0 +1,209 @@
* {
box-sizing: border-box;
}
body {
background-color: #fff;
background-image: url('/pinkliom-small2.png');
background-position: bottom right;
background-repeat: no-repeat;
color: #000;
display: flex;
flex-direction: row;
font-family: sans-serif;
height: 100vh;
margin: 0;
}
.sidebar {
background-color: #f5f5f5;
border-right: 1px solid #dddddd;
color: #000;
display: flex;
flex-direction: column;
justify-content: space-between;
min-height: 100%;
overflow-y: hidden;
padding: 16px;
}
.sidebar a,
.sidebar a:visited {
color: #232323;
}
.sidebar a:focus,
.sidebar a:hover,
.sidebar a:visited:focus,
.sidebar a:visited:hover {
color: #000;
}
header ul {
list-style: none;
padding: 0;
margin: 0;
}
header a {
display: block;
font-size: 20px;
font-weight: 600;
padding: 2px 0;
}
pre {
overflow-x: auto;
}
code {
font-size: 16px;
}
main {
flex: 1;
min-width: 500px;
max-height: 100%;
overflow-y: auto;
}
main a {
font-weight: 500;
}
main a,
main a:visited {
color: #e10862;
}
main a:focus,
main a:hover,
main a:visited:focus,
main a:visited:hover {
color: #a90649;
}
.overlay {
backdrop-filter: blur(8px);
background-color: #ffffffcb;
max-width: 800px;
min-height: 100%;
}
section {
padding: 16px;
}
.web-environment-integrity-message {
display: none;
}
section.web-environment-integrity-message {
background-color: lightyellow;
color: #000;
}
main ul {
list-style: none;
}
main ul li:hover::marker {
content: '# ';
color: #a90649;
}
main blockquote {
border-left: 3px solid #e10862;
padding: 0 16px;
margin: 0 21px;
}
.icon {
display: inline-block;
}
.icon svg {
height: 2em;
width: 2em;
vertical-align: middle;
}
footer p {
max-width: 180px;
}
@media (prefers-color-scheme: dark) {
body {
background-color: #232323;
color: #e5e5e5;
}
.overlay {
background-color: #232323dd;
}
.sidebar {
background-color: #1a1a1a;
border-right: 1px solid #333333;
color: #fff;
}
.sidebar a,
.sidebar a:visited {
color: #e5e5e5;
}
.sidebar a:focus,
.sidebar a:hover,
.sidebar a:visited:focus,
.sidebar a:visited:hover {
color: #fff;
}
main a,
main a:visited {
color: #e10862;
}
main a:focus,
main a:hover,
main a:visited:focus,
main a:visited:hover {
color: #f83687;
}
main ul li::marker {
content: '# ';
color: #e10862;
}
main ul li:hover::marker {
content: '> ';
color: #f83687;
}
main blockquote {
border-left: 3px solid #e10862;
}
}
@media (max-width: 700px) {
body {
display: flex;
flex-direction: column-reverse;
min-height: 100vh;
height: auto;
}
.sidebar {
background-image: url('/pinkliom-small2.png');
background-repeat: no-repeat;
background-position: bottom right;
min-height: auto;
width: 100%;
overflow-x: auto;
}
main {
min-width: 300px;
max-height: none;
}
}

View file

@ -0,0 +1,151 @@
/*
* theme "Base16 Eighties" generated by syntect
*/
.z-code {
color: #d3d0c8;
background-color: #2d2d2d;
}
.z-variable.z-parameter.z-function {
color: #d3d0c8;
}
.z-comment, .z-punctuation.z-definition.z-comment {
color: #747369;
}
.z-punctuation.z-definition.z-string, .z-punctuation.z-definition.z-variable, .z-punctuation.z-definition.z-string, .z-punctuation.z-definition.z-parameters, .z-punctuation.z-definition.z-string, .z-punctuation.z-definition.z-array {
color: #d3d0c8;
}
.z-none {
color: #d3d0c8;
}
.z-keyword.z-operator {
color: #d3d0c8;
}
.z-keyword {
color: #cc99cc;
}
.z-variable {
color: #f2777a;
}
.z-entity.z-name.z-function, .z-meta.z-require, .z-support.z-function.z-any-method, .z-variable.z-function, .z-variable.z-annotation, .z-support.z-macro {
color: #6699cc;
}
.z-entity.z-name.z-label {
color: #d27b53;
}
.z-support.z-class, .z-entity.z-name.z-class, .z-entity.z-name.z-type.z-class {
color: #ffcc66;
}
.z-meta.z-class {
color: #f2f0ec;
}
.z-keyword.z-other.z-special-method {
color: #6699cc;
}
.z-storage {
color: #cc99cc;
}
.z-support.z-function {
color: #66cccc;
}
.z-string, .z-constant.z-other.z-symbol, .z-entity.z-other.z-inherited-class {
color: #99cc99;
}
.z-constant.z-numeric {
color: #f99157;
}
.z-none {
color: #f99157;
}
.z-none {
color: #f99157;
}
.z-constant {
color: #f99157;
}
.z-entity.z-name.z-tag {
color: #f2777a;
}
.z-entity.z-other.z-attribute-name {
color: #f99157;
}
.z-entity.z-other.z-attribute-name.z-id, .z-punctuation.z-definition.z-entity {
color: #6699cc;
}
.z-meta.z-selector {
color: #cc99cc;
}
.z-none {
color: #f99157;
}
.z-markup.z-heading .z-punctuation.z-definition.z-heading, .z-entity.z-name.z-section {
color: #6699cc;
}
.z-keyword.z-other.z-unit {
color: #f99157;
}
.z-markup.z-bold, .z-punctuation.z-definition.z-bold {
color: #ffcc66;
font-weight: bold;
}
.z-markup.z-italic, .z-punctuation.z-definition.z-italic {
color: #cc99cc;
font-style: italic;
}
.z-markup.z-raw.z-inline {
color: #99cc99;
}
.z-string.z-other.z-link, .z-punctuation.z-definition.z-string.z-end.z-markdown, .z-punctuation.z-definition.z-string.z-begin.z-markdown {
color: #f2777a;
}
.z-meta.z-link {
color: #f99157;
}
.z-markup.z-list {
color: #f2777a;
}
.z-markup.z-quote {
color: #f99157;
}
.z-meta.z-separator {
color: #d3d0c8;
background-color: #515151;
}
.z-markup.z-inserted {
color: #99cc99;
}
.z-markup.z-deleted {
color: #f2777a;
}
.z-markup.z-changed {
color: #cc99cc;
}
.z-constant.z-other.z-color {
color: #66cccc;
}
.z-string.z-regexp {
color: #66cccc;
}
.z-constant.z-character.z-escape {
color: #66cccc;
}
.z-punctuation.z-section.z-embedded, .z-variable.z-interpolation {
color: #cc99cc;
}
.z-invalid.z-illegal {
color: #f2f0ec;
background-color: #f2777a;
}
.z-invalid.z-broken {
color: #2d2d2d;
background-color: #f99157;
}
.z-invalid.z-deprecated {
color: #f2f0ec;
background-color: #d27b53;
}
.z-invalid.z-unimplemented {
color: #f2f0ec;
background-color: #747369;
}

View file

@ -0,0 +1,151 @@
/*
* theme "Base16 Equilibrium Light" generated by syntect
*/
.z-code {
color: #43474e;
background-color: #f5f0e7;
}
.z-variable.z-parameter.z-function {
color: #43474e;
}
.z-comment, .z-punctuation.z-definition.z-comment {
color: #73777f;
}
.z-punctuation.z-definition.z-string, .z-punctuation.z-definition.z-variable, .z-punctuation.z-definition.z-string, .z-punctuation.z-definition.z-parameters, .z-punctuation.z-definition.z-string, .z-punctuation.z-definition.z-array {
color: #43474e;
}
.z-none {
color: #43474e;
}
.z-keyword.z-operator {
color: #43474e;
}
.z-keyword {
color: #4e66b6;
}
.z-variable {
color: #d02023;
}
.z-entity.z-name.z-function, .z-meta.z-require, .z-support.z-function.z-any-method {
color: #0073b5;
}
.z-entity.z-name.z-label {
color: #c42775;
}
.z-support.z-class, .z-entity.z-name.z-class, .z-entity.z-name.z-type.z-class {
color: #9d6f00;
}
.z-meta.z-class {
color: #181c22;
}
.z-keyword.z-other.z-special-method {
color: #0073b5;
}
.z-storage {
color: #4e66b6;
}
.z-support.z-function {
color: #007a72;
}
.z-string, .z-constant.z-other.z-symbol, .z-entity.z-other.z-inherited-class {
color: #637200;
}
.z-constant.z-numeric {
color: #bf3e05;
}
.z-none {
color: #bf3e05;
}
.z-none {
color: #bf3e05;
}
.z-constant {
color: #bf3e05;
}
.z-entity.z-name.z-tag {
color: #d02023;
}
.z-entity.z-other.z-attribute-name {
color: #bf3e05;
}
.z-entity.z-other.z-attribute-name.z-id, .z-punctuation.z-definition.z-entity {
color: #0073b5;
}
.z-meta.z-selector {
color: #4e66b6;
}
.z-none {
color: #bf3e05;
}
.z-markup.z-heading .z-punctuation.z-definition.z-heading, .z-entity.z-name.z-section {
color: #0073b5;
}
.z-keyword.z-other.z-unit {
color: #bf3e05;
}
.z-markup.z-bold, .z-punctuation.z-definition.z-bold {
color: #9d6f00;
font-weight: bold;
}
.z-markup.z-italic, .z-punctuation.z-definition.z-italic {
color: #4e66b6;
font-style: italic;
}
.z-markup.z-raw.z-inline {
color: #637200;
}
.z-string.z-other.z-link, .z-punctuation.z-definition.z-string.z-end.z-markdown {
color: #d02023;
}
.z-meta.z-link {
color: #bf3e05;
}
.z-markup.z-list {
color: #d02023;
}
.z-markup.z-quote {
color: #bf3e05;
}
.z-meta.z-separator {
color: #43474e;
background-color: #d8d4cb;
}
.z-markup.z-inserted {
color: #637200;
}
.z-markup.z-deleted {
color: #d02023;
}
.z-markup.z-changed {
color: #4e66b6;
}
.z-constant.z-other.z-color {
color: #007a72;
}
.z-string.z-regexp {
color: #007a72;
}
.z-constant.z-character.z-escape {
color: #007a72;
}
.z-punctuation.z-section.z-embedded, .z-variable.z-interpolation {
color: #c42775;
}
.z-invalid.z-illegal {
color: #181c22;
background-color: #d02023;
}
.z-invalid.z-broken {
color: #f5f0e7;
background-color: #bf3e05;
}
.z-invalid.z-deprecated {
color: #181c22;
background-color: #c42775;
}
.z-invalid.z-unimplemented {
color: #181c22;
background-color: #73777f;
}

46
templates/base.html Normal file
View file

@ -0,0 +1,46 @@
<!DOCTYPE html>
<html lang="en">
<head>
{% include "head.html" %}
</head>
<body>
<div class="sidebar">
<header>
{% include "header.html" %}
</header>
<footer>
{% include "footer.html" %}
</footer>
</div>
<main>
<div class="overlay">
<section class="web-environment-integrity-message">
<h2>Your browser contains Google DRM</h2>
<article>
<p>
"Web Environment Integrity" is a Google euphemism for a DRM that is designed to
prevent ad-blocking. In support of an open web, this website does not function with
this DRM. Please install a browser such as
<a href="https://www.mozilla.org/en-US/firefox/new/">Firefox</a> that respects your
freedom and supports ad blockers.
</p>
<p>
Please note that although other browsers such as Vivaldi, Opera, Microsoft Edge,
Brave, and Chromium exist, they are all built from the same Google Chromium codebase
and all inherit the problems of Google's web dominance. The only real options outside
of Chrome are Firefox and Safari.
</p>
</article>
</section>
{% block content %}
{% endblock content %}
</div>
</main>
<script>
if (navigator.getEnvironmentIntegrity !== undefined) {
document.querySelectorAll('.web-environment-integrity-message').forEach((elem) => elem.setAttribute("style", "display: block;"));
document.querySelectorAll('.site-content').forEach((elem) => elem.setAttribute("style", "display: none;"));
}
</script>
</body>
</html>

51
templates/blog-page.html Normal file
View file

@ -0,0 +1,51 @@
{% extends "base.html" %}
{% block content %}
<section class="site-content">
<div><a href="..">&lt;- List</a></div>
<h1>{{ page.title }}</h1>
<time datetime="{{ page.date }}">Published on: <span class="meta-data">{{ page.date }}</span></time>
{% if config.extra.author and config.extra.display_author == true %}
<address rel="author">By <span class="meta-data">{{config.extra.author}}</span></address>
{% endif %}
{% if page.toc and page.extra.toc %}
<h2>Table of contents</h2>
<ul>
{% for h1 in page.toc %}
<li>
<a href="{{ h1.permalink | safe }}">{{ h1.title }}</a>
{% if h1.children %}
<ul>
{% for h2 in h1.children %}
<li>
<a href="{{ h2.permalink | safe }}">{{ h2.title }}</a>
<ul>
{% for h3 in h2.children %}
<li>
<a href="{{ h3.permalink | safe }}">{{ h3.title }}</a>
</li>
{% endfor %}
</ul>
</li>
{% endfor %}
</ul>
{% endif %}
</li>
{% endfor %}
</ul>
{% endif %}
{{ page.content | safe }}
</section>
<section class="site-content">
<p class="tags-data">
{% if page.taxonomies.tags %}
{% for tag in page.taxonomies.tags %}
<a href="/tags/{{ tag | slugify }}">#{{ tag }}</a>
{% endfor %}
{% endif %}
</p>
</section>
{% endblock content %}

13
templates/footer.html Normal file
View file

@ -0,0 +1,13 @@
<div>
<p class="site-content">
favicon by <a target="_blank" href="https://weirder.earth/@dzuk">dzuk</a>. background image by ruca.
</p>
<p class="site-content">
{% if config.generate_feed %}
<a class="icon" target="_blank" rel="noopener noreferrer" href="{{ get_url(path="atom.xml", trailing_slash=false) }}" title="Subscribe via RSS for updates.">
Subscribe via RSS
<svg><use href="{{ get_url(path='icons.svg#rss', trailing_slash=false) | safe }}"></use></svg>
</a>
{% endif %}
</p>
</div>

96
templates/head.html Normal file
View file

@ -0,0 +1,96 @@
<meta charset="UTF-8">
<meta content="IE=edge" http-equiv="X-UA-Compatible"/>
<meta content="text/html; charset=UTF-8" http-equiv="content-type"/>
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
<meta name="robots" content="index, follow">
{% if page.title %}
{% set title = page.title %}
{% elif section.title %}
{% set title = section.title %}
{% elif config.title %}
{% set title = config.title %}
{% endif %}
{% if page.extra.author %}
{% set author = page.extra.author %}
{% elif section.extra.author %}
{% set author = section.extra.author %}
{% elif config.extra.author %}
{% set author = config.extra.author %}
{% endif %}
{% if page.description %}
{% set description = page.description | truncate(length=150) %}
{% elif section.description %}
{% set description = section.description | truncate(length=150) %}
{% elif config.description %}
{% set description = config.description | truncate(length=150) %}
{% endif %}
{% if page.extra.image %}
{% set image = get_url(path=page.extra.image, trailing_slash=false) %}
{% elif section.extra.image %}
{% set image = get_url(path=section.extra.image, trailing_slash=false) %}
{% elif config.extra.favicon %}
{% set image = get_url(path=config.extra.favicon, trailing_slash=false) %}
{% endif %}
{% if page.permalink %}
{% set url = page.permalink %}
{% elif section.permalink %}
{% set url = section.permalink %}
{% elif config.base_url %}
{% set url = config.base_url %}
{% endif %}
{% if title %}
<title>{{ title }}</title>
{% endif %}
{% block metatags %}
{% if title %}
<meta name="title" content="{{ title }}">
{% endif %}
{% if author %}
<meta name="author" content="{{ author }}">
{% endif %}
{% if description %}
<meta name="description" content="{{ description }}">
{% endif %}
<meta property="og:type" content="website">
<meta property="og:url" content="{{ url | safe }}">
{% if title %}
<meta property="og:site_name" content="{{ config.title }}">
{% endif %}
{% if title %}
<meta property="og:title" content="{{ title }}">
{% endif %}
{% if description %}
<meta property="og:description" content="{{ description }}">
{% endif %}
{% if image %}
<meta property="og:image" content="{{ image }}">
{% endif %}
{% set twitter_card = config.extra.twitter_card | default(value=true) %}
{% if twitter_card != false %}
<meta property="twitter:card" content="summary_large_image">
<meta property="twitter:url" content="{{ url | safe }}">
{% if title %}
<meta property="twitter:title" content="{{ title }}">
{% endif %}
{% if description %}
<meta property="twitter:description" content="{{ description }}">
{% endif %}
{% if image %}
<meta property="twitter:image" content="{{ image }}">
{% endif %}
{% endif %}
<link rel="canonical" href="{{ url | safe }}">
{% if image %}
<link rel="shortcut icon" type="image/x-icon" href="{{ get_url(path=config.extra.favicon, trailing_slash=false) }}">
{% endif %}
{% endblock metatags %}
{% if config.generate_feed %}
{% block feed %}
<link rel="alternate" type="application/atom+xml" title="RSS" href="{{ get_url(path="atom.xml", trailing_slash=false) }}">
{% endblock feed %}
{% endif %}
{% block css %}
<link rel="stylesheet" type="text/css" href="/styles.css" />
<link rel="stylesheet" type="text/css" href="/syntax-theme-dark.css" media="(prefers-color-scheme: dark)" />
<link rel="stylesheet" type="text/css" href="/syntax-theme-light.css" media="(prefers-color-scheme: light)" />
{% endblock css %}

14
templates/header.html Normal file
View file

@ -0,0 +1,14 @@
{% if config.extra.header_nav %}
<nav>
<h2>Links</h2>
<ul class="site-content">
{% for nav_item in config.extra.header_nav %}
<li>
<a href="{{ nav_item.url }}">
{{ nav_item.name }}
</a>
</li>
{% endfor %}
</ul>
</nav>
{% endif %}

27
templates/index.html Normal file
View file

@ -0,0 +1,27 @@
{% extends "base.html" %}
{% block content %}
<section class="site-content">
<h1>{{ section.title }}</h1>
{{ section.content | safe }}
{% if paginator %}
{% set pages = paginator.pages %}
{% else %}
{% set pages = section.pages %}
{% endif %}
<ul class="title-list">
{% for page in pages %}
<li>
<a href="{{ page.permalink | safe }}">{{ page.title }}</a>
</li>
{% endfor %}
</ul>
{% if paginator %}
<div class="meta-data">{% if paginator.previous %}<a href="{{ paginator.first }}"></a> &nbsp <a href="{{ paginator.previous }}"><</a>{% endif %} &nbsp {{ paginator.current_index }} / {{ paginator.number_pagers }} &nbsp {% if paginator.next %}<a href="{{ paginator.next }}">></a> &nbsp <a href="{{ paginator.last }}"></a>{% endif %}</div>
</section>
{% endif %}
{% endblock content %}

12
templates/tags/list.html Normal file
View file

@ -0,0 +1,12 @@
{% extends "base.html" %}
{% block content %}
<section class="site-content">
<h1>{{ taxonomy.name }}</h1>
<p>
{% for term in terms %}
<a href="{{ term.permalink | safe }}">#{{ term.name }}</a>[{{ term.pages | length }}]
{% endfor %}
</p>
</section>
{% endblock content %}

View file

@ -0,0 +1,22 @@
{% extends "base.html" %}
{% block content %}
<section class="site-content">
<h1>{{ term.name }}</h1>
{% if paginator %}
{% set pages = paginator.pages %}
{% else %}
{% set pages = term.pages %}
{% endif %}
<ul>
{% for page in pages %}
<li>
<a href="{{ page.permalink | safe }}">{% if page.date %}{{ page.date }} - {% endif %}{{ page.title }}</a>
</li>
{% endfor %}
</ul>
{% if paginator %}
<p>{% if paginator.previous %}<a href="{{ paginator.first }}">&lt;&lt; First</a> <a href="{{ paginator.previous }}">&lt; Previous</a>{% endif %} [{{ paginator.current_index }}/{{ paginator.number_pagers }}] {% if paginator.next %}<a href="{{ paginator.next }}">Next &gt;</a> <a href="{{ paginator.last }}">Last &gt;&gt;</a>{% endif %}</p>
{% endif %}
</section>
{% endblock content %}