Compare commits

..

16 commits
gin ... main

Author SHA1 Message Date
3390b94d70
cleaned up woodpecker.yml 2025-04-20 19:27:25 +02:00
2b0901a982
Corrected Dockerfile 2024-12-20 13:35:30 +01:00
ac51638665
moved shit around, started working on more features 2024-12-20 13:30:56 +01:00
26a9dc1e03
fixed favicon
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-12-05 14:50:30 +01:00
41904b8d19
fixed woodpecker-ci file for best practice
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-11-27 10:27:26 +01:00
bff4de6937
Reverted change in server.go that moved the listen port off of port 80
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-11-27 10:18:07 +01:00
13813e2b9d
fixed typo in dockerfile
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-11-26 09:25:38 +01:00
b20ad0960c
moved to newer version of theme, refractored go code
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2024-11-26 09:09:05 +01:00
Johannes Bülow
31a5e09ecd
New blogpost about nullbulge-ranner in German
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-06-03 22:50:51 +02:00
Johannes Bülow
fc1540a738
publishing xz blogpost
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-04-04 13:41:33 +02:00
Johannes Bülow
b9713badcd
added blog entry on the xz situation
All checks were successful
ci/woodpecker/manual/woodpecker Pipeline was successful
2024-04-04 13:26:13 +02:00
Johannes Bülow
047623a2e0
fixed formatting error on about page
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-03-16 19:20:53 +01:00
Johannes Bülow
e422c8c6c4
published Babelfish article
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-03-16 19:16:26 +01:00
Johannes Bülow
2a6727faa0
removed ppc64le and armv7 from build
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-03-16 19:06:23 +01:00
Johannes Bülow
ad43152957
added new Blogpost on Babelfish
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2024-03-16 19:00:08 +01:00
Johannes Bülow
63211c3f37
yes
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-12 10:51:51 +01:00
197 changed files with 3597 additions and 2085 deletions

46
.air.toml Normal file
View file

@ -0,0 +1,46 @@
root = "."
testdata_dir = "testdata"
tmp_dir = "tmp"
[build]
args_bin = []
bin = "./www"
cmd = "make webserver"
delay = 1000
exclude_dir = ["hugo", "tmp", "vendor"]
exclude_file = []
exclude_regex = ["_test.go", ".*_templ.go"]
exclude_unchanged = false
follow_symlink = false
full_bin = "PORT=8080 HOST=127.0.0.1 DEBUG=true ./www"
include_dir = []
include_ext = ["go", "tpl", "tmpl", "html", "templ", "toml"]
include_file = []
kill_delay = "0s"
log = "build-errors.log"
poll = false
poll_interval = 0
post_cmd = []
pre_cmd = []
rerun = false
rerun_delay = 500
send_interrupt = false
stop_on_error = false
[color]
app = ""
build = "yellow"
main = "magenta"
runner = "green"
watcher = "cyan"
[log]
main_only = false
time = false
[misc]
clean_on_exit = false
[screen]
clear_on_rebuild = false
keep_scroll = true

2
.gitignore vendored
View file

@ -2,3 +2,5 @@
public/ public/
resources/ resources/
app app
www

View file

@ -1,6 +1,3 @@
when:
branch: main
variables: variables:
- &file Dockerfile - &file Dockerfile
- &repo git.jmbit.de/${CI_REPO_OWNER}/${CI_REPO_NAME} - &repo git.jmbit.de/${CI_REPO_OWNER}/${CI_REPO_NAME}
@ -10,22 +7,12 @@ steps:
image: git.jmbit.de/jmb/docker-hugo image: git.jmbit.de/jmb/docker-hugo
commands: commands:
- hugo --minify - hugo --minify
when:
event: [ pull-request, push]
webserver:
image: golang:alpine
commands:
- go mod download && go mod verify
- CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -buildvcs=true -o app .
when:
event: [ pull-request, push]
publish: publish:
image: woodpeckerci/plugin-docker-buildx image: woodpeckerci/plugin-docker-buildx
settings: settings:
dockerfile: *file dockerfile: *file
platforms: linux/arm/v7,linux/arm64/v8,linux/amd64,linux/ppc64le platforms: linux/arm64/v8,linux/amd64
repo: *repo repo: *repo
registry: git.jmbit.de registry: git.jmbit.de
tags: latest tags: latest
@ -33,5 +20,6 @@ steps:
password: password:
from_secret: forgejo_token from_secret: forgejo_token
when: when:
branch: main
event: push event: push

View file

@ -1,10 +1,13 @@
FROM golang:alpine AS builder FROM docker.io/library/golang:alpine AS builder
RUN apk update && apk add --no-cache git RUN apk update \
&& apk add --no-cache git \
&& apk add --no-cache --repository=https://dl-cdn.alpinelinux.org/alpine/edge/community hugo
WORKDIR $GOPATH/src/www-jmbit-de WORKDIR $GOPATH/src/www-jmbit-de
COPY . . COPY . .
RUN go get -d -v RUN go get -d -v
RUN go build -o /go/bin/www RUN cd hugo && hugo
RUN go build -a -installsuffix cgo -ldflags="-w -s" -o /go/bin/www
FROM scratch FROM scratch
COPY --from=builder /go/bin/www /go/bin/www COPY --from=builder /go/bin/www /go/bin/www

View file

@ -1,26 +1,26 @@
HEAD=$(shell git rev-parse --short HEAD) HEAD=$(shell git rev-parse --short HEAD)
CTNAME:=git.jmbit.de/jmb/www-jmbit-de CTNAME:=git.jmbit.de/jmb/www-jmbit-de
all: hugo container all: hugo webserver
dev: dev:
hugo server -D cd hugo && hugo server -D
hugo: hugo:
hugo --minify cd hugo && hugo
webserver: webserver:
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o app . templ generate .
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o www .
container: container:
podman build -t $(CTNAME):latest -t $(CTNAME):$(HEAD) . podman build -t $(CTNAME):latest -t $(CTNAME):$(HEAD) .
nopub: hugo webserver container
podman run --rm -p8080:80 $(CTNAME)
run: run:
podman run --rm -p8080:80 $(CTNAME) podman run --rm -p8080:80 $(CTNAME)
clean: clean:
rm -rf public rm -rf hugo/public
rm -f www
.PHONY: all dev hugo webserver container run clean

View file

@ -1,10 +0,0 @@
---
title: "Tools"
---
# Tools
Sammlung von selbst-programmierten tools
## [Crypttool (WIP)](https://crypttool.jmbit.de)
Verschlüsselt eine Datei im Browser mit einem zufällig generierten Passwort, ohne dass die Datei den PC verlässt.

29
go.mod
View file

@ -2,31 +2,4 @@ module git.jmbit.de/jmb/www-jmbit-de
go 1.21.5 go 1.21.5
require github.com/gin-gonic/gin v1.9.1 require github.com/a-h/templ v0.2.793 // indirect
require (
github.com/bytedance/sonic v1.9.1 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.14.0 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/cpuid/v2 v2.2.4 // indirect
github.com/leodido/go-urn v1.2.4 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pelletier/go-toml/v2 v2.0.8 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.11 // indirect
golang.org/x/arch v0.3.0 // indirect
golang.org/x/crypto v0.9.0 // indirect
golang.org/x/net v0.10.0 // indirect
golang.org/x/sys v0.8.0 // indirect
golang.org/x/text v0.9.0 // indirect
google.golang.org/protobuf v1.30.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

88
go.sum
View file

@ -1,86 +1,2 @@
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= github.com/a-h/templ v0.2.793 h1:Io+/ocnfGWYO4VHdR0zBbf39PQlnzVCVVD+wEEs6/qY=
github.com/bytedance/sonic v1.9.1 h1:6iJ6NqdoxCDr6mbY8h18oSO+cShGSMRGCEo7F2h0x8s= github.com/a-h/templ v0.2.793/go.mod h1:lq48JXoUvuQrU0VThrK31yFwdRjTCnIE5bcPCM9IP1w=
github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams=
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg/+t63MyGU2n5js=
github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk=
github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q=
github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ=
github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY=
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k=
golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g=
golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=

View file

@ -1,6 +1,6 @@
baseurl = "https://www.jmbit.de/" baseurl = "https://www.jmbit.de/"
languageCode = "de-de" languageCode = "de-de"
theme = "hugo-theme-terminal" theme = "terminal"
paginate = 5 paginate = 5
defaultContentLanguage= "de" defaultContentLanguage= "de"
@ -16,7 +16,7 @@ defaultContentLanguage= "de"
[languages.de.params] [languages.de.params]
title = "Johannes Bülow IT Consulting" title = "Johannes Bülow IT Consulting"
subtitle = "Consulting & Support zu IT-Sicherheit, Linux, Hosting, Entwicklung und mehr" subtitle = "Consulting & Support zu IT-Sicherheit, Linux, Hosting, Entwicklung und mehr"
keywords = "" keywords = "linux, it, consulting, security, hosting, development, jmbit, johannes bülow"
copyright = "Johannes Bülow" copyright = "Johannes Bülow"
menuMore = "Mehr anzeigen" menuMore = "Mehr anzeigen"
readMore = "Weiterlesen" readMore = "Weiterlesen"

View file

@ -9,6 +9,7 @@ GPG-Key: [https://www.jmbit.de/gpg.asc.txt](/gpg.asc.txt)
SSH-RSA-Key: [https://www.jmbit.de/id_rsa.pub](/id_rsa.pub) SSH-RSA-Key: [https://www.jmbit.de/id_rsa.pub](/id_rsa.pub)
SSH-ED25519-Key: [https://www.jmbit.de/id_ed25519.pub](/id_ed25519.pub) SSH-ED25519-Key: [https://www.jmbit.de/id_ed25519.pub](/id_ed25519.pub)
Email: kontakt @ jmbit.de Email: kontakt @ jmbit.de
Github: [jmbit](https://github.com/jmbit/)
{{< rawhtml >}} {{< rawhtml >}}
<a target="_blank" rel="noreferrer noopener" href="https://nextcloud.com/sharing#jmb@cloud.jmbit.de" style="padding:10px;background-color:#0082c9;color:#ffffff;border-radius:3px;padding-left:4px;"> <a target="_blank" rel="noreferrer noopener" href="https://nextcloud.com/sharing#jmb@cloud.jmbit.de" style="padding:10px;background-color:#0082c9;color:#ffffff;border-radius:3px;padding-left:4px;">
<span style="background-image:url(https://cloud.jmbit.de/core/img/logo/logo.svg?v=7);width:50px;height:30px;position:relative;top:8px;background-size:contain;display:inline-block;background-repeat:no-repeat; background-position: center center;"></span> <span style="background-image:url(https://cloud.jmbit.de/core/img/logo/logo.svg?v=7);width:50px;height:30px;position:relative;top:8px;background-size:contain;display:inline-block;background-repeat:no-repeat; background-position: center center;"></span>

View file

@ -0,0 +1,43 @@
---
title: "Babelfish für Postgresql - MSSQL-Kompatibilität für Postgres"
date: 2024-03-16
draft: false
---
[Babelfish](https://babelfishpg.org/) ist ein Projekt, das die Verwendung von Postgresql für Software erlaubt, die
eigentlich für MSSQL (Microsoft SQL Server) geschrieben wurden. Dies erlaubt zum einen das einsparen von Lizenzkosten,
die bei MSSQL, insbesondere für hochverfügbare Umgebungen, leicht sehr hoch werden können, zum anderen aber auch, das
größere und modernere Postgres-Ökosystem verwenden zu können.
## Was ist Babelfish?
Ähnlich wie sein [Namensvorbild](https://de.wikipedia.org/wiki/Babelfisch), ist Babelfish kein migrationstool o.ä.,
sondern eine Kompatibilitäts/Übersetzungsschicht, vergleichbar etwa mit [Wine](https://www.winehq.org/). Im Optimalfall
kann man also eine Applikation, die eine MSSQL-Datenbank benötigt, mit einem Postgres-DB-Server betreiben, ohne die
Applikation umbauen zu müssen. Das kann einerseits für eine vereinfachte Migration sein, andererseits aber auch für die
Ablösung bestehender MSSQL-Server durch Postgres-Server.
## Was ist Babelfish nicht?
Babelfish ist aktuell NICHT 100% MSSQL-Kompatibel. Es fehlen vor allem Funktionalitäten, die mit dem DB-Server selbst zu
tun haben (bestimmte tabellen in Systemdatenbanken, manche Stored Procedures...) oder mit dem darunterliegenden OS
(CLR/Assebly Module). Dadurch ist Babelfish nicht plug&play, sollte die Applikation eher exotische Funktionen verwenden.
Ebenfalls sollte es nicht als einfaches Drop-In-Replacement gesehen werden.
## Wie finde ich heraus, ob Babelfish für meine Anwendung funktioniert?
Es gibt mehrere Ressourcen, mit deren Hilfe es möglich ist, die Kompatibilität mit Babelfish zu testen:
- Dokumentation: Es gibt sowohl von AWS für ihre SAAS-Version
[Informationen](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/babelfish-compatibility.tsql.limitations-unsupported.html),
als auch vom [Babelfish Projekt selbst](https://babelfishpg.org/docs/limitations/limitations-of-babelfish/).
Letztere tendieren leider dazu, etwas veraltet zu sein.
- [Babelfish-Compass](https://github.com/babelfish-for-postgresql/babelfish_compass): Compass ist ein Tool, mit dessen
Hilfe es möglich ist, die Kompatibilität sowohl von Skripten, als auch Software und bestehender Datenbanken zu
messen.
## Welche Alternativen gibt es?
Sollte es nicht möglich sein, eine Applikation von MSSQL auf Babelfish & Postgres zu migrieren, gibt es noch ein paar
andere Möglichkeiten, die Datenbank zu modernisieren. Seit Version 2019 kann MSSQL auch unter Linux betrieben werden,
was abgesehen von der Möglichkeit, Windows Lizenzen einzusparen, die Möglichkeit bietet, die Server mit den üblichen
Verwaltungstools zu verwalten, sowie Dateisysteme und Storage-Backends zu verwenden, die Windows nicht unterstützt.
Andererseits erlaubt es auch den Betrieb der Datenbank auf einem Kubernetes-Cluster, das dann Skalierung, Resilienz und
Verwaltung der DB-Engine übernimmt.
Sollten Sie nach dieser Einleitung weitere Fragen zu Babelfish haben, können Sie mich gerne kontaktieren.

View file

@ -0,0 +1,70 @@
---
title: "Gedanken zu XZ"
date: 2024-04-04
draft: false
---
Dieser Blogpost ist dazu da, meine Gedanken zu der XZ-Situation zusammenzufassen.
## 1. Die Entdeckung
Die [Entdeckung der Backdoor in liblzma](https://www.openwall.com/lists/oss-security/2024/03/29/4)
war einerseits ein purer Glücksgriff, andererseits auch ein Beispiel dafür, warum
Open Source so wichtig für die Entdeckung und Analyse von Schwachstellen ist. In diesem Fall war es dem Entdecker -
trotz der Tatsache, dass er eigentlich Datenbank-Entwickler ist - in verhältnismäßig kurzer Zeit möglich, die Ursache
der "langsamen" SSH-Logins (800 statt 300 ms) zu ermitteln und zu analysieren. Im Vergleich dazu hatte ich deutlich mehr
Zeit investiert in die letztlich erfolglose Analyse eines Memory leaks unter Microsoft Windows.
## 2. Die potenziellen Auswirkungen
Wäre die Backdoor erfolgreich verbreitet worden, wäre früher oder später -
[abhängig vom Patchzyklus](https://infosec.exchange/@SecureOwl/112181879860988729) - ein großer Teil der Server im
Internet verwundbar gewesen:
![Shodan zeigt 19 698 358 OpenSSH Server](/img/blog/shodan-openssh-2024-04-04.png)
Der Angreifer hätte ähnlichen Zugriff auf diese Server gehabt wie damals mit Ethernal Blue auf Windows-Server... Nur
dass laut Shodan nur etwa 420 000 Windows Server mit offenem SMB-Port im Internet stehen.
## 3. Analyse
Die Analyse der Backdoor (abgesehen von dem nicht gerade hilfreichen Takedown durch Github) hat einige interessante
Informationen zu Tage befördert. Einmal die Tatsache, dass diese Backdoor sehr gut versteckt war, enthalten in einer
Testfile, mit dem "Aktivierungscode" nicht in der Versionskontrolle enthalten[^1]. Ebenso auffällig ist, dass die
Backdoor/RCE einen bestimmtes SSH-Zertifikat benötigt, um aktiviert zu werden, und die Payload innerhalb dieses
Zertifikats (genauer, dem CA-Teil) enthalten ist, wo binäre Daten kaum auffallen [^2] . Später ist ebenfalls aufgefallen, dass
der Name "Jia Cheong Tan" zwar chinesisch klingt, aber eine Mischung aus Kantonesisch und Mandarin ist[^3]. Aus der
Analyse der Git commit logs geht ebenfalls heraus, dass die Commits zu UrzeitenSch gemacht wurden, die für China eher
unüblich sind[^4]. Die Vermutung liegt also nahe, dass die tatsächliche Person (oder Personen?) hinter der Backdoor
vermutlich eher in Osteuropa oder dem Nahen Osten (UTC+2/3) zu finden ist.
## 4. Lessons Learned
- Die XZ-Backdoor ist eine seltene Möglichkeit, in die Vorgehensweise und den Code von möglichen staatlichen Akteuren oder
anderen APTs[^5] hineinsehen zu können und sein Sicherheitsvorgehen dahingehend zu optimieren.
- Interessant ist, dass die Backdoor nicht im eigentlichen Source Code des Git trees enthalten war,
sondern in binären Testdateien (für deren
Generierung kein Sourcecode verfügbar war) versteckt war und der Code zur Aktivierung nur im Release-Tarball enthalten
war, nicht jedoch im Git tree, was in Kombination dafür spricht, dass der Urheber der Sicherheitslücke versucht hat, so
wenig "permanente" Spuren wie möglich zu hinterlassen, die von (automatischer) Code-Analyse einfach gefunden worden
wären.
- Ebenfalls stellt sich die Frage, in wie vielen anderen Projekten (Open Source wie proprietär), ähnliche Angriffe
versucht wurden und vielleicht sogar erfolgreich waren. In Zukunft werde zumindest ich deutlich mehr Vorsicht gegenüber
binären Dateien in Source Code walten lassen. Möglich wäre z.B., dass eine Backdoor in einem binary blob Treiber
enthalten ist, der von einem Hardware-Hersteller veröffentlicht wird. Sollte dieser Treiber statisch (also nicht als
Kernel Modul) in den Kernel compiliert werden, wäre es möglich, diese Schwachstelle auf Millionen von Geräten zu
installieren.
- Ähnliches Vorgehen in proprietärer Software (z.B. Microsoft Exchange) dürfte in ähnlicher Weise umsetzbar sein. Das
Plazieren eines Maulwurfs in einem solchen Entwicklerteam könnte sogar einfacher sein, da das Vertrauen einem anderen
Mitarbeiter gegenüber deutlich schneller anwächst als einem Fremden gegenüber.[^6]
- Mobbing und Burnout können ein echtes Sicherheitsrisiko sein. "Jia Tan" wäre vermutlich nie in diese Position gekommen,
wäre der eigentliche Maintainer und Entwickler von xz nicht von Burnout betroffen und effektiv dazu gemobbt worden,
"Jia Tan" zum Co-Maintainer und sogar primären Maintainer zu machen.
[^1]: https://gynvael.coldwind.pl/?id=782
[^2]: https://bsky.app/profile/filippo.abyssdomain.expert/post/3kowjkx2njy2b
[^3]: https://boehs.org/node/everything-i-know-about-the-xz-backdoor
[^4]: https://rheaeve.substack.com/p/xz-backdoor-times-damned-times-and
[^5]: https://en.wikipedia.org/wiki/Advanced_persistent_threat
[^6]: https://infosec.exchange/@SecureOwl/112181879860988729

View file

@ -0,0 +1,218 @@
---
title: "Nullbulge-Ranner - Compiled Python Malware"
date: 2024-06-03
draft: false
---
Ich bin in den letzten Tagen über [Eric Parker](https://www.youtube.com/@EricParker) auf Malware gestößen, über BeamNG-Mods verteilt wurde.
Das interessante an dieser Malware ist, dass sie zwar in Python geschrieben ist, aber mithilfe von Pyinstaller[^1] kompiliert wurde.
Dadurch, in Verbindung mit der gewählten Python-Version, ist die Malware effektiv nicht dekompilierbar und nur schwer zu reverse engineeren.
Die meisten Informationen über die Malware mussten daher über dynamische Analyse in Sandboxen und VMs gewonnen werden.
## Oberflächliche statische Analyse
Der Erste Schritt war, die Datei "statisch" zu analysieren, das heißt, sich die Eigenschaften der Malware anzuschauen ohne die Malware selbst auszuführen.
Dafür habe ich initial die Tools "capa"[^2], "detect-it-easy"[^3] und "yara"[^4] verwendet.
Detect-It-Easy gibt uns genauere Informationen über die Datei, vor allem, dass sie mit PyInstaller "gepackt" wurde.
```
PE64
Linker: Microsoft Linker(14.36.33135)
Compiler: Microsoft Visual C/C++(19.36.33135)[C]
Tool: Visual Studio(2022 version 17.6)
Packer: PyInstaller
```
Capa findet schon sehr viele Informationen:
{{< rawhtml >}}
<pre>
┍━━━━━━━━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┑
│ ATT&amp;CK Tactic │ ATT&amp;CK Technique │
┝━━━━━━━━━━━━━━━━━━━━━━━━┿━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┥
<font color="#06989A">DEFENSE EVASION</font><font color="#06989A">Obfuscated Files or Information</font> T1027 │
│ │ <font color="#06989A">Virtualization/Sandbox Evasion</font>::System Checks T1497.001 │
├────────────────────────┼────────────────────────────────────────────────────────────────────────────────────┤
<font color="#06989A">DISCOVERY</font><font color="#06989A">File and Directory Discovery</font> T1083 │
│ │ <font color="#06989A">System Information Discovery</font> T1082 │
├────────────────────────┼────────────────────────────────────────────────────────────────────────────────────┤
<font color="#06989A">EXECUTION</font><font color="#06989A">Command and Scripting Interpreter</font> T1059 │
│ │ <font color="#06989A">Shared Modules</font> T1129 │
┕━━━━━━━━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┙
┍━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┑
│ MBC Objective │ MBC Behavior │
┝━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┿━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┥
<font color="#06989A">ANTI-BEHAVIORAL ANALYSIS</font><font color="#06989A">Virtual Machine Detection</font> [B0009] │
├─────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤
<font color="#06989A">DATA</font><font color="#06989A">Checksum</font>::Adler [C0032.005] │
│ │ <font color="#06989A">Compress Data</font> [C0024] │
│ │ <font color="#06989A">Compression Library</font> [C0060] │
│ │ <font color="#06989A">Encode Data</font>::XOR [C0026.002] │
├─────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤
<font color="#06989A">DEFENSE EVASION</font><font color="#06989A">Obfuscated Files or Information</font>::Encoding-Standard Algorithm [E1027.m02] │
├─────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤
<font color="#06989A">DISCOVERY</font><font color="#06989A">Analysis Tool Discovery</font>::Process detection [B0013.001] │
│ │ <font color="#06989A">File and Directory Discovery</font> [E1083] │
│ │ <font color="#06989A">System Information Discovery</font> [E1082] │
├─────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤
<font color="#06989A">EXECUTION</font><font color="#06989A">Command and Scripting Interpreter</font> [E1059] │
├─────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤
<font color="#06989A">FILE SYSTEM</font><font color="#06989A">Create Directory</font> [C0046] │
│ │ <font color="#06989A">Delete Directory</font> [C0048] │
│ │ <font color="#06989A">Delete File</font> [C0047] │
│ │ <font color="#06989A">Read File</font> [C0051] │
│ │ <font color="#06989A">Writes File</font> [C0052] │
├─────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤
<font color="#06989A">OPERATING SYSTEM</font><font color="#06989A">Environment Variable</font>::Set Variable [C0034.001] │
├─────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤
<font color="#06989A">PROCESS</font><font color="#06989A">Create Process</font> [C0017] │
│ │ <font color="#06989A">Terminate Process</font> [C0018] │
┕━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┙
┍━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┑
│ Capability │ Namespace │
┝━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┿━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┥
<font color="#06989A">reference analysis tools strings</font> │ anti-analysis │
<font color="#06989A">reference anti-VM strings targeting Qemu</font> │ anti-analysis/anti-vm/vm-detection │
<font color="#06989A">reference anti-VM strings targeting Xen</font> │ anti-analysis/anti-vm/vm-detection │
<font color="#06989A">compute adler32 checksum</font> │ data-manipulation/checksum/adler32 │
<font color="#06989A">compress data via ZLIB inflate or deflate</font> │ data-manipulation/compression │
<font color="#06989A">encode data using XOR</font> (6 matches) │ data-manipulation/encoding/xor │
<font color="#06989A">accept command line arguments</font> │ host-interaction/cli │
<font color="#06989A">query environment variable</font> (4 matches) │ host-interaction/environment-variable │
<font color="#06989A">set environment variable</font> (4 matches) │ host-interaction/environment-variable │
<font color="#06989A">get common file path</font> │ host-interaction/file-system │
<font color="#06989A">create directory</font> (2 matches) │ host-interaction/file-system/create │
<font color="#06989A">delete directory</font> │ host-interaction/file-system/delete │
<font color="#06989A">delete file</font> │ host-interaction/file-system/delete │
<font color="#06989A">enumerate files on Windows</font> │ host-interaction/file-system/files/list │
<font color="#06989A">get file size</font> │ host-interaction/file-system/meta │
<font color="#06989A">read file on Windows</font> (10 matches) │ host-interaction/file-system/read │
<font color="#06989A">write file on Windows</font> (2 matches) │ host-interaction/file-system/write │
<font color="#06989A">get disk information</font> (2 matches) │ host-interaction/hardware/storage │
<font color="#06989A">create process on Windows</font> │ host-interaction/process/create │
<font color="#06989A">terminate process</font> │ host-interaction/process/terminate │
<font color="#06989A">link many functions at runtime</font> (2 matches) │ linking/runtime-linking │
<font color="#06989A">linked against ZLIB</font> │ linking/static/zlib │
<font color="#06989A">parse PE header</font> (3 matches) │ load-code/pe │
<font color="#06989A">resolve function by parsing PE exports</font> │ load-code/pe │
┕━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┙
</pre>
{{</ rawhtml >}}
Auch Yara findet einige Pattern in der Datei:
```
DebuggerException__SetConsoleCtrl
anti_dbg
screenshot
win_token
win_files_operation
Big_Numbers1
CRC32_poly_Constant
CRC32_table
MachO_File_pyinstaller
IsPE64
IsWindowsGUI
IsPacked
HasOverlay
HasDigitalSignature
HasDebugData
HasRichSignature
Microsoft_Visual_Cpp_80
Microsoft_Visual_Cpp_80_DLL
```
Zusammenfassend können wir aus dieser statischen Analyse also sagen, dass die Malware es versucht, einem die Analyse schwerer zu machen und möglicherweise ein
RAT ist (kann laut YARA screenshots machen).
## Dynamische Analyse mit CAPE
Eine [CAPE-Sandbox-Umgebung](https://www.jmbit.de/blog/2023-11-30-capev2-sandbox/) ist eine gute Möglichkeit, lokal dynamische Analysen von Malware oder potenzieller
Malware durchzuführen. In diesem Fall enthält die zu analysierende Datei zwar keine sensiblen Daten, sollte das aber der Fall sein, ist es ggf. nicht sinnvoll,
die Datei auf eine Cloud-Platform hochzuladen.
Hier fielen vor allem die Anti-Analyse-Funktionen sowie die Requests zu Discord auf. Da die Malware jedoch ohne Verbindung zu Discord relativ inaktiv ist und keine user-interaktion bietet, ist die
dynamische analyse hier abgesehen von den Informationen über die installation der Software und ihr Verhalten gegenüber Virtualisierung und Debuggern nicht besonders ergibig.
[REPORT](https://cloud.jmbit.de/s/qLtzrFyjY3TfQmX)
## Analyse des Webtraffic mithilfe von MITMProxy
Um den Webtraffic genauer anzusehen und mitlesen zu können und eventuelle API-Keys abfangen zu können, habe ich die Malware in einer VM gestartet, die über mitmproxy[^5] ins Internet gegangen ist.
Hier wurde aber lediglich versucht, sich als ein Bot in Discord einzuloggen, der Zugriff wurde jedoch abgelehnt:
```http
GET /api/v10/users/@me HTTP/1.1
Host: discord.com
User-Agent: DiscordBot (https://github.com/Rapptz/discord.py 2.3.2) Python/3.10 aiohttp/3.9.5
Authorization: Bot <REDACTED>
HTTP/1.1 401 Unauthorized
{"message": "401: Unauthorized", "code": 0}
```
## Analyse des Programmcodes
Nachdem ich der Malware in der Dynamischen Analyse kaum Informationen entlocken konnte, ging es an die statische Analyse. Da Python 3.10 leider zu neu für die meisten Decompiler ist[^6], musste ich mich mit dem
Ergebnis eines Disassemblers zufrieden geben. Aus dem Output dieses (Immerhin 21355 Zeilen!) lies sich der Verdacht, dass es sich bei der Malware um eine Version von PySilon handelt, bestätigen.
Es wurden jedoch einige zusätzliche Funktionen eingefügt, so zum Beispiel Ransomware und die Möglichkeit des Nachladens eines Cryptominers. Ebenfalls bin ich über während der Analyse auf andere Malware der
gleichen Gruppe gestoßen.
Die Ransomware-Mitteilung `NULLBULGE-RANSOMWARE-NOTE.TXT` würde diesen Text enthalten:
```
READ THIS ENTIRELY BEFORE ACTING, IF YOU SHUT DOWN NOW, ALL WILL BE LOST.
Your computer is now infected with ransomware. Your file are encrypted with a secure algorithm that is impossible to crack.
By now it has moved from your main drive, and has started encrypting other drives.
DONT PANIC! IF YOU START LOOKING FOR THE VIRUS, YOU WILL NOT GET ANY FILES ALREADY ENCRYPTED BACK! BUT THEY CAN BE SAVED!
To recover your files you need a key. This key is generated once your file have been encrypted. To obtain the key, you must purchase it.
You can do this by sending 100 USD to this monero address:
45i7kjWZuzJ4PdSbandaaE8S6mQATmneTYEpgsaaCqDmc7foEJDXwxd3ABR8bn6YE4c7hZ2dYEEr1CwG48gAknPL6zUpYyV
Don't know how to get monero? Here are some websites:
https://www.kraken.com/learn/buy-monero-xmr
https://localmonero.co/?language=en
https://www.bestchange.com/visa-mastercard-usd-to-monero.html
Cant get monero and want to pay via giftcards instead? contact the email below.
Once you have sent the ransom to the monero address you must write an email this this email address: ZeCBMail@proton.me
In this email you will include your personal ID so we know who you are. Your personal ID is:
<ID>
Payment is flexable, if you want to discuss pricing send an email with your discord username and I will contact you.
Be warned... pricing can go up too!
Once you have completeted all of the steps, you will be provided with the key to decrypt your files.
Don't know how ransomware works? Read up here:
https://www.trellix.com/en-us/security-awareness/ransomware/what-is-ransomware.html
https://www.checkpoint.com/cyber-hub/threat-prevention/ransomware/
https://www.trendmicro.com/vinfo/us/security/definition/Ransomware
Note: Messing with the ransomware will simply make your files harder to decrypt. Deleting the virus will make it impossible, as the key can not be generated.
Good luck
-NullBulge
```
Der Crypto-Miner ist XMRIG und mined für den Pool "xmrpool.eu".
Der Bot wird sowohl über Discord-Reactions als auch über direkte Befehle gesteuert. Die Reactions können einfachere Funktionen abbilden, wie z.B. das wipen der Malware vom System.
Interessanter sind jedoch die "richtigen" Befehle, z.B.:
* '.ss' -> Macht einen Screenshot vom Bildschirm des Opfers
* '.screenrec' -> zeichnet 15 Sekunden den Bildschirm auf
* '.join' -> Tritt einem Voice Channel bei und überträgt die Aufnahmen des Mikrofons
* '.show' -> Zeigt informationen, z.B. alle laufenden Prozesse
* '.kill' -> Beendet einen Prozesse
* '.block-input' -> Deaktiviert Tastatur- und Mauseingaben
* '.break-windows' -> Bennent den Boot-Manager um und verhindert damit, dass Windows rebooten kann
* '.xmrig' -> Führt den Cryptominer aus
* '.webcam photo' -> Macht ein Bild mit der Webcam
* '.encrypt' -> Verschlüsselt alle Dateien im angegebenen Verzeichnis
* '.cmd' -> Führt beliebigen Befehl aus
* '.admin' -> Kann Funktionen ausführen wie Defender, Taskmanager oder UAC deaktiveren.
[^1]: Pyinstaller ist Software, die es ermöglicht, in Python geschriebene Programme so zu compilen und bundlen, dass sie auf Systemen ohne Python-Interpreter
benutzt werden können. Das kann z.B. als PE-File (Windows .exe) oder ELF (Linux/Unix) sein.
[^2]: [mandiant/capa](https://github.com/mandiant/capa), ein Tool, das eine Datei analysiert und versucht, deren Fähigkeiten (capabilities) zu erfassen.
[^3]: [horsicq/Detect-It-Easy](https://github.com/horsicq/Detect-It-Easy) gibt einem die Eigenschaften einer Datei zurück.
[^4]: [Yara](https://virustotal.github.io/yara/) ist eine Bibliothek zur Analyse von Malware anhand von Pattern/Eigenschaften der Dateien.
[^5]: [MITMProxy](https://mitmproxy.org/) ist ein Forward-Proxy, der alle Verbindungen die über ihn laufen aufzeichnet
[^6]: Weder [pycdc](https://github.com/zrax/pycdc) noch [unpyc37-3.10](https://github.com/greyblue9/unpyc37-3.10) konnten den Bytecode decompilen.

View file

@ -0,0 +1,139 @@
---
title: "Investigating Nullbulge - a BeamNG mods malware Group"
date: 2024-06-05
draft: true
---
Over the last few days, I started Investigating a piece of malware that got downloaded with BeamNG[^1] mods.
It was originally discovered by Eric Parker, who describes both its discovery and major features in [his video](https://youtu.be/k52GwOWGy7o?si=4o5A7UkEpeuYWa20).
## First Sample
The sample originally uncovered by Eric Parker is a modified version of the PySilo[^2] malware that has been compiled using PyInstaller and Python 3.10,
making it fairly difficult to reverse engineer. However, I was still able to analyze it using both static and dynamic analysis tooling.
### General static analysis
First, I used a couple general tools for static file analysis. To be mentioned here are [^3]Capa, Detect-It-Easy[^4] and yara[^5].
All of those gave certain insights on the file and informed the way to go forward.
Detect-It-Easy is essentially a more powerful `file` command that gives you additional information about a file.
In this case, it gave me the following Information:
```
PE64
Linker: Microsoft Linker(14.36.33135)
Compiler: Microsoft Visual C/C++(19.36.33135)[C]
Tool: Visual Studio(2022 version 17.6)
Packer: PyInstaller
```
This tells us the File is a 64Bit PE (Portable Executable) packed with PyInstaller[^6], meaning it's compiled and packed from Python for
64 Bit Windows. In this case, we can likely ignore the Linker, compiler and Tool information, as Pyinstaller likely just uses those under the hood.
Capa is much more verbose, but has a nicely formatted output. It analyzes the calls the program makes to the OS or other common locations to make informed
guesses about the likely capabilities/uses of the program:
{{< rawhtml >}}
<pre>
┍━━━━━━━━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┑
│ ATT&amp;CK Tactic │ ATT&amp;CK Technique │
┝━━━━━━━━━━━━━━━━━━━━━━━━┿━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┥
<font color="#06989A">DEFENSE EVASION</font><font color="#06989A">Obfuscated Files or Information</font> T1027 │
│ │ <font color="#06989A">Virtualization/Sandbox Evasion</font>::System Checks T1497.001 │
├────────────────────────┼────────────────────────────────────────────────────────────────────────────────────┤
<font color="#06989A">DISCOVERY</font><font color="#06989A">File and Directory Discovery</font> T1083 │
│ │ <font color="#06989A">System Information Discovery</font> T1082 │
├────────────────────────┼────────────────────────────────────────────────────────────────────────────────────┤
<font color="#06989A">EXECUTION</font><font color="#06989A">Command and Scripting Interpreter</font> T1059 │
│ │ <font color="#06989A">Shared Modules</font> T1129 │
┕━━━━━━━━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┙
┍━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┑
│ MBC Objective │ MBC Behavior │
┝━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┿━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┥
<font color="#06989A">ANTI-BEHAVIORAL ANALYSIS</font><font color="#06989A">Virtual Machine Detection</font> [B0009] │
├─────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤
<font color="#06989A">DATA</font><font color="#06989A">Checksum</font>::Adler [C0032.005] │
│ │ <font color="#06989A">Compress Data</font> [C0024] │
│ │ <font color="#06989A">Compression Library</font> [C0060] │
│ │ <font color="#06989A">Encode Data</font>::XOR [C0026.002] │
├─────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤
<font color="#06989A">DEFENSE EVASION</font><font color="#06989A">Obfuscated Files or Information</font>::Encoding-Standard Algorithm [E1027.m02] │
├─────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤
<font color="#06989A">DISCOVERY</font><font color="#06989A">Analysis Tool Discovery</font>::Process detection [B0013.001] │
│ │ <font color="#06989A">File and Directory Discovery</font> [E1083] │
│ │ <font color="#06989A">System Information Discovery</font> [E1082] │
├─────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤
<font color="#06989A">EXECUTION</font><font color="#06989A">Command and Scripting Interpreter</font> [E1059] │
├─────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤
<font color="#06989A">FILE SYSTEM</font><font color="#06989A">Create Directory</font> [C0046] │
│ │ <font color="#06989A">Delete Directory</font> [C0048] │
│ │ <font color="#06989A">Delete File</font> [C0047] │
│ │ <font color="#06989A">Read File</font> [C0051] │
│ │ <font color="#06989A">Writes File</font> [C0052] │
├─────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤
<font color="#06989A">OPERATING SYSTEM</font><font color="#06989A">Environment Variable</font>::Set Variable [C0034.001] │
├─────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤
<font color="#06989A">PROCESS</font><font color="#06989A">Create Process</font> [C0017] │
│ │ <font color="#06989A">Terminate Process</font> [C0018] │
┕━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┙
┍━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┑
│ Capability │ Namespace │
┝━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┿━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┥
<font color="#06989A">reference analysis tools strings</font> │ anti-analysis │
<font color="#06989A">reference anti-VM strings targeting Qemu</font> │ anti-analysis/anti-vm/vm-detection │
<font color="#06989A">reference anti-VM strings targeting Xen</font> │ anti-analysis/anti-vm/vm-detection │
<font color="#06989A">compute adler32 checksum</font> │ data-manipulation/checksum/adler32 │
<font color="#06989A">compress data via ZLIB inflate or deflate</font> │ data-manipulation/compression │
<font color="#06989A">encode data using XOR</font> (6 matches) │ data-manipulation/encoding/xor │
<font color="#06989A">accept command line arguments</font> │ host-interaction/cli │
<font color="#06989A">query environment variable</font> (4 matches) │ host-interaction/environment-variable │
<font color="#06989A">set environment variable</font> (4 matches) │ host-interaction/environment-variable │
<font color="#06989A">get common file path</font> │ host-interaction/file-system │
<font color="#06989A">create directory</font> (2 matches) │ host-interaction/file-system/create │
<font color="#06989A">delete directory</font> │ host-interaction/file-system/delete │
<font color="#06989A">delete file</font> │ host-interaction/file-system/delete │
<font color="#06989A">enumerate files on Windows</font> │ host-interaction/file-system/files/list │
<font color="#06989A">get file size</font> │ host-interaction/file-system/meta │
<font color="#06989A">read file on Windows</font> (10 matches) │ host-interaction/file-system/read │
<font color="#06989A">write file on Windows</font> (2 matches) │ host-interaction/file-system/write │
<font color="#06989A">get disk information</font> (2 matches) │ host-interaction/hardware/storage │
<font color="#06989A">create process on Windows</font> │ host-interaction/process/create │
<font color="#06989A">terminate process</font> │ host-interaction/process/terminate │
<font color="#06989A">link many functions at runtime</font> (2 matches) │ linking/runtime-linking │
<font color="#06989A">linked against ZLIB</font> │ linking/static/zlib │
<font color="#06989A">parse PE header</font> (3 matches) │ load-code/pe │
<font color="#06989A">resolve function by parsing PE exports</font> │ load-code/pe │
┕━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┙
</pre>
{{</ rawhtml >}}
If we weren't sure already, this wold certainly greatly increase the likelyhood of this software being malicious. No normal software needs to evade
sandboxing and virtualization. We will later see that these features are implemented in a very simple way and not really relevant for most sandboxing
platforms.
Finally, for a good measure, I ran it through yara:
```
DebuggerException__SetConsoleCtrl
anti_dbg
screenshot
win_token
win_files_operation
Big_Numbers1
CRC32_poly_Constant
CRC32_table
MachO_File_pyinstaller
IsPE64
IsWindowsGUI
IsPacked
HasOverlay
HasDigitalSignature
HasDebugData
HasRichSignature
Microsoft_Visual_Cpp_80
Microsoft_Visual_Cpp_80_DLL
```
Yara can be a bit noisy, but in this case it also shows us that the application has some anti-debug operations, the ability to take screenshots and some
features indicative of encryption.
### Dynamic analysis
Dynamic analysis essentially just means watching the Malware do its thing and analyzing that. For this I usually use my own installation of CAPE sandbox,
but hosted services like tria.ge and intezer are also available.

11
hugo/content/tools.md Normal file
View file

@ -0,0 +1,11 @@
---
title: "Tools"
---
# Tools
Sammlung von selbst-programmierten tools
## [CAPE Sandbox](https://cape.jmbit.de)
Dynamic Analysis Sandbox für Malware

8
hugo/hugo.go Normal file
View file

@ -0,0 +1,8 @@
package hugo
import (
"embed"
)
//go:embed public/*
var PublicFS embed.FS

BIN
hugo/static/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 207 B

BIN
hugo/static/favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 207 B

View file

Before

Width:  |  Height:  |  Size: 228 KiB

After

Width:  |  Height:  |  Size: 228 KiB

View file

Before

Width:  |  Height:  |  Size: 122 KiB

After

Width:  |  Height:  |  Size: 122 KiB

View file

Before

Width:  |  Height:  |  Size: 190 KiB

After

Width:  |  Height:  |  Size: 190 KiB

View file

Before

Width:  |  Height:  |  Size: 189 KiB

After

Width:  |  Height:  |  Size: 189 KiB

View file

Before

Width:  |  Height:  |  Size: 112 KiB

After

Width:  |  Height:  |  Size: 112 KiB

View file

Before

Width:  |  Height:  |  Size: 227 KiB

After

Width:  |  Height:  |  Size: 227 KiB

View file

Before

Width:  |  Height:  |  Size: 308 KiB

After

Width:  |  Height:  |  Size: 308 KiB

View file

Before

Width:  |  Height:  |  Size: 63 KiB

After

Width:  |  Height:  |  Size: 63 KiB

View file

Before

Width:  |  Height:  |  Size: 416 KiB

After

Width:  |  Height:  |  Size: 416 KiB

View file

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 291 KiB

View file

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View file

Before

Width:  |  Height:  |  Size: 84 KiB

After

Width:  |  Height:  |  Size: 84 KiB

View file

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 KiB

View file

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 36 KiB

BIN
hugo/static/og-image.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

368
hugo/static/terminal.css Normal file
View file

@ -0,0 +1,368 @@
:root {
--background: #1d212c;
--foreground: #ffffff;
--accent: #23B0FF;
--font-size: 1rem;
--line-height: 1.54rem;
--radius: 3px;
}
html {
box-sizing: border-box;
}
*,
*:before,
*:after {
box-sizing: inherit;
margin: 0;
padding: 0;
}
body {
margin: 0;
padding: 0;
font-family: "Fira Code", Monaco, Consolas, "Ubuntu Mono", monospace;
font-size: 1rem;
font-weight: 400;
line-height: var(--line-height);
letter-spacing: -0.02em;
background-color: var(--background);
color: var(--foreground);
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-webkit-overflow-scrolling: touch;
-webkit-text-size-adjust: 100%;
}
::placeholder {
color: color-mix(in srgb var(--foreground) 50%, black);
}
h1,
h2 {
font-size: calc(var(--font-size) * 1.1);
text-transform: uppercase;
letter-spacing: 0.04em;
}
h1 {
text-decoration: underline;
text-decoration-thickness: 2px;
text-underline-offset: calc(var(--font-size) * 0.2);
}
h3,
h4,
h5,
h6 {
font-size: calc(var(--font-size) * 1.1);
letter-spacing: 0.04em;
}
h1,
h2,
h3,
h4,
h5,
h6,
p,
ul,
ol,
img,
figure,
video,
table {
margin: calc(var(--line-height) * 1.2) 0;
}
a {
color: var(--accent);
}
button {
position: relative;
font: inherit;
font-weight: bold;
text-decoration: none;
text-align: center;
background: transparent;
color: var(--accent);
padding: 5px 18px;
border: 4px solid var(--accent);
border-radius: var(--radius);
transition: background 0.15s linear;
appearance: none;
cursor: pointer;
outline: none;
}
button:hover {
background: color-mix(in srgb, var(--accent) 15%, transparent);
}
button:focus-visible,
a:focus-visible {
outline: 1px solid var(--accent);
outline-offset: 2px;
}
fieldset {
display: inline-block;
border: 2px solid var(--foreground);
border-radius: calc(var(--radius) * 1.6);
padding: 10px;
}
fieldset *:first-child {
margin-top: 0;
}
fieldset input,
fieldset select,
fieldset textarea,
fieldset label,
fieldset button {
margin-top: calc(var(--line-height) * 0.5);
width: 100%;
}
label {
display: inline-block;
}
label input {
margin-top: 0;
}
input,
textarea,
select {
background: transparent;
color: var(--foreground);
border: 1px solid var(--foreground);
border-radius: var(--radius);
padding: 10px;
font: inherit;
appearance: none;
}
input[type="checkbox"] {
width: auto;
}
input:focus-visible,
input:active,
textarea:focus-visible,
textarea:active,
select:focus-visible,
select:active {
border-color: var(--accent);
outline: 1px solid var(--accent);
outline-offset: 2px;
}
input:active,
textarea:active,
select:active {
box-shadow: none;
}
select {
background-image: linear-gradient(
45deg,
transparent 50%,
var(--foreground) 50%
),
linear-gradient(135deg, var(--foreground) 50%, transparent 50%);
background-position: calc(100% - 20px), calc(100% - 1em);
background-size:
5px 5px,
5px 5px;
background-repeat: no-repeat;
padding-right: 40px;
}
select option {
background: var(--background);
}
input[type="checkbox"] {
vertical-align: middle;
padding: 10px;
box-shadow: inset 0 0 0 3px var(--background);
}
input[type="checkbox"]:checked {
background: var(--accent);
}
img {
display: block;
max-width: 100%;
border: 8px solid var(--accent);
border-radius: var(--radius);
padding: 8px;
overflow: hidden;
}
figure img,
figure video {
margin-bottom: 0;
}
figure figcaption {
background: var(--accent);
color: var(--background);
text-align: center;
font-size: 1rem;
font-weight: normal;
margin-top: -8px;
border-radius: 0 0 var(--radius) var(--radius);
}
ul,
ol {
margin-left: 4ch;
padding: 0;
}
ul ul,
ul ol,
ol ul,
ol ol {
margin-top: 0;
}
li::marker {
color: var(--accent);
}
ul li,
ol li {
position: relative;
}
code,
kbd {
font-family:
"Fira Code",
Monaco,
Consolas,
Ubuntu Mono,
monospace !important;
font-feature-settings: normal;
background: color-mix(in srgb, var(--foreground) 5%, transparent);
color: var(--accent);
padding: 1px 6px;
margin: 0 2px;
font-size: 0.95rem;
}
kbd {
border-top: 1px solid color-mix(in srgb, var(--accent) 25%, transparent);
border-left: 1px solid var(--accent);
border-right: 1px solid var(--accent);
border-bottom: 4px solid var(--accent);
border-radius: 4px;
}
code code {
background: transparent;
padding: 0;
margin: 0;
}
pre {
tab-size: 4;
background: color-mix(in srgb, var(--foreground) 5%, transparent) !important;
color: var(--foreground);
padding: 20px 10px;
font-size: 0.95rem !important;
overflow: auto;
border-radius: var(--radius);
border: 1px solid color-mix(in srgb, var(--foreground) 10%, transparent);
}
pre code {
background: none !important;
margin: 0;
padding: 0;
font-size: inherit;
border: none;
}
sup {
line-height: 0;
}
abbr {
position: relative;
text-decoration-style: wavy;
text-decoration-color: var(--accent);
cursor: help;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.25em;
}
mark {
background: color-mix(in srgb, var(--accent) 45%, transparent);
color: var(--foreground);
}
blockquote {
position: relative;
border-top: 1px solid var(--accent);
border-bottom: 1px solid var(--accent);
margin: 0;
padding: 25px;
}
blockquote:before {
content: ">";
display: block;
position: absolute;
left: 0;
color: var(--accent);
}
blockquote p:first-child {
margin-top: 0;
}
blockquote p:last-child {
margin-bottom: 0;
}
table {
table-layout: auto;
border-collapse: collapse;
}
table,
th,
td {
border: 2px solid var(--foreground);
padding: 10px;
}
th {
border-style: solid;
color: var(--foreground);
text-align: left;
text-transform: uppercase;
letter-spacing: 0.04em;
}
hr {
width: 100%;
border: none;
background: var(--accent);
height: 2px;
}

File diff suppressed because one or more lines are too long

View file

@ -88,6 +88,6 @@ typings/
.dynamodb/ .dynamodb/
# End of https://www.gitignore.io/api/node # End of https://www.gitignore.io/api/node
public public
resources
.hugo_build.lock .hugo_build.lock

View file

@ -0,0 +1,12 @@
{
"extends": [
"stylelint-config-standard-scss",
"stylelint-config-prettier-scss"
],
"rules": {
"max-empty-lines": 1,
"color-function-notation": null,
"no-descending-specificity": null,
"selector-class-pattern": null
}
}

View file

@ -23,3 +23,12 @@ eg:
- **Single Page Website** (https://github.com/justinnuwin/hugo-theme-terminal) - **Single Page Website** (https://github.com/justinnuwin/hugo-theme-terminal)
- A layout where the homepage can render lists of pages and the navigation menu can link to sections on the homepage. - A layout where the homepage can render lists of pages and the navigation menu can link to sections on the homepage.
- Justin Nguyen, software and hardware developer. - Justin Nguyen, software and hardware developer.
- **Support for beautiful *KaTeX* formulae** ([amtoine/hugo-theme-terminal-katex](https://github.com/amtoine/hugo-theme-terminal-katex))
- SHORT DESCRIPTION
- Antoine Stevan ([@amtoine](https://github.com/amtoine)), software engineer into open source
- **Configurable timestamping for posts** ([KatieTheDev/hugo-theme-terminal](https://github.com/KatieTheDev/hugo-theme-terminal))
- Allows for configuring timestamping, not just datestamping
- Works with last modification dates as well
- KatieTheDev ([@KatieTheDev](https://github.com/KatieTheDev))

View file

@ -1,6 +1,6 @@
The MIT License (MIT) The MIT License (MIT)
Copyright (c) 2019 panr Copyright (c) 2024 panr
Permission is hereby granted, free of charge, to any person obtaining a copy of Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in this software and associated documentation files (the "Software"), to deal in

View file

@ -1,9 +1,14 @@
# Terminal # Terminal
![Terminal](https://github.com/panr/hugo-theme-terminal/blob/master/images/screenshot.png?raw=true) **Demo: https://panr.github.io/hugo-theme-terminal-demo/**
### DEMO - https://hugo-terminal.now.sh/ **Create your own color scheme: https://panr.github.io/terminal-css/**
### ⚠️ The theme needs at least Hugo **Extended** v0.90.x.
![Terminal](https://github.com/panr/hugo-theme-terminal/blob/master/images/terminal-theme.png?raw=true)
---
⚠️ The theme needs at least Hugo **Extended** v0.90.x.
--- ---
@ -19,11 +24,11 @@
- [Found a bug?](#bug) - [Found a bug?](#bug)
- [New cool idea or feature](#feature) - [New cool idea or feature](#feature)
- [Terminal theme user?](#terminal-theme-user) - [Terminal theme user?](#terminal-theme-user)
- [Licence](#licence) - [License](#license)
## Features ## Features
- **5 duotone themes**, depending on your preferences (orange is default, red, blue, green, pink) - fully customizable color schemes generated by [**Terminal.css**](https://panr.github.io/terminal-css/).
- [**Fira Code**](https://github.com/tonsky/FiraCode) as default monospaced font. It's gorgeous! - [**Fira Code**](https://github.com/tonsky/FiraCode) as default monospaced font. It's gorgeous!
- **really nice duotone**, custom syntax highlighting based on [**PrismJS**](https://prismjs.com) - **really nice duotone**, custom syntax highlighting based on [**PrismJS**](https://prismjs.com)
- fully responsive - fully responsive
@ -99,7 +104,7 @@ You can also choose **one of the 3 possibilities** to install the theme:
# you fetch the theme module. # you fetch the theme module.
# #
# hugo mod init [your website/module name] # hugo mod init [your website/module name]
hugo mod get github.com/panr/hugo-theme-terminal/v3 hugo mod get github.com/panr/hugo-theme-terminal/v4
``` ```
and in your config file add: and in your config file add:
@ -107,9 +112,9 @@ and in your config file add:
```toml ```toml
[module] [module]
# this is needed when you fetch the theme as a submodule to your repo. # this is needed when you fetch the theme as a submodule to your repo.
# replacements = "github.com/panr/hugo-theme-terminal -> themes/terminal" # replacements = "github.com/panr/hugo-theme-terminal/4 -> themes/terminal"
[[module.imports]] [[module.imports]]
path = 'github.com/panr/hugo-theme-terminal/v3' path = 'github.com/panr/hugo-theme-terminal/v4'
``` ```
Keep in mind that the theme by default won't show up in the `themes` directory. This means that you are using the theme as it was on the repository at the moment you fetched it. Your local `go.sum` file keeps all the references. Read more about Hugo Modules in the [official documentation](https://gohugo.io/hugo-modules/). Keep in mind that the theme by default won't show up in the `themes` directory. This means that you are using the theme as it was on the repository at the moment you fetched it. Your local `go.sum` file keeps all the references. Read more about Hugo Modules in the [official documentation](https://gohugo.io/hugo-modules/).
@ -163,9 +168,6 @@ paginate = 5
# the list of set content will show up on your index page (baseurl). # the list of set content will show up on your index page (baseurl).
contentTypeName = "posts" contentTypeName = "posts"
# ["orange", "blue", "red", "green", "pink"]
themeColor = "orange"
# if you set this to 0, only submenu trigger will be visible # if you set this to 0, only submenu trigger will be visible
showMenuItems = 2 showMenuItems = 2
@ -187,15 +189,9 @@ paginate = 5
# If you use git, you can set `enableGitInfo` to `true` and then post will automatically get the last updated # If you use git, you can set `enableGitInfo` to `true` and then post will automatically get the last updated
showLastUpdated = false showLastUpdated = false
# set a custom favicon (default is a `themeColor` square)
# favicon = "favicon.ico"
# Provide a string as a prefix for the last update date. By default, it looks like this: 2020-xx-xx [Updated: 2020-xx-xx] :: Author # Provide a string as a prefix for the last update date. By default, it looks like this: 2020-xx-xx [Updated: 2020-xx-xx] :: Author
# updatedDatePrefix = "Updated" # updatedDatePrefix = "Updated"
# set all headings to their default size (depending on browser settings)
# oneHeadingSize = true # default
# whether to show a page's estimated reading time # whether to show a page's estimated reading time
# readingTime = false # default # readingTime = false # default
@ -207,6 +203,20 @@ paginate = 5
# can be overridden in a page's front-matter # can be overridden in a page's front-matter
# TocTitle = "Table of Contents" # default # TocTitle = "Table of Contents" # default
# Set date/time format for posts
# This will impact the date/time displayed on
# index.html, the posts list page, and on posts themselves
# This value can also be configured per-post on front matter
# If you have any issues with the timezone rendering differently
# than you expected, please ensure your timezone is correctly set
# on your server.
# This value can be customized according to Hugo documentation:
# https://gohugo.io/functions/time/format/
# Default value (no changes needed):
# dateFormat = "2006-01-02"
# Example format, with date, time, and timezone abbreviation:
# dateFormat = "2006-01-02 3:04:06 PM MST"
[params.twitter] [params.twitter]
# set Twitter handles for Twitter cards # set Twitter handles for Twitter cards
@ -219,45 +229,45 @@ paginate = 5
[languages.en] [languages.en]
languageName = "English" languageName = "English"
title = "Terminal" title = "Terminal"
subtitle = "A simple, retro theme for Hugo"
owner = ""
keywords = ""
copyright = ""
menuMore = "Show more"
readMore = "Read more"
readOtherPosts = "Read other posts"
newerPosts = "Newer posts"
olderPosts = "Older posts"
missingContentMessage = "Page not found..."
missingBackButtonLabel = "Back to home page"
minuteReadingTime = "min read"
words = "words"
[languages.en.params.logo] [languages.en.params]
logoText = "Terminal" subtitle = "A simple, retro theme for Hugo"
logoHomeLink = "/" owner = ""
keywords = ""
copyright = ""
menuMore = "Show more"
readMore = "Read more"
readOtherPosts = "Read other posts"
newerPosts = "Newer posts"
olderPosts = "Older posts"
missingContentMessage = "Page not found..."
missingBackButtonLabel = "Back to home page"
minuteReadingTime = "min read"
words = "words"
[languages.en.menu] [languages.en.params.logo]
[[languages.en.menu.main]] logoText = "Terminal"
identifier = "about" logoHomeLink = "/"
name = "About"
url = "/about" [languages.en.menu]
[[languages.en.menu.main]] [[languages.en.menu.main]]
identifier = "showcase" identifier = "about"
name = "Showcase" name = "About"
url = "/showcase" url = "/about"
[[languages.en.menu.main]]
identifier = "showcase"
name = "Showcase"
url = "/showcase"
[module] [module]
# In case you would like to make changes to the theme and keep it locally in you repository, # In case you would like to make changes to the theme and keep it locally in you repository,
# uncomment the line below (and correct the local path if necessary). # uncomment the line below (and correct the local path if necessary).
# -- # --
# replacements = "github.com/panr/hugo-theme-terminal -> themes/terminal" # replacements = "github.com/panr/hugo-theme-terminal/v4 -> themes/terminal"
[[module.imports]] [[module.imports]]
path = 'github.com/panr/hugo-theme-terminal' path = 'github.com/panr/hugo-theme-terminal/v4'
``` ```
to `config.toml` file in your Hugo root directory and change params fields. In case you need, here's [a YAML version](https://gist.github.com/panr/9eeea6f595c257febdadc11763e3a6d1).
**NOTE:** Please keep in mind that currently `main menu` doesn't support nesting. **NOTE:** Please keep in mind that currently `main menu` doesn't support nesting.
## Post archetype ## Post archetype
@ -304,6 +314,6 @@ I'd be happy to know more about you and what you are doing. If you want to share
## License ## License
Copyright © 2019-2022 Radosław Kozieł ([@panr](https://twitter.com/panr)) Copyright © 2019-2024 Radosław Kozieł ([@panr](https://twitter.com/panr))
The theme is released under the MIT License. Check the [original theme license](https://github.com/panr/hugo-theme-terminal/blob/master/LICENSE.md) for additional licensing information. The theme is released under the MIT License. Check the [original theme license](https://github.com/panr/hugo-theme-terminal/blob/master/LICENSE.md) for additional licensing information.

View file

@ -1,27 +1,20 @@
# Meet the users of Terminal theme! # Meet the users of Terminal theme!
- https://xicode.se **magistern** (Teacher) - https://xicode.se **magistern** (Teacher)
- https://devmaster64.com **devmaster64** (Software Developer) - https://devmaster64.com **devmaster64** (Software Developer)
- https://mickie1.gitlab.io/blog/ **mickie** (Engineer)
- https://calloc.net **Vaibhav Yenamandra** (Software Engineer) - https://calloc.net **Vaibhav Yenamandra** (Software Engineer)
- https://potatofrom.space **Kevin Liu** (Software) - https://potatofrom.space **Kevin Liu** (Software)
- https://horochx.org **horochx** (Software Developer) - https://horochx.org **horochx** (Software Developer)
- https://feng.si **Si Feng** (Software Engineer) - https://feng.si **Si Feng** (Software Engineer)
- https://ben-on-vms.com **Benedikt Frenzel** (Technical Support Engineer) - https://ben-on-vms.com **Benedikt Frenzel** (Technical Support Engineer)
- https://johngazzini.com **John Gazzini** (Software Engineer) - https://johngazzini.com **John Gazzini** (Software Engineer)
- https://geekx.tech/ **Sagar Ladla** (Student Developer & Cyber Security Specialist)
- https://tears.io/ **Alex** (SRE) - https://tears.io/ **Alex** (SRE)
- https://ayushkarn.me/ **Ayush Karn** (Student Developer) - https://ayushkarn.me/ **Ayush Karn** (Student Developer)
- https://ssgram.dev **Ramaseshan Parthasarathy** (Software Developer)
- https://zaine.me **Amine Zaine** (Cloud Engineer) - https://zaine.me **Amine Zaine** (Cloud Engineer)
- https://notes.dmaitre.phyip3.dur.ac.uk/computing-club/ **Ryan Moodie** (Physics PhD student) - https://notes.dmaitre.phyip3.dur.ac.uk/computing-club/ **Ryan Moodie** (Physics PhD student)
- https://thecodecousins.com **Stanley Nguyen** (Software Engineer) & **Hoang Do** (Software & IoT Engineer)
- https://schacherbauer.dev **Markus Schacherbauer** (Student Developer)
- https://rinma.dev **Marvin Dalheimer** (Software Developer)
- https://lunar.computer **Lunar Computer** (DevOps Engineer) - https://lunar.computer **Lunar Computer** (DevOps Engineer)
- https://naxxfish.net **Chris Roberts** (Broadcast Systems Engineer) - https://naxxfish.net **Chris Roberts** (Broadcast Systems Engineer)
- https://security.jtang.dev **Jonathan Tang** (Student & Software Engineer)
- https://andreacaravano.net **Andrea Caravano** (Student) - https://andreacaravano.net **Andrea Caravano** (Student)
- https://dawsonverboven.com/ **Dawson Verboven** (Student & Software Developer)
- https://qbunt.com **Jeremy Bunting** (Software Engineer) - https://qbunt.com **Jeremy Bunting** (Software Engineer)
- https://smeik.org **Smeik** (Embedded Developer) - https://smeik.org **Smeik** (Embedded Developer)
- https://code.willstocks.co.uk **Will Stocks** (Blogger & Developer) - https://code.willstocks.co.uk **Will Stocks** (Blogger & Developer)
@ -30,13 +23,9 @@
- https://bgameiro.me/ **Bernardo Gameiro** (Engineer Physicist student) - https://bgameiro.me/ **Bernardo Gameiro** (Engineer Physicist student)
- https://return-to-libc.com/ **elraro** (Cyber Security Specialist) - https://return-to-libc.com/ **elraro** (Cyber Security Specialist)
- https://pablart.com/ **Pablo Diaz-Gutierrez** (Software Engineer, General Tinkerer) - https://pablart.com/ **Pablo Diaz-Gutierrez** (Software Engineer, General Tinkerer)
- https://waterloos.niflheimr.blue/ **cindrmon** (Student and Aspiring Software Engineer)
- https://monocle.rpod.club/ **classx** (DevOps Engineer) - https://monocle.rpod.club/ **classx** (DevOps Engineer)
- https://wjdevschool.com/ **Wojciech Bogócki** (Making Things & Teaching / W&J Dev School)
- https://erisianrite.com/ **ErisianRite** (Coding, Engineering, Tools for Thought) - https://erisianrite.com/ **ErisianRite** (Coding, Engineering, Tools for Thought)
- https://dongzhi.me **Joe** (Software Developer)
- https://isaes.com.tr/ **Isa Es** (Software Engineer) - https://isaes.com.tr/ **Isa Es** (Software Engineer)
- https://conight.com **Conight Wang** (Software Engineer)
- https://blog.m5e.de/ **Christoph Miksche** (Software Developer) - https://blog.m5e.de/ **Christoph Miksche** (Software Developer)
- https://mpostument.com/ **Maksym Postument** (DevOps Engineer) - https://mpostument.com/ **Maksym Postument** (DevOps Engineer)
- https://mathiejosh.xyz **Josh Mathie** (Electrical Engineering Technology Student/Sales and Engineering Tech) - https://mathiejosh.xyz **Josh Mathie** (Electrical Engineering Technology Student/Sales and Engineering Tech)
@ -44,8 +33,6 @@
- https://blog.puvvadi.me **KD Puvvadi** (Software Dev & Cloud Orchestrator) - https://blog.puvvadi.me **KD Puvvadi** (Software Dev & Cloud Orchestrator)
- https://hidden.land/ **Louisload** (Game Developer & Musician) - https://hidden.land/ **Louisload** (Game Developer & Musician)
- https://linuxbase.nl **Michael Trip** (DevOps Engineer) - https://linuxbase.nl **Michael Trip** (DevOps Engineer)
- https://markopolo123.github.io **Markopolo** (DevOps Engineer)
- https://openfoxblog.leven.dev/ **Damon Leven** (Student & Software Developer)
- https://blog.sethforprivacy.com **Seth For Privacy** (Security, privacy, and cryptocurrency writer, podcaster) - https://blog.sethforprivacy.com **Seth For Privacy** (Security, privacy, and cryptocurrency writer, podcaster)
- https://thesprawl.city **crish** (Software and stuff) - https://thesprawl.city **crish** (Software and stuff)
- https://justinnuwin.com **Justin Nguyen** (Software & Hardware Developer) - https://justinnuwin.com **Justin Nguyen** (Software & Hardware Developer)
@ -55,17 +42,27 @@
- https://biplav.xyz **Biplav's Blog** (Student) - https://biplav.xyz **Biplav's Blog** (Student)
- https://santiago.wtf **Nicholas Santiago** (DevOps Engineer) - https://santiago.wtf **Nicholas Santiago** (DevOps Engineer)
- https://2200g.github.io/ **2200g** (Blogger/Student) - https://2200g.github.io/ **2200g** (Blogger/Student)
- https://cristiioan.me **Cristian Margine** (Student)
- https://they.mint.lgbt **Joey Aliaga** (Software Developer & Student) - https://they.mint.lgbt **Joey Aliaga** (Software Developer & Student)
- https://tatewilhelm.me **Tate Wilhelm** (Student, Programmer & Tinkerer) - https://tatewilhelm.me **Tate Wilhelm** (Student, Programmer & Tinkerer)
- https://mikefoden.com **Mike Foden** (Software Developer) - https://mikefoden.com **Mike Foden** (Software Developer)
- https://undemalum.github.io/portfolio/ **Mateusz Konat** (Student) - https://undemalum.github.io/portfolio/ **Mateusz Konat** (Student)
- https://ku0hn.radio **Ben Kuhn** (Ham Radio Operator, InfoSec Engineer, Tinkerer) - https://ku0hn.radio **Ben Kuhn** (Ham Radio Operator, InfoSec Engineer, Tinkerer)
- https://bg117.xyz/projects **bg117** (Student and Hobby Programmer)
- https://www.grumpymetalguy.com **GrumpyMetalGuy** (General Grumper and Developer) - https://www.grumpymetalguy.com **GrumpyMetalGuy** (General Grumper and Developer)
- https://blog.jontes.page **Jonte** (general tech geek) - https://blog.jontes.page **Jonte** (general tech geek)
- https://nazdarthegame.com/ **Michal Skoula** (Software Developer) - https://nazdarthegame.com/ **Michal Skoula** (Software Developer)
- https://1mup.myorange.house **Antonio Garosi** (Street art gallery) - https://1mup.myorange.house **Antonio Garosi** (Street art gallery)
- https://kitchvx.github.io **Nathan Kitching** (IT Student)
- https://dgood.win **Dom Goodwin** (Platform Engineer)
- https://sir-photch.xyz **Sir-Photch** (ComSci-student. German Blog)
- https://drewmorris.info **Drew Morris** (Mathematician && Computer Scientist)
- https://blog.darkiiiiiice.com **MarioMang** (Software Developer)
- https://www.sagbot.com **E. HADDAG** (Computer Scientist)
- https://adamperkowski.dev **Adam Perkowski** (A Random Developer)
- https://imortio.github.io **Azrul** (CompSci Student)
- https://carmar.is **Carmaris** (Amateur Hacker)
- https://ragonneau.github.io **Tom Ragonneau** (Engineer)
- https://katiethe.dev **KatieTheDev** (Amateur porgrammer and tinkerer)
- https://stefka.eu **Jiří Štefka** (Software Developer)
<!-- <!--
TEMPLATE: TEMPLATE:
@ -73,3 +70,5 @@
- https://radoslawkoziel.pl **Radek Kozieł** (Software Designer and Developer) - https://radoslawkoziel.pl **Radek Kozieł** (Software Designer and Developer)
--> -->

View file

@ -1,6 +1,7 @@
+++ +++
title = "{{ replace .TranslationBaseName "-" " " | title }}" title = "{{ replace .TranslationBaseName "-" " " | title }}"
date = "{{ .Date }}" date = "{{ .Date }}"
#dateFormat = "2006-01-02" # This value can be configured for per-post date formatting
author = "" author = ""
authorTwitter = "" #do not include @ authorTwitter = "" #do not include @
cover = "" cover = ""
@ -10,5 +11,4 @@ description = ""
showFullContent = false showFullContent = false
readingTime = false readingTime = false
hideComments = false hideComments = false
color = "" #color from the theme settings
+++ +++

View file

@ -0,0 +1,123 @@
.button-container {
display: table;
margin-left: auto;
margin-right: auto;
}
button,
.button,
a.button {
position: relative;
display: inline-flex;
align-items: center;
justify-content: center;
padding: 8px 18px;
text-decoration: none;
text-align: center;
border-radius: 8;
font: inherit;
font-weight: bold;
appearance: none;
cursor: pointer;
outline: none;
}
button.outline,
.button.outline,
a.button.outline {
background: transparent;
box-shadow: none;
padding: 8px 18px;
}
button.outline :hover,
.button.outline :hover,
a.button.outline :hover {
transform: none;
box-shadow: none;
}
button.link,
.button.link,
a.button.link {
background: none;
font-size: 1rem;
}
button.small,
.button.small,
a.button.small {
font-size: 0.8rem;
}
button.wide,
.button.wide,
a.button.wide {
min-width: 200px;
padding: 14px 24px;
}
a.button.inline {
background: none;
color: var(--accent);
padding: initial;
margin: initial;
border: initial;
font-weight: initial;
text-decoration: none;
}
a.button.inline:active,
a.button.inline:hover {
background: none;
}
a.button.inline::before {
content: "["
}
a.button.inline::after {
content: "]"
}
a.button.inline.prev::before {
content: "← ["
}
a.button.inline.next::after {
content: "] →"
}
a.read-more,
a.read-more:hover,
a.read-more:active {
display: inline-flex;
border: none;
background: none;
box-shadow: none;
padding: 0;
max-width: 100%;
text-decoration: none;
}
.code-toolbar {
margin-bottom: 20px;
}
.code-toolbar .toolbar-item a {
position: relative;
display: inline-flex;
align-items: center;
justify-content: center;
padding: 3px 8px;
margin-bottom: 5px;
text-decoration: none;
text-align: center;
font-size: 13px;
font-weight: 500;
border-radius: 8px;
border: 1px solid transparent;
appearance: none;
cursor: pointer;
outline: none;
}

View file

@ -0,0 +1,117 @@
pre {
margin: 20px 0;
}
.code-toolbar {
position: relative;
margin: 20px 0;
border: 1px solid color-mix(in srgb, var(--accent) 10%, transparent);
}
.code-toolbar + .code-toolbar,
.code-toolbar + .highlight,
.code-toolbar + .highlight .code-toolbar {
border-top: 0;
margin-top: -20px;
}
.code-toolbar pre, .code-toolbar code {
border: none;
}
.code-toolbar code {
display: block;
color: color-mix(in srgb, var(--accent) 50%, var(--foreground));
}
.code-toolbar > .toolbar button {
font-size: 0.8em !important;
font-weight: bold !important;
background: var(--accent) !important;
color: var(--background) !important;
border-radius: var(--radius) !important;
box-shadow: none !important;
border: 1px solid var(--background) !important;
margin: 6px !important;
padding: 10px !important;
user-select: none;
}
.collapsable-code {
position: relative;
width: 100%;
margin: 40px 0;
}
.collapsable-code input[type=checkbox] {
position: absolute;
visibility: hidden;
}
.collapsable-code input[type=checkbox]:checked ~ pre,
.collapsable-code input[type=checkbox]:checked ~ .code-toolbar pre {
display: none;
}
.collapsable-code input[type=checkbox]:checked ~ .code-toolbar {
padding: 0;
border-top: none;
}
.collapsable-code input[type=checkbox]:checked ~ .code-toolbar .toolbar {
display: none;
}
.collapsable-code input[type=checkbox]:checked ~ label .collapsable-code__toggle::after {
content: attr(data-label-expand);
}
.collapsable-code label {
position: relative;
display: flex;
justify-content: space-between;
min-width: 30px;
min-height: 30px;
margin: 0;
border-bottom: 1px solid var(--accent);
cursor: pointer;
}
.collapsable-code__title {
flex: 1;
color: var(--accent);
padding: 3px 10px;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.collapsable-code__language {
color: var(--accent);
border: 1px solid var(--accent);
border-bottom: none;
text-transform: uppercase;
padding: 3px 10px;
}
.collapsable-code__toggle {
color: var(--accent);
font-size: 16px;
padding: 3px 10px;
}
.collapsable-code__toggle::after {
content: attr(data-label-collapse);
}
.collapsable-code pre {
margin-top: 0;
}
.collapsable-code pre::first-line {
line-height: 0;
}
.collapsable-code .code-toolbar {
margin: 0;
}

View file

@ -0,0 +1,19 @@
@font-face {
font-display: swap;
font-family: "Fira Code";
font-style: normal;
font-weight: 400;
src: url("../fonts/FiraCode-Regular.woff") format("woff");
font-feature-settings: "liga", "tnum", "ss01", "locl";
font-variant-ligatures: contextual;
}
@font-face {
font-display: swap;
font-family: "Fira Code";
font-style: normal;
font-weight: 800;
src: url("../fonts/FiraCode-Bold.woff") format("woff");
font-feature-settings: "liga", "tnum", "ss01", "locl";
font-variant-ligatures: contextual;
}

View file

@ -0,0 +1,46 @@
.footer {
padding: 40px 0;
flex-grow: 0;
opacity: 0.5;
}
.footer__inner {
display: flex;
align-items: center;
justify-content: space-between;
margin: 0;
width: 760px;
max-width: 100%;
}
.footer a {
color: inherit;
}
.footer .copyright {
display: flex;
flex-flow: row wrap;
flex: 1;
align-items: center;
font-size: 1rem;
justify-content: center;
}
.footer .copyright--user {
margin: auto;
text-align: center;
}
.footer .copyright > *:first-child:not(:only-child) {
margin-right: 10px;
}
.footer .copyright span {
white-space: nowrap;
}
@media (max-width: 900px) {
.footer__inner {
flex-direction: column;
}
}

View file

@ -0,0 +1,4 @@
body .gist .blob-num,
body .gist .blob-code-inner {
border: none;
}

View file

@ -0,0 +1,45 @@
.header {
display: flex;
flex-direction: column;
position: relative;
}
.header__inner {
display: flex;
align-items: center;
justify-content: space-between;
}
.header__logo {
display: flex;
flex: 1;
}
.header__logo::after {
content: "";
background: repeating-linear-gradient(90deg, var(--accent), var(--accent) 2px, transparent 0, transparent 10px);
display: block;
width: 100%;
right: 10px;
}
.header__logo a {
flex: 0 0 auto;
max-width: 100%;
text-decoration: none;
}
.logo {
display: flex;
align-items: center;
text-decoration: none;
background: var(--accent);
color: var(--background);
padding: 5px 10px;
}
@media print {
.header {
display: none;
}
}

View file

@ -0,0 +1,167 @@
html {
box-sizing: border-box;
}
*,
*::before,
*::after {
box-sizing: inherit;
}
body {
margin: 0;
padding: 0;
font-family: "Fira Code", Monaco, Consolas, "Ubuntu Mono", monospace;
font-size: 1rem;
line-height: 1.54;
letter-spacing: -0.02em;
background-color: var(--background);
color: var(--foreground);
text-rendering: optimizelegibility;
-webkit-font-smoothing: antialiased;
-webkit-overflow-scrolling: touch;
text-size-adjust: 100%;
}
.headings--one-size h1,
.headings--one-size h2,
.headings--one-size h3,
.headings--one-size h4,
.headings--one-size h5,
.headings--one-size h6 {
font-size: 1.4rem;
line-height: 1.3;
margin: 20px 0;
}
.headings--one-size ~ h1:first-child,
.headings--one-size ~ h2:first-child,
.headings--one-size ~ h3:first-child,
.headings--one-size ~ h4:first-child,
.headings--one-size ~ h5:first-child,
.headings--one-size ~ h6:first-child {
margin-top: 20px;
}
img.left {
margin-right: auto;
}
img.center {
margin-left: auto;
margin-right: auto;
}
img.right {
margin-left: auto;
}
figure.left {
margin-right: auto;
}
figure.center {
margin-left: auto;
margin-right: auto;
}
figure.right {
margin-left: auto;
}
figure figcaption.left {
text-align: left;
}
figure figcaption.center {
text-align: center;
}
figure figcaption.right {
text-align: right;
}
blockquote.twitter-tweet {
position: relative;
background: var(--background);
font: inherit;
color: inherit;
border: 1px solid var(--accent);
padding-top: 60px;
}
blockquote.twitter-tweet a {
color: var(--accent);
text-decoration: underline;
}
blockquote.twitter-tweet::before {
content: "> From X:";
position: absolute;
top: 20px;
left: 20px;
color: var(--accent);
font-weight: bold;
}
.container {
display: flex;
flex-direction: column;
padding: 40px;
max-width: 864px;
min-height: 100vh;
border-right: 1px solid color-mix(in srgb, var(--accent) 10%, transparent);
}
.container.full, .container.center {
border: none;
margin: 0 auto;
}
.container.full {
max-width: 100%;
}
.content {
display: flex;
flex-direction: column;
}
.hidden {
display: none;
}
.__h_video {
padding-bottom: 58.23% !important;
overflow: visible !important;
}
iframe[src*="youtube.com"] {
border: 8px solid var(--accent) !important;
padding: 8px !important;
}
@media (max-width: 684px) {
body {
font-size: 1rem;
}
.container {
padding: 20px;
}
ul,
ol {
margin-left: 20px;
}
}
@media print {
.container {
display: initial;
}
.content {
display: initial;
}
}

View file

@ -0,0 +1,148 @@
.navigation-menu {
display: flex;
align-items: flex-start;
justify-content: space-between;
margin: 20px 1px;
}
.navigation-menu__inner {
display: flex;
flex: 1;
flex-wrap: wrap;
list-style: none;
margin: 0;
padding: 0;
}
.navigation-menu__inner > li {
flex: 0 0 auto;
margin-bottom: 10px;
white-space: nowrap;
}
.navigation-menu__inner > li:not(:last-of-type) {
margin-right: 20px;
}
.navigation-menu .spacer {
flex-grow: 1 !important;
}
.menu {
display: flex;
flex-direction: column;
position: relative;
list-style: none;
padding: 0;
margin: 0;
}
.menu__trigger {
margin-right: 0 !important;
color: var(--accent);
user-select: none;
cursor: pointer;
}
.menu__dropdown {
display: none;
flex-direction: column;
position: absolute;
background: var(--background);
box-shadow: 0 10px var(--background), -10px 10px var(--background), 10px 10px var(--background);
color: var(--accent);
border: 2px solid var(--accent);
margin: 0;
padding: 10px;
top: 10px;
left: 0;
list-style: none;
z-index: 99;
}
.open .menu__dropdown {
display: flex;
}
.menu__dropdown > li {
flex: 0 0 auto;
}
.menu__dropdown > li:not(:last-of-type) {
margin-bottom: 10px;
}
.menu__dropdown > li a {
display: flex;
padding: 5px;
}
.menu--mobile .menu__trigger {
color: var(--accent);
border: 2px solid;
margin-left: 10px;
height: 100%;
padding: 3px 8px;
margin-bottom: 0 !important;
position: relative;
cursor: pointer;
display: none;
}
.menu--mobile li {
flex: 0 0 auto;
}
.menu--mobile li:not(:last-of-type) {
margin-bottom: 10px;
}
.menu--language-selector .menu__trigger {
color: var(--accent);
border: 2px solid;
margin-left: 10px;
height: 100%;
padding: 3px 8px;
margin-bottom: 0 !important;
position: relative;
cursor: pointer;
}
.menu--language-selector .menu__dropdown {
left: auto;
right: 0;
}
@media (max-width: 684px) {
.navigation-menu {
margin: 0;
}
.navigation-menu__inner {
flex-direction: column;
align-items: flex-start;
padding: 0;
}
.navigation-menu__inner li {
margin: 0;
padding: 5px;
}
.menu--desktop {
display: none;
}
.menu--mobile .menu__trigger {
display: block;
}
.menu--mobile .menu__dropdown {
left: auto;
right: 0;
}
.menu--language-selector .menu__trigger {
display: none;
}
}

View file

@ -0,0 +1,96 @@
.pagination {
margin-top: 50px;
}
.pagination__title {
display: flex;
text-align: center;
position: relative;
margin: 100px 0 20px;
}
.pagination__title-h {
text-align: center;
margin: 0 auto;
padding: 5px 10px;
background: var(--background);
color: color-mix(in srgb var(--foreground) 30%, transparent);
font-size: 0.8rem;
text-transform: uppercase;
text-decoration: none;
letter-spacing: 0.1em;
z-index: 1;
}
.pagination__title hr {
position: absolute;
left: 0;
right: 0;
width: 100%;
margin-top: 15px;
z-index: 0;
}
.pagination__buttons {
display: flex;
align-items: center;
justify-content: center;
flex-flow: row wrap;
gap: 10px;
}
.pagination__buttons a {
display: inline-flex;
max-width: 100%;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
text-decoration: none;
}
.button {
position: relative;
display: inline-flex;
align-items: center;
justify-content: center;
font-size: 1rem;
padding: 0;
appearance: none;
}
.button a {
display: flex;
justify-content: center;
flex: 1;
padding: 8px 16px;
text-decoration: none;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.button__text {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.next .button__icon {
margin-left: 8px;
}
.prev .button__icon {
margin-right: 8px;
}
@media (max-width: 684px) {
.button {
flex: 1;
}
}
@media print {
.pagination {
display: none;
}
}

View file

@ -0,0 +1,141 @@
.index-content {
margin-top: 20px;
}
.framed {
border: 1px solid var(--accent);
padding: 20px;
}
.framed *:first-child {
margin-top: 0;
}
.framed *:last-child {
margin-bottom: 0;
}
.posts {
width: 100%;
}
.post {
width: 100%;
text-align: left;
padding: 40px 0;
}
.post:not(:last-of-type) {
border-bottom: 1px solid color-mix(in srgb, var(--foreground) 10%, transparent);
}
.post-meta {
font-size: 1rem;
margin-bottom: 10px;
color: color-mix(in srgb, var(--foreground) 50%, transparent);
}
.post-meta > *:not(:first-child)::before {
content: "::";
display: inline-block;
margin: 0 8px;
}
.post-title {
position: relative;
color: var(--accent);
margin-top: 0 !important;
margin-bottom: 15px !important;
padding-bottom: 15px;
border-bottom: 3px dotted var(--accent);
text-decoration: none !important;
}
.post-title::after {
content: "";
position: absolute;
bottom: 2px;
display: block;
width: 100%;
border-bottom: 3px dotted var(--accent);
}
.post-title a {
text-decoration: none;
}
.post-tags {
display: block;
margin-bottom: 20px;
font-size: 1rem;
color: var(--accent);
}
.table-of-contents {
margin: 40px 0;
}
.post-content {
margin-top: 30px;
}
.post-cover {
margin: 40px 0;
}
.post ul {
list-style: none;
}
.post ul li:not(:empty)::before {
content: "-";
position: absolute;
left: -20px;
color: var(--accent);
}
.post--regulation h1 {
justify-content: center;
}
.post--regulation h2 {
justify-content: center;
margin-bottom: 10px;
}
.post--regulation h2 + h2 {
margin-top: -10px;
margin-bottom: 20px;
}
.hanchor {
position: absolute;
color: var(--accent);
text-decoration: none;
margin-left: 10px;
visibility: hidden;
}
h1:hover .hanchor,
h2:hover .hanchor,
h3:hover .hanchor,
h4:hover .hanchor,
h5:hover .hanchor,
h6:hover .hanchor {
visibility: visible;
}
.footnotes {
color: color-mix(in srgb, var(--foreground) 50%, transparent);
}
.footnotes hr {
background: color-mix(in srgb, var(--foreground) 50%, transparent);
}
@media (max-width: 684px) {
.post-cover {
padding: 10px;
border-width: 10px;
}
}

View file

@ -0,0 +1,322 @@
/* PrismJS 1.24.1
https://prismjs.com/download.html#themes=prism-tomorrow&languages=markup+css+clike+javascript+actionscript+apacheconf+applescript+bash+c+csharp+cpp+cmake+coffeescript+csp+css-extras+diff+django+docker+elixir+elm+erlang+fsharp+flow+git+go+graphql+haml+handlebars+haskell+http+java+json+kotlin+latex+less+llvm+makefile+markdown+markup-templating+nasm+objectivec+ocaml+perl+php+php-extras+powershell+processing+pug+python+r+jsx+tsx+reason+ruby+rust+sass+scss+scala+scheme+sql+stylus+swift+textile+toml+twig+typescript+vim+visual-basic+wasm+yaml&plugins=line-highlight+line-numbers+jsonp-highlight+highlight-keywords+command-line+toolbar+copy-to-clipboard */
/**
* prism.js tomorrow night eighties for JavaScript, CoffeeScript, CSS and HTML
* Based on https://github.com/chriskempson/tomorrow-theme
* @author Rose Pritchard
*/
code[class*=language-],
pre[class*=language-] {
color: #ccc;
background: none;
font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;
font-size: 1em;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
word-wrap: normal;
line-height: 1.5;
tab-size: 4;
hyphens: none;
}
/* Code blocks */
pre[class*=language-] {
padding: 1em;
margin: 0.5em 0;
overflow: auto;
}
:not(pre) > code[class*=language-],
pre[class*=language-] {
background: #2d2d2d;
}
/* Inline code */
:not(pre) > code[class*=language-] {
padding: 0.1em;
border-radius: 0.3em;
white-space: normal;
}
.token.comment,
.token.block-comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: #999;
}
.token.punctuation {
color: #ccc;
}
.token.tag,
.token.attr-name,
.token.namespace,
.token.deleted {
color: #e2777a;
}
.token.function-name {
color: #6196cc;
}
.token.boolean,
.token.number,
.token.function {
color: #f08d49;
}
.token.property,
.token.class-name,
.token.constant,
.token.symbol {
color: #f8c555;
}
.token.selector,
.token.important,
.token.atrule,
.token.keyword,
.token.builtin {
color: #cc99cd;
}
.token.string,
.token.char,
.token.attr-value,
.token.regex,
.token.variable {
color: #7ec699;
}
.token.operator,
.token.entity,
.token.url {
color: #67cdcc;
}
.token.important,
.token.bold {
font-weight: bold;
}
.token.italic {
font-style: italic;
}
.token.entity {
cursor: help;
}
.token.inserted {
color: green;
}
pre[data-line] {
position: relative;
padding: 1em 0 1em 3em;
}
.line-highlight {
position: absolute;
left: 0;
right: 0;
padding: inherit 0;
margin-top: 1em;
/* Same as .prisms padding-top */
background: hsla(24deg, 20%, 50%, 8%);
background: linear-gradient(to right, hsla(24deg, 20%, 50%, 10%) 70%, hsla(24deg, 20%, 50%, 0%));
pointer-events: none;
line-height: inherit;
white-space: pre;
}
@media print {
.line-highlight {
/*
* This will prevent browsers from replacing the background color with white.
* It's necessary because the element is layered on top of the displayed code.
*/
-webkit-print-color-adjust: exact;
color-adjust: exact;
}
}
.line-highlight::before,
.line-highlight[data-end]::after {
content: attr(data-start);
position: absolute;
top: 0.4em;
left: 0.6em;
min-width: 1em;
padding: 0 0.5em;
background-color: hsla(24deg, 20%, 50%, 40%);
color: hsl(24deg, 20%, 95%);
font: bold 65%/1.5 sans-serif;
text-align: center;
vertical-align: 0.3em;
border-radius: 999px;
text-shadow: none;
box-shadow: 0 1px white;
}
.line-highlight[data-end]::after {
content: attr(data-end);
top: auto;
bottom: 0.4em;
}
.line-numbers .line-highlight::before,
.line-numbers .line-highlight::after {
content: none;
}
pre[id].linkable-line-numbers span.line-numbers-rows {
pointer-events: all;
}
pre[id].linkable-line-numbers span.line-numbers-rows > span::before {
cursor: pointer;
}
pre[id].linkable-line-numbers span.line-numbers-rows > span:hover::before {
background-color: rgba(128, 128, 128, 20%);
}
pre[class*=language-].line-numbers {
position: relative;
padding-left: 3.8em;
counter-reset: linenumber;
}
pre[class*=language-].line-numbers > code {
position: relative;
white-space: inherit;
}
.line-numbers .line-numbers-rows {
position: absolute;
pointer-events: none;
top: 0;
font-size: 100%;
left: -3.8em;
width: 3em;
/* works for line-numbers below 1000 lines */
letter-spacing: -1px;
border-right: 1px solid #999;
user-select: none;
}
.line-numbers-rows > span {
display: block;
counter-increment: linenumber;
}
.line-numbers-rows > span::before {
content: counter(linenumber);
color: #999;
display: block;
padding-right: 0.8em;
text-align: right;
}
.command-line-prompt {
border-right: 1px solid #999;
display: block;
float: left;
font-size: 100%;
letter-spacing: -1px;
margin-right: 1em;
pointer-events: none;
user-select: none;
}
.command-line-prompt > span::before {
color: #999;
content: " ";
display: block;
padding-right: 0.8em;
}
.command-line-prompt > span[data-user]::before {
content: "["attr(data-user) "@"attr(data-host) "] $";
}
.command-line-prompt > span[data-user=root]::before {
content: "["attr(data-user) "@"attr(data-host) "] #";
}
.command-line-prompt > span[data-prompt]::before {
content: attr(data-prompt);
}
div.code-toolbar {
position: relative;
}
div.code-toolbar > .toolbar {
position: absolute;
top: 0.3em;
right: 0.2em;
transition: opacity 0.3s ease-in-out;
opacity: 0;
}
div.code-toolbar:hover > .toolbar {
opacity: 1;
}
/* Separate line b/c rules are thrown out if selector is invalid.
IE11 and old Edge versions don't support :focus-within. */
div.code-toolbar:focus-within > .toolbar {
opacity: 1;
}
div.code-toolbar > .toolbar > .toolbar-item {
display: inline-block;
}
div.code-toolbar > .toolbar > .toolbar-item > a {
cursor: pointer;
}
div.code-toolbar > .toolbar > .toolbar-item > button {
background: none;
border: 0;
color: inherit;
font: inherit;
line-height: normal;
overflow: visible;
padding: 0;
/* for button */
user-select: none;
}
div.code-toolbar > .toolbar > .toolbar-item > a,
div.code-toolbar > .toolbar > .toolbar-item > button,
div.code-toolbar > .toolbar > .toolbar-item > span {
color: #bbb;
font-size: 0.8em;
padding: 0 0.5em;
background: #f5f2f0;
background: rgba(224, 224, 224, 20%);
box-shadow: 0 2px 0 0 rgba(0, 0, 0, 20%);
border-radius: 0.5em;
}
div.code-toolbar > .toolbar > .toolbar-item > a:hover,
div.code-toolbar > .toolbar > .toolbar-item > a:focus,
div.code-toolbar > .toolbar > .toolbar-item > button:hover,
div.code-toolbar > .toolbar > .toolbar-item > button:focus,
div.code-toolbar > .toolbar > .toolbar-item > span:hover,
div.code-toolbar > .toolbar > .toolbar-item > span:focus {
color: inherit;
text-decoration: none;
}

View file

@ -0,0 +1,115 @@
code.language-css,
code.language-scss,
.token.boolean,
.token.string,
.token.entity,
.token.url,
.language-css .token.string,
.language-scss .token.string,
.style .token.string,
.token.attr-value,
.token.keyword,
.token.control,
.token.directive,
.token.statement,
.token.regex,
.token.atrule,
.token.number,
.token.inserted,
.token.important {
color: var(--accent) !important;
}
.token.tag-id,
.token.atrule-id,
.token.operator,
.token.unit,
.token.placeholder,
.token.variable,
.token.attr-name,
.token.namespace,
.token.deleted,
.token.property,
.token.class-name,
.token.constant,
.token.symbol {
color: color-mix(in srgb, var(--accent) 70%, transparent) !important;
}
.token.property,
.token.function,
.token.function-name,
.token.deleted,
code.language-javascript,
code.language-html,
.command-line-prompt > span::before {
color: var(--accent) !important;
}
.token.selector,
.token.tag,
.token.punctuation {
color: color-mix(in srgb, var(--accent) 50%, var(--foreground)) !important;
}
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: color-mix(in srgb, var(--foreground) 30%, transparent) !important;
}
.token.namespace {
opacity: 0.7 !important;
}
pre[data-line] {
position: relative;
}
pre[class*=language-] {
margin: 0;
overflow: auto;
}
.line-highlight {
position: absolute;
left: 0;
right: 0;
padding: 0;
margin: 0;
background: color-mix(in srgb, var(--foreground) 7%, transparent);
pointer-events: none;
line-height: inherit;
white-space: pre;
}
.line-highlight::before,
.line-highlight[data-end]::after {
content: attr(data-start);
position: absolute;
/* top: .4em; */
left: 0.6em;
min-width: 1em;
padding: 0 0.5em;
background-color: color-mix(in srgb, var(--foreground) 40%, transparent);
color: var(--foreground);
font: bold 65%/1.5 sans-serif;
text-align: center;
vertical-align: 0.3em;
border-radius: 999px;
text-shadow: none;
box-shadow: 0 1px var(--foreground);
}
.line-highlight[data-end]::after {
content: attr(data-end);
top: auto;
bottom: 0.4em;
}
.line-numbers .line-highlight::before,
.line-numbers .line-highlight::after {
content: none;
}

View file

@ -0,0 +1,373 @@
:root {
--background: #1a170f;
--foreground: #eceae5;
--accent: #eec35e;
--font-size: 1rem;
--line-height: 1.54rem;
--radius: 0;
}
html {
box-sizing: border-box;
}
*,
*::before,
*::after {
box-sizing: inherit;
margin: 0;
padding: 0;
}
body {
margin: 0;
padding: 0;
font-family:
"Fira Code",
Monaco,
Consolas,
"Ubuntu Mono",
monospace;
font-size: 1rem;
font-weight: 400;
line-height: var(--line-height);
letter-spacing: -0.02em;
background-color: var(--background);
color: var(--foreground);
text-rendering: optimizelegibility;
-webkit-font-smoothing: antialiased;
-webkit-overflow-scrolling: touch;
text-size-adjust: 100%;
}
::placeholder {
color: color-mix(in srgb var(--foreground) 50%, black);
}
h1,
h2 {
font-size: calc(var(--font-size) * 1.1);
text-transform: uppercase;
letter-spacing: 0.04em;
}
h1 {
text-decoration: underline;
text-decoration-thickness: 2px;
text-underline-offset: calc(var(--font-size) * 0.2);
}
h3,
h4,
h5,
h6 {
font-size: calc(var(--font-size) * 1.1);
letter-spacing: 0.04em;
}
h1,
h2,
h3,
h4,
h5,
h6,
p,
ul,
ol,
img,
figure,
video,
table {
margin: calc(var(--line-height) * 1.2) 0;
}
a {
color: var(--accent);
}
button {
position: relative;
font: inherit;
font-weight: bold;
text-decoration: none;
text-align: center;
background: transparent;
color: var(--accent);
padding: 5px 18px;
border: 4px solid var(--accent);
border-radius: var(--radius);
transition: background 0.15s linear;
appearance: none;
cursor: pointer;
outline: none;
}
button:hover {
background: color-mix(in srgb, var(--accent) 15%, transparent);
}
button:focus-visible,
a:focus-visible {
outline: 1px solid var(--accent);
outline-offset: 2px;
}
fieldset {
display: inline-block;
border: 2px solid var(--foreground);
border-radius: calc(var(--radius) * 1.6);
padding: 10px;
}
fieldset *:first-child {
margin-top: 0;
}
fieldset input,
fieldset select,
fieldset textarea,
fieldset label,
fieldset button {
margin-top: calc(var(--line-height) * 0.5);
width: 100%;
}
label {
display: inline-block;
}
label input {
margin-top: 0;
}
input,
textarea,
select {
background: transparent;
color: var(--foreground);
border: 1px solid var(--foreground);
border-radius: var(--radius);
padding: 10px;
font: inherit;
appearance: none;
}
input[type="checkbox"] {
width: auto;
}
input:focus-visible,
input:active,
textarea:focus-visible,
textarea:active,
select:focus-visible,
select:active {
border-color: var(--accent);
outline: 1px solid var(--accent);
outline-offset: 2px;
}
input:active,
textarea:active,
select:active {
box-shadow: none;
}
select {
background-image: linear-gradient(
45deg,
transparent 50%,
var(--foreground) 50%
),
linear-gradient(135deg, var(--foreground) 50%, transparent 50%);
background-position: calc(100% - 20px), calc(100% - 1em);
background-size:
5px 5px,
5px 5px;
background-repeat: no-repeat;
padding-right: 40px;
}
select option {
background: var(--background);
}
input[type="checkbox"] {
vertical-align: middle;
padding: 10px;
box-shadow: inset 0 0 0 3px var(--background);
}
input[type="checkbox"]:checked {
background: var(--accent);
}
img {
display: block;
max-width: 100%;
border: 8px solid var(--accent);
border-radius: var(--radius);
padding: 8px;
overflow: hidden;
}
figure img,
figure video {
margin-bottom: 0;
}
figure figcaption {
background: var(--accent);
color: var(--background);
text-align: center;
font-size: 1rem;
font-weight: normal;
margin-top: -8px;
border-radius: 0 0 var(--radius) var(--radius);
}
ul,
ol {
margin-left: 4ch;
padding: 0;
}
ul ul,
ul ol,
ol ul,
ol ol {
margin-top: 0;
}
li::marker {
color: var(--accent);
}
ul li,
ol li {
position: relative;
}
code,
kbd {
font-family:
"Fira Code",
Monaco,
Consolas,
"Ubuntu Mono",
monospace !important;
font-feature-settings: normal;
background: color-mix(in srgb, var(--foreground) 5%, transparent);
color: var(--accent);
padding: 1px 6px;
margin: 0 2px;
font-size: 0.95rem;
}
kbd {
border-top: 1px solid color-mix(in srgb, var(--accent) 25%, transparent);
border-left: 1px solid var(--accent);
border-right: 1px solid var(--accent);
border-bottom: 4px solid var(--accent);
border-radius: 4px;
}
code code {
background: transparent;
padding: 0;
margin: 0;
}
pre {
tab-size: 4;
background: color-mix(in srgb, var(--foreground) 5%, transparent) !important;
color: var(--foreground);
padding: 20px 10px;
font-size: 0.95rem !important;
overflow: auto;
border-radius: var(--radius);
border: 1px solid color-mix(in srgb, var(--foreground) 10%, transparent);
}
pre code {
background: none !important;
margin: 0;
padding: 0;
font-size: inherit;
border: none;
}
sup {
line-height: 0;
}
abbr {
position: relative;
text-decoration-style: wavy;
text-decoration-color: var(--accent);
cursor: help;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.25em;
}
mark {
background: color-mix(in srgb, var(--accent) 45%, transparent);
color: var(--foreground);
}
blockquote {
position: relative;
border-top: 1px solid var(--accent);
border-bottom: 1px solid var(--accent);
margin: 0;
padding: 25px;
}
blockquote::before {
content: ">";
display: block;
position: absolute;
left: 0;
color: var(--accent);
}
blockquote p:first-child {
margin-top: 0;
}
blockquote p:last-child {
margin-bottom: 0;
}
table {
table-layout: auto;
border-collapse: collapse;
}
table,
th,
td {
border: 2px solid var(--foreground);
padding: 10px;
}
th {
border-style: solid;
color: var(--foreground);
text-align: left;
text-transform: uppercase;
letter-spacing: 0.04em;
}
hr {
width: 100%;
border: none;
background: var(--accent);
height: 2px;
}

View file

@ -0,0 +1,18 @@
.terms h3 {
font-size: initial;
}
.terms ul {
list-style: none;
}
.terms ul li a {
color: var(--accent);
}
.terms ul li:not(:empty)::before {
content: "-";
position: absolute;
left: -20px;
color: var(--accent);
}

View file

@ -3,9 +3,11 @@ languageCode = "en-us"
theme = "hugo-theme-terminal" theme = "hugo-theme-terminal"
paginate = 5 paginate = 5
[markup.goldmark.renderer]
unsafe = true
[params] [params]
contentTypeName = "posts" contentTypeName = "posts"
themeColor = "orange"
showMenuItems = 2 showMenuItems = 2
fullWidthTheme = false fullWidthTheme = false
centerTheme = false centerTheme = false

View file

@ -14,9 +14,8 @@ This theme is pretty basic and covers all of the essentials. All you have to do
The theme includes: The theme includes:
- **5 duotone themes**, depending on your preferences (orange, red, blue, green, pink) - fully customizable color schemes generated by [**terminal.css**](https://panr.github.io/terminal-css/).
- [**Fira Code**](https://github.com/tonsky/FiraCode) as default monospaced font. It's gorgeous! - great reading experience thanks to [**Fira Code**](https://github.com/tonsky/FiraCode).
- **really nice, custom duotone** syntax highlighting based on [**PrismJS**](https://prismjs.com) - nice code highlighting thanks to [**PrismJS**](https://prismjs.com) that matches the theme's color scheme.
- mobile friendly layout
So, there you have it... enjoy! So, there you have it... enjoy!

Some files were not shown because too many files have changed in this diff Show more