fix(svg): escape xml characters in productivity badge [skip ci]

This commit is contained in:
NickiCloud 2026-09-02 21:32:02 +02:00
parent c4c47ab445
commit e7ffe773d7
5 changed files with 45 additions and 62 deletions

View File

@ -12,7 +12,7 @@
<img src="https://img.shields.io/badge/Gitea_Server-Online_%E2%97%8F-2ea44f?style=flat-square&logo=gitea&logoColor=white" alt="Gitea Online" /> <img src="https://img.shields.io/badge/Gitea_Server-Online_%E2%97%8F-2ea44f?style=flat-square&logo=gitea&logoColor=white" alt="Gitea Online" />
<img src="https://img.shields.io/badge/Homelab-Debian_12_Bookworm-A81D33?style=flat-square&logo=debian&logoColor=white" alt="Debian 12" /> <img src="https://img.shields.io/badge/Homelab-Debian_12_Bookworm-A81D33?style=flat-square&logo=debian&logoColor=white" alt="Debian 12" />
<img src="https://img.shields.io/badge/CI%2FCD-Gitea_Act_Runner-609926?style=flat-square&logo=docker&logoColor=white" alt="Runner Active" /> <img src="https://img.shields.io/badge/CI%2FCD-Gitea_Act_Runner-609926?style=flat-square&logo=docker&logoColor=white" alt="Runner Active" />
<img src="https://img.shields.io/badge/Telemetry-Zuletzt_aktualisiert_02.09.2026%2019%3A15_UTC-7e3f98?style=flat-square" alt="Last Sync" /> <img src="https://img.shields.io/badge/Telemetry-Zuletzt_aktualisiert_02.09.2026%2019%3A31_UTC-7e3f98?style=flat-square" alt="Last Sync" />
</p> </p>
<!-- END_SYS_TELEMETRY --> <!-- END_SYS_TELEMETRY -->
@ -25,7 +25,6 @@
[![MudBlazor](https://img.shields.io/badge/MudBlazor-9c27b0?style=for-the-badge&logo=blazor&logoColor=white)](https://mudblazor.com/) [![MudBlazor](https://img.shields.io/badge/MudBlazor-9c27b0?style=for-the-badge&logo=blazor&logoColor=white)](https://mudblazor.com/)
[![JetBrains Rider](https://img.shields.io/badge/JetBrains_Rider-000000?style=for-the-badge&logo=rider&logoColor=white)](https://www.jetbrains.com/rider/) [![JetBrains Rider](https://img.shields.io/badge/JetBrains_Rider-000000?style=for-the-badge&logo=rider&logoColor=white)](https://www.jetbrains.com/rider/)
[![Pop!_OS](https://img.shields.io/badge/Pop!_OS-48B9C7?style=for-the-badge&logo=popos&logoColor=white)](https://pop.system76.com/)
[![Debian](https://img.shields.io/badge/Debian-A81D33?style=for-the-badge&logo=debian&logoColor=white)](https://www.debian.org/) [![Debian](https://img.shields.io/badge/Debian-A81D33?style=for-the-badge&logo=debian&logoColor=white)](https://www.debian.org/)
[![Docker](https://img.shields.io/badge/Docker-2496ED?style=for-the-badge&logo=docker&logoColor=white)](https://www.docker.com/) [![Docker](https://img.shields.io/badge/Docker-2496ED?style=for-the-badge&logo=docker&logoColor=white)](https://www.docker.com/)
[![WebCore Consulting](https://img.shields.io/badge/WebCore-Consulting-0284c7?style=for-the-badge&logo=buffer&logoColor=white)](https://www.webcore-consulting.de) [![WebCore Consulting](https://img.shields.io/badge/WebCore-Consulting-0284c7?style=for-the-badge&logo=buffer&logoColor=white)](https://www.webcore-consulting.de)
@ -42,7 +41,7 @@ Ich bin **Nicki (Nicklas)**, angehender Softwareentwickler mit fundiertem Fokus
- 💻 **Fokus:** C#, .NET 10, Cross-Platform Desktop mit **Avalonia UI**, moderne Web-Apps mit **Blazor / MudBlazor** und modulare Microservices. - 💻 **Fokus:** C#, .NET 10, Cross-Platform Desktop mit **Avalonia UI**, moderne Web-Apps mit **Blazor / MudBlazor** und modulare Microservices.
- 🏢 **Team & Consulting:** Softwareentwickler bei **WebCore Consulting** Entwicklung von Management-Tools, Kundenportalen und Security-Services. - 🏢 **Team & Consulting:** Softwareentwickler bei **WebCore Consulting** Entwicklung von Management-Tools, Kundenportalen und Security-Services.
- 🐧 **Entwicklungsumgebung:** Vollständiger Linux-Workflow mit **JetBrains Rider auf Pop!_OS** maximale Produktivität ohne Windows-Overhead. - 🐧 **Entwicklungsumgebung:** Vollständiger Linux-Workflow mit **JetBrains Rider auf Fedora** maximale Produktivität ohne Windows-Overhead.
- 🏰 **Self-Hosted Homelab:** Eigener Debian-Rootserver mit Docker-Containern: Gitea & Gitea Actions, Mailcow Enterprise Suite, Nginx Reverse Proxy mit Let's Encrypt, gehärtet durch UFW & fail2ban. - 🏰 **Self-Hosted Homelab:** Eigener Debian-Rootserver mit Docker-Containern: Gitea & Gitea Actions, Mailcow Enterprise Suite, Nginx Reverse Proxy mit Let's Encrypt, gehärtet durch UFW & fail2ban.
- 🎮 **Gaming Corner:** Wenn der Build grün ist: Redstone-Komplexe in **Minecraft**, taktische Runden in **Rainbow Six Siege** oder Grinden in **Warframe**. - 🎮 **Gaming Corner:** Wenn der Build grün ist: Redstone-Komplexe in **Minecraft**, taktische Runden in **Rainbow Six Siege** oder Grinden in **Warframe**.
- 🦊 **Branding:** Lila Fuchs (Purple Fox) steht für Agilität, Eleganz, Scharfsinn und sauberen Code. - 🦊 **Branding:** Lila Fuchs (Purple Fox) steht für Agilität, Eleganz, Scharfsinn und sauberen Code.
@ -64,11 +63,6 @@ Ich bin **Nicki (Nicklas)**, angehender Softwareentwickler mit fundiertem Fokus
<img src="heatmap.svg" alt="Nicki's Gitea Contribution Heatmap" width="100%" /> <img src="heatmap.svg" alt="Nicki's Gitea Contribution Heatmap" width="100%" />
</div> </div>
#### 📌 Zuletzt aktualisierte persönliche Projekte:
<!-- START_LATEST_REPOS -->
- 🚀 [**.profile**](https://git.webcore-consulting.dev/NickiCloud/.profile) 🦊 Gitea-Profil & dynamische Aktivitäts-Statistiken mit .NET 10
`C#` • 🕒 *Aktualisiert am 02.09.2026*
<!-- END_LATEST_REPOS -->
</details> </details>
@ -115,11 +109,11 @@ Ich bin **Nicki (Nicklas)**, angehender Softwareentwickler mit fundiertem Fokus
> *Echtzeit-Feed der letzten Aktionen und Commits über alle privaten &amp; Team-Repositories.* > *Echtzeit-Feed der letzten Aktionen und Commits über alle privaten &amp; Team-Repositories.*
<!-- START_RECENT_ACTIVITY --> <!-- START_RECENT_ACTIVITY -->
- ⚡ **feat: add live commit radar, activity feed and homelab telemetry [skip ci]** auf [`NickiCloud/.profile`](https://git.webcore-consulting.dev/NickiCloud/.profile) • 🕒 *vor 2 Minuten* - ⚡ **feat: add productivity biorhythm clock, developer achievements and quote [skip ci]** auf [`NickiCloud/.profile`](https://git.webcore-consulting.dev/NickiCloud/.profile) • 🕒 *vor 15 Minuten*
- ⚡ **feat: add team telemetry dashboard, byte-level language analytics and tabs [skip ci]** auf [`NickiCloud/.profile`](https://git.webcore-consulting.dev/NickiCloud/.profile) • 🕒 *vor 6 Minuten* - ⚡ **feat: add live commit radar, activity feed and homelab telemetry [skip ci]** auf [`NickiCloud/.profile`](https://git.webcore-consulting.dev/NickiCloud/.profile) • 🕒 *vor 18 Minuten*
- ⚡ **fix(svg): remove utf-8 bom and add xml declaration for gitea typesniffer [skip ci]** auf [`NickiCloud/.profile`](https://git.webcore-consulting.dev/NickiCloud/.profile) • 🕒 *vor 14 Minuten* - ⚡ **feat: add team telemetry dashboard, byte-level language analytics and tabs [skip ci]** auf [`NickiCloud/.profile`](https://git.webcore-consulting.dev/NickiCloud/.profile) • 🕒 *vor 22 Minuten*
- ⚡ **chore(profile): update activity heatmap & stats (22 contributions) [skip ci]** auf [`NickiCloud/.profile`](https://git.webcore-consulting.dev/NickiCloud/.profile) • 🕒 *vor 21 Minuten* - ⚡ **fix(svg): remove utf-8 bom and add xml declaration for gitea typesniffer [skip ci]** auf [`NickiCloud/.profile`](https://git.webcore-consulting.dev/NickiCloud/.profile) • 🕒 *vor 30 Minuten*
- ⚡ **Initial profile setup** auf [`NickiCloud/.profile`](https://git.webcore-consulting.dev/NickiCloud/.profile) • 🕒 *vor 22 Minuten* - ⚡ **chore(profile): update activity heatmap & stats (22 contributions) [skip ci]** auf [`NickiCloud/.profile`](https://git.webcore-consulting.dev/NickiCloud/.profile) • 🕒 *vor 37 Minuten*
<!-- END_RECENT_ACTIVITY --> <!-- END_RECENT_ACTIVITY -->
</details> </details>
@ -142,7 +136,7 @@ Ich bin **Nicki (Nicklas)**, angehender Softwareentwickler mit fundiertem Fokus
| 🏆 **Streak Master** | `Gold` | Mindestens 4 Tage ununterbrochen aktiv gecodet | **4 Tage** ✅ | | 🏆 **Streak Master** | `Gold` | Mindestens 4 Tage ununterbrochen aktiv gecodet | **4 Tage** ✅ |
| 💾 **Code Sovereign** | `Diamond` | Über 1,5 MB Code in Gitea verwaltet | **1,9 MB** ✅ | | 💾 **Code Sovereign** | `Diamond` | Über 1,5 MB Code in Gitea verwaltet | **1,9 MB** ✅ |
| ⚡ **Zero-Dependency** | `Master` | Reines .NET 10 BCL ohne fremde NuGet-Pakete | **100% Native** ✅ | | ⚡ **Zero-Dependency** | `Master` | Reines .NET 10 BCL ohne fremde NuGet-Pakete | **100% Native** ✅ |
| 🌙 **Night-Owl Veteran** | `Elite` | Hohe nächtliche Coding-Aktivität | **26,3% Nachts** ✅ | | 🌙 **Night-Owl Veteran** | `Elite` | Hohe nächtliche Coding-Aktivität | **21,1% Nachts** ✅ |
| 🏰 **Homelab Overlord** | `Legendary` | Self-Hosted Debian, Docker, Gitea, Mailcow | **Vollautonom** ✅ | | 🏰 **Homelab Overlord** | `Legendary` | Self-Hosted Debian, Docker, Gitea, Mailcow | **Vollautonom** ✅ |
<!-- END_ACHIEVEMENTS --> <!-- END_ACHIEVEMENTS -->
@ -157,32 +151,11 @@ Ich bin **Nicki (Nicklas)**, angehender Softwareentwickler mit fundiertem Fokus
<br/> <br/>
<details open> <details open>
<summary><h3>🛡️ Tab 5: Homelab, Server-Infrastruktur &amp; Telemetrie</h3></summary>
```
┌─────────────────────────────────────────────────────────────┐
│ 🌐 WebCore & HomeLab Architecture │
│ │
│ [ Internet / Cloudflare ] │
│ │ │
│ ▼ │
│ [ Debian 12 Host ] ─── [ UFW & fail2ban Security Wall ] │
│ │ │
│ ▼ │
│ [ Nginx Reverse Proxy (SSL/TLS Termination) ] │
│ │ │
│ ┌───────┼─────────────────────────┬──────────────┐ │
│ ▼ ▼ ▼ ▼ │
│ [Gitea] [Act-Runner] [Mailcow] [Services] │
│ (Git) (C# / .NET 10 Actions) (E-Mail) (WebCore) │
└─────────────────────────────────────────────────────────────┘
```
| Service | Host / Umgebung | Funktion | Status | | Service | Host / Umgebung | Funktion | Status |
| :--- | :--- | :--- | :---: | | :--- | :--- | :--- | :---: |
| 🦊 **Gitea Service** | `git.webcore-consulting.dev` | Versionsverwaltung, API & Git LFS | `🟢 ONLINE` | | 🦊 **Gitea Service** | `git.webcore-consulting.dev` | Versionsverwaltung, API & Git LFS | `🟢 ONLINE` |
| ⚡ **Gitea Act-Runner** | Docker `catthehacker/ubuntu:act` | Autonome CI/CD-Pipeline (.NET 10) | `🟢 AKTIV` | | ✉️ **Mailcow Suite** | Docker Stack / Debian 13 | Enterprise Mail (DKIM, SPF, DMARC) | `🟢 ONLINE` |
| ✉️ **Mailcow Suite** | Docker Stack / Debian 12 | Enterprise Mail (DKIM, SPF, DMARC) | `🟢 ONLINE` |
| 🛡️ **Nginx Proxy** | Reverse Proxy Host | SSL/TLS 1.3 Offloading & HSTS | `🟢 AKTIV` | | 🛡️ **Nginx Proxy** | Reverse Proxy Host | SSL/TLS 1.3 Offloading & HSTS | `🟢 AKTIV` |
| 🔒 **Security Wall** | UFW Firewall & fail2ban | SSH & HTTP Brute-Force Abwehr | `🟢 SCHARF` | | 🔒 **Security Wall** | UFW Firewall & fail2ban | SSH & HTTP Brute-Force Abwehr | `🟢 SCHARF` |
@ -191,13 +164,13 @@ Ich bin **Nicki (Nicklas)**, angehender Softwareentwickler mit fundiertem Fokus
<br/> <br/>
<details open> <details open>
<summary><h3>🎮 Tab 6: Gaming Battlestation &amp; Loadouts</h3></summary> <summary><h3>🎮 Tab 5: Gaming Battlestation &amp; Loadouts</h3></summary>
| Game | Fokus & Rolle | Lieblingselement / Operator | | Game | Fokus & Rolle | Lieblingselement / Operator |
| :--- | :--- | :--- | | :--- | :--- | :--- |
| ⛏️ **Minecraft** | Technical Automation & Redstone | Automatisierte Farmen, Create Mod, Server-Hosting | | ⛏️ **Minecraft** | Technical Automation & Redstone | Automatisierte Farmen, Create Mod, Server-Hosting |
| 🎯 **Rainbow Six Siege** | Tactical Anchor & Area Denial | Smoke, Mute, Thermite, Thatcher | | 🎯 **Rainbow Six Siege** | Tactical Anchor & Area Denial | Smoke, Mute, Thermite, Thatcher |
| ⚔️ **Warframe** | High-Level Survival & Grinding | Mesa Prime, Wisp, Volt | | ⚔️ **Warframe** | High-Level Survival & Grinding | Harrow, Ash, Oberon |
</details> </details>
@ -209,7 +182,7 @@ Ich bin **Nicki (Nicklas)**, angehender Softwareentwickler mit fundiertem Fokus
| :--- | :---: | :--- | | :--- | :---: | :--- |
| 📝 **Markdown Editor Pro** | `Avalonia UI``C#` | Desktop-Editor mit Live-Rendering, Math-Support und Theme-Engine. | | 📝 **Markdown Editor Pro** | `Avalonia UI``C#` | Desktop-Editor mit Live-Rendering, Math-Support und Theme-Engine. |
| 💧 **CloudDrop** | `ASP.NET Core``Docker` | Self-hosted File-Sharing Service für schnelle Uploads & temporäre Links. | | 💧 **CloudDrop** | `ASP.NET Core``Docker` | Self-hosted File-Sharing Service für schnelle Uploads & temporäre Links. |
| 💳 **KasseApp** | `C#``SQLite` • `Avalonia` | Modulares Kassensystem mit Offline-Synchronisation für Events & Vereine. | | 💳 **KasseApp** | `C#``PostgreSQL` • `Avalonia` | Modulares Kassensystem mit Offline-Synchronisation für Events & Vereine. |
| 🥤 **DrinkReminder** | `C#``Avalonia UI` | Schicker Desktop- & Mobile-Helfer für gesunde Hydration im Entwickleralltag. | | 🥤 **DrinkReminder** | `C#``Avalonia UI` | Schicker Desktop- & Mobile-Helfer für gesunde Hydration im Entwickleralltag. |
--- ---
@ -219,9 +192,9 @@ Ich bin **Nicki (Nicklas)**, angehender Softwareentwickler mit fundiertem Fokus
```csharp ```csharp
var nicki = new Developer var nicki = new Developer
{ {
Drink = "Kühles Spezi oder Club-Mate", Drink = "Wasser",
Workstation = "Pop!_OS on Linux Kernel", Workstation = "Fedora on Linux Kernel",
IDE = "JetBrains Rider 2024+", IDE = "JetBrains Rider",
Team = "WebCore Consulting", Team = "WebCore Consulting",
Motto = "Measure twice, refactor once, ship autonomously." Motto = "Measure twice, refactor once, ship autonomously."
}; };

View File

@ -74,7 +74,7 @@
<text class="title" x="0" y="14">🦊 NickiCloud <tspan font-weight="400" fill="var(--accent)"></tspan> <tspan font-weight="500" font-size="12" fill="var(--text-sub)">Persönliche Aktivität</tspan></text> <text class="title" x="0" y="14">🦊 NickiCloud <tspan font-weight="400" fill="var(--accent)"></tspan> <tspan font-weight="500" font-size="12" fill="var(--text-sub)">Persönliche Aktivität</tspan></text>
<rect x="510" y="0" width="190" height="22" rx="11" fill="var(--metric-bg)" stroke="var(--metric-border)" stroke-width="1" /> <rect x="510" y="0" width="190" height="22" rx="11" fill="var(--metric-bg)" stroke="var(--metric-border)" stroke-width="1" />
<circle cx="522" cy="11" r="4" fill="var(--accent)" /> <circle cx="522" cy="11" r="4" fill="var(--accent)" />
<text class="subtitle" x="532" y="15" font-weight="600">26 Commits im letzten Jahr</text> <text class="subtitle" x="532" y="15" font-weight="600">27 Commits im letzten Jahr</text>
</g> </g>
<!-- Month Labels --> <!-- Month Labels -->
<text class="lbl-month" x="34" y="54">Sep</text> <text class="lbl-month" x="34" y="54">Sep</text>
@ -1173,7 +1173,7 @@
<title>01.09.2026: 9 Commits</title> <title>01.09.2026: 9 Commits</title>
</rect> </rect>
<rect class="cell lvl-4" x="697" y="90" width="10" height="10" rx="2" style="animation-delay: 612ms;"> <rect class="cell lvl-4" x="697" y="90" width="10" height="10" rx="2" style="animation-delay: 612ms;">
<title>02.09.2026: 10 Commits</title> <title>02.09.2026: 11 Commits</title>
</rect> </rect>
<rect class="cell lvl-0" x="697" y="103" width="10" height="10" rx="2" style="animation-delay: 612ms;"> <rect class="cell lvl-0" x="697" y="103" width="10" height="10" rx="2" style="animation-delay: 612ms;">
<title>03.09.2026: 0 Commits</title> <title>03.09.2026: 0 Commits</title>
@ -1192,7 +1192,7 @@
<g transform="translate(34, 166)"> <g transform="translate(34, 166)">
<rect width="216" height="36" rx="8" fill="var(--metric-bg)" stroke="var(--metric-border)" stroke-width="1" /> <rect width="216" height="36" rx="8" fill="var(--metric-bg)" stroke="var(--metric-border)" stroke-width="1" />
<text x="12" y="27" font-size="16">📦</text> <text x="12" y="27" font-size="16">📦</text>
<text class="stat-val" x="40" y="20">26</text> <text class="stat-val" x="40" y="20">27</text>
<text class="stat-lbl" x="40" y="33">Jahres-Beiträge</text> <text class="stat-lbl" x="40" y="33">Jahres-Beiträge</text>
</g> </g>
<g transform="translate(264, 166)"> <g transform="translate(264, 166)">
@ -1209,28 +1209,28 @@
</g> </g>
<!-- Top Languages Bar --> <!-- Top Languages Bar -->
<g clip-path="url(#langBarClip)"> <g clip-path="url(#langBarClip)">
<rect x="34.0" y="215" width="388.0" height="8" fill="#a855f7"> <rect x="34.0" y="215" width="390.1" height="8" fill="#a855f7">
<title>C#: 57,4%</title> <title>C#: 57,7%</title>
</rect> </rect>
<rect x="422.0" y="215" width="265.0" height="8" fill="#e34c26"> <rect x="424.1" y="215" width="263.6" height="8" fill="#e34c26">
<title>HTML: 39,2%</title> <title>HTML: 39,0%</title>
</rect> </rect>
<rect x="687.0" y="215" width="14.9" height="8" fill="#563d7c"> <rect x="687.7" y="215" width="14.9" height="8" fill="#563d7c">
<title>CSS: 2,2%</title> <title>CSS: 2,2%</title>
</rect> </rect>
<rect x="701.9" y="215" width="2.7" height="8" fill="#f1e05a"> <rect x="702.6" y="215" width="2.7" height="8" fill="#f1e05a">
<title>JavaScript: 0,4%</title> <title>JavaScript: 0,4%</title>
</rect> </rect>
<rect x="704.6" y="215" width="2.7" height="8" fill="#012456"> <rect x="705.3" y="215" width="2.7" height="8" fill="#012456">
<title>PowerShell: 0,4%</title> <title>PowerShell: 0,4%</title>
</rect> </rect>
</g> </g>
<!-- Language Legend --> <!-- Language Legend -->
<g transform="translate(34, 238)"> <g transform="translate(34, 238)">
<circle cx="4" cy="4" r="4" fill="#a855f7" /> <circle cx="4" cy="4" r="4" fill="#a855f7" />
<text class="lang-lbl" x="13" y="7">C# 57,4%</text> <text class="lang-lbl" x="13" y="7">C# 57,7%</text>
<circle cx="89" cy="4" r="4" fill="#e34c26" /> <circle cx="89" cy="4" r="4" fill="#e34c26" />
<text class="lang-lbl" x="98" y="7">HTML 39,2%</text> <text class="lang-lbl" x="98" y="7">HTML 39,0%</text>
<circle cx="188" cy="4" r="4" fill="#563d7c" /> <circle cx="188" cy="4" r="4" fill="#563d7c" />
<text class="lang-lbl" x="197" y="7">CSS 2,2%</text> <text class="lang-lbl" x="197" y="7">CSS 2,2%</text>
<circle cx="273" cy="4" r="4" fill="#f1e05a" /> <circle cx="273" cy="4" r="4" fill="#f1e05a" />

Before

Width:  |  Height:  |  Size: 64 KiB

After

Width:  |  Height:  |  Size: 64 KiB

View File

@ -46,7 +46,7 @@
<text class="title" x="0" y="14">⏱️ Coding Biorhythmus <tspan font-weight="400" fill="var(--accent)"></tspan> <tspan font-weight="500" font-size="12" fill="var(--text-sub)">Aktivitäts-Phasen (CET)</tspan></text> <text class="title" x="0" y="14">⏱️ Coding Biorhythmus <tspan font-weight="400" fill="var(--accent)"></tspan> <tspan font-weight="500" font-size="12" fill="var(--text-sub)">Aktivitäts-Phasen (CET)</tspan></text>
<rect x="390" y="0" width="310" height="22" rx="11" fill="var(--metric-bg)" stroke="var(--metric-border)" stroke-width="1" /> <rect x="390" y="0" width="310" height="22" rx="11" fill="var(--metric-bg)" stroke="var(--metric-border)" stroke-width="1" />
<circle cx="402" cy="11" r="4" fill="var(--accent)" /> <circle cx="402" cy="11" r="4" fill="var(--accent)" />
<text class="subtitle" x="412" y="15" font-weight="600">🌙 Night-Owl (Höchste Produktivität am Abend & nachts)</text> <text class="subtitle" x="412" y="15" font-weight="600">🌙 Night-Owl (Produktiv am Abend und nachts)</text>
</g> </g>
<!-- Bucket: Morgen --> <!-- Bucket: Morgen -->
<g transform="translate(34, 60)"> <g transform="translate(34, 60)">
@ -69,15 +69,15 @@
<text class="bar-lbl" x="0" y="12">🌆 Abend</text> <text class="bar-lbl" x="0" y="12">🌆 Abend</text>
<text class="bar-time" x="110" y="12">(18:00 - 24:00)</text> <text class="bar-time" x="110" y="12">(18:00 - 24:00)</text>
<rect x="200" y="0" width="430" height="16" rx="4" fill="var(--metric-bg)" stroke="var(--metric-border)" stroke-width="0.8" /> <rect x="200" y="0" width="430" height="16" rx="4" fill="var(--metric-bg)" stroke="var(--metric-border)" stroke-width="0.8" />
<rect x="200" y="0" width="294.1" height="16" rx="4" fill="var(--bar-evening)" /> <rect x="200" y="0" width="316.9" height="16" rx="4" fill="var(--bar-evening)" />
<text class="stat-val" x="644" y="13" font-size="12">68,4%</text> <text class="stat-val" x="644" y="13" font-size="12">73,7%</text>
</g> </g>
<!-- Bucket: Nacht --> <!-- Bucket: Nacht -->
<g transform="translate(34, 168)"> <g transform="translate(34, 168)">
<text class="bar-lbl" x="0" y="12">🌙 Nacht</text> <text class="bar-lbl" x="0" y="12">🌙 Nacht</text>
<text class="bar-time" x="110" y="12">(00:00 - 06:00)</text> <text class="bar-time" x="110" y="12">(00:00 - 06:00)</text>
<rect x="200" y="0" width="430" height="16" rx="4" fill="var(--metric-bg)" stroke="var(--metric-border)" stroke-width="0.8" /> <rect x="200" y="0" width="430" height="16" rx="4" fill="var(--metric-bg)" stroke="var(--metric-border)" stroke-width="0.8" />
<rect x="200" y="0" width="113.1" height="16" rx="4" fill="var(--bar-night)" /> <rect x="200" y="0" width="90.7" height="16" rx="4" fill="var(--bar-night)" />
<text class="stat-val" x="644" y="13" font-size="12">26,3%</text> <text class="stat-val" x="644" y="13" font-size="12">21,1%</text>
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

View File

@ -184,8 +184,8 @@ public static class StatsCalculator
}; };
string archetype = (nightCount + eveningCount >= morningCount + afternoonCount) string archetype = (nightCount + eveningCount >= morningCount + afternoonCount)
? "🌙 Night-Owl (Höchste Produktivität am Abend & nachts)" ? "🌙 Night-Owl (Produktiv am Abend und nachts)"
: "⚡ Day-Runner (Fokus während der regulären Tagesstunden)"; : "⚡ Day-Runner (Fokus am Tag)";
var productivity = new ProductivityStats var productivity = new ProductivityStats
{ {

View File

@ -387,7 +387,7 @@ public static class SvgGenerator
sb.AppendLine(" <g transform=\"translate(24, 20)\">"); sb.AppendLine(" <g transform=\"translate(24, 20)\">");
sb.AppendLine(" <text class=\"title\" x=\"0\" y=\"14\">⏱️ Coding Biorhythmus <tspan font-weight=\"400\" fill=\"var(--accent)\">•</tspan> <tspan font-weight=\"500\" font-size=\"12\" fill=\"var(--text-sub)\">Aktivitäts-Phasen (CET)</tspan></text>"); sb.AppendLine(" <text class=\"title\" x=\"0\" y=\"14\">⏱️ Coding Biorhythmus <tspan font-weight=\"400\" fill=\"var(--accent)\">•</tspan> <tspan font-weight=\"500\" font-size=\"12\" fill=\"var(--text-sub)\">Aktivitäts-Phasen (CET)</tspan></text>");
string badgeText = prod.DevArchetype; string badgeText = XmlEscape(prod.DevArchetype);
sb.AppendLine($" <rect x=\"390\" y=\"0\" width=\"310\" height=\"22\" rx=\"11\" fill=\"var(--metric-bg)\" stroke=\"var(--metric-border)\" stroke-width=\"1\" />"); sb.AppendLine($" <rect x=\"390\" y=\"0\" width=\"310\" height=\"22\" rx=\"11\" fill=\"var(--metric-bg)\" stroke=\"var(--metric-border)\" stroke-width=\"1\" />");
sb.AppendLine($" <circle cx=\"402\" cy=\"11\" r=\"4\" fill=\"var(--accent)\" />"); sb.AppendLine($" <circle cx=\"402\" cy=\"11\" r=\"4\" fill=\"var(--accent)\" />");
sb.AppendLine($" <text class=\"subtitle\" x=\"412\" y=\"15\" font-weight=\"600\">{badgeText}</text>"); sb.AppendLine($" <text class=\"subtitle\" x=\"412\" y=\"15\" font-weight=\"600\">{badgeText}</text>");
@ -429,6 +429,16 @@ public static class SvgGenerator
return sb.ToString(); return sb.ToString();
} }
private static string XmlEscape(string? text)
{
if (string.IsNullOrEmpty(text)) return string.Empty;
return text.Replace("&", "&amp;")
.Replace("<", "&lt;")
.Replace(">", "&gt;")
.Replace("\"", "&quot;")
.Replace("'", "&apos;");
}
private static void RenderMetricCard(StringBuilder sb, int x, int y, int w, int h, string icon, string value, string label) private static void RenderMetricCard(StringBuilder sb, int x, int y, int w, int h, string icon, string value, string label)
{ {
sb.AppendLine($" <g transform=\"translate({x}, {y})\">"); sb.AppendLine($" <g transform=\"translate({x}, {y})\">");