Compare commits
16 commits
Author | SHA1 | Date | |
---|---|---|---|
3390b94d70 | |||
2b0901a982 | |||
ac51638665 | |||
26a9dc1e03 | |||
41904b8d19 | |||
bff4de6937 | |||
13813e2b9d | |||
b20ad0960c | |||
|
31a5e09ecd | ||
|
fc1540a738 | ||
|
b9713badcd | ||
|
047623a2e0 | ||
|
e422c8c6c4 | ||
|
2a6727faa0 | ||
|
ad43152957 | ||
|
63211c3f37 |
46
.air.toml
Normal 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
|
@ -2,3 +2,5 @@
|
||||||
public/
|
public/
|
||||||
resources/
|
resources/
|
||||||
app
|
app
|
||||||
|
www
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
16
Makefile
|
@ -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
|
||||||
|
|
|
@ -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
|
@ -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
|
@ -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=
|
|
||||||
|
|
|
@ -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"
|
|
@ -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>
|
43
hugo/content/blog/2024-03-16-babelfish-psql.md
Normal 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.
|
70
hugo/content/blog/2024-04-04-xz-thoughts.md
Normal 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:
|
||||||
|

|
||||||
|
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
|
||||||
|
|
218
hugo/content/blog/2024-06-03-Nullbulge-Ranner.md
Normal 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&CK Tactic │ ATT&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.
|
139
hugo/content/blog/2024-06-05-nullbulge-investigation.md
Normal 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&CK Tactic │ ATT&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
|
@ -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
|
@ -0,0 +1,8 @@
|
||||||
|
package hugo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"embed"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:embed public/*
|
||||||
|
var PublicFS embed.FS
|
BIN
hugo/static/favicon.ico
Normal file
After Width: | Height: | Size: 207 B |
BIN
hugo/static/favicon.png
Normal file
After Width: | Height: | Size: 207 B |
Before Width: | Height: | Size: 228 KiB After Width: | Height: | Size: 228 KiB |
Before Width: | Height: | Size: 122 KiB After Width: | Height: | Size: 122 KiB |
Before Width: | Height: | Size: 190 KiB After Width: | Height: | Size: 190 KiB |
Before Width: | Height: | Size: 189 KiB After Width: | Height: | Size: 189 KiB |
Before Width: | Height: | Size: 112 KiB After Width: | Height: | Size: 112 KiB |
Before Width: | Height: | Size: 227 KiB After Width: | Height: | Size: 227 KiB |
Before Width: | Height: | Size: 308 KiB After Width: | Height: | Size: 308 KiB |
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 63 KiB |
Before Width: | Height: | Size: 416 KiB After Width: | Height: | Size: 416 KiB |
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 45 KiB |
BIN
hugo/static/img/blog/2024-06-03-cape-analysis.png
Normal file
After Width: | Height: | Size: 291 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 84 KiB After Width: | Height: | Size: 84 KiB |
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 68 KiB |
BIN
hugo/static/img/blog/shodan-openssh-2024-04-04.png
Normal file
After Width: | Height: | Size: 220 KiB |
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 36 KiB |
BIN
hugo/static/og-image.png
Normal file
After Width: | Height: | Size: 17 KiB |
368
hugo/static/terminal.css
Normal 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;
|
||||||
|
}
|
1
hugo/static/themestyles.css
Normal 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
|
12
hugo/themes/terminal/.stylelintrc.json
Normal 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
|
||||||
|
}
|
||||||
|
}
|
|
@ -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))
|
|
@ -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
|
|
@ -1,9 +1,14 @@
|
||||||
# Terminal
|
# Terminal
|
||||||
|
|
||||||

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

|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
⚠️ 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.
|
|
@ -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)
|
||||||
|
|
||||||
-->
|
-->
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
||||||
+++
|
+++
|
123
hugo/themes/terminal/assets/css/buttons.css
Normal 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;
|
||||||
|
}
|
117
hugo/themes/terminal/assets/css/code.css
Normal 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;
|
||||||
|
}
|
19
hugo/themes/terminal/assets/css/fonts.css
Normal 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;
|
||||||
|
}
|
46
hugo/themes/terminal/assets/css/footer.css
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
4
hugo/themes/terminal/assets/css/gist.css
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
body .gist .blob-num,
|
||||||
|
body .gist .blob-code-inner {
|
||||||
|
border: none;
|
||||||
|
}
|
45
hugo/themes/terminal/assets/css/header.css
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
167
hugo/themes/terminal/assets/css/main.css
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
148
hugo/themes/terminal/assets/css/menu.css
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
96
hugo/themes/terminal/assets/css/pagination.css
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
141
hugo/themes/terminal/assets/css/post.css
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
322
hugo/themes/terminal/assets/css/prism.css
Normal 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 .prism’s 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;
|
||||||
|
}
|
115
hugo/themes/terminal/assets/css/syntax.css
Normal 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;
|
||||||
|
}
|
373
hugo/themes/terminal/assets/css/terminal.css
Normal 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;
|
||||||
|
}
|
18
hugo/themes/terminal/assets/css/terms.css
Normal 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);
|
||||||
|
}
|
|
@ -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
|
|
@ -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!
|