commit 842dc3534d6243c86c11a5d11f09f8ca45a9ecc2 Author: asonix Date: Sat Feb 10 01:08:15 2024 -0600 Mostly hijack anemone's HTML and my personal site's CSS diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..44bce82 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.envrc +.direnv +public diff --git a/config.toml b/config.toml new file mode 100644 index 0000000..dc722a7 --- /dev/null +++ b/config.toml @@ -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" diff --git a/content/001-forgejo-actions.md b/content/001-forgejo-actions.md new file mode 100644 index 0000000..08755c8 --- /dev/null +++ b/content/001-forgejo-actions.md @@ -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/). diff --git a/content/_index.md b/content/_index.md new file mode 100644 index 0000000..53b71fc --- /dev/null +++ b/content/_index.md @@ -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)* diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..587cbde --- /dev/null +++ b/flake.lock @@ -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 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..68b2015 --- /dev/null +++ b/flake.nix @@ -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 + ]; + }; + }); +} diff --git a/highlight_themes/base16-eighties.tmTheme b/highlight_themes/base16-eighties.tmTheme new file mode 100644 index 0000000..02eb7ab --- /dev/null +++ b/highlight_themes/base16-eighties.tmTheme @@ -0,0 +1,560 @@ + + + + + author + Template: Chris Kempson, Scheme: Chris Kempson (http://chriskempson.com) + name + Base16 Eighties + semanticClass + theme.base16.eighties + colorSpaceName + sRGB + gutterSettings + + background + #393939 + divider + #393939 + foreground + #747369 + selectionBackground + #515151 + selectionForeground + #a09f93 + + settings + + + settings + + background + #2d2d2d + caret + #d3d0c8 + foreground + #d3d0c8 + invisibles + #747369 + lineHighlight + #74736955 + selection + #515151 + + + + name + Text + scope + variable.parameter.function + settings + + foreground + #d3d0c8 + + + + name + Comments + scope + comment, punctuation.definition.comment + settings + + foreground + #747369 + + + + name + Punctuation + scope + punctuation.definition.string, punctuation.definition.variable, punctuation.definition.string, punctuation.definition.parameters, punctuation.definition.string, punctuation.definition.array + settings + + foreground + #d3d0c8 + + + + name + Delimiters + scope + none + settings + + foreground + #d3d0c8 + + + + name + Operators + scope + keyword.operator + settings + + foreground + #d3d0c8 + + + + name + Keywords + scope + keyword + settings + + foreground + #cc99cc + + + + name + Variables + scope + variable + settings + + foreground + #f2777a + + + + name + Functions + scope + entity.name.function, meta.require, support.function.any-method, variable.function, variable.annotation, support.macro + settings + + foreground + #6699cc + + + + name + Labels + scope + entity.name.label + settings + + foreground + #d27b53 + + + + name + Classes + scope + support.class, entity.name.class, entity.name.type.class + settings + + foreground + #ffcc66 + + + + name + Classes + scope + meta.class + settings + + foreground + #f2f0ec + + + + name + Methods + scope + keyword.other.special-method + settings + + foreground + #6699cc + + + + name + Storage + scope + storage + settings + + foreground + #cc99cc + + + + name + Support + scope + support.function + settings + + foreground + #66cccc + + + + name + Strings, Inherited Class + scope + string, constant.other.symbol, entity.other.inherited-class + settings + + foreground + #99cc99 + + + + name + Integers + scope + constant.numeric + settings + + foreground + #f99157 + + + + name + Floats + scope + none + settings + + foreground + #f99157 + + + + name + Boolean + scope + none + settings + + foreground + #f99157 + + + + name + Constants + scope + constant + settings + + foreground + #f99157 + + + + name + Tags + scope + entity.name.tag + settings + + foreground + #f2777a + + + + name + Attributes + scope + entity.other.attribute-name + settings + + foreground + #f99157 + + + + name + Attribute IDs + scope + entity.other.attribute-name.id, punctuation.definition.entity + settings + + foreground + #6699cc + + + + name + Selector + scope + meta.selector + settings + + foreground + #cc99cc + + + + name + Values + scope + none + settings + + foreground + #f99157 + + + + name + Headings + scope + markup.heading punctuation.definition.heading, entity.name.section + settings + + fontStyle + + foreground + #6699cc + + + + name + Units + scope + keyword.other.unit + settings + + foreground + #f99157 + + + + name + Bold + scope + markup.bold, punctuation.definition.bold + settings + + fontStyle + bold + foreground + #ffcc66 + + + + name + Italic + scope + markup.italic, punctuation.definition.italic + settings + + fontStyle + italic + foreground + #cc99cc + + + + name + Code + scope + markup.raw.inline + settings + + foreground + #99cc99 + + + + name + Link Text + scope + string.other.link, punctuation.definition.string.end.markdown, punctuation.definition.string.begin.markdown + settings + + foreground + #f2777a + + + + name + Link Url + scope + meta.link + settings + + foreground + #f99157 + + + + name + Lists + scope + markup.list + settings + + foreground + #f2777a + + + + name + Quotes + scope + markup.quote + settings + + foreground + #f99157 + + + + name + Separator + scope + meta.separator + settings + + background + #515151 + foreground + #d3d0c8 + + + + name + Inserted + scope + markup.inserted + settings + + foreground + #99cc99 + + + + name + Deleted + scope + markup.deleted + settings + + foreground + #f2777a + + + + name + Changed + scope + markup.changed + settings + + foreground + #cc99cc + + + + name + Colors + scope + constant.other.color + settings + + foreground + #66cccc + + + + name + Regular Expressions + scope + string.regexp + settings + + foreground + #66cccc + + + + name + Escape Characters + scope + constant.character.escape + settings + + foreground + #66cccc + + + + name + Embedded + scope + punctuation.section.embedded, variable.interpolation + settings + + foreground + #cc99cc + + + + name + Illegal + scope + invalid.illegal + settings + + background + #f2777a + foreground + #f2f0ec + + + + name + Broken + scope + invalid.broken + settings + + background + #f99157 + foreground + #2d2d2d + + + + name + Deprecated + scope + invalid.deprecated + settings + + background + #d27b53 + foreground + #f2f0ec + + + + name + Unimplemented + scope + invalid.unimplemented + settings + + background + #747369 + foreground + #f2f0ec + + + + uuid + uuid + + diff --git a/highlight_themes/base16-equilibrium-light.tmTheme b/highlight_themes/base16-equilibrium-light.tmTheme new file mode 100644 index 0000000..feed9eb --- /dev/null +++ b/highlight_themes/base16-equilibrium-light.tmTheme @@ -0,0 +1,561 @@ + + + + + author + Carlo Abelli + name + Base16 Equilibrium Light + semanticClass + base16.equilibrium.light + colorSpaceName + sRGB + gutterSettings + + background + #e7e2d9 + divider + #e7e2d9 + foreground + #73777f + selectionBackground + #d8d4cb + selectionForeground + #5a5f66 + + settings + + + settings + + background + #f5f0e7 + caret + #43474e + foreground + #43474e + invisibles + #73777f + lineHighlight + #73777f55 + selection + #d8d4cb + + + + name + Text + scope + variable.parameter.function + settings + + foreground + #43474e + + + + name + Comments + scope + comment, punctuation.definition.comment + settings + + foreground + #73777f + + + + name + Punctuation + scope + punctuation.definition.string, punctuation.definition.variable, punctuation.definition.string, punctuation.definition.parameters, punctuation.definition.string, punctuation.definition.array + settings + + foreground + #43474e + + + + name + Delimiters + scope + none + settings + + foreground + #43474e + + + + name + Operators + scope + keyword.operator + settings + + foreground + #43474e + + + + name + Keywords + scope + keyword + settings + + foreground + #4e66b6 + + + + name + Variables + scope + variable + settings + + foreground + #d02023 + + + + name + Functions + scope + entity.name.function, meta.require, support.function.any-method + settings + + foreground + #0073b5 + + + + name + Labels + scope + entity.name.label + settings + + foreground + #c42775 + + + + name + Classes + scope + support.class, entity.name.class, entity.name.type.class + settings + + foreground + #9d6f00 + + + + name + Classes + scope + meta.class + settings + + foreground + #181c22 + + + + name + Methods + scope + keyword.other.special-method + settings + + foreground + #0073b5 + + + + name + Storage + scope + storage + settings + + foreground + #4e66b6 + + + + name + Support + scope + support.function + settings + + foreground + #007a72 + + + + name + Strings, Inherited Class + scope + string, constant.other.symbol, entity.other.inherited-class + settings + + foreground + #637200 + + + + name + Integers + scope + constant.numeric + settings + + foreground + #bf3e05 + + + + name + Floats + scope + none + settings + + foreground + #bf3e05 + + + + name + Boolean + scope + none + settings + + foreground + #bf3e05 + + + + name + Constants + scope + constant + settings + + foreground + #bf3e05 + + + + name + Tags + scope + entity.name.tag + settings + + foreground + #d02023 + + + + name + Attributes + scope + entity.other.attribute-name + settings + + foreground + #bf3e05 + + + + name + Attribute IDs + scope + entity.other.attribute-name.id, punctuation.definition.entity + settings + + foreground + #0073b5 + + + + name + Selector + scope + meta.selector + settings + + foreground + #4e66b6 + + + + name + Values + scope + none + settings + + foreground + #bf3e05 + + + + name + Headings + scope + markup.heading punctuation.definition.heading, entity.name.section + settings + + fontStyle + + foreground + #0073b5 + + + + name + Units + scope + keyword.other.unit + settings + + foreground + #bf3e05 + + + + name + Bold + scope + markup.bold, punctuation.definition.bold + settings + + fontStyle + bold + foreground + #9d6f00 + + + + name + Italic + scope + markup.italic, punctuation.definition.italic + settings + + fontStyle + italic + foreground + #4e66b6 + + + + name + Code + scope + markup.raw.inline + settings + + foreground + #637200 + + + + name + Link Text + scope + string.other.link, punctuation.definition.string.end.markdown + settings + + foreground + #d02023 + + + + name + Link Url + scope + meta.link + settings + + foreground + #bf3e05 + + + + name + Lists + scope + markup.list + settings + + foreground + #d02023 + + + + name + Quotes + scope + markup.quote + settings + + foreground + #bf3e05 + + + + name + Separator + scope + meta.separator + settings + + background + #d8d4cb + foreground + #43474e + + + + name + Inserted + scope + markup.inserted + settings + + foreground + #637200 + + + + name + Deleted + scope + markup.deleted + settings + + foreground + #d02023 + + + + name + Changed + scope + markup.changed + settings + + foreground + #4e66b6 + + + + name + Colors + scope + constant.other.color + settings + + foreground + #007a72 + + + + name + Regular Expressions + scope + string.regexp + settings + + foreground + #007a72 + + + + name + Escape Characters + scope + constant.character.escape + settings + + foreground + #007a72 + + + + name + Embedded + scope + punctuation.section.embedded, variable.interpolation + settings + + foreground + #c42775 + + + + name + Illegal + scope + invalid.illegal + settings + + background + #d02023 + foreground + #181c22 + + + + name + Broken + scope + invalid.broken + settings + + background + #bf3e05 + foreground + #f5f0e7 + + + + name + Deprecated + scope + invalid.deprecated + settings + + background + #c42775 + foreground + #181c22 + + + + name + Unimplemented + scope + invalid.unimplemented + settings + + background + #73777f + foreground + #181c22 + + + + uuid + uuid + + + diff --git a/static/favicon.ico b/static/favicon.ico new file mode 100644 index 0000000..7c64ae9 Binary files /dev/null and b/static/favicon.ico differ diff --git a/static/icons.svg b/static/icons.svg new file mode 100644 index 0000000..bbd28c7 --- /dev/null +++ b/static/icons.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/static/pinkliom-small2.png b/static/pinkliom-small2.png new file mode 100644 index 0000000..03cd5f3 Binary files /dev/null and b/static/pinkliom-small2.png differ diff --git a/static/styles.css b/static/styles.css new file mode 100644 index 0000000..af9cd76 --- /dev/null +++ b/static/styles.css @@ -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; + } +} diff --git a/static/syntax-theme-dark.css b/static/syntax-theme-dark.css new file mode 100644 index 0000000..db0168c --- /dev/null +++ b/static/syntax-theme-dark.css @@ -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; +} diff --git a/static/syntax-theme-light.css b/static/syntax-theme-light.css new file mode 100644 index 0000000..8008b27 --- /dev/null +++ b/static/syntax-theme-light.css @@ -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; +} diff --git a/templates/base.html b/templates/base.html new file mode 100644 index 0000000..10e0a3e --- /dev/null +++ b/templates/base.html @@ -0,0 +1,46 @@ + + + + {% include "head.html" %} + + + +
+
+
+

Your browser contains Google DRM

+
+

+ "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 + Firefox that respects your + freedom and supports ad blockers. +

+

+ 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. +

+
+
+ {% block content %} + {% endblock content %} +
+
+ + + diff --git a/templates/blog-page.html b/templates/blog-page.html new file mode 100644 index 0000000..33ceff0 --- /dev/null +++ b/templates/blog-page.html @@ -0,0 +1,51 @@ +{% extends "base.html" %} + +{% block content %} +
+
<- List
+

{{ page.title }}

+ + {% if config.extra.author and config.extra.display_author == true %} + + {% endif %} + + {% if page.toc and page.extra.toc %} +

Table of contents

+ + {% endif %} + + {{ page.content | safe }} +
+ +
+

+ {% if page.taxonomies.tags %} + {% for tag in page.taxonomies.tags %} + #{{ tag }} + {% endfor %} + {% endif %} +

+
+{% endblock content %} diff --git a/templates/footer.html b/templates/footer.html new file mode 100644 index 0000000..2648270 --- /dev/null +++ b/templates/footer.html @@ -0,0 +1,13 @@ +
+

+ favicon by dzuk. background image by ruca. +

+

+ {% if config.generate_feed %} + + Subscribe via RSS + + + {% endif %} +

+
diff --git a/templates/head.html b/templates/head.html new file mode 100644 index 0000000..2932749 --- /dev/null +++ b/templates/head.html @@ -0,0 +1,96 @@ + + + + + +{% 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 }} +{% endif %} +{% block metatags %} +{% if title %} + +{% endif %} +{% if author %} + +{% endif %} +{% if description %} + +{% endif %} + + +{% if title %} + +{% endif %} +{% if title %} + +{% endif %} +{% if description %} + +{% endif %} +{% if image %} + +{% endif %} +{% set twitter_card = config.extra.twitter_card | default(value=true) %} +{% if twitter_card != false %} + + +{% if title %} + +{% endif %} +{% if description %} + +{% endif %} +{% if image %} + +{% endif %} +{% endif %} + +{% if image %} + +{% endif %} +{% endblock metatags %} +{% if config.generate_feed %} +{% block feed %} + +{% endblock feed %} +{% endif %} +{% block css %} + + + +{% endblock css %} diff --git a/templates/header.html b/templates/header.html new file mode 100644 index 0000000..e4819ee --- /dev/null +++ b/templates/header.html @@ -0,0 +1,14 @@ +{% if config.extra.header_nav %} + +{% endif %} diff --git a/templates/index.html b/templates/index.html new file mode 100644 index 0000000..eb47448 --- /dev/null +++ b/templates/index.html @@ -0,0 +1,27 @@ +{% extends "base.html" %} + +{% block content %} +
+

{{ section.title }}

+ + {{ section.content | safe }} + + {% if paginator %} + {% set pages = paginator.pages %} + {% else %} + {% set pages = section.pages %} + {% endif %} + + + + {% if paginator %} + +
+{% endif %} +{% endblock content %} diff --git a/templates/tags/list.html b/templates/tags/list.html new file mode 100644 index 0000000..d510688 --- /dev/null +++ b/templates/tags/list.html @@ -0,0 +1,12 @@ +{% extends "base.html" %} + +{% block content %} +
+

{{ taxonomy.name }}

+

+ {% for term in terms %} + #{{ term.name }}[{{ term.pages | length }}] + {% endfor %} +

+
+{% endblock content %} diff --git a/templates/tags/single.html b/templates/tags/single.html new file mode 100644 index 0000000..e7d4b29 --- /dev/null +++ b/templates/tags/single.html @@ -0,0 +1,22 @@ +{% extends "base.html" %} + +{% block content %} +
+

{{ term.name }}

+ {% if paginator %} + {% set pages = paginator.pages %} + {% else %} + {% set pages = term.pages %} + {% endif %} + + {% if paginator %} +

{% if paginator.previous %}<< First < Previous{% endif %} [{{ paginator.current_index }}/{{ paginator.number_pagers }}] {% if paginator.next %}Next > Last >>{% endif %}

+ {% endif %} +
+{% endblock content %}