Compare commits
13
Commits
af31b6165c
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
09f0dc42e4
|
||
|
|
8e2303fcdf
|
||
|
|
4917abe9e6
|
||
|
|
b52629d1f6
|
||
|
|
b9159581f3
|
||
|
|
9e9163f01b
|
||
|
|
54a69b51ae
|
||
|
|
975ba4f312
|
||
|
|
6cd5ed61c4 | ||
|
|
1adca36802
|
||
|
|
3b1ef34bce
|
||
|
|
6b33be6956
|
||
|
|
f94a5cbe17
|
No files matched your search
@@ -1,6 +1,8 @@
|
|||||||
name: Build site
|
name: Build site
|
||||||
|
|
||||||
on: push
|
on:
|
||||||
|
- push
|
||||||
|
- workflow_dispatch
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
@@ -16,8 +18,53 @@ jobs:
|
|||||||
- name: Build site
|
- name: Build site
|
||||||
run: ./scripts/calepin.sh compile site public
|
run: ./scripts/calepin.sh compile site public
|
||||||
|
|
||||||
|
# The official upload-artifact@v4 refuses to run on Gitea (it detects a
|
||||||
|
# non-GitHub server and aborts with GHESNotSupportedError). v3 uses the
|
||||||
|
# artifact API that Gitea implements. On Gitea >= 1.22 with a current
|
||||||
|
# act_runner, christopherhx/gitea-upload-artifact@v4 is a drop-in
|
||||||
|
# replacement if you want the v4 API.
|
||||||
- name: Upload site artifact
|
- name: Upload site artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: public
|
name: public
|
||||||
path: public/
|
path: public/
|
||||||
|
|
||||||
|
deploy:
|
||||||
|
needs: build
|
||||||
|
# Publish only from main; move the gate to publish from another branch.
|
||||||
|
if: github.ref == 'refs/heads/main'
|
||||||
|
# Write access for the automatic Actions token to push the pages branch.
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
# NOTE: must match your act_runner labels (e.g. ubuntu-latest, ubuntu-24.04).
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Download site artifact
|
||||||
|
uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
name: public
|
||||||
|
path: public
|
||||||
|
|
||||||
|
- name: Check artifact layout
|
||||||
|
run: test -f public/index.html
|
||||||
|
|
||||||
|
# Publishing interfaces with prod; it never runs under local act tests
|
||||||
|
# (act sets env.ACT, the Gitea runner does not). The force-push to the
|
||||||
|
# `pages` branch is what triggers the git-pages webhook.
|
||||||
|
- name: Publish to pages branch
|
||||||
|
env:
|
||||||
|
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||||
|
run: |
|
||||||
|
if [ -z "$GITEA_TOKEN" ]; then
|
||||||
|
echo "::error::Missing GITEA_TOKEN (the automatic Actions token)."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
cd public
|
||||||
|
git init -q -b pages .
|
||||||
|
git config user.name "Yggdrasil CI"
|
||||||
|
git config user.email "ci@noreply.kb28.ch"
|
||||||
|
git add -A
|
||||||
|
git commit -q -m "Publish site from ${GITHUB_SHA}"
|
||||||
|
repo_host="${GITHUB_SERVER_URL#*://}"
|
||||||
|
repo_host="${repo_host%/}"
|
||||||
|
git push -q --force "https://${GITHUB_REPOSITORY_OWNER}:${GITEA_TOKEN}@${repo_host}/${GITHUB_REPOSITORY}.git" pages
|
||||||
@@ -8,3 +8,5 @@ tools/
|
|||||||
|
|
||||||
# IDE
|
# IDE
|
||||||
.idea/
|
.idea/
|
||||||
|
.zed/
|
||||||
|
.vscode/
|
||||||
@@ -21,3 +21,11 @@ watch: tools
|
|||||||
# Remove generated output and build caches
|
# Remove generated output and build caches
|
||||||
clean:
|
clean:
|
||||||
./scripts/clean.sh
|
./scripts/clean.sh
|
||||||
|
|
||||||
|
# Remove all EXIF metadata from a file
|
||||||
|
strip-exif file:
|
||||||
|
exiftool -all= -overwrite_original {{ quote(file) }}
|
||||||
|
|
||||||
|
# Run the CI workflow locally with act (requires act + docker)
|
||||||
|
ci:
|
||||||
|
act push -W .gitea/workflows/build.yml -j build --artifact-server-path /tmp/act-artifacts
|
||||||
@@ -24,6 +24,7 @@ checksum-verified into `tools/` on first use (no global installs, no cargo):
|
|||||||
just preview # build, then serve the site locally
|
just preview # build, then serve the site locally
|
||||||
just watch # rebuild on change and serve
|
just watch # rebuild on change and serve
|
||||||
just clean # remove public/ and build caches
|
just clean # remove public/ and build caches
|
||||||
|
just ci # run the CI workflow locally with act (needs act + docker)
|
||||||
|
|
||||||
## Adding a page
|
## Adding a page
|
||||||
|
|
||||||
@@ -49,6 +50,10 @@ target = "<category>/<page>.typ"
|
|||||||
|
|
||||||
Sidebar labels come from the page's `#metadata(...)` line, not from the config.
|
Sidebar labels come from the page's `#metadata(...)` line, not from the config.
|
||||||
|
|
||||||
|
Every page also renders a printable PDF twin (`pdf = true` in
|
||||||
|
`calepin.toml`, selectable in the page's view picker). Add `pdf: false` to a
|
||||||
|
page's `#metadata(...)` to skip its PDF, as `404.typ` does.
|
||||||
|
|
||||||
## Adding a category
|
## Adding a category
|
||||||
|
|
||||||
1. Create `site/<category>/` with an `index.typ`, using
|
1. Create `site/<category>/` with an `index.typ`, using
|
||||||
@@ -68,8 +73,16 @@ sidebar.
|
|||||||
|
|
||||||
## Deployment
|
## Deployment
|
||||||
|
|
||||||
`just build` produces a fully static site in `public/`: HTML pages plus
|
`just build` produces a fully static site in `public/`: HTML pages with
|
||||||
`sitemap.xml`, `robots.txt`, and `llms.txt`. The Gitea Actions workflow in
|
printable PDF twins, plus `sitemap.xml`, `robots.txt`, and `llms.txt`. The
|
||||||
|
Gitea Actions workflow in
|
||||||
`.gitea/workflows/build.yml` builds the site on every push with the same
|
`.gitea/workflows/build.yml` builds the site on every push with the same
|
||||||
pinned toolchain and uploads `public/` as an artifact for deployment to any
|
pinned toolchain and uploads `public/` as an artifact.
|
||||||
static host.
|
|
||||||
|
Pushes to `main` are also published: the `deploy` job force-pushes `public/`
|
||||||
|
to the repo's `pages` branch using the automatic Actions token (no secrets to
|
||||||
|
configure). A Gitea webhook on the repo then notifies the self-hosted
|
||||||
|
[git-pages](https://codeberg.org/git-pages/git-pages) server, which clones
|
||||||
|
the `pages` branch and serves the site. The push step is gated with
|
||||||
|
`if: ${{ !env.ACT }}` so local `act` runs never publish, and
|
||||||
|
`workflow_dispatch` enables manual publishes from the Gitea UI.
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
#set document(title: [Not found])
|
#set document(title: [Not found])
|
||||||
|
#metadata((pdf: false)) <website-metadata>
|
||||||
|
|
||||||
#title()
|
#title()
|
||||||
|
|
||||||
|
|||||||
+14
-16
@@ -2,7 +2,7 @@ title = "Yggdrasil"
|
|||||||
description = "Personal knowledge base."
|
description = "Personal knowledge base."
|
||||||
base-url = "https://yggdrasil.kb28.ch"
|
base-url = "https://yggdrasil.kb28.ch"
|
||||||
theme = "themes/yggdrasil"
|
theme = "themes/yggdrasil"
|
||||||
pdf = false
|
pdf = true
|
||||||
minify = true
|
minify = true
|
||||||
search = "pagefind"
|
search = "pagefind"
|
||||||
logo = "assets/yggdrasil.svg"
|
logo = "assets/yggdrasil.svg"
|
||||||
@@ -22,12 +22,16 @@ include = [
|
|||||||
]
|
]
|
||||||
exclude = ["drafts/**"]
|
exclude = ["drafts/**"]
|
||||||
|
|
||||||
|
[toc]
|
||||||
|
enabled = true
|
||||||
|
depth = 2
|
||||||
|
floating = true
|
||||||
|
|
||||||
[menus]
|
[menus]
|
||||||
main = [
|
main = [
|
||||||
{ label = "Home", target = "home/index.typ" },
|
{ label = "Home", target = "home/index.typ" },
|
||||||
{ label = "IT", target = "it/index.typ" },
|
{ label = "Computer Science", target = "cs/index.typ" },
|
||||||
{ label = "OT", target = "ot/index.typ" },
|
{ label = "HomeLab", target = "homelab/index.typ" },
|
||||||
{ label = "Security", target = "security/index.typ" },
|
|
||||||
{ label = "Medias", target = "medias/index.typ" },
|
{ label = "Medias", target = "medias/index.typ" },
|
||||||
]
|
]
|
||||||
social = [
|
social = [
|
||||||
@@ -54,24 +58,18 @@ item = [
|
|||||||
|
|
||||||
|
|
||||||
[[sidebar.section]]
|
[[sidebar.section]]
|
||||||
title = "IT"
|
title = "Computer Science"
|
||||||
item = [
|
item = [
|
||||||
{ target = "it/index.typ" },
|
{ target = "cs/index.typ" },
|
||||||
{ glob = "it/*" }
|
{ glob = "cs/*" }
|
||||||
]
|
]
|
||||||
|
|
||||||
[[sidebar.section]]
|
|
||||||
title = "OT"
|
|
||||||
item = [
|
|
||||||
{ target = "ot/index.typ" },
|
|
||||||
{ glob = "ot/*" }
|
|
||||||
]
|
|
||||||
|
|
||||||
[[sidebar.section]]
|
[[sidebar.section]]
|
||||||
title = "Security"
|
title = "HomeLab"
|
||||||
item = [
|
item = [
|
||||||
{ target = "security/index.typ" },
|
{ target = "homelab/index.typ" },
|
||||||
{ glob = "security/*" }
|
{ glob = "homelab/*" }
|
||||||
]
|
]
|
||||||
|
|
||||||
[[sidebar.section]]
|
[[sidebar.section]]
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
#set document(title: [Computer Science])
|
||||||
|
#metadata((title: "Overview", translation_key: "cs-index")) <website-metadata>
|
||||||
|
|
||||||
|
#title()
|
||||||
|
|
||||||
|
Placeholder page for the Computer Science category.
|
||||||
|
The real content comes later.
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 4.8 MiB |
Binary file not shown.
|
After Width: | Height: | Size: 5.2 MiB |
+52
-2
@@ -1,6 +1,56 @@
|
|||||||
|
#import "/lib/lib.typ": *
|
||||||
#set document(title: [Gardening])
|
#set document(title: [Gardening])
|
||||||
#metadata((title: "Gardening", translation_key: "home-gardening")) <website-metadata>
|
#metadata((
|
||||||
|
title: "Gardening",
|
||||||
|
translation_key: "home-gardening",
|
||||||
|
date: "2026-10-11",
|
||||||
|
tags: ("plants", "yucca", "dracaena", "light", "water"),
|
||||||
|
author: "Rémi Herdero",
|
||||||
|
summary: "Some plants description and advices for keep them alive"
|
||||||
|
)) <website-metadata>
|
||||||
|
|
||||||
#title()
|
#title()
|
||||||
|
|
||||||
Placeholder page — the real content comes later.
|
= Yucca elephantipes <home:gardening:yucca>
|
||||||
|
#calepin.elements.columns(
|
||||||
|
columns: 2,
|
||||||
|
wrap: true,
|
||||||
|
[
|
||||||
|
Yucca (@fig:plant:yucca_elephantipes) from central America is accustomed to arid conditions.
|
||||||
|
|
||||||
|
#tag(fill: yellow.lighten(30%))[Light ++]
|
||||||
|
#tag(fill: blue.lighten(50%))[Water --]
|
||||||
|
|
||||||
|
This plant love light and should be placed on one of the most brightful parts of the room. It even tolerates direct sunlight very well.
|
||||||
|
|
||||||
|
The Yucca stores water in its thick trunk. You need to let the soil dry out almost completely between waterings. Generally speaking, watering once *every 2 to 3 weeks* is more than enough. It's better to forget about it for a while than to overwater it, otherwise its roots will decay. Usually we can put around #frackable(1, 2) liter every 2 Weeks. But it's important to check the dirt is dry before watering.
|
||||||
|
|
||||||
|
],[
|
||||||
|
#figure(
|
||||||
|
image("assets/yucca_elephantipes.jpg", width: 60%),
|
||||||
|
caption: "Yucca elephantipes"
|
||||||
|
) <fig:plant:yucca_elephantipes>
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
= Dracaena marginata <home:gardening:dracaena>
|
||||||
|
#calepin.elements.columns(
|
||||||
|
columns: 2,
|
||||||
|
wrap: true,
|
||||||
|
[
|
||||||
|
The Dracaena (@fig:plant:dracaena_marginata) come from Madagascar.
|
||||||
|
|
||||||
|
#tag(fill: yellow.lighten(30%))[Light +]
|
||||||
|
#tag(fill: blue.lighten(50%))[Water -]
|
||||||
|
|
||||||
|
This plant prefer lot of indirect light. Avoid to place it in direct sunlight because it can burn its leaves.
|
||||||
|
|
||||||
|
The Dracaena don't need a lot of water. Before watering, make sure the first 3 or 4 centimeters of soil are dry. In average, water the plant once with #frackable(1, 2) litre *every 10 to 14 days*. The extremity of the leaves tend to turn brown when the air is too dry or the water contain too much calcium or chlorine.
|
||||||
|
|
||||||
|
], [
|
||||||
|
#figure(
|
||||||
|
image("assets/dracaena_marginata.jpg", width: 60%),
|
||||||
|
caption: [Dracaena marginata]
|
||||||
|
) <fig:plant:dracaena_marginata>
|
||||||
|
]
|
||||||
|
)
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
#set document(title: [Washing clothes])
|
|
||||||
#metadata((title: "Washing clothes", translation_key: "home-washing-clothes")) <website-metadata>
|
|
||||||
|
|
||||||
#title()
|
|
||||||
|
|
||||||
Placeholder page — the real content comes later.
|
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
#set document(title: [Backup])
|
||||||
|
#metadata((title: "Backup", translation_key: "homelab-backup")) <website-metadata>
|
||||||
|
|
||||||
|
#title()
|
||||||
|
|
||||||
|
Placeholder page — the real content comes later.
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
#set document(title: [HomeLab])
|
||||||
|
#metadata((title: "Overview", translation_key: "homelab")) <website-metadata>
|
||||||
|
|
||||||
|
#title()
|
||||||
|
|
||||||
|
Placeholder page for the homelab category.
|
||||||
|
The real content comes later.
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
#set document(title: [IT])
|
|
||||||
#metadata((title: "Overview", translation_key: "it-index")) <website-metadata>
|
|
||||||
|
|
||||||
#title()
|
|
||||||
|
|
||||||
Placeholder page for the IT category.
|
|
||||||
The real content comes later.
|
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
// #import "@preview/calepin:0.1.0" as calepin
|
||||||
|
#import "@preview/hes-so-core:0.1.0"
|
||||||
|
#import "@preview/frackable:0.2.0": *
|
||||||
|
|
||||||
|
// #import "@preview/cetz:0.5.2"
|
||||||
|
//
|
||||||
|
// #let drawing(..args) = {
|
||||||
|
// let canvas = cetz.canvas(..args)
|
||||||
|
// context if target() == "html" {
|
||||||
|
// html.frame(canvas)
|
||||||
|
// } else {
|
||||||
|
// canvas
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
#let tag(body, fill: yellow, stroke: auto) = {
|
||||||
|
let stroke-color = if stroke == auto {
|
||||||
|
fill.darken(25%)
|
||||||
|
} else if type(stroke) == color {
|
||||||
|
stroke
|
||||||
|
} else if type(stroke) == stroke {
|
||||||
|
stroke.paint
|
||||||
|
} else {
|
||||||
|
fill.darken(25%)
|
||||||
|
}
|
||||||
|
|
||||||
|
let stroke-rule = if stroke == auto {
|
||||||
|
1pt + stroke-color
|
||||||
|
} else if type(stroke) == color {
|
||||||
|
1pt + stroke
|
||||||
|
} else {
|
||||||
|
stroke
|
||||||
|
}
|
||||||
|
|
||||||
|
context if target() == "html" {
|
||||||
|
let bg-hex = fill.to-hex()
|
||||||
|
let border-hex = stroke-color.to-hex()
|
||||||
|
html.elem("span", attrs: (
|
||||||
|
style: "display: inline-block; background-color: " + bg-hex
|
||||||
|
+ "; border: 1px solid " + border-hex
|
||||||
|
+ "; color: #1f2933; border-radius: 1em; padding: 0.2em 0.6em; font-size: 0.85em; font-weight: 500; line-height: 1.2;"
|
||||||
|
))[#body]
|
||||||
|
} else {
|
||||||
|
box(
|
||||||
|
fill: fill,
|
||||||
|
stroke: stroke-rule,
|
||||||
|
radius: 1em,
|
||||||
|
inset: (x: 0.5em, y: 0.5em)
|
||||||
|
)[#body]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
#set document(title: [OT])
|
|
||||||
#metadata((title: "Overview", translation_key: "ot-index")) <website-metadata>
|
|
||||||
|
|
||||||
#title()
|
|
||||||
|
|
||||||
Placeholder page for the OT category.
|
|
||||||
The real content comes later.
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
#set document(title: [Security])
|
|
||||||
#metadata((title: "Overview", translation_key: "security")) <website-metadata>
|
|
||||||
|
|
||||||
#title()
|
|
||||||
|
|
||||||
Placeholder page for the security category.
|
|
||||||
The real content comes later.
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
#set document(title: [SSH])
|
|
||||||
#metadata((title: "SSH", translation_key: "security-ssh")) <website-metadata>
|
|
||||||
|
|
||||||
#title()
|
|
||||||
|
|
||||||
Placeholder page — the real content comes later.
|
|
||||||
Reference in new issue
Block a user