fix: new version with themes + multi arch builds
b56ed7e0c7d0a33fd6c702129c1fe0d9a7546a8f
| @@ -87,34 +87,48 @@ jobs: | ||
| 87 | 87 | uses: actions/upload-artifact@v7 |
| 88 | 88 | with: |
| 89 | 89 | name: ${{ env.BINARY_NAME }}-${{ matrix.goos }}-${{ matrix.goarch }}${{ matrix.goarm && format('v{0}', matrix.goarm) || '' }} |
| 90 | 90 | path: dist/* |
| 91 | 91 | if-no-files-found: error |
| 92 | 92 | |
| 93 | 93 | release: |
| 94 | 94 | needs: build |
| 95 | 95 | runs-on: ubuntu-latest |
| 96 | 96 | steps: |
| 97 | +- name: Checkout |
|
| 98 | +uses: actions/checkout@v6 |
|
| 99 | +with: |
|
| 100 | +path: src |
|
| 101 | + | |
| 97 | 102 | - name: Download all artifacts |
| 98 | 103 | uses: actions/download-artifact@v8 |
| 99 | 104 | with: |
| 100 | 105 | path: artifacts |
| 101 | 106 | merge-multiple: true |
| 102 | 107 | |
| 103 | 108 | - name: Merge checksums |
| 104 | 109 | run: | |
| 105 | 110 | cd artifacts |
| 106 | 111 | cat checksums-*.txt > checksums.txt |
| 107 | 112 | rm checksums-*.txt |
| 108 | 113 | echo "=== checksums.txt ===" |
| 109 | 114 | cat checksums.txt |
| 110 | 115 | |
| 116 | +# Templates are no longer embedded in the binary — ship the default theme |
|
| 117 | +# so a new site can be bootstrapped without cloning the repository. |
|
| 118 | +- name: Package default theme |
|
| 119 | +run: | |
|
| 120 | +set -euo pipefail |
|
| 121 | + tar -czf artifacts/${BINARY_NAME}-theme-default.tar.gz -C src themes/default |
|
| 122 | +cd artifacts |
|
| 123 | + sha256sum ${BINARY_NAME}-theme-default.tar.gz >> checksums.txt |
|
| 124 | + | |
| 111 | 125 | - name: Determine tag |
| 112 | 126 | id: tag |
| 113 | 127 | run: | |
| 114 | 128 | if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then |
| 115 | 129 | echo "version=${{ github.event.inputs.tag }}" >> "$GITHUB_OUTPUT" |
| 116 | 130 | else |
| 117 | 131 | echo "version=${GITHUB_REF#refs/tags/}" >> "$GITHUB_OUTPUT" |
| 118 | 132 | fi |
| 119 | 133 | |
| 120 | 134 | - name: List release assets |
| @@ -1,4 +1,4 @@ | ||
| 1 | 1 | output/ |
| 2 | 2 | newblog |
| 3 | 3 | .DS_Store |
| 4 | -quilldrop |
|
\ No newline at end of file |
||
| 4 | +quilldrop |
| @@ -1,26 +1,104 @@ | ||
| 1 | -.PHONY: serve build docker-images docker-static docker-run |
|
| 1 | +.PHONY: serve serve-dev generate build build-native build-macos build-linux \ |
|
| 2 | +build-raspberry build-windows checksums new-theme clean \ |
|
| 3 | +docker-images docker-static docker-run |
|
| 2 | 4 | |
| 3 | 5 | GIT := $(shell git pull --quiet 2>/dev/null || true) |
| 4 | 6 | LATEST_TAG := $(shell git tag --sort=-version:refname | head -n 1) |
| 5 | 7 | |
| 6 | 8 | tag: |
| 7 | 9 | @echo "Latest tag: $(LATEST_TAG)" |
| 8 | 10 | |
| 9 | 11 | serve: |
| 10 | 12 | go run . serve |
| 11 | 13 | |
| 14 | +# Server mit Template-Live-Reload (Theme-Entwicklung), optional: make serve-dev THEME=newdesign |
|
| 15 | +serve-dev: |
|
| 16 | +go run . serve -dev $(if $(THEME),-theme $(THEME)) |
|
| 17 | + | |
| 12 | 18 | generate: |
| 13 | 19 | go run . generate |
| 14 | 20 | |
| 15 | -build: |
|
| 16 | -GOOS=linux GOARCH=arm64 go build -o quilldrop |
|
| 21 | +# --------------------------------------------------------------------------- |
|
| 22 | +# Builds |
|
| 23 | +# |
|
| 24 | +# Alle Binaries landen in $(DIST)/ und heissen quilldrop-<os>-<arch>[v<arm>]. |
|
| 25 | +# Einzelne Ziele: make build-linux, build-macos, build-windows, build-raspberry |
|
| 26 | +# --------------------------------------------------------------------------- |
|
| 27 | + | |
| 28 | +BINARY_NAME := quilldrop |
|
| 29 | +DIST := dist |
|
| 30 | +GOFLAGS_REL := -trimpath -ldflags=-s\ -w |
|
| 31 | + | |
| 32 | +# $(call go_build,GOOS,GOARCH[,GOARM][,Kommentar]) |
|
| 33 | +define go_build |
|
| 34 | +@mkdir -p $(DIST) |
|
| 35 | +@echo " -> $(1)/$(2)$(if $(3),v$(3))$(if $(4), [$(4)])" |
|
| 36 | +@GOOS=$(1) GOARCH=$(2) GOARM=$(3) CGO_ENABLED=0 \ |
|
| 37 | +go build $(GOFLAGS_REL) \ |
|
| 38 | +-o $(DIST)/$(BINARY_NAME)-$(1)-$(2)$(if $(3),v$(3))$(if $(filter windows,$(1)),.exe) . |
|
| 39 | +endef |
|
| 40 | + | |
| 41 | +# Alle Plattformen |
|
| 42 | +build: build-macos build-linux build-windows checksums |
|
| 43 | +@echo "" |
|
| 44 | +@ls -1 $(DIST) |
|
| 45 | + | |
| 46 | +# Nur fuer die aktuelle Maschine -> ./quilldrop |
|
| 47 | +build-native: |
|
| 48 | +CGO_ENABLED=0 go build $(GOFLAGS_REL) -o $(BINARY_NAME) . |
|
| 49 | + | |
| 50 | +build-macos: |
|
| 51 | +@echo "macOS:" |
|
| 52 | +$(call go_build,darwin,amd64,,Intel) |
|
| 53 | +$(call go_build,darwin,arm64,,Apple Silicon M1-M4) |
|
| 54 | + | |
| 55 | +build-linux: |
|
| 56 | +@echo "Linux:" |
|
| 57 | +$(call go_build,linux,amd64,,x86_64) |
|
| 58 | +$(call go_build,linux,386,,x86 32-bit) |
|
| 59 | +$(call go_build,linux,arm64,,ARM 64-bit) |
|
| 60 | +$(call go_build,linux,arm,7,ARMv7 32-bit) |
|
| 61 | +$(call go_build,linux,arm,6,ARMv6 32-bit) |
|
| 62 | + | |
| 63 | +# Raspberry Pi (Teilmenge von build-linux, zum separaten Bauen) |
|
| 64 | +# armv6 : Pi 1, Pi Zero / Zero W, CM1 |
|
| 65 | +# armv7 : Pi 2 und Pi 3/4/5 mit 32-bit OS |
|
| 66 | +# arm64 : Pi 3/4/5, Pi Zero 2 W, CM3/CM4/CM5 mit 64-bit OS (Raspberry Pi OS 64-bit) |
|
| 67 | +build-raspberry: |
|
| 68 | +@echo "Raspberry Pi:" |
|
| 69 | +$(call go_build,linux,arm,6,Pi 1 / Zero / Zero W / CM1) |
|
| 70 | +$(call go_build,linux,arm,7,Pi 2 / Pi 3-5 mit 32-bit OS) |
|
| 71 | +$(call go_build,linux,arm64,,Pi 3-5 / Zero 2 W / CM3-CM5 mit 64-bit OS) |
|
| 72 | + | |
| 73 | +build-windows: |
|
| 74 | +@echo "Windows:" |
|
| 75 | +$(call go_build,windows,amd64,,x86_64) |
|
| 76 | +$(call go_build,windows,386,,x86 32-bit) |
|
| 77 | +$(call go_build,windows,arm64,,ARM 64-bit) |
|
| 78 | + | |
| 79 | +# SHA256-Summen ueber alle gebauten Binaries |
|
| 80 | +checksums: |
|
| 81 | +@cd $(DIST) && \ |
|
| 82 | +if command -v sha256sum >/dev/null 2>&1; then \ |
|
| 83 | +sha256sum $(BINARY_NAME)-* > checksums.txt; \ |
|
| 84 | +else \ |
|
| 85 | +shasum -a 256 $(BINARY_NAME)-* > checksums.txt; \ |
|
| 86 | +fi |
|
| 87 | +@echo "Checksums: $(DIST)/checksums.txt" |
|
| 88 | + | |
| 89 | +# Copy the default theme: make new-theme NAME=newdesign |
|
| 90 | +new-theme: |
|
| 91 | + @test -n "$(NAME)" || { echo "Usage: make new-theme NAME=<theme>"; exit 1; } |
|
| 92 | + @test ! -d themes/$(NAME) || { echo "themes/$(NAME) already exists"; exit 1; } |
|
| 93 | +cp -r themes/default themes/$(NAME) |
|
| 94 | +@echo "Created themes/$(NAME) — activate with 'theme: $(NAME)' in config.yaml or 'go run . serve -theme $(NAME)'" |
|
| 17 | 95 | |
| 18 | 96 | docker-static: |
| 19 | 97 | podman build --platform linux/arm64 -t quilldrop -f ./Dockerfile-static . |
| 20 | 98 | |
| 21 | 99 | docker-images: |
| 22 | 100 | @echo "Building for tag: $(LATEST_TAG)" |
| 23 | 101 | @echo "Building AMD64..." |
| 24 | 102 | podman build --platform linux/amd64 \ |
| 25 | 103 | -t ghcr.io/9it-full-service/quilldrop:$(LATEST_TAG)-images-amd64 \ |
| 26 | 104 | -f ./Dockerfile-images . |
| @@ -48,21 +126,21 @@ docker-images: | ||
| 48 | 126 | # -f ./Dockerfile-images . |
| 49 | 127 | # podman manifest push --all ghcr.io/9it-full-service/quilldrop:$(LATEST_TAG)-images |
| 50 | 128 | |
| 51 | 129 | docker-run: |
| 52 | 130 | podman run --rm -i -p 8081:80 quilldrop:latest |
| 53 | 131 | |
| 54 | 132 | test: |
| 55 | 133 | go test ./... |
| 56 | 134 | |
| 57 | 135 | clean: |
| 58 | -rm -rf bin/ |
|
| 136 | +rm -rf bin/ $(DIST)/ $(BINARY_NAME) |
|
| 59 | 137 | |
| 60 | 138 | docker-up: |
| 61 | 139 | docker compose up -d |
| 62 | 140 | |
| 63 | 141 | docker-down: |
| 64 | 142 | docker compose down |
| 65 | 143 | |
| 66 | 144 | generate-keys: |
| 67 | 145 | @mkdir -p keys |
| 68 | 146 | openssl genrsa -out keys/private.pem 2048 |
| @@ -200,117 +200,178 @@ quilldrop/ | ||
| 200 | 200 | ├── config.yaml # Konfiguration |
| 201 | 201 | ├── content/ # Blog-Posts (Markdown) |
| 202 | 202 | │ ├── 2025-11-06-mein-post.md |
| 203 | 203 | │ └── ... |
| 204 | 204 | ├── sites/ # Statische Seiten |
| 205 | 205 | │ ├── ueber-mich.md |
| 206 | 206 | │ ├── impressum.md |
| 207 | 207 | │ └── projekte/ |
| 208 | 208 | │ └── mein-projekt/ |
| 209 | 209 | │ └── index.md |
| 210 | -├── static/ # Statische Assets |
|
| 211 | -│ ├── css/style.css |
|
| 212 | -│ ├── js/ |
|
| 213 | -│ │ ├── theme.js # Dark/Light Toggle + TOC Generator |
|
| 214 | -│ │ └── search.js # Client-seitige Volltextsuche |
|
| 210 | +├── static/ # Seiten-Assets (Icons, Bilder, ...) |
|
| 211 | +│ ├── icons/ |
|
| 215 | 212 | │ └── images/ |
| 213 | +├── themes/ # Themes — ein Verzeichnis je Theme |
|
| 214 | +│ └── default/ |
|
| 215 | +│ ├── templates/ |
|
| 216 | +│ │ ├── base.html # Base Layout + Navbar + Suche |
|
| 217 | +│ │ ├── home.html # Homepage + Pagination |
|
| 218 | +│ │ ├── post.html # Einzelner Post + Prev/Next Navigation |
|
| 219 | +│ │ ├── page.html # Statische Seite |
|
| 220 | +│ │ ├── tags.html # Tag-Übersicht |
|
| 221 | +│ │ ├── tag.html # Tag-Seite |
|
| 222 | +│ │ ├── categories.html # Kategorie-Übersicht |
|
| 223 | +│ │ └── category.html # Kategorie-Seite |
|
| 224 | +│ └── static/ # Theme-Assets (werden nach /static/ gemerged) |
|
| 225 | +│ ├── css/style.css |
|
| 226 | +│ └── js/ |
|
| 227 | +│ ├── theme.js # Dark/Light Toggle + TOC Generator |
|
| 228 | +│ └── search.js # Client-seitige Volltextsuche |
|
| 216 | 229 | ├── internal/ |
| 217 | 230 | │ ├── config/config.go # YAML Config Loader |
| 218 | 231 | │ ├── content/ |
| 219 | 232 | │ │ ├── post.go # Post Struct + FlexTime + Tags/Categories |
| 220 | 233 | │ │ ├── parser.go # Markdown + Frontmatter Parser |
| 221 | 234 | │ │ └── page.go # Statische Seiten Parser |
| 222 | 235 | │ ├── server/server.go # HTTP Server |
| 223 | 236 | │ ├── generator/ |
| 224 | 237 | │ │ ├── generator.go # Static Site Generator |
| 225 | 238 | │ │ └── search.go # Search-Index Generator (JSON) |
| 226 | 239 | │ └── templates/ |
| 227 | -│ ├── render.go # Template Engine + Functions |
|
| 228 | -│ ├── rss.go # RSS Feed Generator |
|
| 229 | -│ ├── base.html # Base Layout + Navbar + Suche |
|
| 230 | -│ ├── home.html # Homepage + Pagination |
|
| 231 | -│ ├── post.html # Einzelner Post + Prev/Next Navigation |
|
| 232 | -│ ├── page.html # Statische Seite |
|
| 233 | -│ ├── tags.html # Tag-Übersicht |
|
| 234 | -│ ├── tag.html # Tag-Seite |
|
| 235 | -│ ├── categories.html # Kategorie-Übersicht |
|
| 236 | -│ └── category.html # Kategorie-Seite |
|
| 240 | +│ ├── render.go # Template Engine + Functions (lädt das Theme) |
|
| 241 | +│ └── rss.go # RSS Feed Generator |
|
| 237 | 242 | └── output/ # Generierte statische Dateien |
| 238 | 243 | ``` |
| 239 | 244 | |
| 240 | 245 | ### Technologie-Stack |
| 241 | 246 | |
| 242 | 247 | | Komponente | Technologie | |
| 243 | 248 | |-----------|-------------| |
| 244 | 249 | | Sprache | Go (Standard Library + minimale Dependencies) | |
| 245 | 250 | | HTTP Server | `net/http` (Go Standard Library) | |
| 246 | -| Templates | `html/template` mit `embed.FS` | |
|
| 251 | +| Templates | `html/template`, zur Laufzeit aus `themes/<name>/templates/` geladen | |
|
| 247 | 252 | | Markdown | Goldmark + GFM + Emoji + Chroma | |
| 248 | 253 | | Konfiguration | YAML via `gopkg.in/yaml.v3` | |
| 249 | 254 | | Syntax Highlighting | Chroma (Dracula Theme) | |
| 250 | 255 | | Fonts | Inter + JetBrains Mono (Google Fonts) | |
| 251 | 256 | | CSS | Vanilla CSS mit Custom Properties | |
| 252 | 257 | | JavaScript | Vanilla JS — Theme Toggle, Suche, TOC (kein Framework) | |
| 253 | 258 | |
| 254 | 259 | ### Dependencies |
| 255 | 260 | |
| 256 | 261 | QuillDrop hat bewusst minimale Abhängigkeiten - **kein Web-Framework**, **kein CSS-Framework**, **kein JS-Framework**: |
| 257 | 262 | |
| 258 | 263 | - `github.com/yuin/goldmark` - Markdown Parser (CommonMark-konform) |
| 259 | 264 | - `github.com/yuin/goldmark-emoji` - Emoji Shortcodes |
| 260 | 265 | - `github.com/yuin/goldmark-highlighting/v2` - Syntax Highlighting |
| 261 | 266 | - `github.com/alecthomas/chroma/v2` - Syntax Highlighting Engine |
| 262 | 267 | - `gopkg.in/yaml.v3` - YAML Parser |
| 263 | 268 | |
| 264 | -### Embedded Assets |
|
| 269 | +### Themes |
|
| 265 | 270 | |
| 266 | -Alle HTML-Templates werden via Go's `//go:embed` Directive direkt in das Binary eingebettet. Das bedeutet: |
|
| 271 | +Templates und deren Assets liegen ausserhalb des Binaries in `themes/<name>/`. Dadurch |
|
| 272 | +kann dasselbe QuillDrop-Binary beliebig viele Websites bedienen, jede mit eigenem Design: |
|
| 267 | 273 | |
| 268 | -- **Einzelnes Binary** - Keine externen Template-Dateien nötig |
|
| 269 | -- **Schneller Start** - Kein Dateisystem-Zugriff für Templates |
|
| 270 | -- **Einfaches Deployment** - Ein Binary + Config + Content = fertig |
|
| 274 | +``` |
|
| 275 | +themes/ |
|
| 276 | +├── default/ |
|
| 277 | +│ ├── templates/ # Pflicht: base, home, post, page, tags, tag, categories, category |
|
| 278 | +│ └── static/ # Optional: CSS, JS, Theme-Bilder |
|
| 279 | +└── newdesign/ |
|
| 280 | +├── templates/ |
|
| 281 | +└── static/ |
|
| 282 | +``` |
|
| 283 | + | |
| 284 | +Das aktive Theme wird in der `config.yaml` gewählt: |
|
| 285 | + | |
| 286 | +```yaml |
|
| 287 | +themesDir: "themes" # Default |
|
| 288 | +theme: "default" # liest aus themes/default/ |
|
| 289 | +``` |
|
| 290 | + | |
| 291 | +Oder temporär per Flag, z. B. um ein Redesign zu testen: |
|
| 292 | + | |
| 293 | +```bash |
|
| 294 | +./quilldrop serve -theme newdesign |
|
| 295 | +./quilldrop generate -theme newdesign |
|
| 296 | +``` |
|
| 297 | + | |
| 298 | +**Neues Theme anlegen:** |
|
| 299 | + | |
| 300 | +```bash |
|
| 301 | +cp -r themes/default themes/newdesign # oder: make new-theme NAME=newdesign |
|
| 302 | +# themes/newdesign/templates/*.html und themes/newdesign/static/css/style.css anpassen |
|
| 303 | +./quilldrop serve -theme newdesign -dev |
|
| 304 | +``` |
|
| 305 | + | |
| 306 | +**Live-Reload:** Mit `-dev` werden die Templates bei jedem Request neu aus dem |
|
| 307 | +Theme-Verzeichnis gelesen — Änderungen an HTML, CSS und JS sind nach einem |
|
| 308 | +Browser-Reload sichtbar, ohne den Server neu zu starten (im Dev-Modus wird |
|
| 309 | +zusätzlich `Cache-Control: no-store` gesetzt, damit der Browser nichts |
|
| 310 | +zwischenspeichert). Ein fehlerhaftes Template liefert eine 500 statt einer halb |
|
| 311 | +gerenderten Seite; die genaue Fehlermeldung mit Datei und Zeile steht im |
|
| 312 | +Server-Log. Ohne `-dev` werden die Templates wie bisher einmal beim Start |
|
| 313 | +geparst. Neue oder geänderte Markdown-Dateien erfordern weiterhin einen Neustart. |
|
| 314 | + | |
| 315 | +Ein Theme muss alle acht Templates enthalten (`base.html`, `home.html`, `post.html`, |
|
| 316 | +`page.html`, `tags.html`, `tag.html`, `categories.html`, `category.html`); |
|
| 317 | +fehlt eines oder existiert das Theme nicht, bricht QuillDrop mit einer klaren |
|
| 318 | +Fehlermeldung ab. |
|
| 319 | + | |
| 320 | +**Statische Assets** werden gemerged: zuerst `themes/<name>/static/`, danach das |
|
| 321 | +eigene `static/` der Seite — gleichnamige Dateien der Seite gewinnen also |
|
| 322 | +(z. B. `static/icons/favicon.ico`). Das Design gehört ins Theme (CSS, JS), |
|
| 323 | +seitenspezifisches Material bleibt in `static/` (Icons, Bilder). Beides wird unter |
|
| 324 | +`/static/` ausgeliefert; `static/images/` und `static/videos/` zusätzlich unter |
|
| 325 | +`/images/` und `/videos/`. |
|
| 271 | 326 | |
| 272 | 327 | ## Konfiguration |
| 273 | 328 | |
| 274 | 329 | Die gesamte Konfiguration erfolgt über eine einzige `config.yaml`: |
| 275 | 330 | |
| 276 | 331 | ```yaml |
| 277 | 332 | title: "Mein Blog" |
| 278 | 333 | description: "Tech Blog - DevOps, Kubernetes, Self-Hosted" |
| 279 | 334 | author: "Max Mustermann" |
| 280 | 335 | baseURL: "https://mein-blog.de" |
| 281 | 336 | port: 8080 |
| 282 | 337 | postsPerPage: 5 |
| 283 | 338 | contentDir: "content" |
| 284 | 339 | sitesDir: "sites" |
| 340 | +staticDir: "static" |
|
| 285 | 341 | outputDir: "output" |
| 342 | +themesDir: "themes" |
|
| 343 | +theme: "default" |
|
| 286 | 344 | |
| 287 | 345 | menu: |
| 288 | 346 | - label: "Home" |
| 289 | 347 | url: "/" |
| 290 | 348 | - label: "Tags" |
| 291 | 349 | url: "/tags" |
| 292 | 350 | - label: "Über mich" |
| 293 | 351 | url: "/sites/ueber-mich" |
| 294 | 352 | ``` |
| 295 | 353 | |
| 296 | 354 | | Option | Default | Beschreibung | |
| 297 | 355 | |--------|---------|-------------| |
| 298 | 356 | | `title` | - | Titel der Website | |
| 299 | 357 | | `description` | - | Beschreibung (Meta-Tag + Hero) | |
| 300 | 358 | | `author` | - | Autor der Website | |
| 301 | 359 | | `baseURL` | - | Basis-URL für RSS und absolute Links | |
| 302 | 360 | | `port` | `8080` | Port für den dynamischen Server | |
| 303 | 361 | | `postsPerPage` | `5` | Anzahl Posts pro Seite | |
| 304 | 362 | | `contentDir` | `content` | Verzeichnis für Blog-Posts | |
| 305 | 363 | | `sitesDir` | `sites` | Verzeichnis für statische Seiten | |
| 364 | +| `staticDir` | `static` | Verzeichnis für Seiten-Assets | |
|
| 306 | 365 | | `outputDir` | `output` | Ausgabeverzeichnis für statische Generierung | |
| 366 | +| `themesDir` | `themes` | Verzeichnis mit allen Themes | |
|
| 367 | +| `theme` | `default` | Aktives Theme, gelesen aus `<themesDir>/<theme>/` (Override: `-theme`) | |
|
| 307 | 368 | | `menu` | `[]` | Navigationsmenü mit optionalen Untermenüs | |
| 308 | 369 | |
| 309 | 370 | ## Schnellstart |
| 310 | 371 | |
| 311 | 372 | ### Installation |
| 312 | 373 | |
| 313 | 374 | ```bash |
| 314 | 375 | # Repository klonen |
| 315 | 376 | git clone https://github.com/ruedigerp/quilldrop.git |
| 316 | 377 | cd quilldrop |
| @@ -347,20 +408,23 @@ Das ist mein erster Post mit **QuillDrop**. | ||
| 347 | 408 | ``` |
| 348 | 409 | |
| 349 | 410 | ### Lokale Vorschau |
| 350 | 411 | |
| 351 | 412 | ```bash |
| 352 | 413 | # Dynamischen Server starten |
| 353 | 414 | ./quilldrop serve |
| 354 | 415 | |
| 355 | 416 | # Oder direkt mit Go |
| 356 | 417 | go run . serve |
| 418 | + | |
| 419 | +# Mit Live-Reload für Templates (Theme-Entwicklung) |
|
| 420 | +./quilldrop serve -dev |
|
| 357 | 421 | ``` |
| 358 | 422 | |
| 359 | 423 | Dann im Browser: [http://localhost:8080](http://localhost:8080) |
| 360 | 424 | |
| 361 | 425 | ### Statische Seite generieren |
| 362 | 426 | |
| 363 | 427 | ```bash |
| 364 | 428 | # HTML-Dateien generieren |
| 365 | 429 | ./quilldrop generate |
| 366 | 430 |
| @@ -202,117 +202,176 @@ quilldrop/ | ||
| 202 | 202 | ├── config.yaml # Configuration |
| 203 | 203 | ├── content/ # Blog posts (Markdown) |
| 204 | 204 | │ ├── 2025-11-06-my-post.md |
| 205 | 205 | │ └── ... |
| 206 | 206 | ├── sites/ # Static pages |
| 207 | 207 | │ ├── about.md |
| 208 | 208 | │ ├── legal.md |
| 209 | 209 | │ └── projects/ |
| 210 | 210 | │ └── my-project/ |
| 211 | 211 | │ └── index.md |
| 212 | -├── static/ # Static assets |
|
| 213 | -│ ├── css/style.css |
|
| 214 | -│ ├── js/ |
|
| 215 | -│ │ ├── theme.js # Dark/Light toggle + TOC generator |
|
| 216 | -│ │ └── search.js # Client-side full-text search |
|
| 212 | +├── static/ # Site assets (icons, images, ...) |
|
| 213 | +│ ├── icons/ |
|
| 217 | 214 | │ └── images/ |
| 215 | +├── themes/ # Themes — one directory per theme |
|
| 216 | +│ └── default/ |
|
| 217 | +│ ├── templates/ |
|
| 218 | +│ │ ├── base.html # Base layout + navbar + search |
|
| 219 | +│ │ ├── home.html # Homepage + pagination |
|
| 220 | +│ │ ├── post.html # Single post + prev/next navigation |
|
| 221 | +│ │ ├── page.html # Static page |
|
| 222 | +│ │ ├── tags.html # Tag overview |
|
| 223 | +│ │ ├── tag.html # Tag page |
|
| 224 | +│ │ ├── categories.html # Category overview |
|
| 225 | +│ │ └── category.html # Category page |
|
| 226 | +│ └── static/ # Theme assets (merged into /static/) |
|
| 227 | +│ ├── css/style.css |
|
| 228 | +│ └── js/ |
|
| 229 | +│ ├── theme.js # Dark/Light toggle + TOC generator |
|
| 230 | +│ └── search.js # Client-side full-text search |
|
| 218 | 231 | ├── internal/ |
| 219 | 232 | │ ├── config/config.go # YAML config loader |
| 220 | 233 | │ ├── content/ |
| 221 | 234 | │ │ ├── post.go # Post struct + FlexTime + Tags/Categories |
| 222 | 235 | │ │ ├── parser.go # Markdown + frontmatter parser |
| 223 | 236 | │ │ └── page.go # Static pages parser |
| 224 | 237 | │ ├── server/server.go # HTTP server |
| 225 | 238 | │ ├── generator/ |
| 226 | 239 | │ │ ├── generator.go # Static site generator |
| 227 | 240 | │ │ └── search.go # Search index generator (JSON) |
| 228 | 241 | │ └── templates/ |
| 229 | -│ ├── render.go # Template engine + functions |
|
| 230 | -│ ├── rss.go # RSS feed generator |
|
| 231 | -│ ├── base.html # Base layout + navbar + search |
|
| 232 | -│ ├── home.html # Homepage + pagination |
|
| 233 | -│ ├── post.html # Single post + prev/next navigation |
|
| 234 | -│ ├── page.html # Static page |
|
| 235 | -│ ├── tags.html # Tag overview |
|
| 236 | -│ ├── tag.html # Tag page |
|
| 237 | -│ ├── categories.html # Category overview |
|
| 238 | -│ └── category.html # Category page |
|
| 242 | +│ ├── render.go # Template engine + functions (loads the theme) |
|
| 243 | +│ └── rss.go # RSS feed generator |
|
| 239 | 244 | └── output/ # Generated static files |
| 240 | 245 | ``` |
| 241 | 246 | |
| 242 | 247 | ### Technology Stack |
| 243 | 248 | |
| 244 | 249 | | Component | Technology | |
| 245 | 250 | |-----------|------------| |
| 246 | 251 | | Language | Go (standard library + minimal dependencies) | |
| 247 | 252 | | HTTP Server | `net/http` (Go standard library) | |
| 248 | -| Templates | `html/template` with `embed.FS` | |
|
| 253 | +| Templates | `html/template`, loaded from `themes/<name>/templates/` at runtime | |
|
| 249 | 254 | | Markdown | Goldmark + GFM + Emoji + Chroma | |
| 250 | 255 | | Configuration | YAML via `gopkg.in/yaml.v3` | |
| 251 | 256 | | Syntax Highlighting | Chroma (Dracula theme) | |
| 252 | 257 | | Fonts | Inter + JetBrains Mono (Google Fonts) | |
| 253 | 258 | | CSS | Vanilla CSS with custom properties | |
| 254 | 259 | | JavaScript | Vanilla JS — theme toggle, search, TOC (no framework) | |
| 255 | 260 | |
| 256 | 261 | ### Dependencies |
| 257 | 262 | |
| 258 | 263 | QuillDrop intentionally has minimal dependencies — **no web framework**, **no CSS framework**, **no JS framework**: |
| 259 | 264 | |
| 260 | 265 | - `github.com/yuin/goldmark` — Markdown parser (CommonMark compliant) |
| 261 | 266 | - `github.com/yuin/goldmark-emoji` — Emoji shortcodes |
| 262 | 267 | - `github.com/yuin/goldmark-highlighting/v2` — Syntax highlighting |
| 263 | 268 | - `github.com/alecthomas/chroma/v2` — Syntax highlighting engine |
| 264 | 269 | - `gopkg.in/yaml.v3` — YAML parser |
| 265 | 270 | |
| 266 | -### Embedded Assets |
|
| 271 | +### Themes |
|
| 267 | 272 | |
| 268 | -All HTML templates are embedded directly into the binary via Go's `//go:embed` directive. This means: |
|
| 273 | +Templates and their assets live outside the binary, in `themes/<name>/`. The same |
|
| 274 | +QuillDrop binary can therefore drive any number of websites, each with its own look: |
|
| 269 | 275 | |
| 270 | -- **Single binary** — No external template files needed |
|
| 271 | -- **Fast startup** — No filesystem access for templates |
|
| 272 | -- **Easy deployment** — One binary + config + content = done |
|
| 276 | +``` |
|
| 277 | +themes/ |
|
| 278 | +├── default/ |
|
| 279 | +│ ├── templates/ # required: base, home, post, page, tags, tag, categories, category |
|
| 280 | +│ └── static/ # optional: CSS, JS, theme images |
|
| 281 | +└── newdesign/ |
|
| 282 | +├── templates/ |
|
| 283 | +└── static/ |
|
| 284 | +``` |
|
| 285 | + | |
| 286 | +The active theme is selected in `config.yaml`: |
|
| 287 | + | |
| 288 | +```yaml |
|
| 289 | +themesDir: "themes" # default |
|
| 290 | +theme: "default" # reads from themes/default/ |
|
| 291 | +``` |
|
| 292 | + | |
| 293 | +Or temporarily via flag, e.g. to preview a redesign: |
|
| 294 | + | |
| 295 | +```bash |
|
| 296 | +./quilldrop serve -theme newdesign |
|
| 297 | +./quilldrop generate -theme newdesign |
|
| 298 | +``` |
|
| 299 | + | |
| 300 | +**Creating a new theme:** |
|
| 301 | + | |
| 302 | +```bash |
|
| 303 | +cp -r themes/default themes/newdesign # or: make new-theme NAME=newdesign |
|
| 304 | +# edit themes/newdesign/templates/*.html and themes/newdesign/static/css/style.css |
|
| 305 | +./quilldrop serve -theme newdesign -dev |
|
| 306 | +``` |
|
| 307 | + | |
| 308 | +**Live reload:** With `-dev` the templates are re-read from the theme directory on |
|
| 309 | +every request — changes to HTML, CSS and JS become visible after a browser reload, |
|
| 310 | +without restarting the server (dev mode also sends `Cache-Control: no-store` so the |
|
| 311 | +browser does not cache assets). A broken template returns a 500 instead of a |
|
| 312 | +half-rendered page; the exact error with file and line is written to the server log. |
|
| 313 | +Without `-dev` templates are parsed once at startup, as before. New or changed |
|
| 314 | +Markdown files still require a restart. |
|
| 315 | + | |
| 316 | +A theme must provide all eight templates (`base.html`, `home.html`, `post.html`, |
|
| 317 | +`page.html`, `tags.html`, `tag.html`, `categories.html`, `category.html`); |
|
| 318 | +QuillDrop aborts with a clear error if one is missing or the theme does not exist. |
|
| 319 | + | |
| 320 | +**Static assets** are merged: `themes/<name>/static/` is copied first, then the |
|
| 321 | +site's own `static/` on top — so site files (e.g. `static/icons/favicon.ico`) |
|
| 322 | +override theme files of the same name. Design belongs to the theme (CSS, JS), |
|
| 323 | +site-specific material stays in `static/` (icons, images). Both are served under |
|
| 324 | +`/static/`; `static/images/` and `static/videos/` are additionally published at |
|
| 325 | +`/images/` and `/videos/`. |
|
| 273 | 326 | |
| 274 | 327 | ## Configuration |
| 275 | 328 | |
| 276 | 329 | All configuration is done via a single `config.yaml`: |
| 277 | 330 | |
| 278 | 331 | ```yaml |
| 279 | 332 | title: "My Blog" |
| 280 | 333 | description: "Tech Blog - DevOps, Kubernetes, Self-Hosted" |
| 281 | 334 | author: "Jane Doe" |
| 282 | 335 | baseURL: "https://my-blog.com" |
| 283 | 336 | port: 8080 |
| 284 | 337 | postsPerPage: 5 |
| 285 | 338 | contentDir: "content" |
| 286 | 339 | sitesDir: "sites" |
| 340 | +staticDir: "static" |
|
| 287 | 341 | outputDir: "output" |
| 342 | +themesDir: "themes" |
|
| 343 | +theme: "default" |
|
| 288 | 344 | |
| 289 | 345 | menu: |
| 290 | 346 | - label: "Home" |
| 291 | 347 | url: "/" |
| 292 | 348 | - label: "Tags" |
| 293 | 349 | url: "/tags" |
| 294 | 350 | - label: "About" |
| 295 | 351 | url: "/sites/about" |
| 296 | 352 | ``` |
| 297 | 353 | |
| 298 | 354 | | Option | Default | Description | |
| 299 | 355 | |--------|---------|-------------| |
| 300 | 356 | | `title` | — | Website title | |
| 301 | 357 | | `description` | — | Description (meta tag + hero) | |
| 302 | 358 | | `author` | — | Website author | |
| 303 | 359 | | `baseURL` | — | Base URL for RSS and absolute links | |
| 304 | 360 | | `port` | `8080` | Port for the dynamic server | |
| 305 | 361 | | `postsPerPage` | `5` | Number of posts per page | |
| 306 | 362 | | `contentDir` | `content` | Directory for blog posts | |
| 307 | 363 | | `sitesDir` | `sites` | Directory for static pages | |
| 364 | +| `staticDir` | `static` | Directory for site assets | |
|
| 308 | 365 | | `outputDir` | `output` | Output directory for static generation | |
| 366 | +| `themesDir` | `themes` | Directory containing all themes | |
|
| 367 | +| `theme` | `default` | Active theme, read from `<themesDir>/<theme>/` (override: `-theme`) | |
|
| 309 | 368 | | `menu` | `[]` | Navigation menu with optional submenus | |
| 310 | 369 | |
| 311 | 370 | ## Quick Start |
| 312 | 371 | |
| 313 | 372 | ### Installation |
| 314 | 373 | |
| 315 | 374 | ```bash |
| 316 | 375 | # Clone the repository |
| 317 | 376 | git clone https://github.com/ruedigerp/quilldrop.git |
| 318 | 377 | cd quilldrop |
| @@ -349,20 +408,23 @@ This is my first post with **QuillDrop**. | ||
| 349 | 408 | ``` |
| 350 | 409 | |
| 351 | 410 | ### Local Preview |
| 352 | 411 | |
| 353 | 412 | ```bash |
| 354 | 413 | # Start the dynamic server |
| 355 | 414 | ./quilldrop serve |
| 356 | 415 | |
| 357 | 416 | # Or run directly with Go |
| 358 | 417 | go run . serve |
| 418 | + | |
| 419 | +# With template live reload (theme development) |
|
| 420 | +./quilldrop serve -dev |
|
| 359 | 421 | ``` |
| 360 | 422 | |
| 361 | 423 | Then open in the browser: [http://localhost:8080](http://localhost:8080) |
| 362 | 424 | |
| 363 | 425 | ### Generate Static Site |
| 364 | 426 | |
| 365 | 427 | ```bash |
| 366 | 428 | # Generate HTML files |
| 367 | 429 | ./quilldrop generate |
| 368 | 430 |
| @@ -1,20 +1,25 @@ | ||
| 1 | 1 | title: "Küpper Blog" |
| 2 | 2 | description: "Tech Blog - DevOps, Kubernetes, Self-Hosted" |
| 3 | 3 | author: "Rüdiger Küpper" |
| 4 | 4 | baseURL: "https://blog.kuepper.nrw" |
| 5 | -port: 8080 |
|
| 5 | +port: 8180 |
|
| 6 | 6 | postsPerPage: 5 |
| 7 | 7 | contentDir: "content" |
| 8 | 8 | sitesDir: "sites" |
| 9 | +staticDir: "static" |
|
| 9 | 10 | outputDir: "output" |
| 10 | 11 | |
| 12 | +# Theme: read from <themesDir>/<theme>/ |
|
| 13 | +themesDir: "themes" |
|
| 14 | +theme: "ehc" |
|
| 15 | + | |
| 11 | 16 | menu: |
| 12 | 17 | - label: "Home" |
| 13 | 18 | url: "/" |
| 14 | 19 | - label: "Projekte" |
| 15 | 20 | children: |
| 16 | 21 | # - label: "VM-Manager" |
| 17 | 22 | # url: "/sites/projects/vm-manager/" |
| 18 | 23 | - label: "VM-Tracker" |
| 19 | 24 | url: "/sites/projects/vm-tracker/" |
| 20 | 25 | - label: "QuillDrop" |
| @@ -1,44 +1,101 @@ | ||
| 1 | 1 | package config |
| 2 | 2 | |
| 3 | 3 | import ( |
| 4 | 4 | "os" |
| 5 | +"path/filepath" |
|
| 5 | 6 | |
| 6 | 7 | "gopkg.in/yaml.v3" |
| 7 | 8 | ) |
| 8 | 9 | |
| 9 | 10 | type MenuItem struct { |
| 10 | 11 | Label string `yaml:"label"` |
| 11 | 12 | URL string `yaml:"url,omitempty"` |
| 12 | 13 | Children []MenuItem `yaml:"children,omitempty"` |
| 13 | 14 | } |
| 14 | 15 | |
| 16 | +// LLMsConfig toggles generation/serving of the llms.txt convention files. |
|
| 17 | +// Both default to true so behaviour without the block stays unchanged. |
|
| 18 | +type LLMsConfig struct { |
|
| 19 | +Enabled *bool `yaml:"enabled,omitempty"` // llms.txt |
|
| 20 | +Full *bool `yaml:"full,omitempty"` // llms-full.txt |
|
| 21 | +} |
|
| 22 | + | |
| 23 | +// EnabledOrDefault returns whether llms.txt should be produced (default: true). |
|
| 24 | +func (l LLMsConfig) EnabledOrDefault() bool { |
|
| 25 | + if l.Enabled == nil { |
|
| 26 | +return true |
|
| 27 | +} |
|
| 28 | +return *l.Enabled |
|
| 29 | +} |
|
| 30 | + | |
| 31 | +// FullOrDefault returns whether llms-full.txt should be produced (default: true). |
|
| 32 | +func (l LLMsConfig) FullOrDefault() bool { |
|
| 33 | + if l.Full == nil { |
|
| 34 | +return true |
|
| 35 | +} |
|
| 36 | +return *l.Full |
|
| 37 | +} |
|
| 38 | + | |
| 15 | 39 | type Config struct { |
| 16 | 40 | Title string `yaml:"title"` |
| 17 | 41 | Description string `yaml:"description"` |
| 18 | 42 | Author string `yaml:"author"` |
| 19 | 43 | BaseURL string `yaml:"baseURL"` |
| 20 | 44 | Port int `yaml:"port"` |
| 21 | 45 | PostsPerPage int `yaml:"postsPerPage"` |
| 22 | 46 | ContentDir string `yaml:"contentDir"` |
| 23 | 47 | SitesDir string `yaml:"sitesDir"` |
| 48 | +StaticDir string `yaml:"staticDir"` |
|
| 24 | 49 | OutputDir string `yaml:"outputDir"` |
| 50 | +ThemesDir string `yaml:"themesDir"` |
|
| 51 | +Theme string `yaml:"theme"` |
|
| 25 | 52 | Menu []MenuItem `yaml:"menu"` |
| 53 | +LLMs LLMsConfig `yaml:"llms"` |
|
| 54 | +} |
|
| 55 | + | |
| 56 | +// ThemeDir returns the directory of the active theme, e.g. "themes/default". |
|
| 57 | +func (c *Config) ThemeDir() string { |
|
| 58 | +return filepath.Join(c.ThemesDir, c.Theme) |
|
| 59 | +} |
|
| 60 | + | |
| 61 | +// ThemeTemplatesDir returns the template directory of the active theme. |
|
| 62 | +func (c *Config) ThemeTemplatesDir() string { |
|
| 63 | +return filepath.Join(c.ThemeDir(), "templates") |
|
| 64 | +} |
|
| 65 | + | |
| 66 | +// ThemeStaticDir returns the static asset directory of the active theme. |
|
| 67 | +// The directory is optional; a theme may ship without own assets. |
|
| 68 | +func (c *Config) ThemeStaticDir() string { |
|
| 69 | +return filepath.Join(c.ThemeDir(), "static") |
|
| 26 | 70 | } |
| 27 | 71 | |
| 28 | 72 | func Load(path string) (*Config, error) { |
| 29 | 73 | data, err := os.ReadFile(path) |
| 30 | 74 | if err != nil { |
| 31 | 75 | return nil, err |
| 32 | 76 | } |
| 33 | 77 | cfg := &Config{ |
| 34 | 78 | Port: 8080, |
| 35 | 79 | PostsPerPage: 5, |
| 36 | 80 | ContentDir: "content", |
| 37 | 81 | SitesDir: "sites", |
| 82 | +StaticDir: "static", |
|
| 38 | 83 | OutputDir: "output", |
| 84 | +ThemesDir: "themes", |
|
| 85 | +Theme: "default", |
|
| 39 | 86 | } |
| 40 | 87 | if err := yaml.Unmarshal(data, cfg); err != nil { |
| 41 | 88 | return nil, err |
| 42 | 89 | } |
| 90 | +// Empty values in config.yaml must not override the defaults. |
|
| 91 | + if cfg.StaticDir == "" { |
|
| 92 | +cfg.StaticDir = "static" |
|
| 93 | +} |
|
| 94 | + if cfg.ThemesDir == "" { |
|
| 95 | +cfg.ThemesDir = "themes" |
|
| 96 | +} |
|
| 97 | + if cfg.Theme == "" { |
|
| 98 | +cfg.Theme = "default" |
|
| 99 | +} |
|
| 43 | 100 | return cfg, nil |
| 44 | 101 | } |
| @@ -7,23 +7,24 @@ import ( | ||
| 7 | 7 | "os" |
| 8 | 8 | "path/filepath" |
| 9 | 9 | "strings" |
| 10 | 10 | |
| 11 | 11 | "github.com/ruedigerp/newblog/internal/config" |
| 12 | 12 | "github.com/ruedigerp/newblog/internal/content" |
| 13 | 13 | "github.com/ruedigerp/newblog/internal/templates" |
| 14 | 14 | ) |
| 15 | 15 | |
| 16 | 16 | func Generate(cfg *config.Config, posts []*content.Post, pages []*content.Page) { |
| 17 | - if err := templates.Init(); err != nil { |
|
| 17 | + if err := templates.Init(cfg.ThemeDir()); err != nil { |
|
| 18 | 18 | log.Fatalf("Failed to init templates: %v", err) |
| 19 | 19 | } |
| 20 | + log.Printf("Using theme %q from %s", cfg.Theme, cfg.ThemeDir()) |
|
| 20 | 21 | |
| 21 | 22 | out := cfg.OutputDir |
| 22 | 23 | |
| 23 | 24 | // Clean and recreate output directory |
| 24 | 25 | os.RemoveAll(out) |
| 25 | 26 | os.MkdirAll(out, 0755) |
| 26 | 27 | |
| 27 | 28 | site := templates.SiteData{ |
| 28 | 29 | Title: cfg.Title, |
| 29 | 30 | Description: cfg.Description, |
| @@ -137,26 +138,35 @@ func Generate(cfg *config.Config, posts []*content.Post, pages []*content.Page) | ||
| 137 | 138 | if rssCount > len(posts) { |
| 138 | 139 | rssCount = len(posts) |
| 139 | 140 | } |
| 140 | 141 | writeTemplate(filepath.Join(out, "index.xml"), func(f *os.File) error { |
| 141 | 142 | return templates.RenderRSS(f, site, posts[:rssCount]) |
| 142 | 143 | }) |
| 143 | 144 | |
| 144 | 145 | // 9. Search index |
| 145 | 146 | GenerateSearchIndex(posts, filepath.Join(out, "search-index.json")) |
| 146 | 147 | |
| 147 | -// 10. Copy static assets (skip images/ subdirectory — handled separately) |
|
| 148 | - copyStaticDir("static", filepath.Join(out, "static"), []string{"images", "videos"}) |
|
| 148 | +// 9b. llms.txt / llms-full.txt for LLM ingestion (https://llmstxt.org/) |
|
| 149 | +GenerateLLMsFiles(cfg, posts, pages, out) |
|
| 150 | + | |
| 151 | +// 10. Copy static assets: theme assets first, site assets afterwards so |
|
| 152 | +// files in the site's static/ override the ones shipped with the theme. |
|
| 153 | +// (skip images/ subdirectory — handled separately) |
|
| 154 | +// Theme assets are copied as-is: a theme's own images belong to /static/images/. |
|
| 155 | + if _, err := os.Stat(cfg.ThemeStaticDir()); err == nil { |
|
| 156 | +copyStaticDir(cfg.ThemeStaticDir(), filepath.Join(out, "static"), nil) |
|
| 157 | +} |
|
| 158 | + copyStaticDir(cfg.StaticDir, filepath.Join(out, "static"), []string{"images", "videos"}) |
|
| 149 | 159 | |
| 150 | 160 | // 11. Copy images + videos to root /images/ and /videos/ (cover paths use /images/...) |
| 151 | 161 | for _, dir := range []string{"images", "videos"} { |
| 152 | - src := filepath.Join("static", dir) |
|
| 162 | +src := filepath.Join(cfg.StaticDir, dir) |
|
| 153 | 163 | dst := filepath.Join(out, dir) |
| 154 | 164 | if _, err := os.Stat(src); err == nil { |
| 155 | 165 | copyStaticDir(src, dst, nil) |
| 156 | 166 | } |
| 157 | 167 | } |
| 158 | 168 | |
| 159 | 169 | log.Printf("Generated %d posts, %d pages, %d tag pages, %d category pages, RSS feed into %s/", |
| 160 | 170 | len(posts), len(pages), len(tagMap), len(catMap), out) |
| 161 | 171 | } |
| 162 | 172 |
| @@ -0,0 +1,159 @@ | ||
| 1 | +package generator |
|
| 2 | + | |
| 3 | +import ( |
|
| 4 | +"fmt" |
|
| 5 | +"io" |
|
| 6 | +"log" |
|
| 7 | +"os" |
|
| 8 | +"strings" |
|
| 9 | + | |
| 10 | +"github.com/ruedigerp/newblog/internal/config" |
|
| 11 | +"github.com/ruedigerp/newblog/internal/content" |
|
| 12 | +) |
|
| 13 | + | |
| 14 | +// RenderLLMsTxt writes an llms.txt index pointing LLMs at the site's resources. |
|
| 15 | +// Follows the proposal at https://llmstxt.org/ — H1 title, blockquote summary, |
|
| 16 | +// then H2 sections with markdown link lists. |
|
| 17 | +func RenderLLMsTxt(w io.Writer, cfg *config.Config, posts []*content.Post, pages []*content.Page) error { |
|
| 18 | + bw := &errWriter{w: w} |
|
| 19 | + | |
| 20 | + bw.printf("# %s\n\n", cfg.Title) |
|
| 21 | + bw.printf("> %s\n\n", cfg.Description) |
|
| 22 | + if cfg.Author != "" { |
|
| 23 | + bw.printf("Author: %s\n", cfg.Author) |
|
| 24 | +} |
|
| 25 | + bw.printf("Site: %s\n\n", cfg.BaseURL) |
|
| 26 | + bw.printf("Diese Datei folgt der llms.txt-Konvention (https://llmstxt.org/) und listet "+ |
|
| 27 | +"alle Inhalte des Blogs, damit Sprachmodelle sie effizient finden und einordnen können. "+ |
|
| 28 | +"Die vollständigen Texte liegen unter %s/llms-full.txt.\n\n", strings.TrimRight(cfg.BaseURL, "/")) |
|
| 29 | + | |
| 30 | +// Blog posts |
|
| 31 | + bw.printf("## Blogposts\n\n") |
|
| 32 | + for _, p := range posts { |
|
| 33 | +url := strings.TrimRight(cfg.BaseURL, "/") + "/posts/" + p.Slug + "/" |
|
| 34 | +preview := strings.TrimSpace(p.GetPreview()) |
|
| 35 | + date := p.Date.Format("2006-01-02") |
|
| 36 | + if preview != "" { |
|
| 37 | + bw.printf("- [%s](%s) — %s (%s)\n", p.Title, url, preview, date) |
|
| 38 | + } else { |
|
| 39 | + bw.printf("- [%s](%s) (%s)\n", p.Title, url, date) |
|
| 40 | +} |
|
| 41 | +} |
|
| 42 | + bw.printf("\n") |
|
| 43 | + | |
| 44 | +// Static pages |
|
| 45 | + if len(pages) > 0 { |
|
| 46 | + bw.printf("## Seiten\n\n") |
|
| 47 | + for _, pg := range pages { |
|
| 48 | +url := strings.TrimRight(cfg.BaseURL, "/") + "/sites/" + pg.Slug + "/" |
|
| 49 | + if pg.Description != "" { |
|
| 50 | + bw.printf("- [%s](%s) — %s\n", pg.Title, url, pg.Description) |
|
| 51 | + } else { |
|
| 52 | + bw.printf("- [%s](%s)\n", pg.Title, url) |
|
| 53 | +} |
|
| 54 | +} |
|
| 55 | + bw.printf("\n") |
|
| 56 | +} |
|
| 57 | + | |
| 58 | +// Optional resources |
|
| 59 | +base := strings.TrimRight(cfg.BaseURL, "/") |
|
| 60 | + bw.printf("## Optional\n\n") |
|
| 61 | + bw.printf("- [Tags](%s/tags/) — Übersicht aller Tags\n", base) |
|
| 62 | + bw.printf("- [Kategorien](%s/categories/) — Übersicht aller Kategorien\n", base) |
|
| 63 | + bw.printf("- [RSS Feed](%s/index.xml) — RSS-Feed mit den neuesten Posts\n", base) |
|
| 64 | + if cfg.LLMs.FullOrDefault() { |
|
| 65 | + bw.printf("- [Volltext](%s/llms-full.txt) — Alle Blogposts als Markdown in einer Datei\n", base) |
|
| 66 | +} |
|
| 67 | + | |
| 68 | +return bw.err |
|
| 69 | +} |
|
| 70 | + | |
| 71 | +// RenderLLMsFullTxt writes llms-full.txt — every post's full markdown content |
|
| 72 | +// concatenated with metadata headers, suitable for LLM ingestion. |
|
| 73 | +func RenderLLMsFullTxt(w io.Writer, cfg *config.Config, posts []*content.Post) error { |
|
| 74 | + bw := &errWriter{w: w} |
|
| 75 | + | |
| 76 | + bw.printf("# %s\n\n", cfg.Title) |
|
| 77 | + bw.printf("> %s\n\n", cfg.Description) |
|
| 78 | + if cfg.Author != "" { |
|
| 79 | + bw.printf("Author: %s\n", cfg.Author) |
|
| 80 | +} |
|
| 81 | + bw.printf("Site: %s\n\n", cfg.BaseURL) |
|
| 82 | + if cfg.LLMs.EnabledOrDefault() { |
|
| 83 | + bw.printf("Dies ist der konsolidierte Volltext aller Blogposts (neueste zuerst). "+ |
|
| 84 | +"Eine knappe Übersicht steht unter %s/llms.txt.\n\n", strings.TrimRight(cfg.BaseURL, "/")) |
|
| 85 | + } else { |
|
| 86 | + bw.printf("Dies ist der konsolidierte Volltext aller Blogposts (neueste zuerst).\n\n") |
|
| 87 | +} |
|
| 88 | + | |
| 89 | +base := strings.TrimRight(cfg.BaseURL, "/") |
|
| 90 | + for i, p := range posts { |
|
| 91 | + if i > 0 { |
|
| 92 | + bw.printf("\n---\n\n") |
|
| 93 | +} |
|
| 94 | +url := base + "/posts/" + p.Slug + "/" |
|
| 95 | + bw.printf("## %s\n\n", p.Title) |
|
| 96 | + bw.printf("- URL: %s\n", url) |
|
| 97 | + bw.printf("- Datum: %s\n", p.Date.Format("2006-01-02")) |
|
| 98 | + if !p.Update.Time.IsZero() { |
|
| 99 | + bw.printf("- Aktualisiert: %s\n", p.Update.Format("2006-01-02")) |
|
| 100 | +} |
|
| 101 | + if p.Author != "" { |
|
| 102 | + bw.printf("- Autor: %s\n", p.Author) |
|
| 103 | +} |
|
| 104 | + if len(p.Tags) > 0 { |
|
| 105 | + bw.printf("- Tags: %s\n", strings.Join(p.Tags, ", ")) |
|
| 106 | +} |
|
| 107 | + if len(p.Categories) > 0 { |
|
| 108 | + bw.printf("- Kategorien: %s\n", strings.Join(p.Categories, ", ")) |
|
| 109 | +} |
|
| 110 | + bw.printf("\n") |
|
| 111 | +// Body is the preprocessed markdown (Hugo shortcodes already stripped). |
|
| 112 | +body := strings.TrimSpace(p.Content) |
|
| 113 | + bw.printf("%s\n", body) |
|
| 114 | +} |
|
| 115 | + | |
| 116 | +return bw.err |
|
| 117 | +} |
|
| 118 | + | |
| 119 | +// errWriter swallows repeated writes after the first error so callers don't |
|
| 120 | +// have to check every Fprintf. |
|
| 121 | +type errWriter struct { |
|
| 122 | +w io.Writer |
|
| 123 | +err error |
|
| 124 | +} |
|
| 125 | + | |
| 126 | +func (e *errWriter) printf(format string, args ...interface{}) { |
|
| 127 | + if e.err != nil { |
|
| 128 | +return |
|
| 129 | +} |
|
| 130 | +_, e.err = fmt.Fprintf(e.w, format, args...) |
|
| 131 | +} |
|
| 132 | + | |
| 133 | +// GenerateLLMsFiles writes llms.txt and llms-full.txt into outDir, |
|
| 134 | +// honoring cfg.LLMs.Enabled / cfg.LLMs.Full (both default to true). |
|
| 135 | +func GenerateLLMsFiles(cfg *config.Config, posts []*content.Post, pages []*content.Page, outDir string) { |
|
| 136 | + if cfg.LLMs.EnabledOrDefault() { |
|
| 137 | + if err := writeFile(outDir+"/llms.txt", func(f *os.File) error { |
|
| 138 | +return RenderLLMsTxt(f, cfg, posts, pages) |
|
| 139 | + }); err != nil { |
|
| 140 | + log.Printf("Error writing llms.txt: %v", err) |
|
| 141 | +} |
|
| 142 | +} |
|
| 143 | + if cfg.LLMs.FullOrDefault() { |
|
| 144 | + if err := writeFile(outDir+"/llms-full.txt", func(f *os.File) error { |
|
| 145 | +return RenderLLMsFullTxt(f, cfg, posts) |
|
| 146 | + }); err != nil { |
|
| 147 | + log.Printf("Error writing llms-full.txt: %v", err) |
|
| 148 | +} |
|
| 149 | +} |
|
| 150 | +} |
|
| 151 | + | |
| 152 | +func writeFile(path string, render func(f *os.File) error) error { |
|
| 153 | +f, err := os.Create(path) |
|
| 154 | + if err != nil { |
|
| 155 | +return err |
|
| 156 | +} |
|
| 157 | +defer f.Close() |
|
| 158 | +return render(f) |
|
| 159 | +} |
| @@ -1,29 +1,34 @@ | ||
| 1 | 1 | package server |
| 2 | 2 | |
| 3 | 3 | import ( |
| 4 | 4 | "encoding/json" |
| 5 | 5 | "fmt" |
| 6 | 6 | "log" |
| 7 | 7 | "net/http" |
| 8 | +"os" |
|
| 9 | +"path" |
|
| 10 | +"path/filepath" |
|
| 8 | 11 | "strconv" |
| 9 | 12 | "strings" |
| 10 | 13 | |
| 11 | 14 | "github.com/ruedigerp/newblog/internal/config" |
| 12 | 15 | "github.com/ruedigerp/newblog/internal/content" |
| 16 | +"github.com/ruedigerp/newblog/internal/generator" |
|
| 13 | 17 | "github.com/ruedigerp/newblog/internal/templates" |
| 14 | 18 | ) |
| 15 | 19 | |
| 16 | 20 | func Start(cfg *config.Config, posts []*content.Post, pages []*content.Page) { |
| 17 | - if err := templates.Init(); err != nil { |
|
| 21 | + if err := templates.Init(cfg.ThemeDir()); err != nil { |
|
| 18 | 22 | log.Fatalf("Failed to init templates: %v", err) |
| 19 | 23 | } |
| 24 | + log.Printf("Using theme %q from %s", cfg.Theme, cfg.ThemeDir()) |
|
| 20 | 25 | |
| 21 | 26 | tagMap := content.CollectTags(posts) |
| 22 | 27 | catMap := content.CollectCategories(posts) |
| 23 | 28 | postMap := make(map[string]*content.Post) |
| 24 | 29 | postIndex := make(map[string]int) |
| 25 | 30 | for i, p := range posts { |
| 26 | 31 | postMap[p.Slug] = p |
| 27 | 32 | postIndex[p.Slug] = i |
| 28 | 33 | } |
| 29 | 34 | pageMap := make(map[string]*content.Page) |
| @@ -34,39 +39,64 @@ func Start(cfg *config.Config, posts []*content.Post, pages []*content.Page) { | ||
| 34 | 39 | site := templates.SiteData{ |
| 35 | 40 | Title: cfg.Title, |
| 36 | 41 | Description: cfg.Description, |
| 37 | 42 | Author: cfg.Author, |
| 38 | 43 | BaseURL: cfg.BaseURL, |
| 39 | 44 | Menu: cfg.Menu, |
| 40 | 45 | } |
| 41 | 46 | |
| 42 | 47 | mux := http.NewServeMux() |
| 43 | 48 | |
| 44 | -// Static files |
|
| 45 | - mux.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static")))) |
|
| 49 | +// Static files: the site's static/ wins, the theme's static/ is the fallback. |
|
| 50 | +// Mirrors the merge order used by the generator. |
|
| 51 | + mux.Handle("/static/", http.StripPrefix("/static/", |
|
| 52 | +staticHandler(cfg.StaticDir, cfg.ThemeStaticDir()))) |
|
| 46 | 53 | |
| 47 | 54 | // Images (served from static/images, so /images/... paths in posts work directly) |
| 48 | - mux.Handle("/images/", http.StripPrefix("/images/", http.FileServer(http.Dir("static/images")))) |
|
| 55 | + mux.Handle("/images/", http.StripPrefix("/images/", |
|
| 56 | +http.FileServer(http.Dir(filepath.Join(cfg.StaticDir, "images"))))) |
|
| 49 | 57 | |
| 50 | 58 | // RSS Feed |
| 51 | 59 | mux.HandleFunc("/index.xml", func(w http.ResponseWriter, r *http.Request) { |
| 52 | 60 | w.Header().Set("Content-Type", "application/rss+xml; charset=utf-8") |
| 53 | 61 | rssCount := 20 |
| 54 | 62 | if rssCount > len(posts) { |
| 55 | 63 | rssCount = len(posts) |
| 56 | 64 | } |
| 57 | 65 | if err := templates.RenderRSS(w, site, posts[:rssCount]); err != nil { |
| 58 | 66 | log.Printf("Error rendering RSS: %v", err) |
| 59 | 67 | http.Error(w, "Internal Server Error", 500) |
| 60 | 68 | } |
| 61 | 69 | }) |
| 62 | 70 | |
| 71 | +// llms.txt — concise index for LLMs (https://llmstxt.org/) |
|
| 72 | + if cfg.LLMs.EnabledOrDefault() { |
|
| 73 | + mux.HandleFunc("/llms.txt", func(w http.ResponseWriter, r *http.Request) { |
|
| 74 | + w.Header().Set("Content-Type", "text/markdown; charset=utf-8") |
|
| 75 | + if err := generator.RenderLLMsTxt(w, cfg, posts, pages); err != nil { |
|
| 76 | + log.Printf("Error rendering llms.txt: %v", err) |
|
| 77 | +http.Error(w, "Internal Server Error", 500) |
|
| 78 | +} |
|
| 79 | +}) |
|
| 80 | +} |
|
| 81 | + | |
| 82 | +// llms-full.txt — full markdown of every post |
|
| 83 | + if cfg.LLMs.FullOrDefault() { |
|
| 84 | + mux.HandleFunc("/llms-full.txt", func(w http.ResponseWriter, r *http.Request) { |
|
| 85 | + w.Header().Set("Content-Type", "text/markdown; charset=utf-8") |
|
| 86 | + if err := generator.RenderLLMsFullTxt(w, cfg, posts); err != nil { |
|
| 87 | + log.Printf("Error rendering llms-full.txt: %v", err) |
|
| 88 | +http.Error(w, "Internal Server Error", 500) |
|
| 89 | +} |
|
| 90 | +}) |
|
| 91 | +} |
|
| 92 | + | |
| 63 | 93 | // Search index |
| 64 | 94 | mux.HandleFunc("/search-index.json", func(w http.ResponseWriter, r *http.Request) { |
| 65 | 95 | w.Header().Set("Content-Type", "application/json; charset=utf-8") |
| 66 | 96 | |
| 67 | 97 | months := []string{ |
| 68 | 98 | "", "Januar", "Februar", "März", "April", "Mai", "Juni", |
| 69 | 99 | "Juli", "August", "September", "Oktober", "November", "Dezember", |
| 70 | 100 | } |
| 71 | 101 | |
| 72 | 102 | type searchEntry struct { |
| @@ -249,23 +279,58 @@ func Start(cfg *config.Config, posts []*content.Post, pages []*content.Page) { | ||
| 249 | 279 | mux.HandleFunc("/categories/", func(w http.ResponseWriter, r *http.Request) { |
| 250 | 280 | cat := strings.TrimPrefix(r.URL.Path, "/categories/") |
| 251 | 281 | cat = strings.TrimSuffix(cat, "/") |
| 252 | 282 | if cat == "" { |
| 253 | 283 | renderCategoriesIndex(w) |
| 254 | 284 | return |
| 255 | 285 | } |
| 256 | 286 | handleCategory(w, r, site, catMap) |
| 257 | 287 | }) |
| 258 | 288 | |
| 289 | +var handler http.Handler = mux |
|
| 290 | + if templates.DevMode() { |
|
| 291 | +// Templates are re-parsed per request; keep the browser from caching |
|
| 292 | +// the theme's CSS/JS so edits show up on reload. |
|
| 293 | +handler = noCache(mux) |
|
| 294 | + log.Printf("Dev mode: templates in %s are reloaded on every request", cfg.ThemeTemplatesDir()) |
|
| 295 | +} |
|
| 296 | + | |
| 259 | 297 | addr := fmt.Sprintf(":%d", cfg.Port) |
| 260 | 298 | log.Printf("Blog server starting on http://localhost%s", addr) |
| 261 | -log.Fatal(http.ListenAndServe(addr, mux)) |
|
| 299 | +log.Fatal(http.ListenAndServe(addr, handler)) |
|
| 300 | +} |
|
| 301 | + | |
| 302 | +// noCache disables browser caching — used in dev mode only. |
|
| 303 | +func noCache(next http.Handler) http.Handler { |
|
| 304 | + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
|
| 305 | + w.Header().Set("Cache-Control", "no-store, max-age=0") |
|
| 306 | +next.ServeHTTP(w, r) |
|
| 307 | +}) |
|
| 308 | +} |
|
| 309 | + | |
| 310 | +// staticHandler serves static assets from several directories: the first |
|
| 311 | +// directory that contains the requested file wins. |
|
| 312 | +func staticHandler(dirs ...string) http.Handler { |
|
| 313 | +servers := make([]http.Handler, len(dirs)) |
|
| 314 | + for i, d := range dirs { |
|
| 315 | +servers[i] = http.FileServer(http.Dir(d)) |
|
| 316 | +} |
|
| 317 | + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
|
| 318 | + rel := filepath.FromSlash(path.Clean("/" + r.URL.Path)) |
|
| 319 | + for i, d := range dirs { |
|
| 320 | + if info, err := os.Stat(filepath.Join(d, rel)); err == nil && !info.IsDir() { |
|
| 321 | +servers[i].ServeHTTP(w, r) |
|
| 322 | +return |
|
| 323 | +} |
|
| 324 | +} |
|
| 325 | +http.NotFound(w, r) |
|
| 326 | +}) |
|
| 262 | 327 | } |
| 263 | 328 | |
| 264 | 329 | func handleTag(w http.ResponseWriter, r *http.Request, site templates.SiteData, tagMap map[string][]*content.Post) { |
| 265 | 330 | tag := strings.TrimPrefix(r.URL.Path, "/tags/") |
| 266 | 331 | tag = strings.TrimSuffix(tag, "/") |
| 267 | 332 | if tag == "" { |
| 268 | 333 | http.Redirect(w, r, "/tags", http.StatusFound) |
| 269 | 334 | return |
| 270 | 335 | } |
| 271 | 336 | for t, tagPosts := range tagMap { |
| @@ -1,27 +1,26 @@ | ||
| 1 | 1 | package templates |
| 2 | 2 | |
| 3 | 3 | import ( |
| 4 | -"embed" |
|
| 4 | +"bytes" |
|
| 5 | 5 | "fmt" |
| 6 | 6 | "html/template" |
| 7 | 7 | "io" |
| 8 | +"os" |
|
| 9 | +"path/filepath" |
|
| 8 | 10 | "strings" |
| 9 | 11 | "time" |
| 10 | 12 | |
| 11 | 13 | "github.com/ruedigerp/newblog/internal/config" |
| 12 | 14 | "github.com/ruedigerp/newblog/internal/content" |
| 13 | 15 | ) |
| 14 | 16 | |
| 15 | -//go:embed *.html |
|
| 16 | -var templateFS embed.FS |
|
| 17 | - | |
| 18 | 17 | type SiteData struct { |
| 19 | 18 | Title string |
| 20 | 19 | Description string |
| 21 | 20 | Author string |
| 22 | 21 | BaseURL string |
| 23 | 22 | Menu []config.MenuItem |
| 24 | 23 | } |
| 25 | 24 | |
| 26 | 25 | type HomeData struct { |
| 27 | 26 | Site SiteData |
| @@ -135,83 +134,150 @@ var funcMap = template.FuncMap{ | ||
| 135 | 134 | } |
| 136 | 135 | } |
| 137 | 136 | return result |
| 138 | 137 | }, |
| 139 | 138 | "isEllipsis": func(n int) bool { |
| 140 | 139 | return n == -1 |
| 141 | 140 | }, |
| 142 | 141 | } |
| 143 | 142 | |
| 144 | 143 | var ( |
| 145 | -homeTmpl *template.Template |
|
| 146 | -postTmpl *template.Template |
|
| 147 | -tagsTmpl *template.Template |
|
| 148 | -tagTmpl *template.Template |
|
| 149 | -categoriesTmpl *template.Template |
|
| 150 | -categoryTmpl *template.Template |
|
| 151 | -pageTmpl *template.Template |
|
| 144 | +homeTmpl *view |
|
| 145 | +postTmpl *view |
|
| 146 | +tagsTmpl *view |
|
| 147 | +tagTmpl *view |
|
| 148 | +categoriesTmpl *view |
|
| 149 | +categoryTmpl *view |
|
| 150 | +pageTmpl *view |
|
| 152 | 151 | ) |
| 153 | 152 | |
| 153 | +// templateDir holds the directory the templates of the active theme were |
|
| 154 | +// loaded from (e.g. "themes/default/templates"). |
|
| 155 | +var templateDir string |
|
| 156 | + | |
| 157 | +// devMode re-parses templates on every render, so theme edits become visible |
|
| 158 | +// without restarting the server. |
|
| 159 | +var devMode bool |
|
| 160 | + | |
| 161 | +// SetDevMode enables or disables template live reload. Must be called before |
|
| 162 | +// serving requests. |
|
| 163 | +func SetDevMode(enabled bool) { |
|
| 164 | +devMode = enabled |
|
| 165 | +} |
|
| 166 | + | |
| 167 | +// DevMode reports whether template live reload is enabled. |
|
| 168 | +func DevMode() bool { |
|
| 169 | +return devMode |
|
| 170 | +} |
|
| 171 | + | |
| 172 | +// view is a page template together with the theme files it was built from, |
|
| 173 | +// so it can be re-parsed on demand in dev mode. |
|
| 174 | +type view struct { |
|
| 175 | +files []string |
|
| 176 | +tmpl *template.Template |
|
| 177 | +} |
|
| 178 | + | |
| 179 | +func newView(files ...string) (*view, error) { |
|
| 180 | +tmpl, err := parseTemplate(files...) |
|
| 181 | + if err != nil { |
|
| 182 | +return nil, err |
|
| 183 | +} |
|
| 184 | + return &view{files: files, tmpl: tmpl}, nil |
|
| 185 | +} |
|
| 186 | + | |
| 187 | +func (v *view) execute(w io.Writer, data any) error { |
|
| 188 | + if !devMode { |
|
| 189 | +return v.tmpl.ExecuteTemplate(w, "base", data) |
|
| 190 | +} |
|
| 191 | +// Live reload: parse the theme files again and render into a buffer first, |
|
| 192 | +// so a broken template does not emit half a page. |
|
| 193 | +tmpl, err := parseTemplate(v.files...) |
|
| 194 | + if err != nil { |
|
| 195 | +return err |
|
| 196 | +} |
|
| 197 | +var buf bytes.Buffer |
|
| 198 | + if err := tmpl.ExecuteTemplate(&buf, "base", data); err != nil { |
|
| 199 | +return err |
|
| 200 | +} |
|
| 201 | +_, err = w.Write(buf.Bytes()) |
|
| 202 | +return err |
|
| 203 | +} |
|
| 204 | + | |
| 154 | 205 | func parseTemplate(files ...string) (*template.Template, error) { |
| 155 | - return template.New("").Funcs(funcMap).ParseFS(templateFS, files...) |
|
| 206 | +paths := make([]string, 0, len(files)) |
|
| 207 | + for _, f := range files { |
|
| 208 | +path := filepath.Join(templateDir, f) |
|
| 209 | + if _, err := os.Stat(path); err != nil { |
|
| 210 | + return nil, fmt.Errorf("missing template %s in theme: %w", f, err) |
|
| 211 | +} |
|
| 212 | +paths = append(paths, path) |
|
| 213 | +} |
|
| 214 | + return template.New("").Funcs(funcMap).ParseFiles(paths...) |
|
| 156 | 215 | } |
| 157 | 216 | |
| 158 | -func Init() error { |
|
| 159 | -var err error |
|
| 160 | - homeTmpl, err = parseTemplate("base.html", "home.html") |
|
| 217 | +// Init loads all templates of the theme located in themeDir |
|
| 218 | +// (e.g. "themes/default"). The templates are expected in themeDir/templates. |
|
| 219 | +func Init(themeDir string) error { |
|
| 220 | +templateDir = filepath.Join(themeDir, "templates") |
|
| 221 | +info, err := os.Stat(templateDir) |
|
| 222 | + if err != nil || !info.IsDir() { |
|
| 223 | + return fmt.Errorf("theme templates not found in %s (check 'theme' and 'themesDir' in config.yaml)", templateDir) |
|
| 224 | +} |
|
| 225 | + | |
| 226 | + homeTmpl, err = newView("base.html", "home.html") |
|
| 161 | 227 | if err != nil { |
| 162 | 228 | return fmt.Errorf("home template: %w", err) |
| 163 | 229 | } |
| 164 | - postTmpl, err = parseTemplate("base.html", "post.html") |
|
| 230 | + postTmpl, err = newView("base.html", "post.html") |
|
| 165 | 231 | if err != nil { |
| 166 | 232 | return fmt.Errorf("post template: %w", err) |
| 167 | 233 | } |
| 168 | - tagsTmpl, err = parseTemplate("base.html", "tags.html") |
|
| 234 | + tagsTmpl, err = newView("base.html", "tags.html") |
|
| 169 | 235 | if err != nil { |
| 170 | 236 | return fmt.Errorf("tags template: %w", err) |
| 171 | 237 | } |
| 172 | - tagTmpl, err = parseTemplate("base.html", "tag.html") |
|
| 238 | + tagTmpl, err = newView("base.html", "tag.html") |
|
| 173 | 239 | if err != nil { |
| 174 | 240 | return fmt.Errorf("tag template: %w", err) |
| 175 | 241 | } |
| 176 | - categoriesTmpl, err = parseTemplate("base.html", "categories.html") |
|
| 242 | + categoriesTmpl, err = newView("base.html", "categories.html") |
|
| 177 | 243 | if err != nil { |
| 178 | 244 | return fmt.Errorf("categories template: %w", err) |
| 179 | 245 | } |
| 180 | - categoryTmpl, err = parseTemplate("base.html", "category.html") |
|
| 246 | + categoryTmpl, err = newView("base.html", "category.html") |
|
| 181 | 247 | if err != nil { |
| 182 | 248 | return fmt.Errorf("category template: %w", err) |
| 183 | 249 | } |
| 184 | - pageTmpl, err = parseTemplate("base.html", "page.html") |
|
| 250 | + pageTmpl, err = newView("base.html", "page.html") |
|
| 185 | 251 | if err != nil { |
| 186 | 252 | return fmt.Errorf("page template: %w", err) |
| 187 | 253 | } |
| 188 | 254 | return nil |
| 189 | 255 | } |
| 190 | 256 | |
| 191 | 257 | func RenderHome(w io.Writer, data HomeData) error { |
| 192 | -return homeTmpl.ExecuteTemplate(w, "base", data) |
|
| 258 | +return homeTmpl.execute(w, data) |
|
| 193 | 259 | } |
| 194 | 260 | |
| 195 | 261 | func RenderPost(w io.Writer, data PostData) error { |
| 196 | -return postTmpl.ExecuteTemplate(w, "base", data) |
|
| 262 | +return postTmpl.execute(w, data) |
|
| 197 | 263 | } |
| 198 | 264 | |
| 199 | 265 | func RenderTags(w io.Writer, data TagsData) error { |
| 200 | -return tagsTmpl.ExecuteTemplate(w, "base", data) |
|
| 266 | +return tagsTmpl.execute(w, data) |
|
| 201 | 267 | } |
| 202 | 268 | |
| 203 | 269 | func RenderTag(w io.Writer, data TagData) error { |
| 204 | -return tagTmpl.ExecuteTemplate(w, "base", data) |
|
| 270 | +return tagTmpl.execute(w, data) |
|
| 205 | 271 | } |
| 206 | 272 | |
| 207 | 273 | func RenderCategories(w io.Writer, data CategoriesData) error { |
| 208 | -return categoriesTmpl.ExecuteTemplate(w, "base", data) |
|
| 274 | +return categoriesTmpl.execute(w, data) |
|
| 209 | 275 | } |
| 210 | 276 | |
| 211 | 277 | func RenderCategory(w io.Writer, data CategoryData) error { |
| 212 | -return categoryTmpl.ExecuteTemplate(w, "base", data) |
|
| 278 | +return categoryTmpl.execute(w, data) |
|
| 213 | 279 | } |
| 214 | 280 | |
| 215 | 281 | func RenderPage(w io.Writer, data PageData) error { |
| 216 | -return pageTmpl.ExecuteTemplate(w, "base", data) |
|
| 282 | +return pageTmpl.execute(w, data) |
|
| 217 | 283 | } |
| @@ -1,51 +1,117 @@ | ||
| 1 | 1 | package main |
| 2 | 2 | |
| 3 | 3 | import ( |
| 4 | +"flag" |
|
| 4 | 5 | "fmt" |
| 5 | 6 | "log" |
| 6 | 7 | "os" |
| 8 | +"path/filepath" |
|
| 9 | +"sort" |
|
| 10 | +"strings" |
|
| 7 | 11 | |
| 8 | 12 | "github.com/ruedigerp/newblog/internal/config" |
| 9 | 13 | "github.com/ruedigerp/newblog/internal/content" |
| 10 | 14 | "github.com/ruedigerp/newblog/internal/generator" |
| 11 | 15 | "github.com/ruedigerp/newblog/internal/server" |
| 16 | +"github.com/ruedigerp/newblog/internal/templates" |
|
| 12 | 17 | ) |
| 13 | 18 | |
| 19 | +func usage() { |
|
| 20 | + fmt.Println("Usage: quilldrop <serve|generate> [flags]") |
|
| 21 | +fmt.Println() |
|
| 22 | + fmt.Println("Commands:") |
|
| 23 | + fmt.Println(" serve Start the dynamic HTTP server") |
|
| 24 | + fmt.Println(" generate Generate static HTML files") |
|
| 25 | +fmt.Println() |
|
| 26 | + fmt.Println("Flags:") |
|
| 27 | + fmt.Println(" -config <path> Config file (default: config.yaml)") |
|
| 28 | + fmt.Println(" -theme <name> Theme to use, overrides 'theme' from the config") |
|
| 29 | + fmt.Println(" -dev serve: reload templates on every request (live reload)") |
|
| 30 | +} |
|
| 31 | + | |
| 14 | 32 | func main() { |
| 15 | 33 | if len(os.Args) < 2 { |
| 16 | - fmt.Println("Usage: newblog <serve|generate>") |
|
| 17 | -fmt.Println() |
|
| 18 | - fmt.Println("Commands:") |
|
| 19 | - fmt.Println(" serve Start the dynamic HTTP server") |
|
| 20 | - fmt.Println(" generate Generate static HTML files") |
|
| 34 | +usage() |
|
| 35 | +os.Exit(1) |
|
| 36 | +} |
|
| 37 | + | |
| 38 | +cmd := os.Args[1] |
|
| 39 | + if cmd != "serve" && cmd != "generate" { |
|
| 40 | + fmt.Printf("Unknown command: %s\n", cmd) |
|
| 41 | +usage() |
|
| 21 | 42 | os.Exit(1) |
| 22 | 43 | } |
| 23 | 44 | |
| 24 | - cfg, err := config.Load("config.yaml") |
|
| 45 | +fs := flag.NewFlagSet(cmd, flag.ExitOnError) |
|
| 46 | + configPath := fs.String("config", "config.yaml", "path to the config file") |
|
| 47 | + theme := fs.String("theme", "", "theme to use, overrides 'theme' from the config") |
|
| 48 | + dev := fs.Bool("dev", false, "serve: reload templates on every request") |
|
| 49 | + if err := fs.Parse(os.Args[2:]); err != nil { |
|
| 50 | +os.Exit(1) |
|
| 51 | +} |
|
| 52 | + if *dev && cmd != "serve" { |
|
| 53 | + log.Fatalf("-dev is only supported for 'serve'") |
|
| 54 | +} |
|
| 55 | +templates.SetDevMode(*dev) |
|
| 56 | + | |
| 57 | +cfg, err := config.Load(*configPath) |
|
| 25 | 58 | if err != nil { |
| 26 | 59 | log.Fatalf("Failed to load config: %v", err) |
| 27 | 60 | } |
| 61 | + if *theme != "" { |
|
| 62 | +cfg.Theme = *theme |
|
| 63 | +} |
|
| 64 | + if err := checkTheme(cfg); err != nil { |
|
| 65 | + log.Fatalf("%v", err) |
|
| 66 | +} |
|
| 28 | 67 | |
| 29 | 68 | posts, err := content.LoadAll(cfg.ContentDir) |
| 30 | 69 | if err != nil { |
| 31 | 70 | log.Fatalf("Failed to load posts: %v", err) |
| 32 | 71 | } |
| 33 | 72 | log.Printf("Loaded %d posts", len(posts)) |
| 34 | 73 | |
| 35 | 74 | pages, err := content.LoadAllPages(cfg.SitesDir) |
| 36 | 75 | if err != nil { |
| 37 | 76 | log.Fatalf("Failed to load pages: %v", err) |
| 38 | 77 | } |
| 39 | 78 | log.Printf("Loaded %d pages", len(pages)) |
| 40 | 79 | |
| 41 | - switch os.Args[1] { |
|
| 80 | + switch cmd { |
|
| 42 | 81 | case "serve": |
| 43 | 82 | server.Start(cfg, posts, pages) |
| 44 | 83 | case "generate": |
| 45 | 84 | generator.Generate(cfg, posts, pages) |
| 46 | -default: |
|
| 47 | - fmt.Printf("Unknown command: %s\n", os.Args[1]) |
|
| 48 | - fmt.Println("Usage: newblog <serve|generate>") |
|
| 49 | -os.Exit(1) |
|
| 50 | 85 | } |
| 51 | 86 | } |
| 87 | + | |
| 88 | +// checkTheme verifies the configured theme exists and reports the available |
|
| 89 | +// themes otherwise. |
|
| 90 | +func checkTheme(cfg *config.Config) error { |
|
| 91 | + if info, err := os.Stat(cfg.ThemeTemplatesDir()); err == nil && info.IsDir() { |
|
| 92 | +return nil |
|
| 93 | +} |
|
| 94 | + msg := fmt.Sprintf("Theme %q not found: %s is missing", cfg.Theme, cfg.ThemeTemplatesDir()) |
|
| 95 | + if available := availableThemes(cfg.ThemesDir); len(available) > 0 { |
|
| 96 | + msg += fmt.Sprintf(" (available themes: %s)", strings.Join(available, ", ")) |
|
| 97 | +} |
|
| 98 | + return fmt.Errorf("%s", msg) |
|
| 99 | +} |
|
| 100 | + | |
| 101 | +func availableThemes(themesDir string) []string { |
|
| 102 | +entries, err := os.ReadDir(themesDir) |
|
| 103 | + if err != nil { |
|
| 104 | +return nil |
|
| 105 | +} |
|
| 106 | +var themes []string |
|
| 107 | + for _, e := range entries { |
|
| 108 | + if !e.IsDir() { |
|
| 109 | +continue |
|
| 110 | +} |
|
| 111 | + if info, err := os.Stat(filepath.Join(themesDir, e.Name(), "templates")); err == nil && info.IsDir() { |
|
| 112 | +themes = append(themes, e.Name()) |
|
| 113 | +} |
|
| 114 | +} |
|
| 115 | +sort.Strings(themes) |
|
| 116 | +return themes |
|
| 117 | +} |
Binärdatei – kein Textvergleich möglich.
| @@ -0,0 +1,24 @@ | ||
| 1 | +[ |
|
| 2 | + { "src": "/images/partner/Kolling.webp", "name": "Kolling", "url": "https://www.kfz-kolling.de" }, |
|
| 3 | + { "src": "/images/partner/Marcus-Vandamme.webp", "name": "Marcus Vandamme", "url": "https://www.dvag.de/marcus.vandamme/ueber-uns.html" }, |
|
| 4 | + { "src": "/images/partner/albo-tec.png.avif", "name": "Albo-Tec", "url": "https://www.umweltanalytik-bodenmechanik.de" }, |
|
| 5 | + { "src": "/images/partner/alte-waschfabrik.webp", "name": "Alte Waschfabrik", "url": "https://altewaschfabrik.de" }, |
|
| 6 | + { "src": "/images/partner/arbeitsschutzmanagement-rohde.webp", "name": "Arbeitsschutzmanagement Rohde", "url": "https://agz-sbh.de/" }, |
|
| 7 | + { "src": "/images/partner/grizzly-bee-honig.webp", "name": "Grizzly Bee Honig", "url": "https://grizzlybee-honig.de" }, |
|
| 8 | + { "src": "/images/partner/hansa-fliesen-depot.webp", "name": "Hansa Fliesen Depot", "url": "https://hansa-fliesen-depot.de/" }, |
|
| 9 | + { "src": "/images/partner/harmuth.webp", "name": "Harmuth", "url": "https://www.harmuth-entsorgung.de" }, |
|
| 10 | + { "src": "/images/partner/muenstermann.webp", "name": "Münstermann", "url": "https://fenstertechnik-muenstermann.de/" }, |
|
| 11 | + { "src": "/images/partner/schlenkhoff.webp", "name": "Schlenkhoff", "url": "https://www.schlenkhoff.de" }, |
|
| 12 | + { "src": "/images/partner/tankstelle-peters.webp", "name": "Tankstelle Peters", "url": "https://tankstelle-peters.de/" }, |
|
| 13 | + { "src": "/images/partner/utz.webp", "name": "Utz", "url": "https://www.bauunternehmen-utz.de" }, |
|
| 14 | + { "src": "/images/partner/vepa-baumbach.webp", "name": "Vepa Baumbach", "url": "https://vepa-baumbach.de" }, |
|
| 15 | + { "src": "/images/partner/dsl-schweisstechnik.webp", "name": "DSL Schweisstechnik GmbH", "url": "https://www.dsl-schweisstechnik.de" }, |
|
| 16 | + { "src": "/images/partner/amecko-gmbh.webp", "name": "AMECKO GmbH", "url": "https://www.amecko.com/de" }, |
|
| 17 | + { "src": "/images/partner/trautmann-gmbh.webp", "name": "Trautmann Garten- & Landschaftsbeu GmbH", "url": "https://www.trautmann-essen.de" }, |
|
| 18 | + { "src": "/images/partner/joerg-tinnefeld.webp", "name": "Jörg Tinnefeld Außen- und Innenbegrünung", "url": "https://tinnefeld-gruen.de" }, |
|
| 19 | + { "src": "/images/partner/reise-genie.webp", "name": "Reisegenie.de Thorsten Haske", "url": "https://reisegenie.de" }, |
|
| 20 | + { "src": "/images/partner/phillip-doermann-physio.webp", "name": "Phillip Dörmann Physiotherapie", "url": "https://www.physiotherapie-doermann.de" }, |
|
| 21 | + { "src": "/images/partner/LogoCarlundCarla.gif", "name": "CarlundCarla.de Transportervermietung", "url": "https://carlundcarla.de/transporter-mieten-essen" }, |
|
| 22 | + { "src": "/images/partner/solar-richter.webp", "name": "Solar Richter", "url": "https://www.solar-richter.com" }, |
|
| 23 | + { "src": "/images/partner/wohnbau-eg.webp", "name": "Wohnbau eG", "url": "https://www.wohnbau-eg.de" } |
|
| 24 | +] |
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
| @@ -0,0 +1,241 @@ | ||
| 1 | +#!/bin/bash |
|
| 2 | + | |
| 3 | +# Option 1: PNG zu JPEG konvertieren (meist dramatische Größenreduktion) |
|
| 4 | +for i in `find posts -type f ! -name "thumb-*.png" -name "*.png" | grep -v thumbs`; |
|
| 5 | +do |
|
| 6 | + filefull="${i##*/}" |
|
| 7 | + file="${filefull%.[^.]*}" |
|
| 8 | + ext="${filefull:${#file} + 1}" |
|
| 9 | + dir=$(echo ${i} | sed -e "s/${file}\.${ext}//") |
|
| 10 | + source="${dir}${file}.${ext}" |
|
| 11 | + |
|
| 12 | + if [ ! -d ${dir}thumbs/ ]; |
|
| 13 | +then |
|
| 14 | + mkdir ${dir}thumbs/ |
|
| 15 | +fi |
|
| 16 | + |
|
| 17 | +# Als JPEG speichern für dramatische Größenreduktion |
|
| 18 | + dest="${dir}thumbs/${file}.jpg" |
|
| 19 | + |
|
| 20 | + if [ -f ${dest} ]; |
|
| 21 | +then |
|
| 22 | +continue; |
|
| 23 | +fi; |
|
| 24 | + |
|
| 25 | +# PNG zu JPEG mit weißem Hintergrund (für Transparenz) |
|
| 26 | + convert ${source} -background white -flatten -quality 85 -strip ${dest}; |
|
| 27 | + echo "convert ${source} -background white -flatten -quality 85 -strip ${dest};" |
|
| 28 | +done |
|
| 29 | + | |
| 30 | +echo -e "\n=== webp Konvertierung ===" |
|
| 31 | +# for i in posts/**/*.{jpg,jpeg,png,JPG,JPEG,PNG}; do |
|
| 32 | +for i in `find posts -type f ! -name "*.svg" ! -name "*.webp" ! -name "*.gif" | grep -v thumbs`; do |
|
| 33 | +# echo "i: $i" |
|
| 34 | +[ ! -f "$i" ] && continue |
|
| 35 | + |
|
| 36 | +filename=$(basename "$i") |
|
| 37 | + name="${filename%.*}" |
|
| 38 | +dir=$(dirname "$i") |
|
| 39 | + output="${dir}/${name}.webp" |
|
| 40 | + |
|
| 41 | +[ -f "$output" ] && continue |
|
| 42 | + |
|
| 43 | +# Dateigröße prüfen |
|
| 44 | +size=$(stat -f%z "$i" 2>/dev/null || stat -c%s "$i" 2>/dev/null) |
|
| 45 | + |
|
| 46 | +# Qualität basierend auf Dateigröße anpassen |
|
| 47 | +if [ "$size" -gt 1000000 ]; then # > 1MB |
|
| 48 | +quality=75 |
|
| 49 | +elif [ "$size" -gt 500000 ]; then # > 500KB |
|
| 50 | +quality=80 |
|
| 51 | +else |
|
| 52 | +quality=85 |
|
| 53 | +fi |
|
| 54 | + |
|
| 55 | + echo "Konvertiere: $i (${size} bytes) -> $output (quality: $quality)" |
|
| 56 | +cwebp -q $quality "$i" -o "$output" |
|
| 57 | +done |
|
| 58 | + | |
| 59 | +# echo "Generate Thumbnails" |
|
| 60 | +# for i in `find posts -type f ! -name "*.svg" ! -name "*.webp" | grep -v thumbs`; |
|
| 61 | +# do |
|
| 62 | +# # echo $i; |
|
| 63 | +# filefull="${i##*/}" |
|
| 64 | +# file="${filefull%.[^.]*}" |
|
| 65 | +# ext="${filefull:${#file} + 1}" |
|
| 66 | +# dir=$(echo ${i} | sed -e "s/${file}\.${ext}//") |
|
| 67 | +# source="${dir}${file}.${ext}" |
|
| 68 | +# if [ ! -d ${dir}thumbs/ ]; |
|
| 69 | +# then |
|
| 70 | +# mkdir ${dir}thumbs/ |
|
| 71 | +# fi |
|
| 72 | +# dest="${dir}thumbs/${file}-600x600.${ext}" |
|
| 73 | +# if [ -f ${dest} ]; |
|
| 74 | +# then |
|
| 75 | +# continue; |
|
| 76 | +# fi; |
|
| 77 | +# convert ${source} -thumbnail 600x600 ${dest} |
|
| 78 | +# echo "convert ${source} -thumbnail 600x600 ${dest}"; |
|
| 79 | +# done |
|
| 80 | + | |
| 81 | + | |
| 82 | +# Option 2: Wenn Sie PNG behalten möchten - mit pngquant (installieren mit: sudo apt install pngquant) |
|
| 83 | +# for i in `find posts -type f ! -name "thumb-*.png" -name "*.png" | grep -v thumbs`; |
|
| 84 | +# do |
|
| 85 | +# filefull="${i##*/}" |
|
| 86 | +# file="${filefull%.[^.]*}" |
|
| 87 | +# ext="${filefull:${#file} + 1}" |
|
| 88 | +# dir=$(echo ${i} | sed -e "s/${file}\.${ext}//") |
|
| 89 | +# source="${dir}${file}.${ext}" |
|
| 90 | +# |
|
| 91 | +# if [ ! -d ${dir}thumbs/ ]; |
|
| 92 | +# then |
|
| 93 | +# mkdir ${dir}thumbs/ |
|
| 94 | +# fi |
|
| 95 | +# dest="${dir}thumbs/${file}.${ext}" |
|
| 96 | +# |
|
| 97 | +# if [ -f ${dest} ]; |
|
| 98 | +# then |
|
| 99 | +# continue; |
|
| 100 | +# fi; |
|
| 101 | +# |
|
| 102 | +# # PNG verlustbehaftet komprimieren (kann 50-80% Größenreduktion bringen) |
|
| 103 | +# pngquant --quality=65-80 --output ${dest} ${source}; |
|
| 104 | +# done |
|
| 105 | + | |
| 106 | +# Option 3: Moderne WebP Format (beste Komprimierung) |
|
| 107 | +# for i in `find posts -type f ! -name "thumb-*.png" -name "*.png" | grep -v thumbs`; |
|
| 108 | +# do |
|
| 109 | +# filefull="${i##*/}" |
|
| 110 | +# file="${filefull%.[^.]*}" |
|
| 111 | +# ext="${filefull:${#file} + 1}" |
|
| 112 | +# dir=$(echo ${i} | sed -e "s/${file}\.${ext}//") |
|
| 113 | +# source="${dir}${file}.${ext}" |
|
| 114 | +# |
|
| 115 | +# if [ ! -d ${dir}thumbs/ ]; |
|
| 116 | +# then |
|
| 117 | +# mkdir ${dir}thumbs/ |
|
| 118 | +# fi |
|
| 119 | +# dest="${dir}thumbs/${file}.webp" |
|
| 120 | +# |
|
| 121 | +# if [ -f ${dest} ]; |
|
| 122 | +# then |
|
| 123 | +# continue; |
|
| 124 | +# fi; |
|
| 125 | +# |
|
| 126 | +# # Als WebP mit hoher Komprimierung |
|
| 127 | +# convert ${source} -quality 80 -define webp:lossless=false ${dest}; |
|
| 128 | +# done |
|
| 129 | + | |
| 130 | +# # Option 1: Einfache Qualitätsreduzierung (empfohlen für die meisten Fälle) |
|
| 131 | +# for i in `find posts -type f ! -name "thumb-*.png" -name "*.png" | grep -v thumbs`; |
|
| 132 | +# do |
|
| 133 | +# filefull="${i##*/}" |
|
| 134 | +# file="${filefull%.[^.]*}" |
|
| 135 | +# ext="${filefull:${#file} + 1}" |
|
| 136 | +# dir=$(echo ${i} | sed -e "s/${file}\.${ext}//") |
|
| 137 | +# source="${dir}${file}.${ext}" |
|
| 138 | + |
|
| 139 | +# if [ ! -d ${dir}thumbs/ ]; |
|
| 140 | +# then |
|
| 141 | +# mkdir ${dir}thumbs/ |
|
| 142 | +# fi |
|
| 143 | + |
|
| 144 | +# dest="${dir}thumbs/${file}.${ext}" |
|
| 145 | + |
|
| 146 | +# # if [ -f ${dest} ]; |
|
| 147 | +# # then |
|
| 148 | +# # continue; |
|
| 149 | +# # fi; |
|
| 150 | + |
|
| 151 | +# # Komprimierung mit reduzierter Qualität (80% ist ein guter Startwert) |
|
| 152 | +# echo "convert ${source} -quality 80 -strip ${dest};" |
|
| 153 | +# # convert ${source} -quality 60 -strip ${dest}; |
|
| 154 | +# convert ${source} -quality 30 -strip -interlace Plane -resize '1000x1000>' ${dest}; |
|
| 155 | +# # convert ${source} -strip -define png:compression-level=9 ${dest}; |
|
| 156 | +# done |
|
| 157 | + | |
| 158 | +# Option 2: Aggressivere Komprimierung |
|
| 159 | +# convert ${source} -quality 60 -strip -interlace Plane ${dest}; |
|
| 160 | + | |
| 161 | +# Option 3: Für PNG spezifisch optimiert |
|
| 162 | +# convert ${source} -strip -define png:compression-level=9 ${dest}; |
|
| 163 | + | |
| 164 | +# Option 4: Automatische Optimierung basierend auf Dateigröße |
|
| 165 | +# convert ${source} -quality 85 -strip -resize '2000x2000>' ${dest}; |
|
| 166 | + | |
| 167 | +#################################################################################################### |
|
| 168 | + | |
| 169 | +# for i in `find posts -type f ! -name "thumb-*.png" -name "*.png" | grep -v thumbs`; |
|
| 170 | +# do |
|
| 171 | +# filefull="${i##*/}" |
|
| 172 | +# file="${filefull%.[^.]*}" |
|
| 173 | +# ext="${filefull:${#file} + 1}" |
|
| 174 | +# dir=$(echo ${i} | sed -e "s/${file}\.${ext}//") |
|
| 175 | +# source="${dir}${file}.${ext}" |
|
| 176 | +# if [ ! -d ${dir}thumbs/ ]; |
|
| 177 | +# then |
|
| 178 | +# mkdir ${dir}thumbs/ |
|
| 179 | +# fi |
|
| 180 | +# dest="${dir}thumbs/${file}.${ext}" |
|
| 181 | +# if [ -f ${dest} ]; |
|
| 182 | +# then |
|
| 183 | +# continue; |
|
| 184 | +# fi; |
|
| 185 | +# convert ${source} -thumbnail 200x200 ${dest}; |
|
| 186 | +# done |
|
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | +################# |
|
| 191 | + | |
| 192 | + | |
| 193 | +#for i in `find static/images/galleries -type f ! -name "*-thumb.jpg" -name "*.jpg"`; |
|
| 194 | +#do |
|
| 195 | +# echo $i; |
|
| 196 | +# if [ -f ${i%.*}-thumb.jpg ]; |
|
| 197 | +# then |
|
| 198 | +# continue; |
|
| 199 | +# fi; |
|
| 200 | +# convert $i -thumbnail 300x300 ${i%.*}-thumb.jpg; |
|
| 201 | +#done |
|
| 202 | + | |
| 203 | +# for i in `find static/images/galleries -type f ! -name "thumb-*.jpg" -name "*.jpg" | grep -v thumbs`; |
|
| 204 | +# do |
|
| 205 | +# filefull="${i##*/}" |
|
| 206 | +# file="${filefull%.[^.]*}" |
|
| 207 | +# ext="${filefull:${#file} + 1}" |
|
| 208 | +# dir=$(echo ${i} | sed -e "s/${file}\.${ext}//") |
|
| 209 | +# source="${dir}${file}.${ext}" |
|
| 210 | +# if [ ! -d ${dir}thumbs/ ]; |
|
| 211 | +# then |
|
| 212 | +# mkdir ${dir}thumbs/ |
|
| 213 | +# fi |
|
| 214 | +# dest="${dir}thumbs/${file}.${ext}" |
|
| 215 | +# if [ -f ${dest} ]; |
|
| 216 | +# then |
|
| 217 | +# continue; |
|
| 218 | +# fi; |
|
| 219 | +# convert ${source} -thumbnail 300x300 ${dest}; |
|
| 220 | +# done |
|
| 221 | + | |
| 222 | +# for i in `find static/img/posts -type f ! -name "*.svg" | grep -v thumbs`; |
|
| 223 | +# do |
|
| 224 | +# # echo $i; |
|
| 225 | +# filefull="${i##*/}" |
|
| 226 | +# file="${filefull%.[^.]*}" |
|
| 227 | +# ext="${filefull:${#file} + 1}" |
|
| 228 | +# dir=$(echo ${i} | sed -e "s/${file}\.${ext}//") |
|
| 229 | +# source="${dir}${file}.${ext}" |
|
| 230 | +# if [ ! -d ${dir}thumbs/ ]; |
|
| 231 | +# then |
|
| 232 | +# mkdir ${dir}thumbs/ |
|
| 233 | +# fi |
|
| 234 | +# dest="${dir}thumbs/${file}.${ext}" |
|
| 235 | +# if [ -f ${dest} ]; |
|
| 236 | +# then |
|
| 237 | +# continue; |
|
| 238 | +# fi; |
|
| 239 | +# convert ${source} -thumbnail 600x600 ${dest} |
|
| 240 | +# echo "convert ${source} -thumbnail 300x300 ${dest}"; |
|
| 241 | +# done |
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
| @@ -1 +0,0 @@ | ||
| 1 | -<?xml version="1.0" encoding="UTF-8"?> <svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" id="chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a" class="pygal-chart" viewBox="0 0 800 600"> <!--Generated with pygal 2.4.0 (lxml) ©Kozea 2012-2016 on 2018-01-02--> <!--http://pygal.org--> <!--http://github.com/Kozea/pygal--> <defs> <style type="text/css">#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a{-webkit-user-select:none;-webkit-font-smoothing:antialiased;font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .title{font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:16px}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .legends .legend text{font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:14px}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .axis text{font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:10px}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .axis text.major{font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:10px}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .text-overlay text.value{font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:16px}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .text-overlay text.label{font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:10px}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .tooltip{font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:14px}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a text.no_data{font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:64px} #chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a{background-color:rgba(249,249,249,1)}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a path,#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a line,#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a rect,#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a circle{-webkit-transition:150ms;-moz-transition:150ms;transition:150ms}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .graph > .background{fill:rgba(249,249,249,1)}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .plot > .background{fill:rgba(255,255,255,1)}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .graph{fill:rgba(0,0,0,.87)}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a text.no_data{fill:rgba(0,0,0,1)}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .title{fill:rgba(0,0,0,1)}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .legends .legend text{fill:rgba(0,0,0,.87)}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .legends .legend:hover text{fill:rgba(0,0,0,1)}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .axis .line{stroke:rgba(0,0,0,1)}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .axis .guide.line{stroke:rgba(0,0,0,.54)}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .axis .major.line{stroke:rgba(0,0,0,.87)}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .axis text.major{fill:rgba(0,0,0,1)}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .axis.y .guides:hover .guide.line,#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .line-graph .axis.x .guides:hover .guide.line,#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .stackedline-graph .axis.x .guides:hover .guide.line,#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .xy-graph .axis.x .guides:hover .guide.line{stroke:rgba(0,0,0,1)}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .axis .guides:hover text{fill:rgba(0,0,0,1)}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .reactive{fill-opacity:.7;stroke-opacity:.8}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .ci{stroke:rgba(0,0,0,.87)}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .reactive.active,#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .active .reactive{fill-opacity:.8;stroke-opacity:.9;stroke-width:4}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .ci .reactive.active{stroke-width:1.5}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .series text{fill:rgba(0,0,0,1)}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .tooltip rect{fill:rgba(255,255,255,1);stroke:rgba(0,0,0,1);-webkit-transition:opacity 150ms;-moz-transition:opacity 150ms;transition:opacity 150ms}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .tooltip .label{fill:rgba(0,0,0,.87)}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .tooltip .label{fill:rgba(0,0,0,.87)}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .tooltip .legend{font-size:.8em;fill:rgba(0,0,0,.54)}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .tooltip .x_label{font-size:.6em;fill:rgba(0,0,0,1)}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .tooltip .xlink{font-size:.5em;text-decoration:underline}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .tooltip .value{font-size:1.5em}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .bound{font-size:.5em}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .max-value{font-size:.75em;fill:rgba(0,0,0,.54)}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .map-element{fill:rgba(255,255,255,1);stroke:rgba(0,0,0,.54) !important}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .map-element .reactive{fill-opacity:inherit;stroke-opacity:inherit}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .color-0,#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .color-0 a:visited{stroke:#F44336;fill:#F44336}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .text-overlay .color-0 text{fill:black} #chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a text.no_data{text-anchor:middle}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .guide.line{fill:none}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .centered{text-anchor:middle}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .title{text-anchor:middle}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .legends .legend text{fill-opacity:1}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .axis.x text{text-anchor:middle}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .axis.x:not(.web) text[transform]{text-anchor:start}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .axis.x:not(.web) text[transform].backwards{text-anchor:end}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .axis.y text{text-anchor:end}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .axis.y text[transform].backwards{text-anchor:start}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .axis.y2 text{text-anchor:start}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .axis.y2 text[transform].backwards{text-anchor:end}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .axis .guide.line{stroke-dasharray:4,4}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .axis .major.guide.line{stroke-dasharray:6,6}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .horizontal .axis.y .guide.line,#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .horizontal .axis.y2 .guide.line,#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .vertical .axis.x .guide.line{opacity:0}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .horizontal .axis.always_show .guide.line,#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .vertical .axis.always_show .guide.line{opacity:1 !important}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .axis.y .guides:hover .guide.line,#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .axis.y2 .guides:hover .guide.line,#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .axis.x .guides:hover .guide.line{opacity:1}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .axis .guides:hover text{opacity:1}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .nofill{fill:none}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .subtle-fill{fill-opacity:.2}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .dot{stroke-width:1px;fill-opacity:1}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .dot.active{stroke-width:5px}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .dot.negative{fill:transparent}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a text,#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a tspan{stroke:none !important}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .series text.active{opacity:1}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .tooltip rect{fill-opacity:.95;stroke-width:.5}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .tooltip text{fill-opacity:1}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .showable{visibility:hidden}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .showable.shown{visibility:visible}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .gauge-background{fill:rgba(229,229,229,1);stroke:none}#chart-5e7b250e-3170-4c20-bc5f-c832d2d5b55a .bg-lines{stroke:rgba(249,249,249,1);stroke-width:2px}</style> </defs> <title>Pygal</title> <g class="graph bar-graph vertical"> <rect class="background" height="600" width="800" x="0" y="0"></rect> <g class="plot" transform="translate(169, 20)"> <rect class="background" height="540" width="610.4" x="0" y="0"></rect> <g class="axis y always_show"> <g class="guides"> <path class="axis major line" d="M0.000000 529.615385 h610.400000"></path> <text class="major" x="-5" y="533.115384615">0</text> <title>0</title> </g> <g class="guides"> <path class="guide line" d="M0.000000 484.136605 h610.400000"></path> <text class="" x="-5" y="487.63660525">100000</text> <title>100000</title> </g> <g class="guides"> <path class="guide line" d="M0.000000 438.657826 h610.400000"></path> <text class="" x="-5" y="442.157825884">200000</text> <title>200000</title> </g> <g class="guides"> <path class="guide line" d="M0.000000 393.179047 h610.400000"></path> <text class="" x="-5" y="396.679046518">300000</text> <title>300000</title> </g> <g class="guides"> <path class="guide line" d="M0.000000 347.700267 h610.400000"></path> <text class="" x="-5" y="351.200267152">400000</text> <title>400000</title> </g> <g class="guides"> <path class="major guide line" d="M0.000000 302.221488 h610.400000"></path> <text class="major" x="-5" y="305.721487787">500000</text> <title>500000</title> </g> <g class="guides"> <path class="guide line" d="M0.000000 256.742708 h610.400000"></path> <text class="" x="-5" y="260.242708421">600000</text> <title>600000</title> </g> <g class="guides"> <path class="guide line" d="M0.000000 211.263929 h610.400000"></path> <text class="" x="-5" y="214.763929055">700000</text> <title>700000</title> </g> <g class="guides"> <path class="guide line" d="M0.000000 165.785150 h610.400000"></path> <text class="" x="-5" y="169.28514969">800000</text> <title>800000</title> </g> <g class="guides"> <path class="guide line" d="M0.000000 120.306370 h610.400000"></path> <text class="" x="-5" y="123.806370324">900000</text> <title>900000</title> </g> <g class="guides"> <path class="major guide line" d="M0.000000 74.827591 h610.400000"></path> <text class="major" x="-5" y="78.3275909581">1000000</text> <title>1000000</title> </g> <g class="guides"> <path class="guide line" d="M0.000000 29.348812 h610.400000"></path> <text class="" x="-5" y="32.8488115923">1100000</text> <title>1100000</title> </g> </g> <g class="axis x"> <path class="line" d="M0.000000 0.000000 v540.000000"></path> <g class="guides"> <path class="guide line" d="M36.193590 0.000000 v540.000000"></path> <text class="" x="36.1935897436" y="555.0">Jan</text> </g> <g class="guides"> <path class="guide line" d="M85.103846 0.000000 v540.000000"></path> <text class="" x="85.1038461538" y="555.0">Feb</text> </g> <g class="guides"> <path class="guide line" d="M134.014103 0.000000 v540.000000"></path> <text class="" x="134.014102564" y="555.0">Mar</text> </g> <g class="guides"> <path class="guide line" d="M182.924359 0.000000 v540.000000"></path> <text class="" x="182.924358974" y="555.0">Apr</text> </g> <g class="guides"> <path class="guide line" d="M231.834615 0.000000 v540.000000"></path> <text class="" x="231.834615385" y="555.0">Mai</text> </g> <g class="guides"> <path class="guide line" d="M280.744872 0.000000 v540.000000"></path> <text class="" x="280.744871795" y="555.0">Jun</text> </g> <g class="guides"> <path class="guide line" d="M329.655128 0.000000 v540.000000"></path> <text class="" x="329.655128205" y="555.0">Jul</text> </g> <g class="guides"> <path class="guide line" d="M378.565385 0.000000 v540.000000"></path> <text class="" x="378.565384615" y="555.0">Aug</text> </g> <g class="guides"> <path class="guide line" d="M427.475641 0.000000 v540.000000"></path> <text class="" x="427.475641026" y="555.0">Sep</text> </g> <g class="guides"> <path class="guide line" d="M476.385897 0.000000 v540.000000"></path> <text class="" x="476.385897436" y="555.0">Okt</text> </g> <g class="guides"> <path class="guide line" d="M525.296154 0.000000 v540.000000"></path> <text class="" x="525.296153846" y="555.0">Nov</text> </g> <g class="guides"> <path class="guide line" d="M574.206410 0.000000 v540.000000"></path> <text class="" x="574.206410256" y="555.0">Dez</text> </g> </g> <g class="series serie-0 color-0"> <g class="bars"> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="7.64725675035" rx="0" ry="0" width="37.8761025641" x="17.2555384615" y="521.968127865"></rect> <desc class="value">16815</desc> <desc class="x centered">36.1935897436</desc> <desc class="y centered">525.79175624</desc> <desc class="x_label">Jan</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="0.183279480844" rx="0" ry="0" width="37.8761025641" x="66.1657948718" y="529.432105135"></rect> <desc class="value">403</desc> <desc class="x centered">85.1038461538</desc> <desc class="y centered">529.523744875</desc> <desc class="x_label">Feb</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="0.202835355971" rx="0" ry="0" width="37.8761025641" x="115.076051282" y="529.412549259"></rect> <desc class="value">446</desc> <desc class="x centered">134.014102564</desc> <desc class="y centered">529.513966937</desc> <desc class="x_label">Mar</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="16.5888395614" rx="0" ry="0" width="37.8761025641" x="163.986307692" y="513.026545054"></rect> <desc class="value">36476</desc> <desc class="x centered">182.924358974</desc> <desc class="y centered">521.320964835</desc> <desc class="x_label">Apr</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="279.816376228" rx="0" ry="0" width="37.8761025641" x="212.896564103" y="249.799008387"></rect> <desc class="value">615268</desc> <desc class="x centered">231.834615385</desc> <desc class="y centered">389.707196501</desc> <desc class="x_label">Mai</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="302.317002319" rx="0" ry="0" width="37.8761025641" x="261.806820513" y="227.298382296"></rect> <desc class="value">664743</desc> <desc class="x centered">280.744871795</desc> <desc class="y centered">378.456883456</desc> <desc class="x_label">Jun</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="230.647903492" rx="0" ry="0" width="37.8761025641" x="310.717076923" y="298.967481123"></rect> <desc class="value">507155</desc> <desc class="x centered">329.655128205</desc> <desc class="y centered">414.291432869</desc> <desc class="x_label">Jul</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="214.573428925" rx="0" ry="0" width="37.8761025641" x="359.627333333" y="315.04195569"></rect> <desc class="value">471810</desc> <desc class="x centered">378.565384615</desc> <desc class="y centered">422.328670153</desc> <desc class="x_label">Aug</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="194.831090803" rx="0" ry="0" width="37.8761025641" x="408.537589744" y="334.784293813"></rect> <desc class="value">428400</desc> <desc class="x centered">427.475641026</desc> <desc class="y centered">432.199839214</desc> <desc class="x_label">Sep</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="250.100087003" rx="0" ry="0" width="37.8761025641" x="457.447846154" y="279.515297613"></rect> <desc class="value">549927</desc> <desc class="x centered">476.385897436</desc> <desc class="y centered">404.565341114</desc> <desc class="x_label">Okt</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="415.840676584" rx="0" ry="0" width="37.8761025641" x="506.358102564" y="113.774708031"></rect> <desc class="value">914362</desc> <desc class="x centered">525.296153846</desc> <desc class="y centered">321.695046323</desc> <desc class="x_label">Nov</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="519.230769231" rx="0" ry="0" width="37.8761025641" x="555.268358974" y="10.3846153846"></rect> <desc class="value">1141699</desc> <desc class="x centered">574.206410256</desc> <desc class="y centered">270.0</desc> <desc class="x_label">Dez</desc> </g> </g> </g> </g> <g class="titles"></g> <g class="plot overlay" transform="translate(169, 20)"> <g class="series serie-0 color-0"></g> </g> <g class="plot text-overlay" transform="translate(169, 20)"> <g class="series serie-0 color-0"></g> </g> <g class="plot tooltip-overlay" transform="translate(169, 20)"> <g class="tooltip" style="opacity: 0" transform="translate(0 0)"> <rect class="tooltip-box" height="0" rx="0" ry="0" width="0"></rect> <g class="text"></g> </g> </g> <g class="legends" transform="translate(10, 30)"> <g class="legend reactive activate-serie" id="activate-serie-0"> <rect class="color-0 reactive" height="12" width="12" x="0.0" y="1.0"></rect> <text x="17.0" y="11.2">Incomming</text> </g> </g> <g class="legends" transform="translate(790, 30)"></g> </g> </svg> |
|
\ No newline at end of file |
| @@ -1 +0,0 @@ | ||
| 1 | -<?xml version="1.0" encoding="UTF-8"?> <svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" id="chart-9709354d-7015-48f2-b031-eadeaa28582c" class="pygal-chart" viewBox="0 0 800 600"> <!--Generated with pygal 2.4.0 (lxml) ©Kozea 2012-2016 on 2018-01-02--> <!--http://pygal.org--> <!--http://github.com/Kozea/pygal--> <defs> <style type="text/css">#chart-9709354d-7015-48f2-b031-eadeaa28582c{-webkit-user-select:none;-webkit-font-smoothing:antialiased;font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace}#chart-9709354d-7015-48f2-b031-eadeaa28582c .title{font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:16px}#chart-9709354d-7015-48f2-b031-eadeaa28582c .legends .legend text{font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:14px}#chart-9709354d-7015-48f2-b031-eadeaa28582c .axis text{font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:10px}#chart-9709354d-7015-48f2-b031-eadeaa28582c .axis text.major{font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:10px}#chart-9709354d-7015-48f2-b031-eadeaa28582c .text-overlay text.value{font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:16px}#chart-9709354d-7015-48f2-b031-eadeaa28582c .text-overlay text.label{font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:10px}#chart-9709354d-7015-48f2-b031-eadeaa28582c .tooltip{font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:14px}#chart-9709354d-7015-48f2-b031-eadeaa28582c text.no_data{font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:64px} #chart-9709354d-7015-48f2-b031-eadeaa28582c{background-color:rgba(249,249,249,1)}#chart-9709354d-7015-48f2-b031-eadeaa28582c path,#chart-9709354d-7015-48f2-b031-eadeaa28582c line,#chart-9709354d-7015-48f2-b031-eadeaa28582c rect,#chart-9709354d-7015-48f2-b031-eadeaa28582c circle{-webkit-transition:150ms;-moz-transition:150ms;transition:150ms}#chart-9709354d-7015-48f2-b031-eadeaa28582c .graph > .background{fill:rgba(249,249,249,1)}#chart-9709354d-7015-48f2-b031-eadeaa28582c .plot > .background{fill:rgba(255,255,255,1)}#chart-9709354d-7015-48f2-b031-eadeaa28582c .graph{fill:rgba(0,0,0,.87)}#chart-9709354d-7015-48f2-b031-eadeaa28582c text.no_data{fill:rgba(0,0,0,1)}#chart-9709354d-7015-48f2-b031-eadeaa28582c .title{fill:rgba(0,0,0,1)}#chart-9709354d-7015-48f2-b031-eadeaa28582c .legends .legend text{fill:rgba(0,0,0,.87)}#chart-9709354d-7015-48f2-b031-eadeaa28582c .legends .legend:hover text{fill:rgba(0,0,0,1)}#chart-9709354d-7015-48f2-b031-eadeaa28582c .axis .line{stroke:rgba(0,0,0,1)}#chart-9709354d-7015-48f2-b031-eadeaa28582c .axis .guide.line{stroke:rgba(0,0,0,.54)}#chart-9709354d-7015-48f2-b031-eadeaa28582c .axis .major.line{stroke:rgba(0,0,0,.87)}#chart-9709354d-7015-48f2-b031-eadeaa28582c .axis text.major{fill:rgba(0,0,0,1)}#chart-9709354d-7015-48f2-b031-eadeaa28582c .axis.y .guides:hover .guide.line,#chart-9709354d-7015-48f2-b031-eadeaa28582c .line-graph .axis.x .guides:hover .guide.line,#chart-9709354d-7015-48f2-b031-eadeaa28582c .stackedline-graph .axis.x .guides:hover .guide.line,#chart-9709354d-7015-48f2-b031-eadeaa28582c .xy-graph .axis.x .guides:hover .guide.line{stroke:rgba(0,0,0,1)}#chart-9709354d-7015-48f2-b031-eadeaa28582c .axis .guides:hover text{fill:rgba(0,0,0,1)}#chart-9709354d-7015-48f2-b031-eadeaa28582c .reactive{fill-opacity:.7;stroke-opacity:.8}#chart-9709354d-7015-48f2-b031-eadeaa28582c .ci{stroke:rgba(0,0,0,.87)}#chart-9709354d-7015-48f2-b031-eadeaa28582c .reactive.active,#chart-9709354d-7015-48f2-b031-eadeaa28582c .active .reactive{fill-opacity:.8;stroke-opacity:.9;stroke-width:4}#chart-9709354d-7015-48f2-b031-eadeaa28582c .ci .reactive.active{stroke-width:1.5}#chart-9709354d-7015-48f2-b031-eadeaa28582c .series text{fill:rgba(0,0,0,1)}#chart-9709354d-7015-48f2-b031-eadeaa28582c .tooltip rect{fill:rgba(255,255,255,1);stroke:rgba(0,0,0,1);-webkit-transition:opacity 150ms;-moz-transition:opacity 150ms;transition:opacity 150ms}#chart-9709354d-7015-48f2-b031-eadeaa28582c .tooltip .label{fill:rgba(0,0,0,.87)}#chart-9709354d-7015-48f2-b031-eadeaa28582c .tooltip .label{fill:rgba(0,0,0,.87)}#chart-9709354d-7015-48f2-b031-eadeaa28582c .tooltip .legend{font-size:.8em;fill:rgba(0,0,0,.54)}#chart-9709354d-7015-48f2-b031-eadeaa28582c .tooltip .x_label{font-size:.6em;fill:rgba(0,0,0,1)}#chart-9709354d-7015-48f2-b031-eadeaa28582c .tooltip .xlink{font-size:.5em;text-decoration:underline}#chart-9709354d-7015-48f2-b031-eadeaa28582c .tooltip .value{font-size:1.5em}#chart-9709354d-7015-48f2-b031-eadeaa28582c .bound{font-size:.5em}#chart-9709354d-7015-48f2-b031-eadeaa28582c .max-value{font-size:.75em;fill:rgba(0,0,0,.54)}#chart-9709354d-7015-48f2-b031-eadeaa28582c .map-element{fill:rgba(255,255,255,1);stroke:rgba(0,0,0,.54) !important}#chart-9709354d-7015-48f2-b031-eadeaa28582c .map-element .reactive{fill-opacity:inherit;stroke-opacity:inherit}#chart-9709354d-7015-48f2-b031-eadeaa28582c .color-0,#chart-9709354d-7015-48f2-b031-eadeaa28582c .color-0 a:visited{stroke:#F44336;fill:#F44336}#chart-9709354d-7015-48f2-b031-eadeaa28582c .color-1,#chart-9709354d-7015-48f2-b031-eadeaa28582c .color-1 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-9709354d-7015-48f2-b031-eadeaa28582c .text-overlay .color-0 text{fill:black}#chart-9709354d-7015-48f2-b031-eadeaa28582c .text-overlay .color-1 text{fill:black} #chart-9709354d-7015-48f2-b031-eadeaa28582c text.no_data{text-anchor:middle}#chart-9709354d-7015-48f2-b031-eadeaa28582c .guide.line{fill:none}#chart-9709354d-7015-48f2-b031-eadeaa28582c .centered{text-anchor:middle}#chart-9709354d-7015-48f2-b031-eadeaa28582c .title{text-anchor:middle}#chart-9709354d-7015-48f2-b031-eadeaa28582c .legends .legend text{fill-opacity:1}#chart-9709354d-7015-48f2-b031-eadeaa28582c .axis.x text{text-anchor:middle}#chart-9709354d-7015-48f2-b031-eadeaa28582c .axis.x:not(.web) text[transform]{text-anchor:start}#chart-9709354d-7015-48f2-b031-eadeaa28582c .axis.x:not(.web) text[transform].backwards{text-anchor:end}#chart-9709354d-7015-48f2-b031-eadeaa28582c .axis.y text{text-anchor:end}#chart-9709354d-7015-48f2-b031-eadeaa28582c .axis.y text[transform].backwards{text-anchor:start}#chart-9709354d-7015-48f2-b031-eadeaa28582c .axis.y2 text{text-anchor:start}#chart-9709354d-7015-48f2-b031-eadeaa28582c .axis.y2 text[transform].backwards{text-anchor:end}#chart-9709354d-7015-48f2-b031-eadeaa28582c .axis .guide.line{stroke-dasharray:4,4}#chart-9709354d-7015-48f2-b031-eadeaa28582c .axis .major.guide.line{stroke-dasharray:6,6}#chart-9709354d-7015-48f2-b031-eadeaa28582c .horizontal .axis.y .guide.line,#chart-9709354d-7015-48f2-b031-eadeaa28582c .horizontal .axis.y2 .guide.line,#chart-9709354d-7015-48f2-b031-eadeaa28582c .vertical .axis.x .guide.line{opacity:0}#chart-9709354d-7015-48f2-b031-eadeaa28582c .horizontal .axis.always_show .guide.line,#chart-9709354d-7015-48f2-b031-eadeaa28582c .vertical .axis.always_show .guide.line{opacity:1 !important}#chart-9709354d-7015-48f2-b031-eadeaa28582c .axis.y .guides:hover .guide.line,#chart-9709354d-7015-48f2-b031-eadeaa28582c .axis.y2 .guides:hover .guide.line,#chart-9709354d-7015-48f2-b031-eadeaa28582c .axis.x .guides:hover .guide.line{opacity:1}#chart-9709354d-7015-48f2-b031-eadeaa28582c .axis .guides:hover text{opacity:1}#chart-9709354d-7015-48f2-b031-eadeaa28582c .nofill{fill:none}#chart-9709354d-7015-48f2-b031-eadeaa28582c .subtle-fill{fill-opacity:.2}#chart-9709354d-7015-48f2-b031-eadeaa28582c .dot{stroke-width:1px;fill-opacity:1}#chart-9709354d-7015-48f2-b031-eadeaa28582c .dot.active{stroke-width:5px}#chart-9709354d-7015-48f2-b031-eadeaa28582c .dot.negative{fill:transparent}#chart-9709354d-7015-48f2-b031-eadeaa28582c text,#chart-9709354d-7015-48f2-b031-eadeaa28582c tspan{stroke:none !important}#chart-9709354d-7015-48f2-b031-eadeaa28582c .series text.active{opacity:1}#chart-9709354d-7015-48f2-b031-eadeaa28582c .tooltip rect{fill-opacity:.95;stroke-width:.5}#chart-9709354d-7015-48f2-b031-eadeaa28582c .tooltip text{fill-opacity:1}#chart-9709354d-7015-48f2-b031-eadeaa28582c .showable{visibility:hidden}#chart-9709354d-7015-48f2-b031-eadeaa28582c .showable.shown{visibility:visible}#chart-9709354d-7015-48f2-b031-eadeaa28582c .gauge-background{fill:rgba(229,229,229,1);stroke:none}#chart-9709354d-7015-48f2-b031-eadeaa28582c .bg-lines{stroke:rgba(249,249,249,1);stroke-width:2px}</style> </defs> <title>Pygal</title> <g class="graph bar-graph vertical"> <rect class="background" height="600" width="800" x="0" y="0"></rect> <g class="plot" transform="translate(169, 20)"> <rect class="background" height="540" width="610.4" x="0" y="0"></rect> <g class="axis y always_show"> <g class="guides"> <path class="axis major line" d="M0.000000 529.615385 h610.400000"></path> <text class="major" x="-5" y="533.115384615">0</text> <title>0</title> </g> <g class="guides"> <path class="guide line" d="M0.000000 484.136605 h610.400000"></path> <text class="" x="-5" y="487.63660525">100000</text> <title>100000</title> </g> <g class="guides"> <path class="guide line" d="M0.000000 438.657826 h610.400000"></path> <text class="" x="-5" y="442.157825884">200000</text> <title>200000</title> </g> <g class="guides"> <path class="guide line" d="M0.000000 393.179047 h610.400000"></path> <text class="" x="-5" y="396.679046518">300000</text> <title>300000</title> </g> <g class="guides"> <path class="guide line" d="M0.000000 347.700267 h610.400000"></path> <text class="" x="-5" y="351.200267152">400000</text> <title>400000</title> </g> <g class="guides"> <path class="major guide line" d="M0.000000 302.221488 h610.400000"></path> <text class="major" x="-5" y="305.721487787">500000</text> <title>500000</title> </g> <g class="guides"> <path class="guide line" d="M0.000000 256.742708 h610.400000"></path> <text class="" x="-5" y="260.242708421">600000</text> <title>600000</title> </g> <g class="guides"> <path class="guide line" d="M0.000000 211.263929 h610.400000"></path> <text class="" x="-5" y="214.763929055">700000</text> <title>700000</title> </g> <g class="guides"> <path class="guide line" d="M0.000000 165.785150 h610.400000"></path> <text class="" x="-5" y="169.28514969">800000</text> <title>800000</title> </g> <g class="guides"> <path class="guide line" d="M0.000000 120.306370 h610.400000"></path> <text class="" x="-5" y="123.806370324">900000</text> <title>900000</title> </g> <g class="guides"> <path class="major guide line" d="M0.000000 74.827591 h610.400000"></path> <text class="major" x="-5" y="78.3275909581">1000000</text> <title>1000000</title> </g> <g class="guides"> <path class="guide line" d="M0.000000 29.348812 h610.400000"></path> <text class="" x="-5" y="32.8488115923">1100000</text> <title>1100000</title> </g> </g> <g class="axis x"> <path class="line" d="M0.000000 0.000000 v540.000000"></path> <g class="guides"> <path class="guide line" d="M36.193590 0.000000 v540.000000"></path> <text class="" x="36.1935897436" y="555.0">Jan</text> </g> <g class="guides"> <path class="guide line" d="M85.103846 0.000000 v540.000000"></path> <text class="" x="85.1038461538" y="555.0">Feb</text> </g> <g class="guides"> <path class="guide line" d="M134.014103 0.000000 v540.000000"></path> <text class="" x="134.014102564" y="555.0">Mar</text> </g> <g class="guides"> <path class="guide line" d="M182.924359 0.000000 v540.000000"></path> <text class="" x="182.924358974" y="555.0">Apr</text> </g> <g class="guides"> <path class="guide line" d="M231.834615 0.000000 v540.000000"></path> <text class="" x="231.834615385" y="555.0">Mai</text> </g> <g class="guides"> <path class="guide line" d="M280.744872 0.000000 v540.000000"></path> <text class="" x="280.744871795" y="555.0">Jun</text> </g> <g class="guides"> <path class="guide line" d="M329.655128 0.000000 v540.000000"></path> <text class="" x="329.655128205" y="555.0">Jul</text> </g> <g class="guides"> <path class="guide line" d="M378.565385 0.000000 v540.000000"></path> <text class="" x="378.565384615" y="555.0">Aug</text> </g> <g class="guides"> <path class="guide line" d="M427.475641 0.000000 v540.000000"></path> <text class="" x="427.475641026" y="555.0">Sep</text> </g> <g class="guides"> <path class="guide line" d="M476.385897 0.000000 v540.000000"></path> <text class="" x="476.385897436" y="555.0">Okt</text> </g> <g class="guides"> <path class="guide line" d="M525.296154 0.000000 v540.000000"></path> <text class="" x="525.296153846" y="555.0">Nov</text> </g> <g class="guides"> <path class="guide line" d="M574.206410 0.000000 v540.000000"></path> <text class="" x="574.206410256" y="555.0">Dez</text> </g> </g> <g class="series serie-0 color-0"> <g class="bars"> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="7.64725675035" rx="0" ry="0" width="18.9380512821" x="15.9643076923" y="521.968127865"></rect> <desc class="value">16815</desc> <desc class="x centered">25.4333333333</desc> <desc class="y centered">525.79175624</desc> <desc class="x_label">Jan</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="0.183279480844" rx="0" ry="0" width="18.9380512821" x="64.8745641026" y="529.432105135"></rect> <desc class="value">403</desc> <desc class="x centered">74.3435897436</desc> <desc class="y centered">529.523744875</desc> <desc class="x_label">Feb</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="0.202835355971" rx="0" ry="0" width="18.9380512821" x="113.784820513" y="529.412549259"></rect> <desc class="value">446</desc> <desc class="x centered">123.253846154</desc> <desc class="y centered">529.513966937</desc> <desc class="x_label">Mar</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="16.5888395614" rx="0" ry="0" width="18.9380512821" x="162.695076923" y="513.026545054"></rect> <desc class="value">36476</desc> <desc class="x centered">172.164102564</desc> <desc class="y centered">521.320964835</desc> <desc class="x_label">Apr</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="279.816376228" rx="0" ry="0" width="18.9380512821" x="211.605333333" y="249.799008387"></rect> <desc class="value">615268</desc> <desc class="x centered">221.074358974</desc> <desc class="y centered">389.707196501</desc> <desc class="x_label">Mai</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="302.317002319" rx="0" ry="0" width="18.9380512821" x="260.515589744" y="227.298382296"></rect> <desc class="value">664743</desc> <desc class="x centered">269.984615385</desc> <desc class="y centered">378.456883456</desc> <desc class="x_label">Jun</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="230.647903492" rx="0" ry="0" width="18.9380512821" x="309.425846154" y="298.967481123"></rect> <desc class="value">507155</desc> <desc class="x centered">318.894871795</desc> <desc class="y centered">414.291432869</desc> <desc class="x_label">Jul</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="214.573428925" rx="0" ry="0" width="18.9380512821" x="358.336102564" y="315.04195569"></rect> <desc class="value">471810</desc> <desc class="x centered">367.805128205</desc> <desc class="y centered">422.328670153</desc> <desc class="x_label">Aug</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="194.831090803" rx="0" ry="0" width="18.9380512821" x="407.246358974" y="334.784293813"></rect> <desc class="value">428400</desc> <desc class="x centered">416.715384615</desc> <desc class="y centered">432.199839214</desc> <desc class="x_label">Sep</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="250.100087003" rx="0" ry="0" width="18.9380512821" x="456.156615385" y="279.515297613"></rect> <desc class="value">549927</desc> <desc class="x centered">465.625641026</desc> <desc class="y centered">404.565341114</desc> <desc class="x_label">Okt</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="415.840676584" rx="0" ry="0" width="18.9380512821" x="505.066871795" y="113.774708031"></rect> <desc class="value">914362</desc> <desc class="x centered">514.535897436</desc> <desc class="y centered">321.695046323</desc> <desc class="x_label">Nov</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="519.230769231" rx="0" ry="0" width="18.9380512821" x="553.977128205" y="10.3846153846"></rect> <desc class="value">1141699</desc> <desc class="x centered">563.446153846</desc> <desc class="y centered">270.0</desc> <desc class="x_label">Dez</desc> </g> </g> </g> <g class="series serie-1 color-1"> <g class="bars"> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="1.87554486104" rx="0" ry="0" width="18.9380512821" x="37.4848205128" y="527.739839754"></rect> <desc class="value">4124</desc> <desc class="x centered">46.9538461538</desc> <desc class="y centered">528.677612185</desc> <desc class="x_label">Jan</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="0.490261241563" rx="0" ry="0" width="18.9380512821" x="86.3950769231" y="529.125123374"></rect> <desc class="value">1078</desc> <desc class="x centered">95.8641025641</desc> <desc class="y centered">529.370253995</desc> <desc class="x_label">Feb</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="0.545290564595" rx="0" ry="0" width="18.9380512821" x="135.305333333" y="529.070094051"></rect> <desc class="value">1199</desc> <desc class="x centered">144.774358974</desc> <desc class="y centered">529.342739333</desc> <desc class="x_label">Mar</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="1.12059712357" rx="0" ry="0" width="18.9380512821" x="184.215589744" y="528.494787492"></rect> <desc class="value">2464</desc> <desc class="x centered">193.684615385</desc> <desc class="y centered">529.055086054</desc> <desc class="x_label">Apr</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="42.2857142665" rx="0" ry="0" width="18.9380512821" x="233.125846154" y="487.329670349"></rect> <desc class="value">92979</desc> <desc class="x centered">242.594871795</desc> <desc class="y centered">508.472527482</desc> <desc class="x_label">Mai</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="62.9435402178" rx="0" ry="0" width="18.9380512821" x="282.036102564" y="466.671844398"></rect> <desc class="value">138402</desc> <desc class="x centered">291.505128205</desc> <desc class="y centered">498.143614507</desc> <desc class="x_label">Jun</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="52.9400279085" rx="0" ry="0" width="18.9380512821" x="330.946358974" y="476.675356707"></rect> <desc class="value">116406</desc> <desc class="x centered">340.415384615</desc> <desc class="y centered">503.145370661</desc> <desc class="x_label">Jul</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="16.2150039951" rx="0" ry="0" width="18.9380512821" x="379.856615385" y="513.40038062"></rect> <desc class="value">35654</desc> <desc class="x centered">389.325641026</desc> <desc class="y centered">521.507882618</desc> <desc class="x_label">Aug</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="14.2630547847" rx="0" ry="0" width="18.9380512821" x="428.766871795" y="515.352329831"></rect> <desc class="value">31362</desc> <desc class="x centered">438.235897436</desc> <desc class="y centered">522.483857223</desc> <desc class="x_label">Sep</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="10.9476517689" rx="0" ry="0" width="18.9380512821" x="477.677128205" y="518.667732846"></rect> <desc class="value">24072</desc> <desc class="x centered">487.146153846</desc> <desc class="y centered">524.141558731</desc> <desc class="x_label">Okt</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="20.0538677613" rx="0" ry="0" width="18.9380512821" x="526.587384615" y="509.561516854"></rect> <desc class="value">44095</desc> <desc class="x centered">536.056410256</desc> <desc class="y centered">519.588450735</desc> <desc class="x_label">Nov</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="26.327210587" rx="0" ry="0" width="18.9380512821" x="575.497641026" y="503.288174028"></rect> <desc class="value">57889</desc> <desc class="x centered">584.966666667</desc> <desc class="y centered">516.451779322</desc> <desc class="x_label">Dez</desc> </g> </g> </g> </g> <g class="titles"></g> <g class="plot overlay" transform="translate(169, 20)"> <g class="series serie-0 color-0"></g> <g class="series serie-1 color-1"></g> </g> <g class="plot text-overlay" transform="translate(169, 20)"> <g class="series serie-0 color-0"></g> <g class="series serie-1 color-1"></g> </g> <g class="plot tooltip-overlay" transform="translate(169, 20)"> <g class="tooltip" style="opacity: 0" transform="translate(0 0)"> <rect class="tooltip-box" height="0" rx="0" ry="0" width="0"></rect> <g class="text"></g> </g> </g> <g class="legends" transform="translate(10, 30)"> <g class="legend reactive activate-serie" id="activate-serie-0"> <rect class="color-0 reactive" height="12" width="12" x="0.0" y="1.0"></rect> <text x="17.0" y="11.2">Incomming</text> </g> <g class="legend reactive activate-serie" id="activate-serie-1"> <rect class="color-1 reactive" height="12" width="12" x="0.0" y="22.0"></rect> <text x="17.0" y="32.2">Outgoing</text> </g> </g> <g class="legends" transform="translate(790, 30)"></g> </g> </svg> |
|
\ No newline at end of file |
| @@ -1 +0,0 @@ | ||
| 1 | -<?xml version="1.0" encoding="UTF-8"?> <svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" id="chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c" class="pygal-chart" viewBox="0 0 800 600"> <!--Generated with pygal 2.4.0 (lxml) ©Kozea 2012-2016 on 2018-01-02--> <!--http://pygal.org--> <!--http://github.com/Kozea/pygal--> <defs> <style type="text/css">#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c{-webkit-user-select:none;-webkit-font-smoothing:antialiased;font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .title{font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:16px}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .legends .legend text{font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:14px}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .axis text{font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:10px}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .axis text.major{font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:10px}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .text-overlay text.value{font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:16px}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .text-overlay text.label{font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:10px}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .tooltip{font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:14px}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c text.no_data{font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:64px} #chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c{background-color:rgba(249,249,249,1)}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c path,#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c line,#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c rect,#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c circle{-webkit-transition:150ms;-moz-transition:150ms;transition:150ms}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .graph > .background{fill:rgba(249,249,249,1)}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .plot > .background{fill:rgba(255,255,255,1)}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .graph{fill:rgba(0,0,0,.87)}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c text.no_data{fill:rgba(0,0,0,1)}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .title{fill:rgba(0,0,0,1)}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .legends .legend text{fill:rgba(0,0,0,.87)}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .legends .legend:hover text{fill:rgba(0,0,0,1)}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .axis .line{stroke:rgba(0,0,0,1)}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .axis .guide.line{stroke:rgba(0,0,0,.54)}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .axis .major.line{stroke:rgba(0,0,0,.87)}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .axis text.major{fill:rgba(0,0,0,1)}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .axis.y .guides:hover .guide.line,#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .line-graph .axis.x .guides:hover .guide.line,#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .stackedline-graph .axis.x .guides:hover .guide.line,#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .xy-graph .axis.x .guides:hover .guide.line{stroke:rgba(0,0,0,1)}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .axis .guides:hover text{fill:rgba(0,0,0,1)}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .reactive{fill-opacity:.7;stroke-opacity:.8}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .ci{stroke:rgba(0,0,0,.87)}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .reactive.active,#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .active .reactive{fill-opacity:.8;stroke-opacity:.9;stroke-width:4}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .ci .reactive.active{stroke-width:1.5}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .series text{fill:rgba(0,0,0,1)}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .tooltip rect{fill:rgba(255,255,255,1);stroke:rgba(0,0,0,1);-webkit-transition:opacity 150ms;-moz-transition:opacity 150ms;transition:opacity 150ms}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .tooltip .label{fill:rgba(0,0,0,.87)}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .tooltip .label{fill:rgba(0,0,0,.87)}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .tooltip .legend{font-size:.8em;fill:rgba(0,0,0,.54)}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .tooltip .x_label{font-size:.6em;fill:rgba(0,0,0,1)}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .tooltip .xlink{font-size:.5em;text-decoration:underline}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .tooltip .value{font-size:1.5em}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .bound{font-size:.5em}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .max-value{font-size:.75em;fill:rgba(0,0,0,.54)}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .map-element{fill:rgba(255,255,255,1);stroke:rgba(0,0,0,.54) !important}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .map-element .reactive{fill-opacity:inherit;stroke-opacity:inherit}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .color-0,#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .color-0 a:visited{stroke:#F44336;fill:#F44336}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .color-1,#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .color-1 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .text-overlay .color-0 text{fill:black}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .text-overlay .color-1 text{fill:black} #chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c text.no_data{text-anchor:middle}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .guide.line{fill:none}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .centered{text-anchor:middle}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .title{text-anchor:middle}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .legends .legend text{fill-opacity:1}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .axis.x text{text-anchor:middle}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .axis.x:not(.web) text[transform]{text-anchor:start}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .axis.x:not(.web) text[transform].backwards{text-anchor:end}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .axis.y text{text-anchor:end}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .axis.y text[transform].backwards{text-anchor:start}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .axis.y2 text{text-anchor:start}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .axis.y2 text[transform].backwards{text-anchor:end}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .axis .guide.line{stroke-dasharray:4,4}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .axis .major.guide.line{stroke-dasharray:6,6}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .horizontal .axis.y .guide.line,#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .horizontal .axis.y2 .guide.line,#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .vertical .axis.x .guide.line{opacity:0}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .horizontal .axis.always_show .guide.line,#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .vertical .axis.always_show .guide.line{opacity:1 !important}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .axis.y .guides:hover .guide.line,#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .axis.y2 .guides:hover .guide.line,#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .axis.x .guides:hover .guide.line{opacity:1}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .axis .guides:hover text{opacity:1}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .nofill{fill:none}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .subtle-fill{fill-opacity:.2}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .dot{stroke-width:1px;fill-opacity:1}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .dot.active{stroke-width:5px}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .dot.negative{fill:transparent}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c text,#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c tspan{stroke:none !important}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .series text.active{opacity:1}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .tooltip rect{fill-opacity:.95;stroke-width:.5}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .tooltip text{fill-opacity:1}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .showable{visibility:hidden}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .showable.shown{visibility:visible}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .gauge-background{fill:rgba(229,229,229,1);stroke:none}#chart-cb0298f6-7d64-42e6-a487-cfc5dc76aa8c .bg-lines{stroke:rgba(249,249,249,1);stroke-width:2px}</style> </defs> <title>Pygal</title> <g class="graph stackedbar-graph vertical"> <rect class="background" height="600" width="800" x="0" y="0"></rect> <g class="plot" transform="translate(169, 20)"> <rect class="background" height="540" width="610.4" x="0" y="0"></rect> <g class="axis y always_show"> <g class="guides"> <path class="axis major line" d="M0.000000 529.615385 h610.400000"></path> <text class="major" x="-5" y="533.115384615">0</text> <title>0</title> </g> <g class="guides"> <path class="guide line" d="M0.000000 486.331293 h610.400000"></path> <text class="" x="-5" y="489.831292975">100000</text> <title>100000</title> </g> <g class="guides"> <path class="guide line" d="M0.000000 443.047201 h610.400000"></path> <text class="" x="-5" y="446.547201334">200000</text> <title>200000</title> </g> <g class="guides"> <path class="guide line" d="M0.000000 399.763110 h610.400000"></path> <text class="" x="-5" y="403.263109693">300000</text> <title>300000</title> </g> <g class="guides"> <path class="guide line" d="M0.000000 356.479018 h610.400000"></path> <text class="" x="-5" y="359.979018053">400000</text> <title>400000</title> </g> <g class="guides"> <path class="major guide line" d="M0.000000 313.194926 h610.400000"></path> <text class="major" x="-5" y="316.694926412">500000</text> <title>500000</title> </g> <g class="guides"> <path class="guide line" d="M0.000000 269.910835 h610.400000"></path> <text class="" x="-5" y="273.410834771">600000</text> <title>600000</title> </g> <g class="guides"> <path class="guide line" d="M0.000000 226.626743 h610.400000"></path> <text class="" x="-5" y="230.126743131">700000</text> <title>700000</title> </g> <g class="guides"> <path class="guide line" d="M0.000000 183.342651 h610.400000"></path> <text class="" x="-5" y="186.84265149">800000</text> <title>800000</title> </g> <g class="guides"> <path class="guide line" d="M0.000000 140.058560 h610.400000"></path> <text class="" x="-5" y="143.558559849">900000</text> <title>900000</title> </g> <g class="guides"> <path class="major guide line" d="M0.000000 96.774468 h610.400000"></path> <text class="major" x="-5" y="100.274468208">1000000</text> <title>1000000</title> </g> <g class="guides"> <path class="guide line" d="M0.000000 53.490377 h610.400000"></path> <text class="" x="-5" y="56.9903765677">1100000</text> <title>1100000</title> </g> </g> <g class="axis x"> <path class="line" d="M0.000000 0.000000 v540.000000"></path> <g class="guides"> <path class="guide line" d="M36.193590 0.000000 v540.000000"></path> <text class="" x="36.1935897436" y="555.0">Jan</text> </g> <g class="guides"> <path class="guide line" d="M85.103846 0.000000 v540.000000"></path> <text class="" x="85.1038461538" y="555.0">Feb</text> </g> <g class="guides"> <path class="guide line" d="M134.014103 0.000000 v540.000000"></path> <text class="" x="134.014102564" y="555.0">Mar</text> </g> <g class="guides"> <path class="guide line" d="M182.924359 0.000000 v540.000000"></path> <text class="" x="182.924358974" y="555.0">Apr</text> </g> <g class="guides"> <path class="guide line" d="M231.834615 0.000000 v540.000000"></path> <text class="" x="231.834615385" y="555.0">Mai</text> </g> <g class="guides"> <path class="guide line" d="M280.744872 0.000000 v540.000000"></path> <text class="" x="280.744871795" y="555.0">Jun</text> </g> <g class="guides"> <path class="guide line" d="M329.655128 0.000000 v540.000000"></path> <text class="" x="329.655128205" y="555.0">Jul</text> </g> <g class="guides"> <path class="guide line" d="M378.565385 0.000000 v540.000000"></path> <text class="" x="378.565384615" y="555.0">Aug</text> </g> <g class="guides"> <path class="guide line" d="M427.475641 0.000000 v540.000000"></path> <text class="" x="427.475641026" y="555.0">Sep</text> </g> <g class="guides"> <path class="guide line" d="M476.385897 0.000000 v540.000000"></path> <text class="" x="476.385897436" y="555.0">Okt</text> </g> <g class="guides"> <path class="guide line" d="M525.296154 0.000000 v540.000000"></path> <text class="" x="525.296153846" y="555.0">Nov</text> </g> <g class="guides"> <path class="guide line" d="M574.206410 0.000000 v540.000000"></path> <text class="" x="574.206410256" y="555.0">Dez</text> </g> </g> <g class="series serie-0 color-0"> <g class="bars"> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="7.27822000938" rx="0" ry="0" width="43.041025641" x="14.6730769231" y="522.337164606"></rect> <desc class="value">16815</desc> <desc class="x centered">36.1935897436</desc> <desc class="y centered">525.976274611</desc> <desc class="x_label">Jan</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="0.174434889312" rx="0" ry="0" width="43.041025641" x="63.5833333333" y="529.440949726"></rect> <desc class="value">403</desc> <desc class="x centered">85.1038461538</desc> <desc class="y centered">529.528167171</desc> <desc class="x_label">Feb</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="0.193047048718" rx="0" ry="0" width="43.041025641" x="112.493589744" y="529.422337567"></rect> <desc class="value">446</desc> <desc class="x centered">134.014102564</desc> <desc class="y centered">529.518861091</desc> <desc class="x_label">Mar</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="15.7883052669" rx="0" ry="0" width="43.041025641" x="161.403846154" y="513.827079349"></rect> <desc class="value">36476</desc> <desc class="x centered">182.924358974</desc> <desc class="y centered">521.721231982</desc> <desc class="x_label">Apr</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="266.313164956" rx="0" ry="0" width="43.041025641" x="210.314102564" y="263.30221966"></rect> <desc class="value">615268</desc> <desc class="x centered">231.834615385</desc> <desc class="y centered">396.458802137</desc> <desc class="x_label">Mai</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="287.727969295" rx="0" ry="0" width="43.041025641" x="259.224358974" y="241.88741532"></rect> <desc class="value">664743</desc> <desc class="x centered">280.744871795</desc> <desc class="y centered">385.751399968</desc> <desc class="x_label">Jun</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="219.51743496" rx="0" ry="0" width="43.041025641" x="308.134615385" y="310.097949655"></rect> <desc class="value">507155</desc> <desc class="x centered">329.655128205</desc> <desc class="y centered">419.856667135</desc> <desc class="x_label">Jul</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="204.21867277" rx="0" ry="0" width="43.041025641" x="357.044871795" y="325.396711845"></rect> <desc class="value">471810</desc> <desc class="x centered">378.565384615</desc> <desc class="y centered">427.50604823</desc> <desc class="x_label">Aug</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="185.429048589" rx="0" ry="0" width="43.041025641" x="405.955128205" y="344.186336027"></rect> <desc class="value">428400</desc> <desc class="x centered">427.475641026</desc> <desc class="y centered">436.900860321</desc> <desc class="x_label">Sep</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="238.030906637" rx="0" ry="0" width="43.041025641" x="454.865384615" y="291.584477978"></rect> <desc class="value">549927</desc> <desc class="x centered">476.385897436</desc> <desc class="y centered">410.599931297</desc> <desc class="x_label">Okt</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="395.773286008" rx="0" ry="0" width="43.041025641" x="503.775641026" y="133.842098608"></rect> <desc class="value">914362</desc> <desc class="x centered">525.296153846</desc> <desc class="y centered">331.728741612</desc> <desc class="x_label">Nov</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="494.174041421" rx="0" ry="0" width="43.041025641" x="552.685897436" y="35.4413431945"></rect> <desc class="value">1141699</desc> <desc class="x centered">574.206410256</desc> <desc class="y centered">282.528363905</desc> <desc class="x_label">Dez</desc> </g> </g> </g> <g class="series serie-1 color-1"> <g class="bars"> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="1.78503593926" rx="0" ry="0" width="43.041025641" x="14.6730769231" y="520.552128667"></rect> <desc class="value">4124</desc> <desc class="x centered">36.1935897436</desc> <desc class="y centered">521.444646636</desc> <desc class="x_label">Jan</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="0.466602507887" rx="0" ry="0" width="43.041025641" x="63.5833333333" y="528.974347218"></rect> <desc class="value">1078</desc> <desc class="x centered">85.1038461538</desc> <desc class="y centered">529.207648472</desc> <desc class="x_label">Feb</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="0.518976258772" rx="0" ry="0" width="43.041025641" x="112.493589744" y="528.903361308"></rect> <desc class="value">1199</desc> <desc class="x centered">134.014102564</desc> <desc class="y centered">529.162849437</desc> <desc class="x_label">Mar</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="1.06652001803" rx="0" ry="0" width="43.041025641" x="161.403846154" y="512.76055933"></rect> <desc class="value">2464</desc> <desc class="x centered">182.924358974</desc> <desc class="y centered">513.29381934</desc> <desc class="x_label">Apr</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="40.2451155666" rx="0" ry="0" width="43.041025641" x="210.314102564" y="223.057104093"></rect> <desc class="value">92979</desc> <desc class="x centered">231.834615385</desc> <desc class="y centered">243.179661876</desc> <desc class="x_label">Mai</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="59.9060485126" rx="0" ry="0" width="43.041025641" x="259.224358974" y="181.981366808"></rect> <desc class="value">138402</desc> <desc class="x centered">280.744871795</desc> <desc class="y centered">211.934391064</desc> <desc class="x_label">Jun</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="50.3852797153" rx="0" ry="0" width="43.041025641" x="308.134615385" y="259.71266994"></rect> <desc class="value">116406</desc> <desc class="x centered">329.655128205</desc> <desc class="y centered">284.905309797</desc> <desc class="x_label">Jul</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="15.4325100336" rx="0" ry="0" width="43.041025641" x="357.044871795" y="309.964201812"></rect> <desc class="value">35654</desc> <desc class="x centered">378.565384615</desc> <desc class="y centered">317.680456829</desc> <desc class="x_label">Aug</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="13.5747568204" rx="0" ry="0" width="43.041025641" x="405.955128205" y="330.611579206"></rect> <desc class="value">31362</desc> <desc class="x centered">427.475641026</desc> <desc class="y centered">337.398957616</desc> <desc class="x_label">Sep</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="10.4193465397" rx="0" ry="0" width="43.041025641" x="454.865384615" y="281.165131439"></rect> <desc class="value">24072</desc> <desc class="x centered">476.385897436</desc> <desc class="y centered">286.374804709</desc> <desc class="x_label">Okt</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="19.086120209" rx="0" ry="0" width="43.041025641" x="503.775641026" y="114.755978399"></rect> <desc class="value">44095</desc> <desc class="x centered">525.296153846</desc> <desc class="y centered">124.299038503</desc> <desc class="x_label">Nov</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="25.0567278099" rx="0" ry="0" width="43.041025641" x="552.685897436" y="10.3846153846"></rect> <desc class="value">57889</desc> <desc class="x centered">574.206410256</desc> <desc class="y centered">22.9129792896</desc> <desc class="x_label">Dez</desc> </g> </g> </g> </g> <g class="titles"></g> <g class="plot overlay" transform="translate(169, 20)"> <g class="series serie-0 color-0"></g> <g class="series serie-1 color-1"></g> </g> <g class="plot text-overlay" transform="translate(169, 20)"> <g class="series serie-0 color-0"></g> <g class="series serie-1 color-1"></g> </g> <g class="plot tooltip-overlay" transform="translate(169, 20)"> <g class="tooltip" style="opacity: 0" transform="translate(0 0)"> <rect class="tooltip-box" height="0" rx="0" ry="0" width="0"></rect> <g class="text"></g> </g> </g> <g class="legends" transform="translate(10, 30)"> <g class="legend reactive activate-serie" id="activate-serie-0"> <rect class="color-0 reactive" height="12" width="12" x="0.0" y="1.0"></rect> <text x="17.0" y="11.2">Incomming</text> </g> <g class="legend reactive activate-serie" id="activate-serie-1"> <rect class="color-1 reactive" height="12" width="12" x="0.0" y="22.0"></rect> <text x="17.0" y="32.2">Outgoing</text> </g> </g> <g class="legends" transform="translate(790, 30)"></g> </g> </svg> |
|
\ No newline at end of file |
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
| @@ -1 +0,0 @@ | ||
| 1 | -<?xml version="1.0" encoding="UTF-8"?> <svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" id="chart-81cac860-bc94-4923-a62e-2662a0dd99e1" class="pygal-chart" viewBox="0 0 800 600"> <!--Generated with pygal 2.4.0 (lxml) ©Kozea 2012-2016 on 2018-01-02--> <!--http://pygal.org--> <!--http://github.com/Kozea/pygal--> <defs> <style type="text/css">#chart-81cac860-bc94-4923-a62e-2662a0dd99e1{-webkit-user-select:none;-webkit-font-smoothing:antialiased;font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .title{font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:16px}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .legends .legend text{font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:14px}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .axis text{font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:10px}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .axis text.major{font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:10px}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .text-overlay text.value{font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:16px}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .text-overlay text.label{font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:10px}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .tooltip{font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:14px}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 text.no_data{font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:64px} #chart-81cac860-bc94-4923-a62e-2662a0dd99e1{background-color:rgba(249,249,249,1)}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 path,#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 line,#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 rect,#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 circle{-webkit-transition:150ms;-moz-transition:150ms;transition:150ms}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .graph > .background{fill:rgba(249,249,249,1)}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .plot > .background{fill:rgba(255,255,255,1)}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .graph{fill:rgba(0,0,0,.87)}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 text.no_data{fill:rgba(0,0,0,1)}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .title{fill:rgba(0,0,0,1)}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .legends .legend text{fill:rgba(0,0,0,.87)}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .legends .legend:hover text{fill:rgba(0,0,0,1)}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .axis .line{stroke:rgba(0,0,0,1)}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .axis .guide.line{stroke:rgba(0,0,0,.54)}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .axis .major.line{stroke:rgba(0,0,0,.87)}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .axis text.major{fill:rgba(0,0,0,1)}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .axis.y .guides:hover .guide.line,#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .line-graph .axis.x .guides:hover .guide.line,#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .stackedline-graph .axis.x .guides:hover .guide.line,#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .xy-graph .axis.x .guides:hover .guide.line{stroke:rgba(0,0,0,1)}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .axis .guides:hover text{fill:rgba(0,0,0,1)}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .reactive{fill-opacity:.7;stroke-opacity:.8}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .ci{stroke:rgba(0,0,0,.87)}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .reactive.active,#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .active .reactive{fill-opacity:.8;stroke-opacity:.9;stroke-width:4}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .ci .reactive.active{stroke-width:1.5}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .series text{fill:rgba(0,0,0,1)}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .tooltip rect{fill:rgba(255,255,255,1);stroke:rgba(0,0,0,1);-webkit-transition:opacity 150ms;-moz-transition:opacity 150ms;transition:opacity 150ms}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .tooltip .label{fill:rgba(0,0,0,.87)}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .tooltip .label{fill:rgba(0,0,0,.87)}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .tooltip .legend{font-size:.8em;fill:rgba(0,0,0,.54)}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .tooltip .x_label{font-size:.6em;fill:rgba(0,0,0,1)}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .tooltip .xlink{font-size:.5em;text-decoration:underline}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .tooltip .value{font-size:1.5em}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .bound{font-size:.5em}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .max-value{font-size:.75em;fill:rgba(0,0,0,.54)}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .map-element{fill:rgba(255,255,255,1);stroke:rgba(0,0,0,.54) !important}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .map-element .reactive{fill-opacity:inherit;stroke-opacity:inherit}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .color-0,#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .color-0 a:visited{stroke:#F44336;fill:#F44336}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .text-overlay .color-0 text{fill:black} #chart-81cac860-bc94-4923-a62e-2662a0dd99e1 text.no_data{text-anchor:middle}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .guide.line{fill:none}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .centered{text-anchor:middle}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .title{text-anchor:middle}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .legends .legend text{fill-opacity:1}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .axis.x text{text-anchor:middle}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .axis.x:not(.web) text[transform]{text-anchor:start}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .axis.x:not(.web) text[transform].backwards{text-anchor:end}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .axis.y text{text-anchor:end}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .axis.y text[transform].backwards{text-anchor:start}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .axis.y2 text{text-anchor:start}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .axis.y2 text[transform].backwards{text-anchor:end}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .axis .guide.line{stroke-dasharray:4,4}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .axis .major.guide.line{stroke-dasharray:6,6}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .horizontal .axis.y .guide.line,#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .horizontal .axis.y2 .guide.line,#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .vertical .axis.x .guide.line{opacity:0}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .horizontal .axis.always_show .guide.line,#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .vertical .axis.always_show .guide.line{opacity:1 !important}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .axis.y .guides:hover .guide.line,#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .axis.y2 .guides:hover .guide.line,#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .axis.x .guides:hover .guide.line{opacity:1}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .axis .guides:hover text{opacity:1}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .nofill{fill:none}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .subtle-fill{fill-opacity:.2}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .dot{stroke-width:1px;fill-opacity:1}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .dot.active{stroke-width:5px}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .dot.negative{fill:transparent}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 text,#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 tspan{stroke:none !important}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .series text.active{opacity:1}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .tooltip rect{fill-opacity:.95;stroke-width:.5}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .tooltip text{fill-opacity:1}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .showable{visibility:hidden}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .showable.shown{visibility:visible}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .gauge-background{fill:rgba(229,229,229,1);stroke:none}#chart-81cac860-bc94-4923-a62e-2662a0dd99e1 .bg-lines{stroke:rgba(249,249,249,1);stroke-width:2px}</style> </defs> <title>Pygal</title> <g class="graph bar-graph vertical"> <rect class="background" height="600" width="800" x="0" y="0"></rect> <g class="plot" transform="translate(155, 20)"> <rect class="background" height="540" width="624.8" x="0" y="0"></rect> <g class="axis y always_show"> <g class="guides"> <path class="axis major line" d="M0.000000 529.615385 h624.800000"></path> <text class="major" x="-5" y="533.115384615">0</text> <title>0</title> </g> <g class="guides"> <path class="guide line" d="M0.000000 492.099253 h624.800000"></path> <text class="" x="-5" y="495.599252679">10000</text> <title>10000</title> </g> <g class="guides"> <path class="guide line" d="M0.000000 454.583121 h624.800000"></path> <text class="" x="-5" y="458.083120742">20000</text> <title>20000</title> </g> <g class="guides"> <path class="guide line" d="M0.000000 417.066989 h624.800000"></path> <text class="" x="-5" y="420.566988805">30000</text> <title>30000</title> </g> <g class="guides"> <path class="guide line" d="M0.000000 379.550857 h624.800000"></path> <text class="" x="-5" y="383.050856868">40000</text> <title>40000</title> </g> <g class="guides"> <path class="major guide line" d="M0.000000 342.034725 h624.800000"></path> <text class="major" x="-5" y="345.534724932">50000</text> <title>50000</title> </g> <g class="guides"> <path class="guide line" d="M0.000000 304.518593 h624.800000"></path> <text class="" x="-5" y="308.018592995">60000</text> <title>60000</title> </g> <g class="guides"> <path class="guide line" d="M0.000000 267.002461 h624.800000"></path> <text class="" x="-5" y="270.502461058">70000</text> <title>70000</title> </g> <g class="guides"> <path class="guide line" d="M0.000000 229.486329 h624.800000"></path> <text class="" x="-5" y="232.986329122">80000</text> <title>80000</title> </g> <g class="guides"> <path class="guide line" d="M0.000000 191.970197 h624.800000"></path> <text class="" x="-5" y="195.470197185">90000</text> <title>90000</title> </g> <g class="guides"> <path class="major guide line" d="M0.000000 154.454065 h624.800000"></path> <text class="major" x="-5" y="157.954065248">100000</text> <title>100000</title> </g> <g class="guides"> <path class="guide line" d="M0.000000 116.937933 h624.800000"></path> <text class="" x="-5" y="120.437933311">110000</text> <title>110000</title> </g> <g class="guides"> <path class="guide line" d="M0.000000 79.421801 h624.800000"></path> <text class="" x="-5" y="82.9218013746">120000</text> <title>120000</title> </g> <g class="guides"> <path class="guide line" d="M0.000000 41.905669 h624.800000"></path> <text class="" x="-5" y="45.4056694379">130000</text> <title>130000</title> </g> </g> <g class="axis x"> <path class="line" d="M0.000000 0.000000 v540.000000"></path> <g class="guides"> <path class="guide line" d="M37.047436 0.000000 v540.000000"></path> <text class="" x="37.0474358974" y="555.0">Jan</text> </g> <g class="guides"> <path class="guide line" d="M87.111538 0.000000 v540.000000"></path> <text class="" x="87.1115384615" y="555.0">Feb</text> </g> <g class="guides"> <path class="guide line" d="M137.175641 0.000000 v540.000000"></path> <text class="" x="137.175641026" y="555.0">Mar</text> </g> <g class="guides"> <path class="guide line" d="M187.239744 0.000000 v540.000000"></path> <text class="" x="187.23974359" y="555.0">Apr</text> </g> <g class="guides"> <path class="guide line" d="M237.303846 0.000000 v540.000000"></path> <text class="" x="237.303846154" y="555.0">Mai</text> </g> <g class="guides"> <path class="guide line" d="M287.367949 0.000000 v540.000000"></path> <text class="" x="287.367948718" y="555.0">Jun</text> </g> <g class="guides"> <path class="guide line" d="M337.432051 0.000000 v540.000000"></path> <text class="" x="337.432051282" y="555.0">Jul</text> </g> <g class="guides"> <path class="guide line" d="M387.496154 0.000000 v540.000000"></path> <text class="" x="387.496153846" y="555.0">Aug</text> </g> <g class="guides"> <path class="guide line" d="M437.560256 0.000000 v540.000000"></path> <text class="" x="437.56025641" y="555.0">Sep</text> </g> <g class="guides"> <path class="guide line" d="M487.624359 0.000000 v540.000000"></path> <text class="" x="487.624358974" y="555.0">Okt</text> </g> <g class="guides"> <path class="guide line" d="M537.688462 0.000000 v540.000000"></path> <text class="" x="537.688461538" y="555.0">Nov</text> </g> <g class="guides"> <path class="guide line" d="M587.752564 0.000000 v540.000000"></path> <text class="" x="587.752564103" y="555.0">Dez</text> </g> </g> <g class="series serie-0 color-0"> <g class="bars"> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="15.4716528107" rx="0" ry="0" width="38.7696410256" x="17.6626153846" y="514.143731805"></rect> <desc class="value">4124</desc> <desc class="x centered">37.0474358974</desc> <desc class="y centered">521.87955821</desc> <desc class="x_label">Jan</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="4.04423902278" rx="0" ry="0" width="38.7696410256" x="67.7267179487" y="525.571145593"></rect> <desc class="value">1078</desc> <desc class="x centered">87.1115384615</desc> <desc class="y centered">527.593265104</desc> <desc class="x_label">Feb</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="4.49818421921" rx="0" ry="0" width="38.7696410256" x="117.790820513" y="525.117200396"></rect> <desc class="value">1199</desc> <desc class="x centered">137.175641026</desc> <desc class="y centered">527.366292506</desc> <desc class="x_label">Mar</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="9.24397490921" rx="0" ry="0" width="38.7696410256" x="167.854923077" y="520.371409706"></rect> <desc class="value">2464</desc> <desc class="x centered">187.23974359</desc> <desc class="y centered">524.993397161</desc> <desc class="x_label">Apr</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="348.821243135" rx="0" ry="0" width="38.7696410256" x="217.919025641" y="180.794141481"></rect> <desc class="value">92979</desc> <desc class="x centered">237.303846154</desc> <desc class="y centered">355.204763048</desc> <desc class="x_label">Mai</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="519.230769231" rx="0" ry="0" width="38.7696410256" x="267.983128205" y="10.3846153846"></rect> <desc class="value">138402</desc> <desc class="x centered">287.367948718</desc> <desc class="y centered">270.0</desc> <desc class="x_label">Jun</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="436.710285423" rx="0" ry="0" width="38.7696410256" x="318.047230769" y="92.9050991927"></rect> <desc class="value">116406</desc> <desc class="x centered">337.432051282</desc> <desc class="y centered">311.260241904</desc> <desc class="x_label">Jul</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="133.760016807" rx="0" ry="0" width="38.7696410256" x="368.111333333" y="395.855367808"></rect> <desc class="value">35654</desc> <desc class="x centered">387.496153846</desc> <desc class="y centered">462.735376212</desc> <desc class="x_label">Aug</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="117.65809298" rx="0" ry="0" width="38.7696410256" x="418.175435897" y="411.957291635"></rect> <desc class="value">31362</desc> <desc class="x centered">437.56025641</desc> <desc class="y centered">470.786338125</desc> <desc class="x_label">Sep</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="90.3088327981" rx="0" ry="0" width="38.7696410256" x="468.239538462" y="439.306551817"></rect> <desc class="value">24072</desc> <desc class="x centered">487.624358974</desc> <desc class="y centered">484.460968216</desc> <desc class="x_label">Okt</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="165.427383775" rx="0" ry="0" width="38.7696410256" x="518.303641026" y="364.18800084"></rect> <desc class="value">44095</desc> <desc class="x centered">537.688461538</desc> <desc class="y centered">446.901692728</desc> <desc class="x_label">Nov</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="217.177136169" rx="0" ry="0" width="38.7696410256" x="568.36774359" y="312.438248447"></rect> <desc class="value">57889</desc> <desc class="x centered">587.752564103</desc> <desc class="y centered">421.026816531</desc> <desc class="x_label">Dez</desc> </g> </g> </g> </g> <g class="titles"></g> <g class="plot overlay" transform="translate(155, 20)"> <g class="series serie-0 color-0"></g> </g> <g class="plot text-overlay" transform="translate(155, 20)"> <g class="series serie-0 color-0"></g> </g> <g class="plot tooltip-overlay" transform="translate(155, 20)"> <g class="tooltip" style="opacity: 0" transform="translate(0 0)"> <rect class="tooltip-box" height="0" rx="0" ry="0" width="0"></rect> <g class="text"></g> </g> </g> <g class="legends" transform="translate(10, 30)"> <g class="legend reactive activate-serie" id="activate-serie-0"> <rect class="color-0 reactive" height="12" width="12" x="0.0" y="1.0"></rect> <text x="17.0" y="11.2">Outgoing</text> </g> </g> <g class="legends" transform="translate(790, 30)"></g> </g> </svg> |
|
\ No newline at end of file |
| @@ -1 +0,0 @@ | ||
| 1 | -<?xml version="1.0" encoding="UTF-8"?> <svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" id="chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a" class="pygal-chart" viewBox="0 0 800 600"> <!--Generated with pygal 2.4.0 (lxml) ©Kozea 2012-2016 on 2018-01-02--> <!--http://pygal.org--> <!--http://github.com/Kozea/pygal--> <defs> <style type="text/css">#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a{-webkit-user-select:none;-webkit-font-smoothing:antialiased;font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .title{font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:16px}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .legends .legend text{font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:14px}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .axis text{font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:10px}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .axis text.major{font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:10px}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .text-overlay text.value{font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:16px}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .text-overlay text.label{font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:10px}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .tooltip{font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:14px}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a text.no_data{font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:64px} #chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a{background-color:rgba(249,249,249,1)}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a path,#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a line,#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a rect,#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a circle{-webkit-transition:150ms;-moz-transition:150ms;transition:150ms}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .graph > .background{fill:rgba(249,249,249,1)}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .plot > .background{fill:rgba(255,255,255,1)}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .graph{fill:rgba(0,0,0,.87)}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a text.no_data{fill:rgba(0,0,0,1)}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .title{fill:rgba(0,0,0,1)}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .legends .legend text{fill:rgba(0,0,0,.87)}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .legends .legend:hover text{fill:rgba(0,0,0,1)}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .axis .line{stroke:rgba(0,0,0,1)}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .axis .guide.line{stroke:rgba(0,0,0,.54)}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .axis .major.line{stroke:rgba(0,0,0,.87)}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .axis text.major{fill:rgba(0,0,0,1)}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .axis.y .guides:hover .guide.line,#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .line-graph .axis.x .guides:hover .guide.line,#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .stackedline-graph .axis.x .guides:hover .guide.line,#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .xy-graph .axis.x .guides:hover .guide.line{stroke:rgba(0,0,0,1)}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .axis .guides:hover text{fill:rgba(0,0,0,1)}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .reactive{fill-opacity:.7;stroke-opacity:.8}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .ci{stroke:rgba(0,0,0,.87)}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .reactive.active,#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .active .reactive{fill-opacity:.8;stroke-opacity:.9;stroke-width:4}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .ci .reactive.active{stroke-width:1.5}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .series text{fill:rgba(0,0,0,1)}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .tooltip rect{fill:rgba(255,255,255,1);stroke:rgba(0,0,0,1);-webkit-transition:opacity 150ms;-moz-transition:opacity 150ms;transition:opacity 150ms}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .tooltip .label{fill:rgba(0,0,0,.87)}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .tooltip .label{fill:rgba(0,0,0,.87)}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .tooltip .legend{font-size:.8em;fill:rgba(0,0,0,.54)}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .tooltip .x_label{font-size:.6em;fill:rgba(0,0,0,1)}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .tooltip .xlink{font-size:.5em;text-decoration:underline}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .tooltip .value{font-size:1.5em}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .bound{font-size:.5em}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .max-value{font-size:.75em;fill:rgba(0,0,0,.54)}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .map-element{fill:rgba(255,255,255,1);stroke:rgba(0,0,0,.54) !important}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .map-element .reactive{fill-opacity:inherit;stroke-opacity:inherit}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .color-0,#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .color-0 a:visited{stroke:#F44336;fill:#F44336}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .color-1,#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .color-1 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .color-2,#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .color-2 a:visited{stroke:#009688;fill:#009688}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .text-overlay .color-0 text{fill:black}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .text-overlay .color-1 text{fill:black}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .text-overlay .color-2 text{fill:black} #chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a text.no_data{text-anchor:middle}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .guide.line{fill:none}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .centered{text-anchor:middle}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .title{text-anchor:middle}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .legends .legend text{fill-opacity:1}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .axis.x text{text-anchor:middle}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .axis.x:not(.web) text[transform]{text-anchor:start}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .axis.x:not(.web) text[transform].backwards{text-anchor:end}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .axis.y text{text-anchor:end}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .axis.y text[transform].backwards{text-anchor:start}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .axis.y2 text{text-anchor:start}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .axis.y2 text[transform].backwards{text-anchor:end}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .axis .guide.line{stroke-dasharray:4,4}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .axis .major.guide.line{stroke-dasharray:6,6}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .horizontal .axis.y .guide.line,#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .horizontal .axis.y2 .guide.line,#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .vertical .axis.x .guide.line{opacity:0}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .horizontal .axis.always_show .guide.line,#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .vertical .axis.always_show .guide.line{opacity:1 !important}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .axis.y .guides:hover .guide.line,#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .axis.y2 .guides:hover .guide.line,#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .axis.x .guides:hover .guide.line{opacity:1}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .axis .guides:hover text{opacity:1}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .nofill{fill:none}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .subtle-fill{fill-opacity:.2}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .dot{stroke-width:1px;fill-opacity:1}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .dot.active{stroke-width:5px}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .dot.negative{fill:transparent}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a text,#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a tspan{stroke:none !important}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .series text.active{opacity:1}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .tooltip rect{fill-opacity:.95;stroke-width:.5}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .tooltip text{fill-opacity:1}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .showable{visibility:hidden}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .showable.shown{visibility:visible}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .gauge-background{fill:rgba(229,229,229,1);stroke:none}#chart-f702e70e-14b4-42e0-a76c-1ea99a8f548a .bg-lines{stroke:rgba(249,249,249,1);stroke-width:2px}</style> </defs> <title>Pygal</title> <g class="graph bar-graph vertical"> <rect class="background" height="600" width="800" x="0" y="0"></rect> <g class="plot" transform="translate(169, 20)"> <rect class="background" height="540" width="610.4" x="0" y="0"></rect> <g class="axis y always_show"> <g class="guides"> <path class="axis major line" d="M0.000000 529.615385 h610.400000"></path> <text class="major" x="-5" y="533.115384615">0</text> <title>0</title> </g> <g class="guides"> <path class="guide line" d="M0.000000 486.331293 h610.400000"></path> <text class="" x="-5" y="489.831292975">100000</text> <title>100000</title> </g> <g class="guides"> <path class="guide line" d="M0.000000 443.047201 h610.400000"></path> <text class="" x="-5" y="446.547201334">200000</text> <title>200000</title> </g> <g class="guides"> <path class="guide line" d="M0.000000 399.763110 h610.400000"></path> <text class="" x="-5" y="403.263109693">300000</text> <title>300000</title> </g> <g class="guides"> <path class="guide line" d="M0.000000 356.479018 h610.400000"></path> <text class="" x="-5" y="359.979018053">400000</text> <title>400000</title> </g> <g class="guides"> <path class="major guide line" d="M0.000000 313.194926 h610.400000"></path> <text class="major" x="-5" y="316.694926412">500000</text> <title>500000</title> </g> <g class="guides"> <path class="guide line" d="M0.000000 269.910835 h610.400000"></path> <text class="" x="-5" y="273.410834771">600000</text> <title>600000</title> </g> <g class="guides"> <path class="guide line" d="M0.000000 226.626743 h610.400000"></path> <text class="" x="-5" y="230.126743131">700000</text> <title>700000</title> </g> <g class="guides"> <path class="guide line" d="M0.000000 183.342651 h610.400000"></path> <text class="" x="-5" y="186.84265149">800000</text> <title>800000</title> </g> <g class="guides"> <path class="guide line" d="M0.000000 140.058560 h610.400000"></path> <text class="" x="-5" y="143.558559849">900000</text> <title>900000</title> </g> <g class="guides"> <path class="major guide line" d="M0.000000 96.774468 h610.400000"></path> <text class="major" x="-5" y="100.274468208">1000000</text> <title>1000000</title> </g> <g class="guides"> <path class="guide line" d="M0.000000 53.490377 h610.400000"></path> <text class="" x="-5" y="56.9903765677">1100000</text> <title>1100000</title> </g> </g> <g class="axis x"> <path class="line" d="M0.000000 0.000000 v540.000000"></path> <g class="guides"> <path class="guide line" d="M36.193590 0.000000 v540.000000"></path> <text class="" x="36.1935897436" y="555.0">Jan</text> </g> <g class="guides"> <path class="guide line" d="M85.103846 0.000000 v540.000000"></path> <text class="" x="85.1038461538" y="555.0">Feb</text> </g> <g class="guides"> <path class="guide line" d="M134.014103 0.000000 v540.000000"></path> <text class="" x="134.014102564" y="555.0">Mar</text> </g> <g class="guides"> <path class="guide line" d="M182.924359 0.000000 v540.000000"></path> <text class="" x="182.924358974" y="555.0">Apr</text> </g> <g class="guides"> <path class="guide line" d="M231.834615 0.000000 v540.000000"></path> <text class="" x="231.834615385" y="555.0">Mai</text> </g> <g class="guides"> <path class="guide line" d="M280.744872 0.000000 v540.000000"></path> <text class="" x="280.744871795" y="555.0">Jun</text> </g> <g class="guides"> <path class="guide line" d="M329.655128 0.000000 v540.000000"></path> <text class="" x="329.655128205" y="555.0">Jul</text> </g> <g class="guides"> <path class="guide line" d="M378.565385 0.000000 v540.000000"></path> <text class="" x="378.565384615" y="555.0">Aug</text> </g> <g class="guides"> <path class="guide line" d="M427.475641 0.000000 v540.000000"></path> <text class="" x="427.475641026" y="555.0">Sep</text> </g> <g class="guides"> <path class="guide line" d="M476.385897 0.000000 v540.000000"></path> <text class="" x="476.385897436" y="555.0">Okt</text> </g> <g class="guides"> <path class="guide line" d="M525.296154 0.000000 v540.000000"></path> <text class="" x="525.296153846" y="555.0">Nov</text> </g> <g class="guides"> <path class="guide line" d="M574.206410 0.000000 v540.000000"></path> <text class="" x="574.206410256" y="555.0">Dez</text> </g> </g> <g class="series serie-0 color-0"> <g class="bars"> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="7.27822000938" rx="0" ry="0" width="12.6253675214" x="15.5338974359" y="522.337164606"></rect> <desc class="value">16815</desc> <desc class="x centered">21.8465811966</desc> <desc class="y centered">525.976274611</desc> <desc class="x_label">Jan</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="0.174434889312" rx="0" ry="0" width="12.6253675214" x="64.4441538462" y="529.440949726"></rect> <desc class="value">403</desc> <desc class="x centered">70.7568376068</desc> <desc class="y centered">529.528167171</desc> <desc class="x_label">Feb</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="0.193047048718" rx="0" ry="0" width="12.6253675214" x="113.354410256" y="529.422337567"></rect> <desc class="value">446</desc> <desc class="x centered">119.667094017</desc> <desc class="y centered">529.518861091</desc> <desc class="x_label">Mar</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="15.7883052669" rx="0" ry="0" width="12.6253675214" x="162.264666667" y="513.827079349"></rect> <desc class="value">36476</desc> <desc class="x centered">168.577350427</desc> <desc class="y centered">521.721231982</desc> <desc class="x_label">Apr</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="266.313164956" rx="0" ry="0" width="12.6253675214" x="211.174923077" y="263.30221966"></rect> <desc class="value">615268</desc> <desc class="x centered">217.487606838</desc> <desc class="y centered">396.458802137</desc> <desc class="x_label">Mai</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="287.727969295" rx="0" ry="0" width="12.6253675214" x="260.085179487" y="241.88741532"></rect> <desc class="value">664743</desc> <desc class="x centered">266.397863248</desc> <desc class="y centered">385.751399968</desc> <desc class="x_label">Jun</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="219.51743496" rx="0" ry="0" width="12.6253675214" x="308.995435897" y="310.097949655"></rect> <desc class="value">507155</desc> <desc class="x centered">315.308119658</desc> <desc class="y centered">419.856667135</desc> <desc class="x_label">Jul</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="204.21867277" rx="0" ry="0" width="12.6253675214" x="357.905692308" y="325.396711845"></rect> <desc class="value">471810</desc> <desc class="x centered">364.218376068</desc> <desc class="y centered">427.50604823</desc> <desc class="x_label">Aug</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="185.429048589" rx="0" ry="0" width="12.6253675214" x="406.815948718" y="344.186336027"></rect> <desc class="value">428400</desc> <desc class="x centered">413.128632479</desc> <desc class="y centered">436.900860321</desc> <desc class="x_label">Sep</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="238.030906637" rx="0" ry="0" width="12.6253675214" x="455.726205128" y="291.584477978"></rect> <desc class="value">549927</desc> <desc class="x centered">462.038888889</desc> <desc class="y centered">410.599931297</desc> <desc class="x_label">Okt</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="395.773286008" rx="0" ry="0" width="12.6253675214" x="504.636461538" y="133.842098608"></rect> <desc class="value">914362</desc> <desc class="x centered">510.949145299</desc> <desc class="y centered">331.728741612</desc> <desc class="x_label">Nov</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="494.174041421" rx="0" ry="0" width="12.6253675214" x="553.546717949" y="35.4413431945"></rect> <desc class="value">1141699</desc> <desc class="x centered">559.859401709</desc> <desc class="y centered">282.528363905</desc> <desc class="x_label">Dez</desc> </g> </g> </g> <g class="series serie-1 color-1"> <g class="bars"> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="1.78503593926" rx="0" ry="0" width="12.6253675214" x="29.8809059829" y="527.830348676"></rect> <desc class="value">4124</desc> <desc class="x centered">36.1935897436</desc> <desc class="y centered">528.722866646</desc> <desc class="x_label">Jan</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="0.466602507887" rx="0" ry="0" width="12.6253675214" x="78.7911623932" y="529.148782107"></rect> <desc class="value">1078</desc> <desc class="x centered">85.1038461538</desc> <desc class="y centered">529.382083361</desc> <desc class="x_label">Feb</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="0.518976258772" rx="0" ry="0" width="12.6253675214" x="127.701418803" y="529.096408357"></rect> <desc class="value">1199</desc> <desc class="x centered">134.014102564</desc> <desc class="y centered">529.355896486</desc> <desc class="x_label">Mar</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="1.06652001803" rx="0" ry="0" width="12.6253675214" x="176.611675214" y="528.548864597"></rect> <desc class="value">2464</desc> <desc class="x centered">182.924358974</desc> <desc class="y centered">529.082124606</desc> <desc class="x_label">Apr</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="40.2451155666" rx="0" ry="0" width="12.6253675214" x="225.521931624" y="489.370269049"></rect> <desc class="value">92979</desc> <desc class="x centered">231.834615385</desc> <desc class="y centered">509.492826832</desc> <desc class="x_label">Mai</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="59.9060485126" rx="0" ry="0" width="12.6253675214" x="274.432188034" y="469.709336103"></rect> <desc class="value">138402</desc> <desc class="x centered">280.744871795</desc> <desc class="y centered">499.662360359</desc> <desc class="x_label">Jun</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="50.3852797153" rx="0" ry="0" width="12.6253675214" x="323.342444444" y="479.2301049"></rect> <desc class="value">116406</desc> <desc class="x centered">329.655128205</desc> <desc class="y centered">504.422744758</desc> <desc class="x_label">Jul</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="15.4325100336" rx="0" ry="0" width="12.6253675214" x="372.252700855" y="514.182874582"></rect> <desc class="value">35654</desc> <desc class="x centered">378.565384615</desc> <desc class="y centered">521.899129599</desc> <desc class="x_label">Aug</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="13.5747568204" rx="0" ry="0" width="12.6253675214" x="421.162957265" y="516.040627795"></rect> <desc class="value">31362</desc> <desc class="x centered">427.475641026</desc> <desc class="y centered">522.828006205</desc> <desc class="x_label">Sep</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="10.4193465397" rx="0" ry="0" width="12.6253675214" x="470.073213675" y="519.196038076"></rect> <desc class="value">24072</desc> <desc class="x centered">476.385897436</desc> <desc class="y centered">524.405711346</desc> <desc class="x_label">Okt</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="19.086120209" rx="0" ry="0" width="12.6253675214" x="518.983470085" y="510.529264406"></rect> <desc class="value">44095</desc> <desc class="x centered">525.296153846</desc> <desc class="y centered">520.072324511</desc> <desc class="x_label">Nov</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="25.0567278099" rx="0" ry="0" width="12.6253675214" x="567.893726496" y="504.558656806"></rect> <desc class="value">57889</desc> <desc class="x centered">574.206410256</desc> <desc class="y centered">517.08702071</desc> <desc class="x_label">Dez</desc> </g> </g> </g> <g class="series serie-2 color-2"> <g class="bars"> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="9.06325594864" rx="0" ry="0" width="12.6253675214" x="44.2279145299" y="520.552128667"></rect> <desc class="value">20939</desc> <desc class="x centered">50.5405982906</desc> <desc class="y centered">525.083756641</desc> <desc class="x_label">Jan</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="0.641037397199" rx="0" ry="0" width="12.6253675214" x="93.1381709402" y="528.974347218"></rect> <desc class="value">1481</desc> <desc class="x centered">99.4508547009</desc> <desc class="y centered">529.294865917</desc> <desc class="x_label">Feb</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="0.712023307489" rx="0" ry="0" width="12.6253675214" x="142.04842735" y="528.903361308"></rect> <desc class="value">1645</desc> <desc class="x centered">148.361111111</desc> <desc class="y centered">529.259372962</desc> <desc class="x_label">Mar</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="16.8548252849" rx="0" ry="0" width="12.6253675214" x="190.958683761" y="512.76055933"></rect> <desc class="value">38940</desc> <desc class="x centered">197.271367521</desc> <desc class="y centered">521.187971973</desc> <desc class="x_label">Apr</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="306.558280522" rx="0" ry="0" width="12.6253675214" x="239.868940171" y="223.057104093"></rect> <desc class="value">708247</desc> <desc class="x centered">246.181623932</desc> <desc class="y centered">376.336244354</desc> <desc class="x_label">Mai</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="347.634017808" rx="0" ry="0" width="12.6253675214" x="288.779196581" y="181.981366808"></rect> <desc class="value">803145</desc> <desc class="x centered">295.091880342</desc> <desc class="y centered">355.798375712</desc> <desc class="x_label">Jun</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="269.902714676" rx="0" ry="0" width="12.6253675214" x="337.689452991" y="259.71266994"></rect> <desc class="value">623561</desc> <desc class="x centered">344.002136752</desc> <desc class="y centered">394.664027278</desc> <desc class="x_label">Jul</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="219.651182804" rx="0" ry="0" width="12.6253675214" x="386.599709402" y="309.964201812"></rect> <desc class="value">507464</desc> <desc class="x centered">392.912393162</desc> <desc class="y centered">419.789793214</desc> <desc class="x_label">Aug</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="199.003805409" rx="0" ry="0" width="12.6253675214" x="435.509965812" y="330.611579206"></rect> <desc class="value">459762</desc> <desc class="x centered">441.822649573</desc> <desc class="y centered">430.113481911</desc> <desc class="x_label">Sep</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="248.450253177" rx="0" ry="0" width="12.6253675214" x="484.420222222" y="281.165131439"></rect> <desc class="value">573999</desc> <desc class="x centered">490.732905983</desc> <desc class="y centered">405.390258027</desc> <desc class="x_label">Okt</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="414.859406217" rx="0" ry="0" width="12.6253675214" x="533.330478632" y="114.755978399"></rect> <desc class="value">958457</desc> <desc class="x centered">539.643162393</desc> <desc class="y centered">322.185681507</desc> <desc class="x_label">Nov</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="519.230769231" rx="0" ry="0" width="12.6253675214" x="582.240735043" y="10.3846153846"></rect> <desc class="value">1199588</desc> <desc class="x centered">588.553418803</desc> <desc class="y centered">270.0</desc> <desc class="x_label">Dez</desc> </g> </g> </g> </g> <g class="titles"></g> <g class="plot overlay" transform="translate(169, 20)"> <g class="series serie-0 color-0"></g> <g class="series serie-1 color-1"></g> <g class="series serie-2 color-2"></g> </g> <g class="plot text-overlay" transform="translate(169, 20)"> <g class="series serie-0 color-0"></g> <g class="series serie-1 color-1"></g> <g class="series serie-2 color-2"></g> </g> <g class="plot tooltip-overlay" transform="translate(169, 20)"> <g class="tooltip" style="opacity: 0" transform="translate(0 0)"> <rect class="tooltip-box" height="0" rx="0" ry="0" width="0"></rect> <g class="text"></g> </g> </g> <g class="legends" transform="translate(10, 30)"> <g class="legend reactive activate-serie" id="activate-serie-0"> <rect class="color-0 reactive" height="12" width="12" x="0.0" y="1.0"></rect> <text x="17.0" y="11.2">Eingehend</text> </g> <g class="legend reactive activate-serie" id="activate-serie-1"> <rect class="color-1 reactive" height="12" width="12" x="0.0" y="22.0"></rect> <text x="17.0" y="32.2">Ausgehend</text> </g> <g class="legend reactive activate-serie" id="activate-serie-2"> <rect class="color-2 reactive" height="12" width="12" x="0.0" y="43.0"></rect> <text x="17.0" y="53.2">Gesamt</text> </g> </g> <g class="legends" transform="translate(790, 30)"></g> </g> </svg> |
|
\ No newline at end of file |
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
| @@ -1 +0,0 @@ | ||
| 1 | -<?xml version="1.0" encoding="UTF-8"?> <svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" id="chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762" class="pygal-chart" viewBox="0 0 800 600"> <!--Generated with pygal 2.4.0 (lxml) ©Kozea 2012-2016 on 2018-01-02--> <!--http://pygal.org--> <!--http://github.com/Kozea/pygal--> <defs> <style type="text/css">#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762{-webkit-user-select:none;-webkit-font-smoothing:antialiased;font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .title{font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:16px}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .legends .legend text{font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:14px}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .axis text{font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:10px}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .axis text.major{font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:10px}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .text-overlay text.value{font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:16px}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .text-overlay text.label{font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:10px}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .tooltip{font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:14px}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 text.no_data{font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:64px} #chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762{background-color:rgba(249,249,249,1)}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 path,#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 line,#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 rect,#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 circle{-webkit-transition:150ms;-moz-transition:150ms;transition:150ms}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .graph > .background{fill:rgba(249,249,249,1)}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .plot > .background{fill:rgba(255,255,255,1)}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .graph{fill:rgba(0,0,0,.87)}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 text.no_data{fill:rgba(0,0,0,1)}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .title{fill:rgba(0,0,0,1)}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .legends .legend text{fill:rgba(0,0,0,.87)}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .legends .legend:hover text{fill:rgba(0,0,0,1)}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .axis .line{stroke:rgba(0,0,0,1)}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .axis .guide.line{stroke:rgba(0,0,0,.54)}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .axis .major.line{stroke:rgba(0,0,0,.87)}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .axis text.major{fill:rgba(0,0,0,1)}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .axis.y .guides:hover .guide.line,#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .line-graph .axis.x .guides:hover .guide.line,#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .stackedline-graph .axis.x .guides:hover .guide.line,#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .xy-graph .axis.x .guides:hover .guide.line{stroke:rgba(0,0,0,1)}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .axis .guides:hover text{fill:rgba(0,0,0,1)}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .reactive{fill-opacity:.7;stroke-opacity:.8}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .ci{stroke:rgba(0,0,0,.87)}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .reactive.active,#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .active .reactive{fill-opacity:.8;stroke-opacity:.9;stroke-width:4}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .ci .reactive.active{stroke-width:1.5}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .series text{fill:rgba(0,0,0,1)}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .tooltip rect{fill:rgba(255,255,255,1);stroke:rgba(0,0,0,1);-webkit-transition:opacity 150ms;-moz-transition:opacity 150ms;transition:opacity 150ms}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .tooltip .label{fill:rgba(0,0,0,.87)}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .tooltip .label{fill:rgba(0,0,0,.87)}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .tooltip .legend{font-size:.8em;fill:rgba(0,0,0,.54)}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .tooltip .x_label{font-size:.6em;fill:rgba(0,0,0,1)}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .tooltip .xlink{font-size:.5em;text-decoration:underline}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .tooltip .value{font-size:1.5em}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .bound{font-size:.5em}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .max-value{font-size:.75em;fill:rgba(0,0,0,.54)}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .map-element{fill:rgba(255,255,255,1);stroke:rgba(0,0,0,.54) !important}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .map-element .reactive{fill-opacity:inherit;stroke-opacity:inherit}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .color-0,#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .color-0 a:visited{stroke:#F44336;fill:#F44336}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .text-overlay .color-0 text{fill:black} #chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 text.no_data{text-anchor:middle}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .guide.line{fill:none}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .centered{text-anchor:middle}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .title{text-anchor:middle}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .legends .legend text{fill-opacity:1}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .axis.x text{text-anchor:middle}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .axis.x:not(.web) text[transform]{text-anchor:start}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .axis.x:not(.web) text[transform].backwards{text-anchor:end}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .axis.y text{text-anchor:end}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .axis.y text[transform].backwards{text-anchor:start}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .axis.y2 text{text-anchor:start}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .axis.y2 text[transform].backwards{text-anchor:end}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .axis .guide.line{stroke-dasharray:4,4}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .axis .major.guide.line{stroke-dasharray:6,6}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .horizontal .axis.y .guide.line,#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .horizontal .axis.y2 .guide.line,#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .vertical .axis.x .guide.line{opacity:0}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .horizontal .axis.always_show .guide.line,#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .vertical .axis.always_show .guide.line{opacity:1 !important}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .axis.y .guides:hover .guide.line,#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .axis.y2 .guides:hover .guide.line,#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .axis.x .guides:hover .guide.line{opacity:1}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .axis .guides:hover text{opacity:1}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .nofill{fill:none}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .subtle-fill{fill-opacity:.2}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .dot{stroke-width:1px;fill-opacity:1}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .dot.active{stroke-width:5px}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .dot.negative{fill:transparent}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 text,#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 tspan{stroke:none !important}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .series text.active{opacity:1}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .tooltip rect{fill-opacity:.95;stroke-width:.5}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .tooltip text{fill-opacity:1}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .showable{visibility:hidden}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .showable.shown{visibility:visible}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .gauge-background{fill:rgba(229,229,229,1);stroke:none}#chart-b4395bf0-7cbe-4351-97f9-89d6f3bd3762 .bg-lines{stroke:rgba(249,249,249,1);stroke-width:2px}</style> </defs> <title>Pygal</title> <g class="graph bar-graph vertical"> <rect class="background" height="600" width="800" x="0" y="0"></rect> <g class="plot" transform="translate(161, 20)"> <rect class="background" height="540" width="618.8" x="0" y="0"></rect> <g class="axis y always_show"> <g class="guides"> <path class="axis major line" d="M0.000000 529.615385 h618.800000"></path> <text class="major" x="-5" y="533.115384615">0</text> <title>0</title> </g> <g class="guides"> <path class="guide line" d="M0.000000 486.331293 h618.800000"></path> <text class="" x="-5" y="489.831292975">100000</text> <title>100000</title> </g> <g class="guides"> <path class="guide line" d="M0.000000 443.047201 h618.800000"></path> <text class="" x="-5" y="446.547201334">200000</text> <title>200000</title> </g> <g class="guides"> <path class="guide line" d="M0.000000 399.763110 h618.800000"></path> <text class="" x="-5" y="403.263109693">300000</text> <title>300000</title> </g> <g class="guides"> <path class="guide line" d="M0.000000 356.479018 h618.800000"></path> <text class="" x="-5" y="359.979018053">400000</text> <title>400000</title> </g> <g class="guides"> <path class="major guide line" d="M0.000000 313.194926 h618.800000"></path> <text class="major" x="-5" y="316.694926412">500000</text> <title>500000</title> </g> <g class="guides"> <path class="guide line" d="M0.000000 269.910835 h618.800000"></path> <text class="" x="-5" y="273.410834771">600000</text> <title>600000</title> </g> <g class="guides"> <path class="guide line" d="M0.000000 226.626743 h618.800000"></path> <text class="" x="-5" y="230.126743131">700000</text> <title>700000</title> </g> <g class="guides"> <path class="guide line" d="M0.000000 183.342651 h618.800000"></path> <text class="" x="-5" y="186.84265149">800000</text> <title>800000</title> </g> <g class="guides"> <path class="guide line" d="M0.000000 140.058560 h618.800000"></path> <text class="" x="-5" y="143.558559849">900000</text> <title>900000</title> </g> <g class="guides"> <path class="major guide line" d="M0.000000 96.774468 h618.800000"></path> <text class="major" x="-5" y="100.274468208">1000000</text> <title>1000000</title> </g> <g class="guides"> <path class="guide line" d="M0.000000 53.490377 h618.800000"></path> <text class="" x="-5" y="56.9903765677">1100000</text> <title>1100000</title> </g> </g> <g class="axis x"> <path class="line" d="M0.000000 0.000000 v540.000000"></path> <g class="guides"> <path class="guide line" d="M36.691667 0.000000 v540.000000"></path> <text class="" x="36.6916666667" y="555.0">Jan</text> </g> <g class="guides"> <path class="guide line" d="M86.275000 0.000000 v540.000000"></path> <text class="" x="86.275" y="555.0">Feb</text> </g> <g class="guides"> <path class="guide line" d="M135.858333 0.000000 v540.000000"></path> <text class="" x="135.858333333" y="555.0">Mar</text> </g> <g class="guides"> <path class="guide line" d="M185.441667 0.000000 v540.000000"></path> <text class="" x="185.441666667" y="555.0">Apr</text> </g> <g class="guides"> <path class="guide line" d="M235.025000 0.000000 v540.000000"></path> <text class="" x="235.025" y="555.0">Mai</text> </g> <g class="guides"> <path class="guide line" d="M284.608333 0.000000 v540.000000"></path> <text class="" x="284.608333333" y="555.0">Jun</text> </g> <g class="guides"> <path class="guide line" d="M334.191667 0.000000 v540.000000"></path> <text class="" x="334.191666667" y="555.0">Jul</text> </g> <g class="guides"> <path class="guide line" d="M383.775000 0.000000 v540.000000"></path> <text class="" x="383.775" y="555.0">Aug</text> </g> <g class="guides"> <path class="guide line" d="M433.358333 0.000000 v540.000000"></path> <text class="" x="433.358333333" y="555.0">Sep</text> </g> <g class="guides"> <path class="guide line" d="M482.941667 0.000000 v540.000000"></path> <text class="" x="482.941666667" y="555.0">Okt</text> </g> <g class="guides"> <path class="guide line" d="M532.525000 0.000000 v540.000000"></path> <text class="" x="532.525" y="555.0">Nov</text> </g> <g class="guides"> <path class="guide line" d="M582.108333 0.000000 v540.000000"></path> <text class="" x="582.108333333" y="555.0">Dez</text> </g> </g> <g class="series serie-0 color-0"> <g class="bars"> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="9.06325594864" rx="0" ry="0" width="38.3973333333" x="17.493" y="520.552128667"></rect> <desc class="value">20939</desc> <desc class="x centered">36.6916666667</desc> <desc class="y centered">525.083756641</desc> <desc class="x_label">Jan</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="0.641037397199" rx="0" ry="0" width="38.3973333333" x="67.0763333333" y="528.974347218"></rect> <desc class="value">1481</desc> <desc class="x centered">86.275</desc> <desc class="y centered">529.294865917</desc> <desc class="x_label">Feb</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="0.712023307489" rx="0" ry="0" width="38.3973333333" x="116.659666667" y="528.903361308"></rect> <desc class="value">1645</desc> <desc class="x centered">135.858333333</desc> <desc class="y centered">529.259372962</desc> <desc class="x_label">Mar</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="16.8548252849" rx="0" ry="0" width="38.3973333333" x="166.243" y="512.76055933"></rect> <desc class="value">38940</desc> <desc class="x centered">185.441666667</desc> <desc class="y centered">521.187971973</desc> <desc class="x_label">Apr</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="306.558280522" rx="0" ry="0" width="38.3973333333" x="215.826333333" y="223.057104093"></rect> <desc class="value">708247</desc> <desc class="x centered">235.025</desc> <desc class="y centered">376.336244354</desc> <desc class="x_label">Mai</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="347.634017808" rx="0" ry="0" width="38.3973333333" x="265.409666667" y="181.981366808"></rect> <desc class="value">803145</desc> <desc class="x centered">284.608333333</desc> <desc class="y centered">355.798375712</desc> <desc class="x_label">Jun</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="269.902714676" rx="0" ry="0" width="38.3973333333" x="314.993" y="259.71266994"></rect> <desc class="value">623561</desc> <desc class="x centered">334.191666667</desc> <desc class="y centered">394.664027278</desc> <desc class="x_label">Jul</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="219.651182804" rx="0" ry="0" width="38.3973333333" x="364.576333333" y="309.964201812"></rect> <desc class="value">507464</desc> <desc class="x centered">383.775</desc> <desc class="y centered">419.789793214</desc> <desc class="x_label">Aug</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="199.003805409" rx="0" ry="0" width="38.3973333333" x="414.159666667" y="330.611579206"></rect> <desc class="value">459762</desc> <desc class="x centered">433.358333333</desc> <desc class="y centered">430.113481911</desc> <desc class="x_label">Sep</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="248.450253177" rx="0" ry="0" width="38.3973333333" x="463.743" y="281.165131439"></rect> <desc class="value">573999</desc> <desc class="x centered">482.941666667</desc> <desc class="y centered">405.390258027</desc> <desc class="x_label">Okt</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="414.859406217" rx="0" ry="0" width="38.3973333333" x="513.326333333" y="114.755978399"></rect> <desc class="value">958457</desc> <desc class="x centered">532.525</desc> <desc class="y centered">322.185681507</desc> <desc class="x_label">Nov</desc> </g> <g class="bar"> <rect class="rect reactive tooltip-trigger" height="519.230769231" rx="0" ry="0" width="38.3973333333" x="562.909666667" y="10.3846153846"></rect> <desc class="value">1199588</desc> <desc class="x centered">582.108333333</desc> <desc class="y centered">270.0</desc> <desc class="x_label">Dez</desc> </g> </g> </g> </g> <g class="titles"></g> <g class="plot overlay" transform="translate(161, 20)"> <g class="series serie-0 color-0"></g> </g> <g class="plot text-overlay" transform="translate(161, 20)"> <g class="series serie-0 color-0"></g> </g> <g class="plot tooltip-overlay" transform="translate(161, 20)"> <g class="tooltip" style="opacity: 0" transform="translate(0 0)"> <rect class="tooltip-box" height="0" rx="0" ry="0" width="0"></rect> <g class="text"></g> </g> </g> <g class="legends" transform="translate(10, 30)"> <g class="legend reactive activate-serie" id="activate-serie-0"> <rect class="color-0 reactive" height="12" width="12" x="0.0" y="1.0"></rect> <text x="17.0" y="11.2">In & Out</text> </g> </g> <g class="legends" transform="translate(790, 30)"></g> </g> </svg> |
|
\ No newline at end of file |
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
| @@ -0,0 +1,49 @@ | ||
| 1 | +<?xml version="1.0" encoding="UTF-8"?> |
|
| 2 | +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 400" preserveAspectRatio="xMidYMid slice"> |
|
| 3 | +<defs> |
|
| 4 | +<linearGradient id="bg" x1="0" y1="0" x2="0" y2="1"> |
|
| 5 | +<stop offset="0%" stop-color="#1f1f1f"/> |
|
| 6 | +<stop offset="100%" stop-color="#0e0e0e"/> |
|
| 7 | +</linearGradient> |
|
| 8 | +<linearGradient id="fig" x1="0" y1="0" x2="0" y2="1"> |
|
| 9 | +<stop offset="0%" stop-color="#f37021"/> |
|
| 10 | +<stop offset="100%" stop-color="#c5571a"/> |
|
| 11 | +</linearGradient> |
|
| 12 | +<linearGradient id="accent" x1="0" y1="0" x2="1" y2="0"> |
|
| 13 | +<stop offset="0%" stop-color="#f37021"/> |
|
| 14 | +<stop offset="50%" stop-color="#ff7a2a"/> |
|
| 15 | +<stop offset="100%" stop-color="#f37021"/> |
|
| 16 | +</linearGradient> |
|
| 17 | +</defs> |
|
| 18 | + | |
| 19 | +<!-- Hintergrund --> |
|
| 20 | +<rect width="400" height="400" fill="url(#bg)"/> |
|
| 21 | + | |
| 22 | +<!-- EHC Kicker oben --> |
|
| 23 | +<text x="200" y="40" text-anchor="middle" |
|
| 24 | +font-family="Segoe UI, Tahoma, sans-serif" |
|
| 25 | +font-size="15" font-weight="700" |
|
| 26 | +letter-spacing="6" fill="#ffffff" opacity="0.55">EHC</text> |
|
| 27 | + | |
| 28 | +<!-- Personen-Silhouette (mittig, etwas kompakter) --> |
|
| 29 | +<circle cx="200" cy="130" r="46" fill="url(#fig)" opacity="0.88"/> |
|
| 30 | +<path d="M 200 188 C 152 188, 118 226, 118 295 L 282 295 C 282 226, 248 188, 200 188 Z" |
|
| 31 | +fill="url(#fig)" opacity="0.88"/> |
|
| 32 | + | |
| 33 | +<!-- Schwungvoller Pinselstrich als Trenner --> |
|
| 34 | +<path d="M 70 322 Q 200 308, 330 322" |
|
| 35 | +stroke="url(#accent)" stroke-width="3" |
|
| 36 | +fill="none" stroke-linecap="round" opacity="0.8"/> |
|
| 37 | + | |
| 38 | +<!-- "WE ARE" Subtext --> |
|
| 39 | +<text x="200" y="352" text-anchor="middle" |
|
| 40 | +font-family="Georgia, 'Times New Roman', serif" |
|
| 41 | +font-size="13" font-weight="700" |
|
| 42 | +letter-spacing="6" fill="#ffffff" opacity="0.6">WE ARE</text> |
|
| 43 | + | |
| 44 | +<!-- "FAMILY" Hauptzeile mit Gradient --> |
|
| 45 | +<text x="200" y="388" text-anchor="middle" |
|
| 46 | +font-family="Georgia, 'Times New Roman', serif" |
|
| 47 | +font-style="italic" font-size="30" font-weight="900" |
|
| 48 | +letter-spacing="2" fill="url(#accent)">FAMILY</text> |
|
| 49 | +</svg> |
Binärdatei – kein Textvergleich möglich.
Binärdatei – kein Textvergleich möglich.
| @@ -0,0 +1,888 @@ | ||
| 1 | +/* ============================================================ |
|
| 2 | +EHC Essen (Ruhr) e.V. — Quilldrop Theme |
|
| 3 | +============================================================ */ |
|
| 4 | + | |
| 5 | +*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } |
|
| 6 | + | |
| 7 | +:root { |
|
| 8 | +--orange: #f37021; |
|
| 9 | +--orange-bright: #ff7a2a; |
|
| 10 | +--orange-dark: #c5571a; |
|
| 11 | +--black: #0a0a0a; |
|
| 12 | +--dark: #141414; |
|
| 13 | +--gray-mid: #2a2a2a; |
|
| 14 | +--gray-light: #b8b8b8; |
|
| 15 | +--silver: #d8d8d8; |
|
| 16 | +--white: #ffffff; |
|
| 17 | + | |
| 18 | +--corner-img-w: 160px; |
|
| 19 | +--content-right-pad: 220px; |
|
| 20 | +--content-max: 1400px; |
|
| 21 | +} |
|
| 22 | + | |
| 23 | +html { height: 100%; } |
|
| 24 | + | |
| 25 | +body { |
|
| 26 | +min-height: 100vh; |
|
| 27 | +font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; |
|
| 28 | +color: var(--white); |
|
| 29 | +line-height: 1.65; |
|
| 30 | +background: var(--black); |
|
| 31 | +position: relative; |
|
| 32 | +display: flex; |
|
| 33 | +flex-direction: column; |
|
| 34 | +} |
|
| 35 | + | |
| 36 | +a { color: #ff4c00; text-decoration: none; transition: color 0.2s ease; } |
|
| 37 | +a:hover { color: var(--orange-bright); } |
|
| 38 | + | |
| 39 | +img { max-width: 100%; height: auto; display: block; } |
|
| 40 | + | |
| 41 | +/* ====== Fixierter Hintergrund + Overlay ====== */ |
|
| 42 | +.bg-fixed { |
|
| 43 | +position: fixed; inset: 0; z-index: -2; |
|
| 44 | + background-image: url('/images/ehc/ehc-steelers-bg.webp'); |
|
| 45 | +background-size: cover; background-position: center; |
|
| 46 | +background-repeat: no-repeat; pointer-events: none; |
|
| 47 | +} |
|
| 48 | +.bg-overlay { |
|
| 49 | +position: fixed; inset: 0; z-index: -1; |
|
| 50 | +background: linear-gradient(180deg, rgba(0,0,0,0.25) 0%, rgba(0,0,0,0.45) 100%); |
|
| 51 | +pointer-events: none; |
|
| 52 | +} |
|
| 53 | + | |
| 54 | +/* ====== NAVBAR ====== */ |
|
| 55 | +.navbar { |
|
| 56 | +position: sticky; top: 0; z-index: 100; |
|
| 57 | +background: linear-gradient(180deg, rgba(10,10,10,0.95) 0%, rgba(20,20,20,0.92) 100%); |
|
| 58 | +border-bottom: 3px solid #ff4c00; |
|
| 59 | +box-shadow: 0 6px 20px rgba(0,0,0,0.6); |
|
| 60 | +backdrop-filter: blur(6px); |
|
| 61 | +-webkit-backdrop-filter: blur(6px); |
|
| 62 | +} |
|
| 63 | +.nav-inner { |
|
| 64 | +max-width: var(--content-max); |
|
| 65 | +margin: 0 auto; |
|
| 66 | +padding: 12px 30px; |
|
| 67 | +display: flex; align-items: center; |
|
| 68 | +justify-content: space-between; |
|
| 69 | +gap: 30px; |
|
| 70 | +} |
|
| 71 | +.nav-brand { |
|
| 72 | +display: flex; align-items: center; gap: 14px; |
|
| 73 | +text-decoration: none; color: var(--white); |
|
| 74 | +} |
|
| 75 | +.nav-brand img { |
|
| 76 | +height: 64px; width: auto; |
|
| 77 | +filter: drop-shadow(0 4px 8px rgba(0,0,0,0.6)); |
|
| 78 | +} |
|
| 79 | +.nav-brand-text { display: flex; flex-direction: column; line-height: 1.1; } |
|
| 80 | +.nav-brand-text .name { |
|
| 81 | +font-size: 1.15rem; font-weight: 800; letter-spacing: 1.2px; |
|
| 82 | +text-transform: uppercase; color: var(--white); |
|
| 83 | +} |
|
| 84 | +.nav-brand-text .sub { |
|
| 85 | +font-size: 0.72rem; letter-spacing: 3px; color: #ff4c00; |
|
| 86 | +text-transform: uppercase; font-weight: 600; |
|
| 87 | +} |
|
| 88 | +.nav-brand:hover .nav-brand-text .name { color: #ff4c00; } |
|
| 89 | + | |
| 90 | +/* Nav links */ |
|
| 91 | +.nav-links { |
|
| 92 | +display: flex; align-items: center; |
|
| 93 | +gap: 4px; list-style: none; |
|
| 94 | +} |
|
| 95 | +.nav-links > a, |
|
| 96 | +.nav-links .nav-dropdown > .nav-dropdown-toggle { |
|
| 97 | +display: inline-flex; align-items: center; gap: 6px; |
|
| 98 | +padding: 14px 18px; |
|
| 99 | +color: var(--white); text-decoration: none; |
|
| 100 | +font-size: 0.95rem; font-weight: 700; |
|
| 101 | +text-transform: uppercase; letter-spacing: 1.5px; |
|
| 102 | +border-radius: 4px; transition: all 0.25s ease; |
|
| 103 | +position: relative; |
|
| 104 | +background: transparent; border: none; cursor: pointer; |
|
| 105 | +font-family: inherit; |
|
| 106 | +} |
|
| 107 | +.nav-links > a::after, |
|
| 108 | +.nav-links .nav-dropdown > .nav-dropdown-toggle::after { |
|
| 109 | +content: ""; position: absolute; |
|
| 110 | +left: 18px; right: 18px; bottom: 8px; |
|
| 111 | +height: 2px; background: #ff4c00; |
|
| 112 | +transform: scaleX(0); transform-origin: left; |
|
| 113 | +transition: transform 0.3s ease; |
|
| 114 | +} |
|
| 115 | +.nav-links > a:hover, |
|
| 116 | +.nav-links .nav-dropdown:hover > .nav-dropdown-toggle, |
|
| 117 | +.nav-links .nav-dropdown.open > .nav-dropdown-toggle { |
|
| 118 | +color: #ff4c00; background: rgba(243, 112, 33, 0.08); |
|
| 119 | +} |
|
| 120 | +.nav-links > a:hover::after, |
|
| 121 | +.nav-links .nav-dropdown:hover > .nav-dropdown-toggle::after, |
|
| 122 | +.nav-links .nav-dropdown.open > .nav-dropdown-toggle::after { |
|
| 123 | +transform: scaleX(1); |
|
| 124 | +} |
|
| 125 | + | |
| 126 | +/* Dropdown */ |
|
| 127 | +.nav-dropdown { position: relative; } |
|
| 128 | +.nav-dropdown-menu { |
|
| 129 | +position: absolute; top: 100%; left: 0; |
|
| 130 | +min-width: 220px; |
|
| 131 | +background: rgba(15, 15, 15, 0.98); |
|
| 132 | +border: 1px solid rgba(243, 112, 33, 0.4); |
|
| 133 | +border-top: 3px solid #ff4c00; |
|
| 134 | +padding: 8px 0; |
|
| 135 | +opacity: 0; visibility: hidden; |
|
| 136 | +transform: translateY(8px); |
|
| 137 | +transition: opacity 0.2s ease, transform 0.2s ease, visibility 0.2s; |
|
| 138 | +box-shadow: 0 10px 30px rgba(0,0,0,0.7); |
|
| 139 | +} |
|
| 140 | +.nav-dropdown:hover > .nav-dropdown-menu, |
|
| 141 | +.nav-dropdown.open > .nav-dropdown-menu { |
|
| 142 | +opacity: 1; visibility: visible; transform: translateY(0); |
|
| 143 | +} |
|
| 144 | +/* letztes Item: nach links öffnen, damit es nicht aus der Seite ragt */ |
|
| 145 | +.nav-links > .nav-dropdown:last-of-type > .nav-dropdown-menu { left: auto; right: 0; } |
|
| 146 | + | |
| 147 | +.nav-dropdown-menu a { |
|
| 148 | +display: block; padding: 10px 20px; |
|
| 149 | +color: var(--silver); text-decoration: none; |
|
| 150 | +font-size: 0.85rem; text-transform: uppercase; |
|
| 151 | +letter-spacing: 1px; font-weight: 600; |
|
| 152 | +border-left: 3px solid transparent; |
|
| 153 | +transition: all 0.2s ease; |
|
| 154 | +} |
|
| 155 | +.nav-dropdown-menu a:hover { |
|
| 156 | +color: var(--white); background: rgba(243, 112, 33, 0.15); |
|
| 157 | +border-left-color: #ff4c00; padding-left: 26px; |
|
| 158 | +} |
|
| 159 | + | |
| 160 | +/* Search + RSS */ |
|
| 161 | +.search-container { position: relative; } |
|
| 162 | +.search-toggle, .nav-rss { |
|
| 163 | +width: 36px; height: 36px; |
|
| 164 | +display: inline-flex; align-items: center; justify-content: center; |
|
| 165 | +background: rgba(255,255,255,0.05); |
|
| 166 | +border: 1px solid rgba(243, 112, 33, 0.25); |
|
| 167 | +border-radius: 50%; |
|
| 168 | +color: var(--silver); cursor: pointer; |
|
| 169 | +transition: all 0.2s ease; |
|
| 170 | +text-decoration: none; |
|
| 171 | +} |
|
| 172 | +.search-toggle:hover, .nav-rss:hover { |
|
| 173 | +color: #ff4c00; border-color: #ff4c00; |
|
| 174 | +background: rgba(243, 112, 33, 0.1); |
|
| 175 | +} |
|
| 176 | +.search-box { |
|
| 177 | +position: absolute; top: calc(100% + 8px); right: 0; |
|
| 178 | +width: 320px; |
|
| 179 | +background: rgba(15, 15, 15, 0.98); |
|
| 180 | +border: 1px solid rgba(243, 112, 33, 0.4); |
|
| 181 | +border-top: 3px solid #ff4c00; |
|
| 182 | +border-radius: 4px; |
|
| 183 | +padding: 12px; |
|
| 184 | +opacity: 0; visibility: hidden; |
|
| 185 | +transform: translateY(8px); |
|
| 186 | +transition: opacity 0.2s, transform 0.2s, visibility 0.2s; |
|
| 187 | +box-shadow: 0 10px 30px rgba(0,0,0,0.7); |
|
| 188 | +} |
|
| 189 | +.search-container.active .search-box { |
|
| 190 | +opacity: 1; visibility: visible; transform: translateY(0); |
|
| 191 | +} |
|
| 192 | +.search-box input { |
|
| 193 | +width: 100%; padding: 8px 12px; |
|
| 194 | +background: rgba(0,0,0,0.4); |
|
| 195 | +border: 1px solid rgba(243, 112, 33, 0.3); |
|
| 196 | +border-radius: 4px; |
|
| 197 | +color: var(--white); |
|
| 198 | +font-family: inherit; font-size: 0.95rem; |
|
| 199 | +} |
|
| 200 | +.search-box input:focus { outline: none; border-color: #ff4c00; } |
|
| 201 | +.search-results { margin-top: 8px; max-height: 60vh; overflow-y: auto; } |
|
| 202 | +.search-results a { |
|
| 203 | +display: block; padding: 8px 10px; |
|
| 204 | +color: var(--silver); border-radius: 4px; |
|
| 205 | +font-size: 0.88rem; |
|
| 206 | +} |
|
| 207 | +.search-results a:hover { background: rgba(243, 112, 33, 0.1); color: var(--white); } |
|
| 208 | +.search-results .search-result-title { color: var(--white); font-weight: 600; display: block; } |
|
| 209 | +.search-results .search-result-snippet { color: var(--gray-light); font-size: 0.8rem; display: block; margin-top: 2px; } |
|
| 210 | + | |
| 211 | +/* Hamburger (mobile) */ |
|
| 212 | +.hamburger { display: none; background: transparent; border: none; cursor: pointer; padding: 8px; } |
|
| 213 | +.hamburger span { |
|
| 214 | +display: block; width: 24px; height: 2px; |
|
| 215 | +background: var(--white); margin: 5px 0; |
|
| 216 | +transition: all 0.3s ease; |
|
| 217 | +} |
|
| 218 | +.hamburger.active span:nth-child(1) { transform: translateY(7px) rotate(45deg); } |
|
| 219 | +.hamburger.active span:nth-child(2) { opacity: 0; } |
|
| 220 | +.hamburger.active span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); } |
|
| 221 | + | |
| 222 | +/* ====== MAIN / CONTAINER ====== */ |
|
| 223 | +.container { |
|
| 224 | +max-width: var(--content-max); |
|
| 225 | +margin: 0 auto; |
|
| 226 | +padding: 40px 30px 60px; |
|
| 227 | +padding-right: var(--content-right-pad); |
|
| 228 | +flex: 1; |
|
| 229 | +width: 100%; |
|
| 230 | +} |
|
| 231 | + | |
| 232 | +/* ====== HERO (Homepage) ====== */ |
|
| 233 | +.hero-image { |
|
| 234 | +margin-bottom: 32px; |
|
| 235 | +border-radius: 12px; |
|
| 236 | +overflow: hidden; |
|
| 237 | +box-shadow: 0 0 0 2px rgba(243, 112, 33, 0.7), 0 20px 60px rgba(0,0,0,0.7); |
|
| 238 | +position: relative; |
|
| 239 | +} |
|
| 240 | +.hero-image img { width: 100%; display: block; } |
|
| 241 | +.hero-image::after { |
|
| 242 | +content: ""; position: absolute; inset: 0; |
|
| 243 | +background: linear-gradient(180deg, rgba(0,0,0,0) 60%, rgba(0,0,0,0.4) 100%); |
|
| 244 | +pointer-events: none; |
|
| 245 | +} |
|
| 246 | + | |
| 247 | +/* ====== Sektionen ====== */ |
|
| 248 | +.section { |
|
| 249 | +background: rgba(15, 15, 15, 0.78); |
|
| 250 | +border: 1px solid rgba(255,255,255,0.06); |
|
| 251 | +border-radius: 10px; |
|
| 252 | +padding: 32px 36px; |
|
| 253 | +margin-bottom: 28px; |
|
| 254 | +box-shadow: 0 8px 30px rgba(0,0,0,0.5); |
|
| 255 | +backdrop-filter: blur(4px); |
|
| 256 | +} |
|
| 257 | +.section h2 { |
|
| 258 | +font-size: 1.8rem; |
|
| 259 | +text-transform: uppercase; letter-spacing: 2px; |
|
| 260 | +color: var(--white); |
|
| 261 | +margin-bottom: 0; |
|
| 262 | +padding-bottom: 12px; |
|
| 263 | +border-bottom: 2px solid #ff4c00; |
|
| 264 | +display: inline-block; |
|
| 265 | +} |
|
| 266 | +.section h2:not(.no-margin) { margin-bottom: 18px; } |
|
| 267 | +.section p { color: var(--gray-light); margin-bottom: 12px; } |
|
| 268 | + | |
| 269 | +.section-head { |
|
| 270 | +display: flex; align-items: flex-end; justify-content: space-between; |
|
| 271 | +gap: 20px; margin-bottom: 18px; flex-wrap: wrap; |
|
| 272 | +} |
|
| 273 | +.section-head h2 { margin-bottom: 0; } |
|
| 274 | +.all-link { |
|
| 275 | +color: #ff4c00; text-decoration: none; |
|
| 276 | +font-size: 0.9rem; font-weight: 700; |
|
| 277 | +letter-spacing: 1.5px; text-transform: uppercase; |
|
| 278 | +padding-bottom: 4px; |
|
| 279 | +transition: color 0.2s ease, transform 0.2s ease; |
|
| 280 | +} |
|
| 281 | +.all-link:hover { color: var(--orange-bright); transform: translateX(3px); } |
|
| 282 | + | |
| 283 | +/* ====== Partner Karussell ====== */ |
|
| 284 | +.partner-section { |
|
| 285 | +background: rgba(15, 15, 15, 0.78); |
|
| 286 | +border: 1px solid rgba(255,255,255,0.06); |
|
| 287 | +border-radius: 10px; |
|
| 288 | +padding: 32px 36px; |
|
| 289 | +margin-bottom: 28px; |
|
| 290 | +box-shadow: 0 8px 30px rgba(0,0,0,0.5); |
|
| 291 | +backdrop-filter: blur(4px); |
|
| 292 | +} |
|
| 293 | +.carousel { position: relative; overflow: hidden; padding: 10px 0; } |
|
| 294 | +.carousel-track { display: flex; transition: transform 0.7s cubic-bezier(0.4, 0, 0.2, 1); will-change: transform; } |
|
| 295 | +.carousel-slide { |
|
| 296 | +flex: 0 0 calc(100% / 3); |
|
| 297 | +padding: 0 14px; |
|
| 298 | +display: flex; align-items: center; justify-content: center; |
|
| 299 | +} |
|
| 300 | +.partner-link { display: block; width: 100%; text-decoration: none; } |
|
| 301 | +.partner-card { |
|
| 302 | +width: 100%; height: 140px; |
|
| 303 | +background: var(--white); |
|
| 304 | +border-radius: 8px; |
|
| 305 | +display: flex; align-items: center; justify-content: center; |
|
| 306 | +padding: 18px; |
|
| 307 | +box-shadow: 0 6px 16px rgba(0,0,0,0.4); |
|
| 308 | +transition: transform 0.3s ease, box-shadow 0.3s ease; |
|
| 309 | +} |
|
| 310 | +.partner-card:hover { |
|
| 311 | +transform: translateY(-4px); |
|
| 312 | +box-shadow: 0 12px 24px rgba(243, 112, 33, 0.25); |
|
| 313 | +} |
|
| 314 | +.partner-card img { max-width: 100%; max-height: 100%; object-fit: contain; } |
|
| 315 | +.carousel-dots { display: flex; justify-content: center; gap: 8px; margin-top: 20px; } |
|
| 316 | +.carousel-dot { |
|
| 317 | +width: 10px; height: 10px; border-radius: 50%; |
|
| 318 | +background: rgba(255,255,255,0.25); |
|
| 319 | +border: none; cursor: pointer; padding: 0; |
|
| 320 | +transition: all 0.25s ease; |
|
| 321 | +} |
|
| 322 | +.carousel-dot.active { background: #ff4c00; transform: scale(1.3); } |
|
| 323 | + | |
| 324 | +/* ====== Post-Liste / News-Karten ====== */ |
|
| 325 | +.post-list { |
|
| 326 | +display: grid; |
|
| 327 | +grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); |
|
| 328 | +gap: 24px; |
|
| 329 | +} |
|
| 330 | +.post-card { |
|
| 331 | +background: rgba(0,0,0,0.55); |
|
| 332 | +border: 1px solid rgba(243, 112, 33, 0.25); |
|
| 333 | +border-radius: 8px; |
|
| 334 | +overflow: hidden; |
|
| 335 | +display: flex; flex-direction: column; |
|
| 336 | +transition: transform 0.25s ease, border-color 0.25s ease, box-shadow 0.25s ease; |
|
| 337 | +} |
|
| 338 | +.post-card:hover { |
|
| 339 | +border-color: #ff4c00; |
|
| 340 | +transform: translateY(-4px); |
|
| 341 | +box-shadow: 0 12px 28px rgba(243, 112, 33, 0.18); |
|
| 342 | +} |
|
| 343 | +.post-card-cover { |
|
| 344 | +display: block; |
|
| 345 | +aspect-ratio: 16 / 10; |
|
| 346 | +overflow: hidden; |
|
| 347 | +background: #1a1a1a; |
|
| 348 | +} |
|
| 349 | +.post-card-cover img { |
|
| 350 | +width: 100%; height: 100%; |
|
| 351 | +object-fit: cover; |
|
| 352 | +transition: transform 0.5s ease; |
|
| 353 | +} |
|
| 354 | +.post-card:hover .post-card-cover img { transform: scale(1.05); } |
|
| 355 | +.post-card-body { |
|
| 356 | +padding: 20px 22px 22px; |
|
| 357 | +display: flex; flex-direction: column; gap: 10px; |
|
| 358 | +flex: 1; |
|
| 359 | +} |
|
| 360 | +.post-card-meta { |
|
| 361 | +display: flex; align-items: center; justify-content: space-between; |
|
| 362 | +gap: 10px; flex-wrap: wrap; |
|
| 363 | +} |
|
| 364 | +.post-card-meta time { |
|
| 365 | +color: #ff4c00; |
|
| 366 | +font-size: 0.75rem; font-weight: 700; |
|
| 367 | +letter-spacing: 1.8px; text-transform: uppercase; |
|
| 368 | +} |
|
| 369 | +.post-card-title { margin: 0; } |
|
| 370 | +.post-card-title a { |
|
| 371 | +color: var(--white); text-decoration: none; |
|
| 372 | +font-size: 1.1rem; font-weight: 800; line-height: 1.3; |
|
| 373 | +} |
|
| 374 | +.post-card-title a:hover { color: #ff4c00; } |
|
| 375 | +.post-card-preview { color: var(--gray-light); font-size: 0.92rem; flex: 1; margin: 0; } |
|
| 376 | +.read-more { |
|
| 377 | +color: #ff4c00; text-decoration: none; |
|
| 378 | +font-size: 0.78rem; font-weight: 700; |
|
| 379 | +letter-spacing: 1.5px; text-transform: uppercase; |
|
| 380 | +margin-top: 4px; padding-top: 10px; |
|
| 381 | +border-top: 1px solid rgba(243, 112, 33, 0.2); |
|
| 382 | +} |
|
| 383 | +.post-card:hover .read-more { color: var(--orange-bright); } |
|
| 384 | + | |
| 385 | +/* Tags */ |
|
| 386 | +.post-tags { display: flex; flex-wrap: wrap; gap: 6px; } |
|
| 387 | +.tag { |
|
| 388 | +display: inline-block; |
|
| 389 | +padding: 3px 10px; |
|
| 390 | +background: rgba(243, 112, 33, 0.1); |
|
| 391 | +border: 1px solid rgba(243, 112, 33, 0.35); |
|
| 392 | +border-radius: 12px; |
|
| 393 | +color: #ff4c00; |
|
| 394 | +font-size: 0.7rem; font-weight: 700; |
|
| 395 | +letter-spacing: 0.5px; text-transform: uppercase; |
|
| 396 | +text-decoration: none; |
|
| 397 | +transition: all 0.2s ease; |
|
| 398 | +} |
|
| 399 | +.tag:hover { background: rgba(243, 112, 33, 0.2); color: var(--orange-bright); } |
|
| 400 | +.tag-large { |
|
| 401 | +font-size: 0.95rem; |
|
| 402 | +padding: 8px 16px; |
|
| 403 | +border-radius: 20px; |
|
| 404 | +} |
|
| 405 | +.tag-count { |
|
| 406 | +margin-left: 6px; |
|
| 407 | +padding: 1px 8px; |
|
| 408 | +background: rgba(243, 112, 33, 0.3); |
|
| 409 | +border-radius: 10px; |
|
| 410 | +font-size: 0.75rem; |
|
| 411 | +} |
|
| 412 | + | |
| 413 | +/* ====== Single Post ====== */ |
|
| 414 | +.post-single, .page-single { |
|
| 415 | +background: rgba(15, 15, 15, 0.82); |
|
| 416 | +border: 1px solid rgba(255,255,255,0.06); |
|
| 417 | +border-radius: 10px; |
|
| 418 | +padding: 36px 40px; |
|
| 419 | +box-shadow: 0 8px 30px rgba(0,0,0,0.5); |
|
| 420 | +backdrop-filter: blur(4px); |
|
| 421 | +} |
|
| 422 | +.post-header { margin-bottom: 26px; padding-bottom: 14px; border-bottom: 2px solid #ff4c00; } |
|
| 423 | +.post-header-meta { |
|
| 424 | +display: flex; gap: 16px; |
|
| 425 | +color: #ff4c00; |
|
| 426 | +font-size: 0.85rem; font-weight: 700; |
|
| 427 | +letter-spacing: 2px; text-transform: uppercase; |
|
| 428 | +margin-bottom: 10px; |
|
| 429 | +} |
|
| 430 | +.post-title, .page-title { |
|
| 431 | +font-size: 2.2rem; |
|
| 432 | +color: var(--white); |
|
| 433 | +line-height: 1.25; |
|
| 434 | +font-weight: 800; |
|
| 435 | +text-transform: uppercase; |
|
| 436 | +letter-spacing: 3px; |
|
| 437 | +margin-bottom: 14px; |
|
| 438 | +} |
|
| 439 | +.post-cover { |
|
| 440 | +margin: 0 0 28px; |
|
| 441 | +border-radius: 10px; |
|
| 442 | +overflow: hidden; |
|
| 443 | +border: 2px solid rgba(243, 112, 33, 0.7); |
|
| 444 | +box-shadow: 0 12px 36px rgba(0,0,0,0.6); |
|
| 445 | +} |
|
| 446 | +.post-cover img { width: 100%; } |
|
| 447 | +.page-header { margin-bottom: 26px; padding-bottom: 14px; border-bottom: 2px solid #ff4c00; } |
|
| 448 | + | |
| 449 | +/* TOC */ |
|
| 450 | +.toc { |
|
| 451 | +background: rgba(0,0,0,0.35); |
|
| 452 | +border: 1px dashed rgba(243, 112, 33, 0.35); |
|
| 453 | +border-radius: 6px; |
|
| 454 | +padding: 18px 22px; |
|
| 455 | +margin-bottom: 28px; |
|
| 456 | +} |
|
| 457 | +.toc h3 { |
|
| 458 | +color: #ff4c00; font-size: 0.85rem; |
|
| 459 | +text-transform: uppercase; letter-spacing: 2px; |
|
| 460 | +font-weight: 700; margin-bottom: 10px; |
|
| 461 | +} |
|
| 462 | +.toc ul { list-style: none; padding: 0; margin: 0; } |
|
| 463 | +.toc li { margin: 4px 0; } |
|
| 464 | +.toc li a { color: var(--silver); font-size: 0.92rem; } |
|
| 465 | +.toc li a:hover { color: var(--orange-bright); } |
|
| 466 | +.toc .toc-level-1 { padding-left: 16px; } |
|
| 467 | +.toc .toc-level-2 { padding-left: 32px; } |
|
| 468 | +.toc .toc-level-3 { padding-left: 48px; } |
|
| 469 | + | |
| 470 | +/* ============================================================ |
|
| 471 | +Markdown-Content |
|
| 472 | +------------------------------------------------------------ |
|
| 473 | +Alle Selektoren nutzen :where(.post-content), damit ihre |
|
| 474 | +Spezifität bei (0,0,X) bleibt – jede Widget-Klasse (board-card, |
|
| 475 | +partner-tile etc.) gewinnt damit automatisch und Markdown-Regeln |
|
| 476 | +verirren sich nicht in eingebettete HTML-Komponenten. |
|
| 477 | +============================================================ */ |
|
| 478 | +.post-content { color: var(--gray-light); font-size: 1.02rem; line-height: 1.75; } |
|
| 479 | + | |
| 480 | +:where(.post-content) h1, |
|
| 481 | +:where(.post-content) h2, |
|
| 482 | +:where(.post-content) h3, |
|
| 483 | +:where(.post-content) h4 { |
|
| 484 | +color: var(--white); |
|
| 485 | +margin: 28px 0 14px; |
|
| 486 | +line-height: 1.3; |
|
| 487 | +} |
|
| 488 | +:where(.post-content) h1 { font-size: 1.7rem; } |
|
| 489 | +:where(.post-content) h2 { |
|
| 490 | +font-size: 1.4rem; |
|
| 491 | +padding: 8px 14px; |
|
| 492 | +background: rgba(243, 112, 33, 0.12); |
|
| 493 | +border-left: 4px solid #ff4c00; |
|
| 494 | +} |
|
| 495 | +:where(.post-content) h3 { font-size: 1.15rem; color: #ff4c00; } |
|
| 496 | +:where(.post-content) h4 { font-size: 1.02rem; text-transform: uppercase; letter-spacing: 0.5px; } |
|
| 497 | +:where(.post-content) p { margin-bottom: 16px; } |
|
| 498 | +:where(.post-content) a { color: #ff4c00; } |
|
| 499 | +:where(.post-content) a:hover { color: var(--orange-bright); text-decoration: underline; } |
|
| 500 | +:where(.post-content) strong { color: var(--white); font-weight: 700; } |
|
| 501 | +:where(.post-content) ul, |
|
| 502 | +:where(.post-content) ol { margin: 10px 0 18px 22px; } |
|
| 503 | +:where(.post-content) li { margin-bottom: 6px; } |
|
| 504 | +:where(.post-content) li::marker { color: #ff4c00; } |
|
| 505 | +:where(.post-content) blockquote { |
|
| 506 | +margin: 18px 0; |
|
| 507 | +padding: 14px 20px; |
|
| 508 | +background: rgba(0,0,0,0.4); |
|
| 509 | +border-left: 4px solid #ff4c00; |
|
| 510 | +border-radius: 4px; |
|
| 511 | +color: var(--silver); |
|
| 512 | +font-style: italic; |
|
| 513 | +} |
|
| 514 | +:where(.post-content) code { |
|
| 515 | +background: rgba(0,0,0,0.5); |
|
| 516 | +padding: 2px 6px; |
|
| 517 | +border-radius: 4px; |
|
| 518 | +font-family: 'JetBrains Mono', Consolas, monospace; |
|
| 519 | +font-size: 0.9em; |
|
| 520 | +color: var(--orange-bright); |
|
| 521 | +border: 1px solid rgba(243, 112, 33, 0.2); |
|
| 522 | +} |
|
| 523 | +:where(.post-content) pre { |
|
| 524 | +background: rgba(0,0,0,0.6); |
|
| 525 | +border: 1px solid rgba(243, 112, 33, 0.2); |
|
| 526 | +border-radius: 6px; |
|
| 527 | +padding: 16px 18px; |
|
| 528 | +overflow-x: auto; |
|
| 529 | +margin: 16px 0; |
|
| 530 | +} |
|
| 531 | +:where(.post-content) pre code { |
|
| 532 | +background: transparent; |
|
| 533 | +border: none; |
|
| 534 | +padding: 0; |
|
| 535 | +color: var(--silver); |
|
| 536 | +} |
|
| 537 | +:where(.post-content) img { |
|
| 538 | +border-radius: 6px; |
|
| 539 | +margin: 16px 0; |
|
| 540 | +} |
|
| 541 | +:where(.post-content) table { |
|
| 542 | +border-collapse: collapse; |
|
| 543 | +margin: 16px 0; |
|
| 544 | +width: 100%; |
|
| 545 | +} |
|
| 546 | +:where(.post-content) th, |
|
| 547 | +:where(.post-content) td { |
|
| 548 | +border: 1px solid rgba(243, 112, 33, 0.2); |
|
| 549 | +padding: 8px 12px; |
|
| 550 | +text-align: left; |
|
| 551 | +} |
|
| 552 | +:where(.post-content) th { background: rgba(243, 112, 33, 0.12); color: var(--white); } |
|
| 553 | +.highlight { color: #ff4c00; } |
|
| 554 | + | |
| 555 | +/* Post navigation */ |
|
| 556 | +.post-nav { |
|
| 557 | +display: grid; grid-template-columns: 1fr 1fr; |
|
| 558 | +gap: 16px; margin: 36px 0 20px; |
|
| 559 | +} |
|
| 560 | +.post-nav-link { |
|
| 561 | +display: flex; flex-direction: column; gap: 4px; |
|
| 562 | +padding: 16px 18px; |
|
| 563 | +background: rgba(0,0,0,0.4); |
|
| 564 | +border: 1px solid rgba(243, 112, 33, 0.2); |
|
| 565 | +border-radius: 8px; |
|
| 566 | +text-decoration: none; |
|
| 567 | +transition: all 0.25s ease; |
|
| 568 | +color: inherit; |
|
| 569 | +} |
|
| 570 | +.post-nav-link:hover { border-color: #ff4c00; background: rgba(243, 112, 33, 0.08); } |
|
| 571 | +.post-nav-link.disabled { pointer-events: none; opacity: 0.4; } |
|
| 572 | +.post-nav-next { text-align: right; } |
|
| 573 | +.post-nav-label { |
|
| 574 | +color: #ff4c00; |
|
| 575 | +font-size: 0.75rem; font-weight: 700; |
|
| 576 | +letter-spacing: 1.5px; text-transform: uppercase; |
|
| 577 | +} |
|
| 578 | +.post-nav-title { color: var(--white); font-weight: 700; font-size: 0.95rem; } |
|
| 579 | + | |
| 580 | +.post-footer { margin-top: 20px; } |
|
| 581 | +.back-link { |
|
| 582 | +display: inline-block; |
|
| 583 | +color: #ff4c00; |
|
| 584 | +font-weight: 700; |
|
| 585 | +letter-spacing: 1.5px; |
|
| 586 | +text-transform: uppercase; |
|
| 587 | +font-size: 0.9rem; |
|
| 588 | +text-decoration: none; |
|
| 589 | +} |
|
| 590 | +.back-link:hover { color: var(--orange-bright); text-decoration: underline; } |
|
| 591 | + | |
| 592 | +/* ====== Tags-/Kategorien-Seiten ====== */ |
|
| 593 | +.tags-page, .tag-page { |
|
| 594 | +background: rgba(15, 15, 15, 0.82); |
|
| 595 | +border: 1px solid rgba(255,255,255,0.06); |
|
| 596 | +border-radius: 10px; |
|
| 597 | +padding: 36px 40px; |
|
| 598 | +box-shadow: 0 8px 30px rgba(0,0,0,0.5); |
|
| 599 | +backdrop-filter: blur(4px); |
|
| 600 | +} |
|
| 601 | +.tags-page h1, .tag-page h1 { |
|
| 602 | +font-size: 2rem; color: var(--white); |
|
| 603 | +margin-bottom: 24px; padding-bottom: 14px; |
|
| 604 | +border-bottom: 2px solid #ff4c00; |
|
| 605 | +display: inline-block; |
|
| 606 | +} |
|
| 607 | +.tags-cloud { display: flex; flex-wrap: wrap; gap: 10px; } |
|
| 608 | + | |
| 609 | +/* ====== Pagination ====== */ |
|
| 610 | +.pagination { |
|
| 611 | +display: flex; align-items: center; justify-content: center; |
|
| 612 | +gap: 14px; margin: 40px 0 20px; flex-wrap: wrap; |
|
| 613 | +} |
|
| 614 | +.pagination-btn, .pagination-num { |
|
| 615 | +display: inline-block; |
|
| 616 | +padding: 10px 18px; |
|
| 617 | +border: 1px solid rgba(243, 112, 33, 0.3); |
|
| 618 | +border-radius: 6px; |
|
| 619 | +color: var(--silver); text-decoration: none; |
|
| 620 | +font-size: 0.85rem; font-weight: 700; |
|
| 621 | +text-transform: uppercase; letter-spacing: 1px; |
|
| 622 | +transition: all 0.2s ease; |
|
| 623 | +} |
|
| 624 | +.pagination-btn:hover, .pagination-num:hover { |
|
| 625 | +border-color: #ff4c00; |
|
| 626 | +color: var(--white); |
|
| 627 | +background: rgba(243, 112, 33, 0.1); |
|
| 628 | +} |
|
| 629 | +.pagination-num.active { |
|
| 630 | +background: #ff4c00; |
|
| 631 | +color: var(--black); |
|
| 632 | +border-color: #ff4c00; |
|
| 633 | +} |
|
| 634 | +.pagination-btn.disabled { opacity: 0.35; pointer-events: none; } |
|
| 635 | +.pagination-pages { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; } |
|
| 636 | +.pagination-ellipsis { color: var(--gray-light); padding: 0 4px; } |
|
| 637 | + | |
| 638 | +/* ====== Fixed Corner ====== */ |
|
| 639 | +.corner-fixed { |
|
| 640 | +position: fixed; right: 20px; bottom: 20px; |
|
| 641 | +width: var(--corner-img-w); height: auto; |
|
| 642 | +z-index: 50; pointer-events: none; |
|
| 643 | +filter: drop-shadow(0 8px 24px rgba(0,0,0,0.85)); |
|
| 644 | +} |
|
| 645 | + | |
| 646 | +/* ====== Footer ====== */ |
|
| 647 | +.footer { |
|
| 648 | +background: rgba(5, 5, 5, 0.92); |
|
| 649 | +border-top: 3px solid #ff4c00; |
|
| 650 | +padding: 30px; |
|
| 651 | +text-align: center; |
|
| 652 | +color: var(--gray-light); |
|
| 653 | +font-size: 0.9rem; |
|
| 654 | +margin-top: 40px; |
|
| 655 | +} |
|
| 656 | +.footer-inner { |
|
| 657 | +max-width: var(--content-max); |
|
| 658 | +margin: 0 auto; |
|
| 659 | +padding-right: calc(var(--content-right-pad) - 30px); |
|
| 660 | +} |
|
| 661 | +.footer a { color: #ff4c00; margin: 0 8px; } |
|
| 662 | +.footer a:hover { color: var(--orange-bright); text-decoration: underline; } |
|
| 663 | + | |
| 664 | +/* ====== RESPONSIVE ====== */ |
|
| 665 | +@media (max-width: 1100px) { |
|
| 666 | + :root { --corner-img-w: 130px; --content-right-pad: 190px; } |
|
| 667 | +} |
|
| 668 | + | |
| 669 | +@media (max-width: 860px) { |
|
| 670 | + :root { --corner-img-w: 110px; --content-right-pad: 20px; } |
|
| 671 | + | |
| 672 | +/* Eckbild auf Mobile ausblenden – im engen Viewport würde es sonst |
|
| 673 | +die Karten/Texte rechts überlagern */ |
|
| 674 | + .corner-fixed { display: none; } |
|
| 675 | + | |
| 676 | + .nav-inner { padding: 10px 16px; flex-wrap: wrap; } |
|
| 677 | + .nav-brand img { height: 52px; } |
|
| 678 | + .nav-brand-text .name { font-size: 1rem; } |
|
| 679 | + | |
| 680 | + .hamburger { display: inline-block; } |
|
| 681 | + .nav-links { |
|
| 682 | +display: none; |
|
| 683 | +flex-direction: column; |
|
| 684 | +align-items: stretch; |
|
| 685 | +width: 100%; |
|
| 686 | +gap: 0; |
|
| 687 | +margin-top: 10px; |
|
| 688 | +padding-top: 10px; |
|
| 689 | +border-top: 1px solid rgba(243, 112, 33, 0.3); |
|
| 690 | +} |
|
| 691 | + .nav-links.open { display: flex; } |
|
| 692 | +.nav-links > a, |
|
| 693 | + .nav-links .nav-dropdown > .nav-dropdown-toggle { padding: 12px 14px; width: 100%; justify-content: space-between; } |
|
| 694 | + .nav-dropdown-menu { |
|
| 695 | +position: static; opacity: 1; visibility: hidden; |
|
| 696 | +transform: none; box-shadow: none; border: none; |
|
| 697 | +border-left: 3px solid #ff4c00; |
|
| 698 | +background: rgba(0,0,0,0.3); |
|
| 699 | +margin: 4px 0 8px 14px; |
|
| 700 | +padding: 4px 0; |
|
| 701 | +max-height: 0; |
|
| 702 | +overflow: hidden; |
|
| 703 | +transition: max-height 0.3s ease, visibility 0s linear 0.3s; |
|
| 704 | +} |
|
| 705 | + .nav-dropdown.open > .nav-dropdown-menu { |
|
| 706 | +visibility: visible; |
|
| 707 | +max-height: 400px; |
|
| 708 | +transition: max-height 0.3s ease, visibility 0s; |
|
| 709 | +} |
|
| 710 | + .nav-dropdown-menu a { padding: 8px 16px; } |
|
| 711 | + | |
| 712 | + .search-box { width: calc(100vw - 32px); right: -8px; } |
|
| 713 | + | |
| 714 | + .container { padding: 24px 16px 40px; } |
|
| 715 | + .section, .partner-section, .post-single, .page-single, .tags-page, .tag-page { padding: 22px 20px; } |
|
| 716 | + .post-title, .page-title { font-size: 1.5rem; } |
|
| 717 | + .section h2 { font-size: 1.4rem; } |
|
| 718 | + .carousel-slide { flex: 0 0 100%; } |
|
| 719 | + .post-nav { grid-template-columns: 1fr; } |
|
| 720 | +} |
|
| 721 | + | |
| 722 | +/* Eckbild ist auf ≤860 bereits ausgeblendet, daher hier nichts mehr nötig. */ |
|
| 723 | + | |
| 724 | +/* ====== Vorstand ====== */ |
|
| 725 | +.board-grid { |
|
| 726 | +display: grid; |
|
| 727 | +grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); |
|
| 728 | +gap: 26px; |
|
| 729 | +margin: 24px 0 8px; |
|
| 730 | +} |
|
| 731 | +.board-card { |
|
| 732 | +background: rgba(0, 0, 0, 0.5); |
|
| 733 | +border: 1px solid rgba(243, 112, 33, 0.2); |
|
| 734 | +border-radius: 12px; |
|
| 735 | +overflow: hidden; |
|
| 736 | +display: flex; |
|
| 737 | +flex-direction: column; |
|
| 738 | +transition: transform 0.25s ease, border-color 0.25s ease, box-shadow 0.25s ease; |
|
| 739 | +} |
|
| 740 | +.board-card:hover { |
|
| 741 | +transform: translateY(-4px); |
|
| 742 | +border-color: #ff4c00; |
|
| 743 | +box-shadow: 0 14px 30px rgba(243, 112, 33, 0.18); |
|
| 744 | +} |
|
| 745 | +.board-card .photo { |
|
| 746 | +width: 100%; |
|
| 747 | +height: 500px; |
|
| 748 | +aspect-ratio: 1 / 1; |
|
| 749 | +/* background: #1a1a1a; */ |
|
| 750 | +overflow: hidden; |
|
| 751 | +} |
|
| 752 | +.board-card .photo img { |
|
| 753 | +width: 100%; height: 100%; |
|
| 754 | +object-fit: cover; display: block; |
|
| 755 | +} |
|
| 756 | +.board-card .info { |
|
| 757 | +padding: 22px 24px 26px; |
|
| 758 | +display: flex; flex-direction: column; |
|
| 759 | +gap: 10px; flex: 1; |
|
| 760 | +} |
|
| 761 | +.board-card .role { |
|
| 762 | +color: #ff4c00; |
|
| 763 | +font-size: 0.78rem; font-weight: 700; |
|
| 764 | +text-transform: uppercase; letter-spacing: 2px; |
|
| 765 | +} |
|
| 766 | +.board-card .name { |
|
| 767 | +color: var(--white); |
|
| 768 | +font-size: 1.3rem; font-weight: 800; |
|
| 769 | +letter-spacing: 0.3px; |
|
| 770 | +margin: 0; |
|
| 771 | +/* Reset, falls die Karte als h2 in .post-content steht */ |
|
| 772 | +padding: 0; |
|
| 773 | +background: transparent; |
|
| 774 | +border: none; |
|
| 775 | +text-transform: none; |
|
| 776 | +} |
|
| 777 | +.board-card .email { |
|
| 778 | +margin-top: auto; |
|
| 779 | +display: inline-flex; align-items: center; gap: 8px; |
|
| 780 | +color: var(--silver); |
|
| 781 | +text-decoration: none; |
|
| 782 | +font-size: 0.95rem; |
|
| 783 | +word-break: break-all; |
|
| 784 | +padding-top: 12px; |
|
| 785 | +border-top: 1px solid rgba(243, 112, 33, 0.2); |
|
| 786 | +transition: color 0.2s ease; |
|
| 787 | +} |
|
| 788 | +.board-card .email:hover { color: var(--orange-bright); } |
|
| 789 | +.board-card .email::before { |
|
| 790 | +content: "✉"; |
|
| 791 | +color: #ff4c00; |
|
| 792 | +font-size: 1.05rem; |
|
| 793 | +flex-shrink: 0; |
|
| 794 | +} |
|
| 795 | + | |
| 796 | +/* ====== Impressum / Datenschutz Blöcke ====== */ |
|
| 797 | +.impressum-block { margin-bottom: 22px; } |
|
| 798 | +.impressum-block .label { |
|
| 799 | +color: #ff4c00; |
|
| 800 | +font-size: 0.9rem; font-weight: 700; |
|
| 801 | +text-transform: uppercase; letter-spacing: 1.5px; |
|
| 802 | +margin-bottom: 4px; |
|
| 803 | +} |
|
| 804 | +.address-block { |
|
| 805 | +background: rgba(0,0,0,0.4); |
|
| 806 | +border-left: 3px solid #ff4c00; |
|
| 807 | +padding: 14px 18px; |
|
| 808 | +margin: 10px 0 18px; |
|
| 809 | +border-radius: 4px; |
|
| 810 | +} |
|
| 811 | +.uppercase-notice { |
|
| 812 | +background: rgba(243, 112, 33, 0.06); |
|
| 813 | +border: 1px solid rgba(243, 112, 33, 0.3); |
|
| 814 | +border-radius: 6px; |
|
| 815 | +padding: 14px 18px; |
|
| 816 | +margin: 12px 0; |
|
| 817 | +color: var(--silver); |
|
| 818 | +font-size: 0.85rem; |
|
| 819 | +line-height: 1.55; |
|
| 820 | +text-transform: uppercase; |
|
| 821 | +letter-spacing: 0.4px; |
|
| 822 | +} |
|
| 823 | + | |
| 824 | +/* ====== Partner-Grid (Übersichtsseite) ====== */ |
|
| 825 | +.partner-grid { |
|
| 826 | +display: grid; |
|
| 827 | +grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); |
|
| 828 | +gap: 22px; |
|
| 829 | +margin: 20px 0 8px; |
|
| 830 | +} |
|
| 831 | +.partner-tile { |
|
| 832 | +background: rgba(0, 0, 0, 0.5); |
|
| 833 | +border: 1px solid rgba(243, 112, 33, 0.2); |
|
| 834 | +border-radius: 10px; |
|
| 835 | +overflow: hidden; |
|
| 836 | +display: flex; |
|
| 837 | +flex-direction: column; |
|
| 838 | +text-decoration: none; |
|
| 839 | +color: inherit; |
|
| 840 | +transition: transform 0.25s ease, border-color 0.25s ease, box-shadow 0.25s ease; |
|
| 841 | +} |
|
| 842 | +.partner-tile:hover { |
|
| 843 | +transform: translateY(-4px); |
|
| 844 | +border-color: #ff4c00; |
|
| 845 | +box-shadow: 0 12px 28px rgba(243, 112, 33, 0.18); |
|
| 846 | +} |
|
| 847 | +.partner-tile .logo { |
|
| 848 | +background: var(--white); |
|
| 849 | +height: 150px; |
|
| 850 | +display: flex; |
|
| 851 | +align-items: center; |
|
| 852 | +justify-content: center; |
|
| 853 | +padding: 20px; |
|
| 854 | +} |
|
| 855 | +.partner-tile .logo img { |
|
| 856 | +max-width: 100%; |
|
| 857 | +max-height: 100%; |
|
| 858 | +object-fit: contain; |
|
| 859 | +} |
|
| 860 | +.partner-tile .info { |
|
| 861 | +padding: 16px 18px 18px; |
|
| 862 | +flex: 1; |
|
| 863 | +display: flex; |
|
| 864 | +flex-direction: column; |
|
| 865 | +justify-content: space-between; |
|
| 866 | +gap: 10px; |
|
| 867 | +} |
|
| 868 | +.partner-tile .name { |
|
| 869 | +color: var(--white); |
|
| 870 | +font-size: 1.05rem; |
|
| 871 | +font-weight: 700; |
|
| 872 | +letter-spacing: 0.3px; |
|
| 873 | +} |
|
| 874 | +.partner-tile .visit { |
|
| 875 | +color: #ff4c00; |
|
| 876 | +font-size: 0.85rem; |
|
| 877 | +font-weight: 700; |
|
| 878 | +letter-spacing: 1.5px; |
|
| 879 | +text-transform: uppercase; |
|
| 880 | +transition: color 0.2s ease; |
|
| 881 | +} |
|
| 882 | +.partner-tile:hover .visit { color: var(--orange-bright); } |
|
| 883 | +.partner-tile .no-url { |
|
| 884 | +color: rgba(184, 184, 184, 0.55); |
|
| 885 | +font-size: 0.8rem; |
|
| 886 | +font-style: italic; |
|
| 887 | +letter-spacing: 0.5px; |
|
| 888 | +} |
| @@ -0,0 +1,112 @@ | ||
| 1 | +/* ============================================================ |
|
| 2 | +Partner-Carousel — Quilldrop Widget |
|
| 3 | +------------------------------------------------------------ |
|
| 4 | +Erwartet im DOM: |
|
| 5 | +<div id="partner-carousel"></div> |
|
| 6 | +<div id="partner-carousel-dots"></div> (optional) |
|
| 7 | + | |
| 8 | +Daten: /static/data/partners.json |
|
| 9 | +Konfig per data-Attribut auf #partner-carousel: |
|
| 10 | +data-visible="3" Anzahl gleichzeitig sichtbarer Logos |
|
| 11 | +data-interval="3500" Auto-Rotation in ms |
|
| 12 | +============================================================ */ |
|
| 13 | +(function() { |
|
| 14 | +'use strict'; |
|
| 15 | + | |
| 16 | +const DATA_URL = '/static/data/partners.json'; |
|
| 17 | + | |
| 18 | + function esc(s) { |
|
| 19 | +return String(s).replace(/[&<>"]/g, c => |
|
| 20 | + ({ '&': '&', '<': '<', '>': '>', '"': '"' }[c]) |
|
| 21 | +); |
|
| 22 | +} |
|
| 23 | + | |
| 24 | + function build(host, dotsBox, partners, opts) { |
|
| 25 | +const VISIBLE = opts.visible; |
|
| 26 | +const INTERVAL = opts.interval; |
|
| 27 | + | |
| 28 | + host.classList.add('carousel'); |
|
| 29 | +host.innerHTML = ''; |
|
| 30 | + | |
| 31 | + const track = document.createElement('div'); |
|
| 32 | +track.className = 'carousel-track'; |
|
| 33 | +host.appendChild(track); |
|
| 34 | + | |
| 35 | +// Slides + Klone für Endlos-Loop |
|
| 36 | +const all = partners.concat(partners.slice(0, VISIBLE)); |
|
| 37 | + all.forEach(p => { |
|
| 38 | + const slide = document.createElement('div'); |
|
| 39 | +slide.className = 'carousel-slide'; |
|
| 40 | + const card = `<div class="partner-card" title="${esc(p.name)}"> |
|
| 41 | + <img src="${esc(p.src)}" alt="${esc(p.name)}" loading="lazy" /> |
|
| 42 | +</div>`; |
|
| 43 | +slide.innerHTML = p.url |
|
| 44 | + ? `<a href="${esc(p.url)}" target="_blank" rel="noopener" class="partner-link" aria-label="${esc(p.name)}">${card}</a>` |
|
| 45 | +: card; |
|
| 46 | +track.appendChild(slide); |
|
| 47 | +}); |
|
| 48 | + | |
| 49 | +// Dots |
|
| 50 | + if (dotsBox) { |
|
| 51 | +dotsBox.innerHTML = ''; |
|
| 52 | + partners.forEach((_, i) => { |
|
| 53 | + const b = document.createElement('button'); |
|
| 54 | +b.className = 'carousel-dot' + (i === 0 ? ' active' : ''); |
|
| 55 | + b.setAttribute('aria-label', `Partner ${i + 1}`); |
|
| 56 | + b.addEventListener('click', () => goTo(i)); |
|
| 57 | +dotsBox.appendChild(b); |
|
| 58 | +}); |
|
| 59 | +} |
|
| 60 | + | |
| 61 | +let index = 0; |
|
| 62 | + function update() { |
|
| 63 | +track.style.transition = 'transform 0.7s cubic-bezier(0.4, 0, 0.2, 1)'; |
|
| 64 | + track.style.transform = `translateX(-${(100 / VISIBLE) * index}%)`; |
|
| 65 | + if (dotsBox) { |
|
| 66 | +const active = index % partners.length; |
|
| 67 | + [...dotsBox.children].forEach((d, i) => d.classList.toggle('active', i === active)); |
|
| 68 | +} |
|
| 69 | +} |
|
| 70 | + function goTo(i) { index = i; update(); } |
|
| 71 | + function next() { |
|
| 72 | +index++; |
|
| 73 | +update(); |
|
| 74 | + if (index >= partners.length) { |
|
| 75 | + setTimeout(() => { |
|
| 76 | +track.style.transition = 'none'; |
|
| 77 | +index = 0; |
|
| 78 | +track.style.transform = 'translateX(0)'; |
|
| 79 | + if (dotsBox) [...dotsBox.children].forEach((d, i) => d.classList.toggle('active', i === 0)); |
|
| 80 | +}, 720); |
|
| 81 | +} |
|
| 82 | +} |
|
| 83 | + | |
| 84 | +update(); |
|
| 85 | +setInterval(next, INTERVAL); |
|
| 86 | +} |
|
| 87 | + | |
| 88 | + function init() { |
|
| 89 | + const host = document.getElementById('partner-carousel'); |
|
| 90 | +if (!host) return; |
|
| 91 | + const dotsBox = document.getElementById('partner-carousel-dots'); |
|
| 92 | + | |
| 93 | + const opts = { |
|
| 94 | +visible: parseInt(host.dataset.visible, 10) || 3, |
|
| 95 | +interval: parseInt(host.dataset.interval, 10) || 3500 |
|
| 96 | +}; |
|
| 97 | + | |
| 98 | +fetch(DATA_URL) |
|
| 99 | +.then(r => r.json()) |
|
| 100 | + .then(partners => { |
|
| 101 | +if (!Array.isArray(partners) || partners.length === 0) return; |
|
| 102 | +build(host, dotsBox, partners, opts); |
|
| 103 | +}) |
|
| 104 | + .catch(err => console.error('partner-carousel:', err)); |
|
| 105 | +} |
|
| 106 | + | |
| 107 | + if (document.readyState === 'loading') { |
|
| 108 | + document.addEventListener('DOMContentLoaded', init); |
|
| 109 | + } else { |
|
| 110 | +init(); |
|
| 111 | +} |
|
| 112 | +})(); |
| @@ -0,0 +1,72 @@ | ||
| 1 | +/* ============================================================ |
|
| 2 | +Partner-Grid — Quilldrop Widget |
|
| 3 | +------------------------------------------------------------ |
|
| 4 | +Erwartet im DOM: |
|
| 5 | +<div id="partner-grid"></div> |
|
| 6 | + | |
| 7 | +Daten: /static/data/partners.json |
|
| 8 | +Konfig per data-Attribut auf #partner-grid: |
|
| 9 | +data-sort="name|none" alphabetisch sortieren (Default: name) |
|
| 10 | +============================================================ */ |
|
| 11 | +(function() { |
|
| 12 | +'use strict'; |
|
| 13 | + | |
| 14 | +const DATA_URL = '/static/data/partners.json'; |
|
| 15 | + | |
| 16 | + function esc(s) { |
|
| 17 | +return String(s).replace(/[&<>"]/g, c => |
|
| 18 | + ({ '&': '&', '<': '<', '>': '>', '"': '"' }[c]) |
|
| 19 | +); |
|
| 20 | +} |
|
| 21 | + | |
| 22 | + function build(host, partners) { |
|
| 23 | + host.classList.add('partner-grid'); |
|
| 24 | +host.innerHTML = ''; |
|
| 25 | + | |
| 26 | + partners.forEach(p => { |
|
| 27 | +const tag = p.url ? 'a' : 'div'; |
|
| 28 | +const el = document.createElement(tag); |
|
| 29 | +el.className = 'partner-tile'; |
|
| 30 | + if (p.url) { |
|
| 31 | +el.href = p.url; |
|
| 32 | +el.target = '_blank'; |
|
| 33 | +el.rel = 'noopener'; |
|
| 34 | +} |
|
| 35 | +el.innerHTML = ` |
|
| 36 | +<div class="logo"> |
|
| 37 | + <img src="${esc(p.src)}" alt="${esc(p.name)}" loading="lazy" /> |
|
| 38 | +</div> |
|
| 39 | +<div class="info"> |
|
| 40 | + <div class="name">${esc(p.name)}</div> |
|
| 41 | + ${p.url |
|
| 42 | +? `<div class="visit">Website besuchen →</div>` |
|
| 43 | +: `<div class="no-url">Website folgt</div>`} |
|
| 44 | +</div>`; |
|
| 45 | +host.appendChild(el); |
|
| 46 | +}); |
|
| 47 | +} |
|
| 48 | + | |
| 49 | + function init() { |
|
| 50 | + const host = document.getElementById('partner-grid'); |
|
| 51 | +if (!host) return; |
|
| 52 | + | |
| 53 | +const sortMode = host.dataset.sort || 'name'; |
|
| 54 | + | |
| 55 | +fetch(DATA_URL) |
|
| 56 | +.then(r => r.json()) |
|
| 57 | + .then(partners => { |
|
| 58 | +if (!Array.isArray(partners) || partners.length === 0) return; |
|
| 59 | + if (sortMode === 'name') { |
|
| 60 | +partners.sort((a, b) => a.name.localeCompare(b.name, 'de')); |
|
| 61 | +} |
|
| 62 | +build(host, partners); |
|
| 63 | +}) |
|
| 64 | + .catch(err => console.error('partner-grid:', err)); |
|
| 65 | +} |
|
| 66 | + | |
| 67 | + if (document.readyState === 'loading') { |
|
| 68 | + document.addEventListener('DOMContentLoaded', init); |
|
| 69 | + } else { |
|
| 70 | +init(); |
|
| 71 | +} |
|
| 72 | +})(); |
| @@ -0,0 +1,146 @@ | ||
| 1 | +(function () { |
|
| 2 | +'use strict'; |
|
| 3 | + | |
| 4 | +let searchIndex = null; |
|
| 5 | +let debounceTimer = null; |
|
| 6 | + | |
| 7 | + const toggle = document.getElementById('search-toggle'); |
|
| 8 | + const container = document.getElementById('search-container'); |
|
| 9 | + const box = document.getElementById('search-box'); |
|
| 10 | + const input = document.getElementById('search-input'); |
|
| 11 | + const results = document.getElementById('search-results'); |
|
| 12 | + | |
| 13 | +if (!toggle || !input || !results) return; |
|
| 14 | + | |
| 15 | +// Toggle search box |
|
| 16 | + toggle.addEventListener('click', function (e) { |
|
| 17 | +e.stopPropagation(); |
|
| 18 | + const isOpen = container.classList.toggle('active'); |
|
| 19 | + if (isOpen) { |
|
| 20 | +input.focus(); |
|
| 21 | +loadIndex(); |
|
| 22 | + } else { |
|
| 23 | +closeSearch(); |
|
| 24 | +} |
|
| 25 | +}); |
|
| 26 | + | |
| 27 | +// Load search index (lazy, only once) |
|
| 28 | + function loadIndex() { |
|
| 29 | +if (searchIndex !== null) return; |
|
| 30 | + fetch('/search-index.json') |
|
| 31 | + .then(function (res) { return res.json(); }) |
|
| 32 | + .then(function (data) { searchIndex = data; }) |
|
| 33 | + .catch(function (err) { |
|
| 34 | + console.error('Search index load failed:', err); |
|
| 35 | +}); |
|
| 36 | +} |
|
| 37 | + | |
| 38 | +// Search on input |
|
| 39 | + input.addEventListener('input', function () { |
|
| 40 | +clearTimeout(debounceTimer); |
|
| 41 | +debounceTimer = setTimeout(doSearch, 200); |
|
| 42 | +}); |
|
| 43 | + | |
| 44 | + function doSearch() { |
|
| 45 | +var query = input.value.trim().toLowerCase(); |
|
| 46 | + if (!query || !searchIndex) { |
|
| 47 | +results.innerHTML = ''; |
|
| 48 | + results.classList.remove('visible'); |
|
| 49 | +return; |
|
| 50 | +} |
|
| 51 | + | |
| 52 | +var terms = query.split(/\s+/); |
|
| 53 | + var matches = searchIndex.filter(function (entry) { |
|
| 54 | +var haystack = [ |
|
| 55 | +entry.title, |
|
| 56 | +entry.preview, |
|
| 57 | + (entry.tags || []).join(' '), |
|
| 58 | + (entry.categories || []).join(' ') |
|
| 59 | + ].join(' ').toLowerCase(); |
|
| 60 | + | |
| 61 | + return terms.every(function (term) { |
|
| 62 | +return haystack.indexOf(term) !== -1; |
|
| 63 | +}); |
|
| 64 | +}); |
|
| 65 | + | |
| 66 | +renderResults(matches.slice(0, 8)); |
|
| 67 | +} |
|
| 68 | + | |
| 69 | + function renderResults(items) { |
|
| 70 | + if (items.length === 0) { |
|
| 71 | +results.innerHTML = '<div class="search-no-results">Keine Ergebnisse gefunden</div>'; |
|
| 72 | + results.classList.add('visible'); |
|
| 73 | +return; |
|
| 74 | +} |
|
| 75 | + | |
| 76 | +var html = ''; |
|
| 77 | + items.forEach(function (item) { |
|
| 78 | + var tags = (item.tags || []).slice(0, 3).map(function (t) { |
|
| 79 | +return '<span class="search-result-tag">' + escapeHtml(t) + '</span>'; |
|
| 80 | + }).join(''); |
|
| 81 | + | |
| 82 | +html += '<a href="' + escapeHtml(item.url) + '" class="search-result-item">' + |
|
| 83 | +'<div class="search-result-title">' + highlightMatch(escapeHtml(item.title), input.value.trim()) + '</div>' + |
|
| 84 | +'<div class="search-result-meta">' + |
|
| 85 | +'<span class="search-result-date">' + escapeHtml(item.date) + '</span>' + |
|
| 86 | +(tags ? '<span class="search-result-tags">' + tags + '</span>' : '') + |
|
| 87 | +'</div>' + |
|
| 88 | +'</a>'; |
|
| 89 | +}); |
|
| 90 | + | |
| 91 | +results.innerHTML = html; |
|
| 92 | + results.classList.add('visible'); |
|
| 93 | +} |
|
| 94 | + | |
| 95 | + function highlightMatch(text, query) { |
|
| 96 | +if (!query) return text; |
|
| 97 | +var terms = query.toLowerCase().split(/\s+/); |
|
| 98 | + terms.forEach(function (term) { |
|
| 99 | +if (!term) return; |
|
| 100 | + var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + ')', 'gi'); |
|
| 101 | +text = text.replace(regex, '<mark>$1</mark>'); |
|
| 102 | +}); |
|
| 103 | +return text; |
|
| 104 | +} |
|
| 105 | + | |
| 106 | + function escapeHtml(str) { |
|
| 107 | +if (!str) return ''; |
|
| 108 | +return str.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"'); |
|
| 109 | +} |
|
| 110 | + | |
| 111 | + function closeSearch() { |
|
| 112 | + container.classList.remove('active'); |
|
| 113 | +input.value = ''; |
|
| 114 | +results.innerHTML = ''; |
|
| 115 | + results.classList.remove('visible'); |
|
| 116 | +} |
|
| 117 | + | |
| 118 | +// Keyboard shortcuts |
|
| 119 | + input.addEventListener('keydown', function (e) { |
|
| 120 | + if (e.key === 'Escape') { |
|
| 121 | +closeSearch(); |
|
| 122 | +} |
|
| 123 | +}); |
|
| 124 | + | |
| 125 | +// Close on click outside |
|
| 126 | + document.addEventListener('click', function (e) { |
|
| 127 | + if (!container.contains(e.target)) { |
|
| 128 | +closeSearch(); |
|
| 129 | +} |
|
| 130 | +}); |
|
| 131 | + | |
| 132 | +// Prevent search box clicks from closing |
|
| 133 | + box.addEventListener('click', function (e) { |
|
| 134 | +e.stopPropagation(); |
|
| 135 | +}); |
|
| 136 | + | |
| 137 | +// Global shortcut: Ctrl+K or Cmd+K to open search |
|
| 138 | + document.addEventListener('keydown', function (e) { |
|
| 139 | + if ((e.ctrlKey || e.metaKey) && e.key === 'k') { |
|
| 140 | +e.preventDefault(); |
|
| 141 | + container.classList.add('active'); |
|
| 142 | +input.focus(); |
|
| 143 | +loadIndex(); |
|
| 144 | +} |
|
| 145 | +}); |
|
| 146 | +})(); |
| @@ -0,0 +1,94 @@ | ||
| 1 | +(function() { |
|
| 2 | +var html = document.documentElement; |
|
| 3 | + var toggle = document.getElementById('theme-toggle'); |
|
| 4 | + var stored = localStorage.getItem('theme'); |
|
| 5 | + | |
| 6 | + if (stored) { |
|
| 7 | + html.setAttribute('data-theme', stored); |
|
| 8 | +} |
|
| 9 | + | |
| 10 | + function updateIcon() { |
|
| 11 | + if (toggle) { |
|
| 12 | + toggle.textContent = html.getAttribute('data-theme') === 'dark' ? '\u263D' : '\u2600\uFE0F'; |
|
| 13 | +} |
|
| 14 | +} |
|
| 15 | + | |
| 16 | +updateIcon(); |
|
| 17 | + | |
| 18 | + if (toggle) { |
|
| 19 | + toggle.addEventListener('click', function() { |
|
| 20 | + var next = html.getAttribute('data-theme') === 'dark' ? 'light' : 'dark'; |
|
| 21 | + html.setAttribute('data-theme', next); |
|
| 22 | + localStorage.setItem('theme', next); |
|
| 23 | +updateIcon(); |
|
| 24 | +}); |
|
| 25 | +} |
|
| 26 | + | |
| 27 | +// Hamburger menu |
|
| 28 | + var hamburger = document.getElementById('hamburger'); |
|
| 29 | + var navLinks = document.getElementById('nav-links'); |
|
| 30 | + if (hamburger && navLinks) { |
|
| 31 | + hamburger.addEventListener('click', function() { |
|
| 32 | + hamburger.classList.toggle('active'); |
|
| 33 | + navLinks.classList.toggle('open'); |
|
| 34 | +}); |
|
| 35 | +// Close mobile menu when clicking a link |
|
| 36 | + navLinks.querySelectorAll('a').forEach(function(link) { |
|
| 37 | + link.addEventListener('click', function() { |
|
| 38 | + hamburger.classList.remove('active'); |
|
| 39 | + navLinks.classList.remove('open'); |
|
| 40 | +}); |
|
| 41 | +}); |
|
| 42 | +} |
|
| 43 | + | |
| 44 | +// Dropdown toggles (for mobile tap support) |
|
| 45 | + document.querySelectorAll('.nav-dropdown-toggle').forEach(function(btn) { |
|
| 46 | + btn.addEventListener('click', function(e) { |
|
| 47 | +e.preventDefault(); |
|
| 48 | +e.stopPropagation(); |
|
| 49 | + var dropdown = btn.closest('.nav-dropdown'); |
|
| 50 | +// Close other dropdowns |
|
| 51 | + document.querySelectorAll('.nav-dropdown.open').forEach(function(other) { |
|
| 52 | + if (other !== dropdown) other.classList.remove('open'); |
|
| 53 | +}); |
|
| 54 | + dropdown.classList.toggle('open'); |
|
| 55 | +}); |
|
| 56 | +}); |
|
| 57 | + | |
| 58 | +// Close dropdown when clicking outside |
|
| 59 | + document.addEventListener('click', function(e) { |
|
| 60 | + if (!e.target.closest('.nav-dropdown')) { |
|
| 61 | + document.querySelectorAll('.nav-dropdown.open').forEach(function(d) { |
|
| 62 | + d.classList.remove('open'); |
|
| 63 | +}); |
|
| 64 | +} |
|
| 65 | +}); |
|
| 66 | + | |
| 67 | +// TOC generator for posts with toc: true |
|
| 68 | + var toc = document.getElementById('toc'); |
|
| 69 | + if (toc) { |
|
| 70 | + var headings = document.querySelectorAll('.post-content h1, .post-content h2, .post-content h3'); |
|
| 71 | + if (headings.length > 0) { |
|
| 72 | +// Determine the highest (smallest number) heading level used |
|
| 73 | +var minLevel = 6; |
|
| 74 | + headings.forEach(function(h) { |
|
| 75 | +var level = parseInt(h.tagName.charAt(1)); |
|
| 76 | +if (level < minLevel) minLevel = level; |
|
| 77 | +}); |
|
| 78 | + | |
| 79 | + var ul = document.createElement('ul'); |
|
| 80 | + headings.forEach(function(h) { |
|
| 81 | +var level = parseInt(h.tagName.charAt(1)); |
|
| 82 | + var li = document.createElement('li'); |
|
| 83 | +// Indent relative to the highest heading level found |
|
| 84 | +li.className = 'toc-level-' + (level - minLevel); |
|
| 85 | + var a = document.createElement('a'); |
|
| 86 | +a.href = '#' + h.id; |
|
| 87 | +a.textContent = h.textContent; |
|
| 88 | +li.appendChild(a); |
|
| 89 | +ul.appendChild(li); |
|
| 90 | +}); |
|
| 91 | +toc.appendChild(ul); |
|
| 92 | +} |
|
| 93 | +} |
|
| 94 | +})(); |
| @@ -0,0 +1,93 @@ | ||
| 1 | +{{define "base"}}<!DOCTYPE html> |
|
| 2 | +<html lang="de"> |
|
| 3 | +<head> |
|
| 4 | +<meta charset="UTF-8"> |
|
| 5 | +<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
| 6 | + <title>{{block "title" .}}{{.Site.Title}}{{end}}</title> |
|
| 7 | + <meta name="description" content="{{.Site.Description}}"> |
|
| 8 | + <link rel="alternate" type="application/rss+xml" title="{{.Site.Title}} RSS Feed" href="/index.xml"> |
|
| 9 | +<link rel="stylesheet" href="/static/css/style.css"> |
|
| 10 | +<link rel="icon" type="image/png" href="/images/ehc/EHC_Logo.png"> |
|
| 11 | +<link rel="apple-touch-icon" sizes="180x180" href="/static/icons/apple-touch-icon.png"> |
|
| 12 | +<link rel="manifest" href="/static/icons/site.webmanifest"> |
|
| 13 | +<meta name="theme-color" content="#0a0a0a"> |
|
| 14 | +</head> |
|
| 15 | +<body> |
|
| 16 | + | |
| 17 | +<div class="bg-fixed" aria-hidden="true"></div> |
|
| 18 | +<div class="bg-overlay" aria-hidden="true"></div> |
|
| 19 | + | |
| 20 | +<header class="navbar"> |
|
| 21 | +<div class="nav-inner"> |
|
| 22 | +<a href="/" class="nav-brand"> |
|
| 23 | +<img src="/images/ehc/EHC_Logo.webp" alt="EHC Logo"> |
|
| 24 | +<span class="nav-brand-text"> |
|
| 25 | + <span class="name">{{.Site.Title}}</span> |
|
| 26 | +<span class="sub">We Are Family</span> |
|
| 27 | +</span> |
|
| 28 | +</a> |
|
| 29 | + | |
| 30 | +<button class="hamburger" id="hamburger" aria-label="Menü öffnen"> |
|
| 31 | +<span></span><span></span><span></span> |
|
| 32 | +</button> |
|
| 33 | + | |
| 34 | +<nav class="nav-links" id="nav-links" aria-label="Hauptnavigation"> |
|
| 35 | + {{range .Site.Menu}} |
|
| 36 | + {{if hasChildren .}} |
|
| 37 | +<div class="nav-dropdown"> |
|
| 38 | + <button class="nav-dropdown-toggle">{{.Label}} <svg width="10" height="6" viewBox="0 0 10 6" fill="none" aria-hidden="true"><path d="M1 1L5 5L9 1" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg></button> |
|
| 39 | +<div class="nav-dropdown-menu"> |
|
| 40 | + {{range .Children}}<a href="{{.URL}}">{{.Label}}</a>{{end}} |
|
| 41 | +</div> |
|
| 42 | +</div> |
|
| 43 | + {{else}} |
|
| 44 | + <a href="{{.URL}}">{{.Label}}</a> |
|
| 45 | + {{end}} |
|
| 46 | + {{end}} |
|
| 47 | + | |
| 48 | +<div class="search-container" id="search-container"> |
|
| 49 | +<button class="search-toggle" id="search-toggle" aria-label="Suche"> |
|
| 50 | +<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg> |
|
| 51 | +</button> |
|
| 52 | +<div class="search-box" id="search-box"> |
|
| 53 | +<input type="text" id="search-input" placeholder="Suche..." autocomplete="off"> |
|
| 54 | +<div class="search-results" id="search-results"></div> |
|
| 55 | +</div> |
|
| 56 | +</div> |
|
| 57 | + | |
| 58 | +<a href="/index.xml" class="nav-rss" title="RSS Feed" aria-label="RSS Feed"> |
|
| 59 | +<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><circle cx="6.18" cy="17.82" r="2.18"/><path d="M4 4.44v2.83c7.03 0 12.73 5.7 12.73 12.73h2.83c0-8.59-6.97-15.56-15.56-15.56zm0 5.66v2.83c3.9 0 7.07 3.17 7.07 7.07h2.83c0-5.47-4.43-9.9-9.9-9.9z"/></svg> |
|
| 60 | +</a> |
|
| 61 | +</nav> |
|
| 62 | +</div> |
|
| 63 | +</header> |
|
| 64 | + | |
| 65 | +<main class="container"> |
|
| 66 | + {{block "content" .}}{{end}} |
|
| 67 | +</main> |
|
| 68 | + | |
| 69 | +<div class="corner-fixed" aria-hidden="true"> |
|
| 70 | +<img src="/images/ehc/we-are-family.webp" alt=""> |
|
| 71 | +</div> |
|
| 72 | + | |
| 73 | +<footer class="footer"> |
|
| 74 | +<div class="footer-inner"> |
|
| 75 | + © <span id="year"></span> {{.Site.Title}} · We Are Family |
|
| 76 | +· <a href="/sites/impressum/">Impressum</a> |
|
| 77 | +· <a href="/sites/datenschutz/">Datenschutz</a> |
|
| 78 | +</div> |
|
| 79 | +</footer> |
|
| 80 | + | |
| 81 | +<script>document.getElementById('year').textContent = new Date().getFullYear();</script> |
|
| 82 | +<script src="/static/js/theme.js"></script> |
|
| 83 | +<script src="/static/js/search.js"></script> |
|
| 84 | +<script> |
|
| 85 | + (function () { |
|
| 86 | +var i = new Image(1, 1); |
|
| 87 | +i.src = "https://assets.tytik.cloud/assets/img/s.gif" |
|
| 88 | ++ "?u=" + encodeURIComponent(location.href) |
|
| 89 | ++ "&ref=" + encodeURIComponent(document.referrer); |
|
| 90 | +})(); |
|
| 91 | +</script> |
|
| 92 | +</body> |
|
| 93 | +</html>{{end}} |
| @@ -0,0 +1,14 @@ | ||
| 1 | +{{define "title"}}Kategorien · {{.Site.Title}}{{end}} |
|
| 2 | +{{define "content"}} |
|
| 3 | +<div class="tags-page"> |
|
| 4 | +<h1>Kategorien</h1> |
|
| 5 | +<div class="tags-cloud"> |
|
| 6 | + {{range $cat, $count := .Categories}} |
|
| 7 | + <a href="/categories/{{lower $cat}}/" class="tag tag-large">{{$cat}} <span class="tag-count">{{$count}}</span></a> |
|
| 8 | + {{end}} |
|
| 9 | +</div> |
|
| 10 | +<div class="post-footer"> |
|
| 11 | +<a href="/" class="back-link">← Zurück zur Startseite</a> |
|
| 12 | +</div> |
|
| 13 | +</div> |
|
| 14 | +{{end}} |
| @@ -0,0 +1,31 @@ | ||
| 1 | +{{define "title"}}Kategorie: {{.Category}} · {{.Site.Title}}{{end}} |
|
| 2 | +{{define "content"}} |
|
| 3 | +<div class="tag-page"> |
|
| 4 | + <h1>Kategorie: <span class="highlight">{{.Category}}</span></h1> |
|
| 5 | +<div class="post-list"> |
|
| 6 | + {{range .Posts}} |
|
| 7 | +<article class="post-card"> |
|
| 8 | + {{if .GetCover}} |
|
| 9 | + <a href="/posts/{{.Slug}}/" class="post-card-cover"> |
|
| 10 | + <img src="{{.GetCover}}" alt="{{.Title}}" loading="lazy"> |
|
| 11 | +</a> |
|
| 12 | + {{end}} |
|
| 13 | +<div class="post-card-body"> |
|
| 14 | +<div class="post-card-meta"> |
|
| 15 | + <time datetime="{{isoDate .Date.Time}}">{{formatDate .Date.Time}}</time> |
|
| 16 | +<div class="post-tags"> |
|
| 17 | + {{range .Tags}}<a href="/tags/{{lower .}}/" class="tag">{{.}}</a>{{end}} |
|
| 18 | +</div> |
|
| 19 | +</div> |
|
| 20 | + <h2 class="post-card-title"><a href="/posts/{{.Slug}}/">{{.Title}}</a></h2> |
|
| 21 | + <p class="post-card-preview">{{.GetPreview}}</p> |
|
| 22 | + <a href="/posts/{{.Slug}}/" class="read-more">Weiterlesen →</a> |
|
| 23 | +</div> |
|
| 24 | +</article> |
|
| 25 | + {{end}} |
|
| 26 | +</div> |
|
| 27 | +<div class="post-footer"> |
|
| 28 | +<a href="/categories/" class="back-link">← Alle Kategorien</a> |
|
| 29 | +</div> |
|
| 30 | +</div> |
|
| 31 | +{{end}} |
| @@ -0,0 +1,69 @@ | ||
| 1 | +{{define "title"}}{{.Site.Title}}{{end}} |
|
| 2 | +{{define "content"}} |
|
| 3 | + | |
| 4 | +{{if eq .Page 1}} |
|
| 5 | +<div class="hero-image"> |
|
| 6 | +<!-- <img src="/images/ehc/we-are-family-team-short.webp" alt="EHC Essen (Ruhr) e.V. - We Are Family"> --> |
|
| 7 | +<img src="/images/ehc/we-are-family-v2.webp" alt="EHC Essen (Ruhr) e.V. - We Are Family"> |
|
| 8 | +</div> |
|
| 9 | + | |
| 10 | +<section class="partner-section"> |
|
| 11 | +<div class="section-head"> |
|
| 12 | +<h2>Unsere Partner</h2> |
|
| 13 | +<a href="/sites/partner/" class="all-link">Alle Partner anzeigen →</a> |
|
| 14 | +</div> |
|
| 15 | + | |
| 16 | +<!-- Partner-Karussell-Widget; lädt /static/data/partners.json --> |
|
| 17 | +<div id="partner-carousel" data-visible="3" data-interval="3500" aria-label="Partner Karussell"></div> |
|
| 18 | +<div id="partner-carousel-dots" class="carousel-dots"></div> |
|
| 19 | +<script src="/static/js/partner-carousel.js" defer></script> |
|
| 20 | +</section> |
|
| 21 | +{{end}} |
|
| 22 | + | |
| 23 | +<section class="section"> |
|
| 24 | +<div class="section-head"> |
|
| 25 | +<h2>News</h2> |
|
| 26 | + {{if gt .TotalPages 1}}<a href="{{pageURL 2}}" class="all-link">Ältere News →</a>{{end}} |
|
| 27 | +</div> |
|
| 28 | + | |
| 29 | +<div class="post-list"> |
|
| 30 | + {{range .Posts}} |
|
| 31 | +<article class="post-card"> |
|
| 32 | + {{if .GetCover}} |
|
| 33 | + <a href="/posts/{{.Slug}}/" class="post-card-cover"> |
|
| 34 | + <img src="{{.GetCover}}" alt="{{.Title}}" loading="lazy"> |
|
| 35 | +</a> |
|
| 36 | + {{end}} |
|
| 37 | +<div class="post-card-body"> |
|
| 38 | +<div class="post-card-meta"> |
|
| 39 | + <time datetime="{{isoDate .Date.Time}}">{{formatDate .Date.Time}}</time> |
|
| 40 | +<div class="post-tags"> |
|
| 41 | + {{range .Tags}}<a href="/tags/{{lower .}}/" class="tag">{{.}}</a>{{end}} |
|
| 42 | +</div> |
|
| 43 | +</div> |
|
| 44 | + <h2 class="post-card-title"><a href="/posts/{{.Slug}}/">{{.Title}}</a></h2> |
|
| 45 | + <p class="post-card-preview">{{.GetPreview}}</p> |
|
| 46 | + <a href="/posts/{{.Slug}}/" class="read-more">Weiterlesen →</a> |
|
| 47 | +</div> |
|
| 48 | +</article> |
|
| 49 | + {{end}} |
|
| 50 | +</div> |
|
| 51 | +</section> |
|
| 52 | + | |
| 53 | +{{if gt .TotalPages 1}} |
|
| 54 | +<nav class="pagination"> |
|
| 55 | + {{if gt .Page 1}}<a href="{{pageURL (sub .Page 1)}}" class="pagination-btn pagination-prev">← Neuere</a> |
|
| 56 | + {{else}}<span class="pagination-btn pagination-prev disabled">← Neuere</span>{{end}} |
|
| 57 | +<div class="pagination-pages"> |
|
| 58 | + {{range paginationRange $.Page $.TotalPages}} |
|
| 59 | + {{if isEllipsis .}}<span class="pagination-ellipsis">…</span> |
|
| 60 | + {{else if eq . $.Page}}<span class="pagination-num active">{{.}}</span> |
|
| 61 | + {{else}}<a href="{{pageURL .}}" class="pagination-num">{{.}}</a>{{end}} |
|
| 62 | + {{end}} |
|
| 63 | +</div> |
|
| 64 | + {{if lt .Page .TotalPages}}<a href="{{pageURL (add .Page 1)}}" class="pagination-btn pagination-next">Ältere →</a> |
|
| 65 | + {{else}}<span class="pagination-btn pagination-next disabled">Ältere →</span>{{end}} |
|
| 66 | +</nav> |
|
| 67 | +{{end}} |
|
| 68 | + | |
| 69 | +{{end}} |
| @@ -0,0 +1,14 @@ | ||
| 1 | +{{define "title"}}{{.Page.Title}} · {{.Site.Title}}{{end}} |
|
| 2 | +{{define "content"}} |
|
| 3 | +<article class="page-single"> |
|
| 4 | +<header class="page-header"> |
|
| 5 | + <h1 class="page-title">{{.Page.Title}}</h1> |
|
| 6 | +</header> |
|
| 7 | +<div class="post-content"> |
|
| 8 | + {{safeHTML .Page.HTMLContent}} |
|
| 9 | +</div> |
|
| 10 | +<div class="post-footer"> |
|
| 11 | +<a href="/" class="back-link">← Zurück zur Startseite</a> |
|
| 12 | +</div> |
|
| 13 | +</article> |
|
| 14 | +{{end}} |
| @@ -0,0 +1,50 @@ | ||
| 1 | +{{define "title"}}{{.Post.Title}} · {{.Site.Title}}{{end}} |
|
| 2 | +{{define "content"}} |
|
| 3 | +<article class="post-single"> |
|
| 4 | +<header class="post-header"> |
|
| 5 | +<div class="post-header-meta"> |
|
| 6 | + <time datetime="{{isoDate .Post.Date.Time}}">{{formatDate .Post.Date.Time}}</time> |
|
| 7 | + <span class="post-author">{{.Post.Author}}</span> |
|
| 8 | +</div> |
|
| 9 | + <h1 class="post-title">{{.Post.Title}}</h1> |
|
| 10 | +<div class="post-tags"> |
|
| 11 | + {{range .Post.Tags}}<a href="/tags/{{lower .}}/" class="tag">{{.}}</a>{{end}} |
|
| 12 | +</div> |
|
| 13 | +</header> |
|
| 14 | + | |
| 15 | + {{if .Post.GetCover}} |
|
| 16 | +<div class="post-cover"> |
|
| 17 | + <img src="{{.Post.GetCover}}" alt="{{.Post.Title}}" loading="lazy"> |
|
| 18 | +</div> |
|
| 19 | + {{end}} |
|
| 20 | + | |
| 21 | + {{if .Post.TOC}} |
|
| 22 | +<nav class="toc" id="toc"> |
|
| 23 | +<h3>Inhaltsverzeichnis</h3> |
|
| 24 | +</nav> |
|
| 25 | + {{end}} |
|
| 26 | + | |
| 27 | +<div class="post-content"> |
|
| 28 | + {{safeHTML .Post.HTMLContent}} |
|
| 29 | +</div> |
|
| 30 | + | |
| 31 | +<nav class="post-nav"> |
|
| 32 | + {{if .PrevPost}} |
|
| 33 | + <a href="/posts/{{.PrevPost.Slug}}/" class="post-nav-link post-nav-prev"> |
|
| 34 | +<span class="post-nav-label">← Neuerer Artikel</span> |
|
| 35 | + <span class="post-nav-title">{{.PrevPost.Title}}</span> |
|
| 36 | +</a> |
|
| 37 | + {{else}}<span class="post-nav-link post-nav-prev disabled"></span>{{end}} |
|
| 38 | + {{if .NextPost}} |
|
| 39 | + <a href="/posts/{{.NextPost.Slug}}/" class="post-nav-link post-nav-next"> |
|
| 40 | +<span class="post-nav-label">Älterer Artikel →</span> |
|
| 41 | + <span class="post-nav-title">{{.NextPost.Title}}</span> |
|
| 42 | +</a> |
|
| 43 | + {{else}}<span class="post-nav-link post-nav-next disabled"></span>{{end}} |
|
| 44 | +</nav> |
|
| 45 | + | |
| 46 | +<div class="post-footer"> |
|
| 47 | +<a href="/" class="back-link">← Zurück zur Startseite</a> |
|
| 48 | +</div> |
|
| 49 | +</article> |
|
| 50 | +{{end}} |
| @@ -0,0 +1,31 @@ | ||
| 1 | +{{define "title"}}Tag: {{.Tag}} · {{.Site.Title}}{{end}} |
|
| 2 | +{{define "content"}} |
|
| 3 | +<div class="tag-page"> |
|
| 4 | + <h1>Tag: <span class="highlight">{{.Tag}}</span></h1> |
|
| 5 | +<div class="post-list"> |
|
| 6 | + {{range .Posts}} |
|
| 7 | +<article class="post-card"> |
|
| 8 | + {{if .GetCover}} |
|
| 9 | + <a href="/posts/{{.Slug}}/" class="post-card-cover"> |
|
| 10 | + <img src="{{.GetCover}}" alt="{{.Title}}" loading="lazy"> |
|
| 11 | +</a> |
|
| 12 | + {{end}} |
|
| 13 | +<div class="post-card-body"> |
|
| 14 | +<div class="post-card-meta"> |
|
| 15 | + <time datetime="{{isoDate .Date.Time}}">{{formatDate .Date.Time}}</time> |
|
| 16 | +<div class="post-tags"> |
|
| 17 | + {{range .Tags}}<a href="/tags/{{lower .}}/" class="tag">{{.}}</a>{{end}} |
|
| 18 | +</div> |
|
| 19 | +</div> |
|
| 20 | + <h2 class="post-card-title"><a href="/posts/{{.Slug}}/">{{.Title}}</a></h2> |
|
| 21 | + <p class="post-card-preview">{{.GetPreview}}</p> |
|
| 22 | + <a href="/posts/{{.Slug}}/" class="read-more">Weiterlesen →</a> |
|
| 23 | +</div> |
|
| 24 | +</article> |
|
| 25 | + {{end}} |
|
| 26 | +</div> |
|
| 27 | +<div class="post-footer"> |
|
| 28 | +<a href="/tags/" class="back-link">← Alle Tags</a> |
|
| 29 | +</div> |
|
| 30 | +</div> |
|
| 31 | +{{end}} |
| @@ -0,0 +1,14 @@ | ||
| 1 | +{{define "title"}}Tags · {{.Site.Title}}{{end}} |
|
| 2 | +{{define "content"}} |
|
| 3 | +<div class="tags-page"> |
|
| 4 | +<h1>Tags</h1> |
|
| 5 | +<div class="tags-cloud"> |
|
| 6 | + {{range $tag, $count := .Tags}} |
|
| 7 | + <a href="/tags/{{lower $tag}}/" class="tag tag-large">{{$tag}} <span class="tag-count">{{$count}}</span></a> |
|
| 8 | + {{end}} |
|
| 9 | +</div> |
|
| 10 | +<div class="post-footer"> |
|
| 11 | +<a href="/" class="back-link">← Zurück zur Startseite</a> |
|
| 12 | +</div> |
|
| 13 | +</div> |
|
| 14 | +{{end}} |