Initial commit

This commit is contained in:
2026-02-05 12:53:43 +00:00
commit 02f363357a
59 changed files with 23130 additions and 0 deletions

1
.silverbullet.auth.json Normal file
View File

@@ -0,0 +1 @@
{"secret_key":"RUooAjUF+YDmqw+DEjhxdEhGXLX9/fV0W5ucFJTDfH4=","auth_hash":"19f352b46cc85f2d5a751d48c4637592ff73b1422ce1498779c212172ec524ba","salt":"3zppzGkWAnbnKtNJp+cgRg=="}

20
Bürokratie/Steuern.md Normal file
View File

@@ -0,0 +1,20 @@
# 💰 Steuern & Finanzamt
## Basisdaten
| Person | Steuer-ID (TIN) | Steuernummer (FA) | ELSTER Zertifikat Ort |
| :--- | :--- | :--- | :--- |
| **Person A** | `12 345 678 901` | `123/456/789` | `/safe/docs/elster_a.pfx` |
| **Person B** | `...` | `...` | `...` |
## 📂 Checkliste Steuererklärung (Belege sammeln)
Jedes Jahr bis zum `31.07.` (oder Fristverlängerung beachten).
* **Einkommen:** Lohnsteuerbescheinigungen.
* **Werbungskosten:**
* [ ] Fahrtwege (km zur Arbeit).
* [ ] Arbeitsmittel (Laptop, Schreibtisch - Rechnungen!).
* [ ] Fortbildungen.
* **Haushaltsnahe Dienstleistungen:**
* [ ] Handwerkerrechnungen (Nur Arbeitslohn, keine Teile!).
* [ ] Nebenkostenabrechnung (Hausmeister, Gärtner).
* **Versicherungen:** Beiträge KV/PV/RV.

65
CONFIG.md Normal file
View File

@@ -0,0 +1,65 @@
This is where you configure SilverBullet to your liking. See [[^Library/Std/Config]] for a full list of configuration options.
```space-lua
config.set {
plugs = {
"github:joekrill/silverbullet-treeview/treeview.plug.js"
},
-- The treeview plug configuration
treeview = {
-- Determines where the panel is displayed:
-- - "lhs" - left hand side
-- - "rhs" - right hand side
-- - "bhs" - bottom
-- - "modal" - in a modal
position = "lhs",
-- Must be > 0.
-- position = "lhs" | "rhs": determines the width of the panel.
-- position = "modal": sets the margin around the modal window.
-- position = "bhs": No effect
size=0.5,
dragAndDrop = {
-- Set to false to disable drag-and-drop
enabled = true,
-- Set to false to disable the confirmation prompt shown when dragging and
-- dropping pages that causes them to be renamed/moved.
confirmOnRename = true
},
-- An array of exclusion rules that will exclude pages from being
-- displayed in the sidebar.
exclusions = {
{
-- Filter by regular expression:
type = "regex",
-- Regular Expression string to exclude pages from the tree
-- Examples:
-- - Any page that is all-caps: "^[A-Z]+$"
-- - A specific set of pages: "^(?:CONFIG|Library|index).*$"
-- - Any path containing Hidden (e.g. test/Hidden/page1): "Hidden"
rule="^(?:CONFIG|Library|index).*$",
-- Optional: set to true to negate the rule, only showing pages that match this regex.
negate= false,
},
{
-- Filter by page tags:
type = "tags",
tags = {"meta"},
-- Optional: set to true to negate the rule, only showing pages that include any of the tags.
negate = false
}
}
}
}
actionButton.define {
icon = "sidebar",
description = "Toggle Tree View",
run = function()
editor.invokeCommand("Tree View: Toggle")
end
}
```

21
Freizeit/Reisen.md Normal file
View File

@@ -0,0 +1,21 @@
# ✈️ Reisen & Packlisten
## 📄 Dokumente (Check vor Abflug)
* [ ] Reisepässe (Gültig bis mindestens 6 Monate nach Rückkehr?)
* [ ] Auslandskrankenversicherung (Schein/App dabei?)
* [ ] Kreditkarten (Limit geprüft? PIN bekannt?)
## 🎒 Standard-Packliste (Basis)
* **Elektronik:**
* [ ] USB-C Ladegeräte (Anker Multiport)
* [ ] Powerbank (Darf nur ins Handgepäck!)
* [ ] Kopfhörer (Noise Cancelling)
* **Hygiene:**
* [ ] Kulturbeutel (Flüssigkeiten < 100ml für Flug?)
* [ ] Medikamente (siehe [Reiseapotheke](/notfall/medizin))
## 🏕️ Camping / Ferienhaus Spezials
* [ ] Gewürze-Box (Salz, Pfeffer, Öl)
* [ ] Scharfes Messer (fehlt in jedem Ferienhaus)
* [ ] Spüli & Schwamm
* [ ] Mehrfachsteckdose

View File

@@ -0,0 +1 @@
{"type":"excalidraw","version":2,"elements":[],"appState":{},"files":{}}

94
Gesundheit/Medikamente.md Normal file
View File

@@ -0,0 +1,94 @@
# 💊 Hausapotheke & Medikamente
<div class="is-danger">
<strong>HAFTUNGSAUSSCHLUSS:</strong> Dies ist keine medizinische Beratung. Bei Unklarheiten immer die Packungsbeilage lesen oder Arzt/Apotheker konsultieren.<br>
<strong>Notruf:</strong> <a href="tel:112">112</a> | <strong>Giftnotruf:</strong> <a href="tel:116117">116 117</a> (Ärztl. Bereitschaftsdienst)
</div>
---
## ✅ Quick-Check (für Babysitter)
<div class="is-warning">
Für externe Betreuer: Folgende Medikamente dürfen nach Rücksprache oder bei klarem Bedarf gegeben werden. <strong>Alles andere ist tabu!</strong>
</div>
1. **Wunde:** Octenisept (Sprühen), Pflaster.
2. **Insektenstich:** Fenistil Gel.
3. **Fieber > 39,0°C:** Paracetamol Zäpfchen (Dosierung siehe unten!).
4. **Verdacht auf Vergiftung:** 📞 **Sofort anrufen!**
---
## 1. Schmerzen & Fieber (Analgetika)
<div class="is-danger">
<strong>Pädiatrie-Warnung:</strong> Kinder-Dosis immer nach <strong>Körpergewicht (KG)</strong> berechnen! Tabletten für Erwachsene niemals einfach "teilen" (ungenaue Wirkstoffverteilung).
</div>
| Wirkstoff | Handelsname (Bsp.) | Dosis (Erw.) | 👶 Pädiatrie / Kind | Wichtige Hinweise | Bestand |
| :--- | :--- | :--- | :--- | :--- | :--- |
| **Ibuprofen** | *Nurofen / Ibuflam* | 400 mg | ✅ **JA** (> 6kg) | Wirkt auch entzündungshemmend. **Kind:** 10mg pro kg KG. | ✅ |
| **Paracetamol** | *Ben-u-ron* | 500 mg | ✅ **JA** (ab Geburt) | Mittel der 1. Wahl bei Fieber. **Kind:** 10-15mg pro kg KG. | ✅ |
| **Acetylsalicylsäure (ASS)** | *Aspirin* | 500 mg | ❌ **LEBENSGEFAHR** | **Reye-Syndrom!** Niemals unter 12 Jahren geben. | ✅ |
---
## 2. Magen & Darm (Gastrointestinal)
| Indikation | Wirkstoff | Produkt | 👶 Pädiatrie / Kind | Hinweise | Verfall |
| :--- | :--- | :--- | :--- | :--- | :--- |
| **Durchfall** | Loperamid | *Imodium* | ❌ **NEIN** (< 12 J.) | Lahmt den Darm. Bei Kindern Erreger ausschwemmen lassen. | `MM/JJ` |
| **Dehydration** | Elektrolyte | *Elotrans / Oralpädon* | ✅ **JA** | Wichtigste Maßnahme bei Brechdurchfall! | `MM/JJ` |
| **Übelkeit** | Dimenhydrinat | *Vomex* | ⚠️ **VORSICHT** | Kann Atemdepression auslösen. Nur Zäpfchen nach Gewicht! | `MM/JJ` |
| **Sodbrennen** | Pantoprazol | *Pantozol* | ⚠️ **ARZT** | Protonenpumpenhemmer. Nicht für Kinder. | `MM/JJ` |
| **Blähungen** | Simeticon | *Lefax / Sab Simplex* | ✅ **JA** | Wirkt rein physikalisch (Entschäumer). Unbedenklich. | `MM/JJ` |
---
## 3. Erkältung & Atemwege
<div class="is-warning">
<strong>Achtung:</strong> Ätherische Öle (Menthol/Kampfer) können bei Säuglingen einen Stimmritzenkrampf auslösen. Nur spezielle Baby-Produkte nutzen!
</div>
| Indikation | Wirkstoff | Produkt | 👶 Pädiatrie / Kind | Hinweise | Verfall |
| :--- | :--- | :--- | :--- | :--- | :--- |
| **Schnupfen** | Xylometazolin | *Nasic / Olynth* | ⚠️ **DOSIS BEACHTEN** | Strikt trennen: **0,025% (Baby)** vs. 0,1% (Erw). | `MM/JJ` |
| **Hustenlöser** | Acetylcystein | *ACC Akut* | ✅ **JA** (Saft) | Nur morgens geben (Abhusten). Viel trinken! | `MM/JJ` |
| **Halsweh** | Antiseptika | *Neo-Angin* | ❌ **NEIN** | Verschluckungsgefahr bei Lutschtabletten. | `MM/JJ` |
| **Einreiben** | Ätherische Öle | *Wick VapoRub* | ❌ **NEIN** | Nur Thymian-Myrte-Balsam für Kinder nutzen. | `MM/JJ` |
---
## 4. Haut, Allergie & Wunden
| Wirkstoff | Typ | Produkt | 👶 Pädiatrie / Kind | Anwendung | Verfall |
| :--- | :--- | :--- | :--- | :--- | :--- |
| **Cetirizin** | Antihistaminikum | *Cetirizin Saft* | ✅ **JA** (Saft) | Bei Heuschnupfen/Juckreiz. Macht evtl. müde. | `MM/JJ` |
| **Dimetinden** | Gel | *Fenistil* | ✅ **JA** | Insektenstiche & leichter Sonnenbrand. | `MM/JJ` |
| **Octenidin** | Desinfektion | *Octenisept* | ✅ **JA** | Brennt nicht auf der Haut. | `MM/JJ` |
| **Povidon-Jod** | Desinfektion | *Betaisodona* | ⚠️ **ARZT** | Jod-Resorption beachten (Schilddrüse!). | `MM/JJ` |
| **Hydrocortison** | Creme 0.5% | *Soventol* | ⚠️ **KURZZEITIG** | Nur dünn auftragen. Haut ist dünner bei Kindern. | `MM/JJ` |
---
## 5. Dosierhilfe: Aktuelles Gewicht der Kinder
Hier eintragen, um im Notfall (Nachts um 3 Uhr) nicht rechnen oder wiegen zu müssen.
| Kind | Datum | Gewicht (kg) | Max. Paracetamol (15mg/kg) | Max. Ibuprofen (10mg/kg) |
| :--- | :--- | :--- | :--- | :--- |
| *Name* | `TT.MM.` | `XX` kg | `Gewicht * 15` = **... mg** | `Gewicht * 10` = **... mg** |
| *Name* | `TT.MM.` | `XX` kg | ... | ... |
---
## 6. Verbandskasten Inventur
* [ ] Pflaster-Set (Strips & Meterware)
* [ ] Sterile Kompressen
* [ ] Mullbinden
* [ ] Verbandsschere (Scharf!)
* [ ] Zeckenzange / Karte
* [ ] Fieberthermometer (+ Ersatzbatterie CR2032)

41
Haus/Elektrik.md Normal file
View File

@@ -0,0 +1,41 @@
# ⚡ Elektrik & Sicherungskasten
<div class="is-danger">
<strong>Sicherheitsregel:</strong> Arbeiten an der Elektrik nur durch Fachpersonal. Vor Arbeiten immer: <strong>Freischalten, gegen Wiedereinschalten sichern, Spannungsfreiheit feststellen.</strong>
</div>
## 📍 Hauptverteilung (Sicherungskasten)
**Ort:** `[z.B. Flur EG / Keller]`
### FI-Schutzschalter (RCD)
Der FI-Schalter schützt Personen vor Stromschlag.
* **Test-Intervall:** 2x jährlich (Drücken der "T"-Taste).
* **Auslöser:** `30mA` Differenzstrom.
### Belegungsplan (Sicherungen)
| Nr. | Typ | Ampere | Zuständig für (Räume / Großgeräte) |
| :--- | :--- | :--- | :--- |
| **1** | B16 | 16A | Wohnzimmer (Licht & Steckdosen) |
| **2** | B16 | 16A | Küche (Allgemein) |
| **3** | B16 | 16A | *Kühlschrank (Separat)* |
| **4** | B16 | 16A | Waschmaschine |
| **5-7** | **3-Phasen** | 16A | E-Herd / Backofen (Drehstrom) |
| **8** | B16 | 16A | Außenbereich / Garage |
---
## 💡 Leuchtmittel-Inventar
Damit man im Baumarkt weiß, welche Fassung man braucht.
| Raum | Lampe | Fassung (Sockel) | Watt / Lumen | Farbtemp. (Kelvin) |
| :--- | :--- | :--- | :--- | :--- |
| WZ | Decke | `E27` | LED 10W | 2700K (Warmweiß) |
| Küche | Spots | `GU10` | LED 5W | 4000K (Neutral) |
| Bad | Spiegel | `E14` | LED 4W | 3000K |
---
## 🔌 Spezielle Anschlüsse
* **Starkstrom (CEE):** Vorhanden in Garage? `[Ja/Nein]` (z.B. 16A oder 32A rot).
* **Außensteckdosen:** Schaltbar von innen? `[Ja/Nein]` (Schalterort: `...`).

24
Haus/Garten.md Normal file
View File

@@ -0,0 +1,24 @@
# 🌻 Garten & Pflanzen-Datenbank
## 🗺️ Pflanzplan & Standorte
* **Vorgarten (Nordseite):** Schattenverträglich (z.B. Farn, Funkien).
* **Terrasse (Südseite):** Mediterran (Lavendel, Rosmarin).
## 🌿 Pflanzen-Steckbriefe
| Pflanze (Lat. Name) | Standort | Wasserbedarf | Dünger (NPK) | Schnitt |
| :--- | :--- | :--- | :--- | :--- |
| **Hortensie** *(Hydrangea)* | Halbschatten | Hoch (Nie austrocknen!) | Saurer Boden (pH < 5) | Frühjahr (nur alte Blüten) |
| **Lavendel** *(Lavandula)* | Vollsonne | Gering (Staunässe vermeiden) | Kalkhaltig, Mager | Sommer (nach Blüte) + Frühjahr |
| **Tomaten** | Gewächshaus | Täglich | Starkzehrer (Kompost) | Ausgeizen (wöchentlich) |
## 🚜 Geräte-Wartung
| Gerät | Modell | Benzin/Öl/Akku | Wartung |
| :--- | :--- | :--- | :--- |
| **Rasenmäher** | Honda ... | Super E5 (Kein E10!) | Ölwechsel: Jährlich (SAE 30) |
| **Heckenschere** | Makita 18V | Akku LXT | Messer harzen & ölen |
<div class="is-warning">
<strong>Frost-Warnung:</strong> Empfindliche Kübelpflanzen (Oleander, Olive) reinholen, sobald Nachtwerte unter +5°C fallen.
</div>

18
Haus/Großgeräte.md Normal file
View File

@@ -0,0 +1,18 @@
# 🧺 Großgeräte & Inventar
## Küche
| Gerät | Marke / Modell | Kaufdatum | Garantie bis | Seriennummer (S/N) |
| :--- | :--- | :--- | :--- | :--- |
| **Kühlschrank** | Liebherr ... | `01.01.2020` | `Abgelaufen` | `123456789` |
| **Spülmaschine** | Siemens ... | `15.06.2023` | `15.06.2025` | `SN-998877` |
| **Herd/Ofen** | Neff ... | ... | ... | ... |
> 📎 **Tipp:** Verlinke hier die PDFs der Handbücher (im Wiki.js Asset Manager hochladen)!
## Hauswirtschaft
| Gerät | Marke / Modell | Kaufdatum | Wartung |
| :--- | :--- | :--- | :--- |
| **Waschmaschine** | Miele ... | `...` | Flusensieb regelmäßig reinigen! |
| **Trockner** | Bosch ... | `...` | Wärmetauscher absaugen. |

22
Haus/Heizung.md Normal file
View File

@@ -0,0 +1,22 @@
# Heizungsanlage
## Basisdaten
- **Modell:** *z.B. Viessmann Vitodens 200*
- **Installationsjahr:** *z.B. 2018*
- **Brennstoff:** Gas / Öl / Wärmepumpe
- **Letzte Wartung:** `TT.MM.JJJJ`
- **Nächste Wartung fällig:** `TT.MM.JJJJ`
## Bedienung & Einstellungen
* **Sommerbetrieb (Nur Warmwasser):** Anleitung / Foto der Einstellung
* **Winterbetrieb (Heizung + Wasser):** Anleitung / Foto
* **Wasserdruck:** Sollte zwischen **1.5 und 2.0 bar** liegen.
* *Nachfüllen:* Der Schlauch befindet sich [Ort].
## Notfall-Modus & Störungen
Sollte die Heizung auf "Störung" (Rot) stehen:
1. **Reset-Knopf (R)** für 5 Sekunden drücken.
2. Warten bis der Brenner neu startet.
3. Falls Fehlercode **F4** erscheint: Notdienst anrufen (siehe [Kontakte](/notfall/kontakte)).
> **Wichtig:** Der Haupthahn für das Gas befindet sich gelb markiert direkt unter der Therme.

23
Haus/Renovierung.md Normal file
View File

@@ -0,0 +1,23 @@
# 🎨 Renovierung & Materialien
## 🖌️ Wandfarben & Lacke
| Zimmer | Datum | Hersteller / Produkt | Farbcode / Name | Reste vorhanden? |
| :--- | :--- | :--- | :--- | :--- |
| **Wohnzimmer** | `2023` | Alpina | *Weiß, matt* | ✅ (Keller) |
| **Kinderzimmer** | `2024` | Schöner Wohnen | *Hellblau (Code: ...)* | ❌ Leer |
| **Türen/Zargen** | `2020` | Caparol | *Reinweiß RAL 9010 (Lack)* | ✅ |
## 🪵 Böden
| Raum | Art | Produkt / Serie | Verlegeart | Reserve-Paket? |
| :--- | :--- | :--- | :--- | :--- |
| **EG Komplett** | Parkett | *Eiche Landhausdiele, geölt* | Schwimmend | ✅ (Dachboden) |
| **Bad** | Fliese | *Villeroy & Boch, 60x60* | Grau matt | ✅ (2 Stück) |
## 📏 Raum-Maße (Quick-Ref)
| Raum | Fläche (m²) | Deckenhöhe | Besonderheit |
| :--- | :--- | :--- | :--- |
| **Wohnzimmer** | `25 m²` | `2.50 m` | Dachschräge ab 1.20m |
| **Küche** | `12 m²` | `2.50 m` | Fliesenspiegel Höhe: ... |

29
Haus/Versorgung.md Normal file
View File

@@ -0,0 +1,29 @@
# 📂 Verträge & Abos
<div class="is-warning">
<strong>Tipp:</strong> Kündigungsfristen im digitalen Kalender mit Erinnerung (1 Monat vorher) eintragen.
</div>
## 🏠 Wohnen & Energie
| Anbieter | Vertragsart | Kunden-Nr. | Kosten (mtl.) | Kündigungsfrist | Laufzeit bis |
| :--- | :--- | :--- | :--- | :--- | :--- |
| **[Strom-Versorger]** | Strom | `123456` | `XX,XX €` | 6 Wochen | `TT.MM.JJ` |
| **[Gas-Versorger]** | Gas | `123456` | `XX,XX €` | 6 Wochen | `TT.MM.JJ` |
| **[Internet]** | DSL/Glasfaser | `123456` | `XX,XX €` | 1 Monat | `TT.MM.JJ` |
## 🛡️ Versicherungen
| Gesellschaft | Art | Schein-Nr. | Beitrag (jährl.) | Fällig am |
| :--- | :--- | :--- | :--- | :--- |
| **[Name]** | Haftpflicht | `...` | `XX €` | `01.01.` |
| **[Name]** | Hausrat | `...` | `XX €` | `01.01.` |
| **[Name]** | Gebäude | `...` | `XX €` | `01.01.` |
## 📺 Streaming & Dienste
| Dienst | Email/User | Preis | Zyklus | Kündbar |
| :--- | :--- | :--- | :--- | :--- |
| **Netflix** | `user@mail.com` | `15 €` | Mtl. | Monatlich |
| **Spotify** | `user@mail.com` | `10 €` | Mtl. | Monatlich |
| **Amazon Prime** | `user@mail.com` | `89 €` | Jährl. | Jährlich |

23
Haus/Wartung.md Normal file
View File

@@ -0,0 +1,23 @@
# 📅 Jahres-Wartungsplan
## 🌸 Frühling (März/April)
* [ ] **Gartenwasser:** Außenhahn wieder in Betrieb nehmen.
* [ ] **Auto:** Reifenwechsel (Winter -> Sommer).
* [ ] **Dach:** Sichtprüfung nach Stürmen (Ziegel locker?).
* [ ] **Terrasse:** Kärchern / Ölen.
## ☀️ Sommer (Juli/August)
* [ ] **Heizung:** Ist der Sommerbetrieb aktiv? (Nur Warmwasser).
* [ ] **Öltank/Gastank:** Füllstand prüfen, ggf. günstig nachtanken ("Antizyklisch kaufen").
## 🍂 Herbst (Oktober/November)
* [ ] **Gartenwasser:** Absperren & entleeren (Frostschutz).
* [ ] **Auto:** Reifenwechsel (Sommer -> Winter) + Frostschutz Wischwasser.
* [ ] **Dachrinne:** Von Laub befreien (bevor der Schnee kommt).
* [ ] **Heizung:** Wasserdruck prüfen, Heizkörper entlüften.
* [ ] **Lüftungsanlage:** Filter wechseln (Pollenflug vorbei).
## ❄️ Winter (Dezember/Januar)
* [ ] **Rauchmelder:** Jährlicher Test & Batteriewechsel.
* [ ] **Verbandskasten:** Verfallsdaten prüfen.
* [ ] **Dokumente:** Ordner ausmisten / Steuer vorbereiten.

1
IT/Basics.md Normal file
View File

@@ -0,0 +1 @@
Internet Telekom

77
IT/Ports.md Normal file
View File

@@ -0,0 +1,77 @@
# 🔌 Masterplan zur Port-Zuweisung
## ☁️ VPS Gateway (Public Ingress)
*Hier läuft nur das Nötigste für Routing und Management.*
| Dienst | **Host Port** | Inerner Port | Notizen |
| :--- | :--- | :--- | :--- |
| **HTTP Ingress** (Pangolin) | **80** | 80 | Öffentlicher Web-Traffic |
| **HTTPS Ingress** (Pangolin) | **443** | 443 | Öffentlicher SSL-Traffic |
| **Middleware Manager** | **3456** | 3456 | UI für Pangolin |
| **Gotify** | **8080** | **80** | Push Notifications |
---
### 🏠 Home Node: Admin & System
*(Ports 9000 - 9999)*
| Dienst | **Host Port** | Interner Port | Notizen |
| :--- | :--- | :--- | :--- |
| **dockman** | **9000** | 8080 | Stack-Manager (Haupt-Cockpit) |
| **Glance** | **9001** | 8080 | Dashboard / Startseite |
| **Uptime Kuma** | **9002** | 3001 | Status-Überwachung |
| **Whats Up Docker** | **9003** | 3000 | Update-Benachrichtigungen |
| **Omnitools** | **9004** | 80 | Web UI Tools |
### 🏠 Home Node: Core Infrastruktur
*(Standard Ports)*
| Dienst | **Host Port** | Interner Port | Notizen |
| :--- | :--- | :--- | :--- |
| **Vaultwarden** | **8800** | 80 | Passwort-Manager |
| **Gitea (Web)** | **3000** | 3000 | Code Hosting |
| **Gitea (SSH)** | **2222** | 22 | **Kritisch:** SSH Passthrough |
| **Seafile** | **8900** | 80 | Datei-Synchronisation |
### 🏠 Home Node: Smart Home
*(IoT Standard Ports)*
| Dienst | **Host Port** | Interner Port | Notizen |
| :--- | :--- | :--- | :--- |
| **Home Assistant** | **8123** | 8123 | Automatisierungs-Hub |
| **MagicMirror** | **8180** | 8080 | Smart Mirror Display |
### 🏠 Home Node: Medien
*(Ports 7000 - 7999)*
| Dienst | **Host Port** | Interner Port | Notizen |
| :--- | :--- | :--- | :--- |
| **Jellyfin** | **7003** | 8096 | Video Streaming |
| **Immich** | **7999** | 2283 | Foto-Backup |
| **Immich-Drop** | **7998** | 8080 | Foto-Upload |
| **Immich-Public** | **7997** | 3000 | Foto-Sharing |
| **Immich-Kiosk** | **7996** | 3000 | Foto-Kiosk |
| **Immich-Tools** | **7995** | 3000 | Immich Powertools |
| **Audiobookshelf** | **7001** | 80 | Hörbücher |
| **RomM** | **7000** | 8080 | Retro Game Manager |
### 🏠 Home Node: Produktivität & SaaS
*(Ports 8000 - 8099)*
| Dienst | **Host Port** | Interner Port | Notizen |
| :--- | :--- | :--- | :--- |
| **Paperless-ngx** | **8000** | 8000 | Dokumentenmanagement |
| **Focalboard** | **8001** | 8000 | Aufgabenverwaltung |
| **Stirling PDF** | **8002** | 8080 | PDF Werkzeuge |
| **Gramps** | **8003** | 5000 | Ahnentafel |
| **Silverbullet** | **8004** | 3000 | Markdown Notizen |
| **Rx Resume** | **8005** | 3000 | Lebenslauf-Ersteller |
| **Fossflow** | **8006** | 80 | Projektmanagement |
| **Trip** | **8007** | 80 | Reisen/Karten |
| **Norish** | **8008** | 80 | Rezepte/Ernährung |
| **Koffan** | **8009** | 80 | Einkaufszettel |
| **Yubal** | **8010** | 80 | YT-Downloader |
---

28
IT/Services.md Normal file
View File

@@ -0,0 +1,28 @@
# 🖥️ [[]]
- Audiobookshelf 📼
- dockman 🧬
- filegator 💾
- focalboard 📇
- fossflow 📐
- gitea 🗳️
- gramps 👨‍👩‍👧‍👦
- glance 📱
- home assistant 🛎️
- immich 🖼️
- IT Tools ⌨️
- jellyfin 🎥
- Koffan 🗒️
- magicmirror 🧚🏼‍♂️
- norish 👩🏼‍🍳👨🏼‍🍳
- omnitools 📑
- paperless 🗃️
- rx resume 👨🏼‍🎓
- RomM 🎮
- seafile 🗄️
- silverbullet 📒
- stirling pdf 📎
- trip 🗺️
- uptime kuma 📊
- vaultwarden 🗝️
- whats up docker 📫
- yubal 📥

View File

@@ -0,0 +1,31 @@
# VW Golf (XX-AB 123)
## 📊 Basisdaten
| Parameter | Wert |
| :--- | :--- |
| **FIN / VIN** | `W V W Z Z Z ...` |
| **Erstzulassung** | `01.01.2020` |
| **HSN / TSN** | `0603 / ...` (Wichtig für Ersatzteile!) |
| **Motorcode** | `...` |
| **Lackcode** | `...` (Steht oft im Kofferraum/Serviceheft) |
## ⛽ Betriebsstoffe & Drücke
<div class="is-warning">
Werte gelten für **kalte** Reifen.
</div>
| Beladung | Vorne (bar) | Hinten (bar) |
| :--- | :--- | :--- |
| **Leer (1-2 Pers)** | 2.3 | 2.1 |
| **Voll / Urlaub** | 2.6 | 2.9 |
* **Motoröl:** `5W-30` (Norm: VW 504 00) - *Füllmenge: 4,5 Liter*
* **Kühlmittel:** `G13` (Rosa)
* **Wischwasser:** Ca. 3-4 Liter Tankvolumen.
* **Scheibenwischer:** Vorne `Bosch A863S`, Hinten `A330H`
## 📅 Wartungshistorie
| Datum | km-Stand | Was wurde gemacht? | Wer? |
| :--- | :--- | :--- | :--- |
| `15.10.2025` | 120.000 | Ölwechsel + Filter | Werkstatt Müller |
| `01.04.2025` | 115.000 | Räderwechsel (Sommer) | Eigenleistung |

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,30 @@
---
name: Library/LogeshG5/silverbullet-excalidraw
tags: meta/library
files:
- excalidraw.plug.js
share.uri: "https://github.com/LogeshG5/silverbullet-excalidraw/blob/main/PLUG.md"
share.hash: 199c6406
share.mode: pull
---
# SilverBullet plug for Excalidraw diagrams
This plug adds [Excalidraw](https://excalidraw.com/) support to Silverbullet.
### Create New Diagram
Run `Excalidraw: Create diagram` command and type in the name of the diagram. (or) Use `/excalidraw` slash command.
A code widget will be inserted. Move away from the code widget and you will see the diagram.
If you wish to create SVG/PNG files, Run `Excalidraw: Create SVG/PNG diagram`.
### Use Document Picker
Run `Navigate: Document Picker` and select .excalidraw files to open the editor.
### Edit SVG/PNG Diagram
Run `Excalidraw: Edit diagram`.
If multiple diagrams are present in a page, you will be prompted to choose one.

View File

@@ -0,0 +1,111 @@
---
author: malys
description: Generate and copy links to specific cursor positions and headers in markdown documents
name: "Library/Malys/CursorPosition"
tags: meta/library
share.uri: "https://github.com/malys/silverbullet-libraries/blob/main/src/CursorPosition.md"
share.hash: a8544328
share.mode: pull
---
# Cursor Position Link Generator
This script provides functionality to generate and copy links to specific cursor positions and headers within markdown documents. It's particularly useful for creating precise references within a document or across multiple documents.
## Features
- **External Links**: Generate full URLs pointing to specific cursor positions or headers
- **Internal Links**: Create markdown-style internal links for use within the same document
## Usage
### External Links (Ctrl+Shift+C)
Copies a full URL to the current cursor position or header to the clipboard.
- If the cursor is on a header line: Creates a URL with the header as an anchor (e.g., `https://your-host/Page#Header Name`)
- If not on a header: Creates a URL with the cursor position (e.g., `https://your-host/Page@123`)
### Internal Links (Ctrl+Shift+L)
Copies a markdown-style internal link to the current cursor position or header.
- If on a header: Creates a link like `[Header Name@123]`
- If not on a header: Creates a link like `[Page Name@123]`
---
## Source
```space-lua
-- [[Page#Header]] -> http(s)://host/Page#Header
-- [[Page@pos]] -> http(s)://host/Page@pos
local function replace_space_with_percent20(s)
local parts = {}
for i = 1, #s do
local c = s:sub(i, i)
if c == " " then
parts[#parts+1] = "%20"
else
parts[#parts+1] = c
end
end
return table.concat(parts)
end
local function build_page_url(pageName)
-- get direct url from js
local BASE_URL = js.window.location.origin
local path = replace_space_with_percent20(pageName)
if BASE_URL:sub(-1) == "/" then
return BASE_URL .. path
else
return BASE_URL .. "/" .. path
end
end
command.define {
name = "Cursor: Copy external link",
key = "Ctrl-Shift-c",
run = function()
local currentLine = editor.getCurrentLine().text
local pageName = editor.getCurrentPage()
local pos = editor.getCursor()
local headerMarks, headerName = string.match(currentLine, "^(#+) +(.+)$")
local pageUrl = build_page_url(pageName)
local out
if headerMarks and headerName and headerName:match("%S") then
headerName = headerName:match("^%s*(.+)")
headerName = replace_space_with_percent20(headerName)
out = string.format("%s#%s", pageUrl, headerName)
-- editor.flashNotification("Copied header external link: " .. out, "info")
editor.flashNotification("Copied header link: " .. out, "info")
else
out = string.format("%s@%d", pageUrl, pos)
-- editor.flashNotification("Copied cursor external link: " .. out, "info")
editor.flashNotification("Copied cursor link: " .. out, "info")
end
editor.copyToClipboard(out)
end
}
command.define {
name = "Cursor: Copy internal link",
key = "Ctrl-Shift-l",
run = function()
local currentLine = editor.getCurrentLine().text
local pageName = editor.getCurrentPage()
local pos = editor.getCursor()
local headerMarks, headerName = string.match(currentLine, "^(#+) +(.+)$")
local out
if headerMarks and headerName and headerName:match("%S") then
headerName = headerName:match("^%s*(.+)")
out = string.format("[[%s@%s]]", replace_space_with_percent20(headerName), pos)
editor.flashNotification("Copied header internal link: " .. out, "info")
else
out = string.format("[[%s@%d]]", replace_space_with_percent20(pageName), pos)
editor.flashNotification("Copied cursor internal link: " .. out, "info")
end
editor.copyToClipboard(out)
end
}
```

View File

@@ -0,0 +1,361 @@
---
author: malys
description: MarkMap mindmap integration.
name: "Library/Malys/MarkmapMindmap"
tags: meta/library
share.uri: "https://github.com/malys/silverbullet-libraries/blob/main/src/MarkmapMindmap.md"
share.hash: 65e1843c
share.mode: pull
---
# Markmap mindmap
This library provides a way to preview your [MarkMap](https://markmap.js.org/) mind map in a panel while you are editing your space.
With MarkMap Preview, you can:
- Preview your slides without leaving the context of your space
- See how your slides look in real-time as you modify your markdown
- Use the MarkMap Preview panel to navigate through your slides and see them in action
![](https://community.silverbullet.md/uploads/default/original/2X/4/493e4db01035bc5d0ef5189f8f502ac7fc449709.gif)
## Disclaimer & Contributions
This code is provided **as-is**, **without any kind of support or warranty**.
I do **not** provide user support, bug-fixing on demand, or feature development.
If you detect a bug, please **actively participate in debugging it** (analysis, proposed fix, or pull request) **before reporting it**. Bug reports without investigation may be ignored.
🚫 **No new features will be added.**
**All types of contributions are welcome**, including bug fixes, refactoring, documentation improvements, and optimizations.
By using or contributing to this project, you acknowledge and accept these conditions.
## Configuration
To easily manage JS code source, we use a dynamic introspection mechanism based on md page path.
If you dont install program to default path `Library/Malys/xxx`,we have to set:
```lua
config.set("markmap.source ","xxxx")
-- ex: config.set("markmap.source ","Library/Malys/MarkmapMindmap")
-- where xxx is the path of MarkmapMindmap md page
```
> **warning** Caution
> **Depends on** [Utilities.md](https://github.com/malys/silverbullet-libraries/blob/main/src/Utilities.md). It will be installed automatically.
## Code
```space-lua
local source=config.get("markmap.source") or "Library/Malys/MarkmapMindmap"
local panelSize=config.get("markmap.panelSize") or 4
if library~=nil and (mls == nil or (mls ~=nil and mls.debug == nil)) then
library.install("https://github.com/malys/silverbullet-libraries/blob/main/src/Utilities.md")
editor.flashNotification("'Utilities' has been installed", "Info")
end
local function isVisible()
local current_panel_id = config.get("markmap.panelPosition") or "rhs"
local iframe = js.window.document.querySelector(".sb-panel."..current_panel_id..".is-expanded iframe")
if iframe and iframe.contentDocument then
local el = iframe.contentDocument.getElementById("mindmap")
if el then
return true
end
return false
end
end
local function show()
local page_content = editor.getText()
local contentBase64=encoding.base64Encode(page_content)
local content1= mls.getCodeBlock(source,"innerHTML","@CONTENT@", contentBase64)
local js = mls.getCodeBlock(source,"jsInject","@CONTENT@",content1)
local panel_html= mls.getCodeBlock(source,"template")
local current_panel_id = config.get("markmap.panelPosition") or "rhs"
editor.showPanel(current_panel_id,panelSize, panel_html, js)
end
local function hide()
local current_panel_id = config.get("markmap.panelPosition") or "rhs"
editor.hidePanel(current_panel_id)
end
local update = function(mode)
if ((not isVisible() and mode) or (not mode and isVisible())) then
show()
else
hide()
end
end
-- Define the command
command.define({
name = "Markmap: Toggle preview",
description = "Toggle Marp slides render in a panel",
run = function(e)
update(true)
end
})
event.listen({
name = "editor:pageSaved",
run = function(e)
update(false)
end
})
```
## JS templates
```js jsInject
const scriptId = "markmap-inject";
// Remove existing script if present
const existingScript = document.getElementById(scriptId);
if (existingScript) {
existingScript.remove();
}
// Create and inject the script again
const script = document.createElement("script");
script.type = "module";
script.id = scriptId;
script.textContent = `@CONTENT@`;
document.documentElement.appendChild(script);
```
```js innerHTML
function b64DecodeUnicode(str) {
return decodeURIComponent(
atob(str)
.split("")
.map(c => "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2))
.join("")
);
}
import { Transformer } from "https://esm.sh/markmap-lib?bundle";
import { Markmap, deriveOptions } from "https://esm.sh/markmap-view?bundle";
import { Toolbar } from "https://esm.sh/markmap-toolbar?bundle";
const transformer = new Transformer();
const { root } = transformer.transform(b64DecodeUnicode("@CONTENT@"));
const svg = document.getElementById("mindmap");
const base = deriveOptions(null) || {};
const options = {
...base,
duration: 0,
autoFit: false
};
svg.innerHTML = "";
window.mm = Markmap.create(
"svg#mindmap",
options,
root
);
const existing = document.getElementsByClassName("mm-toolbar");
if(existing.length==0){
// 👉 Toolbar
const toolbar = new Toolbar();
toolbar.attach(window.mm);
const el = toolbar.render();
el.style.position = "absolute";
el.style.bottom = "20px";
el.style.right = "20px";
document.body.appendChild(el);
}
// 👉 print
window.addEventListener("beforeprint", () => {
window.mm?.fit();
});
```
## HTML template
```html template
<style>
html,
html {
overflow-y: scroll !important;
width: 90% !important;
}
@media print {
.no-print,
.mm-toolbar {
display: none !important;
}
.markmap-toolbar {
display: none !important;
}
.markmap-dark {
background: white !important;
color: black !important;
}
* {
animation: none !important;
transition: none !important;
}
/* Remove default page margins */
@page {
margin: 0;
}
/* 2⃣ Reset layout sizing */
html,
body {
margin: 0 !important;
padding: 0 !important;
height: auto !important;
overflow: visible !important;
}
/* Hide all toolbars */
.no-print,
.markmap-toolbar {
display: none !important;
}
}
body {
overflow: initial !important;
color: var(--top-color);
font-family: georgia, times, serif;
font-size: 13pt;
margin-top: revert;
margin-bottom: revert;
padding-left: 20px;
padding-right: 20px;
}
img {
max-width: 100%;
}
table {
width: 100%;
border-spacing: 0;
}
ul li p {
margin: 0;
}
thead tr {
background-color: var(--editor-table-head-background-color);
color: var(--editor-table-head-color);
}
th,
td {
padding: 8px;
}
tbody tr:nth-of-type(even) {
background-color: var(--editor-table-even-background-color);
}
a[href] {
text-decoration: none;
color: var(--link-color);
}
blockquote {
border-left: 1px solid var(--editor-blockquote-border-color);
margin-left: 2px;
padding-left: 10px;
background-color: var(--editor-blockquote-background-color);
color: var(--editor-blockquote-color);
}
hr {
margin: 1em 0 1em 0;
text-align: center;
border-color: var(--editor-ruler-color);
border-width: 0;
border-style: dotted;
}
hr:after {
content: "···";
letter-spacing: 1em;
}
span.highlight {
background-color: var(--highlight-color);
}
.markmap {
--markmap-a-color: #0097e6;
--markmap-a-hover-color: #00a8ff;
--markmap-highlight-bg: #ffeaa7;
--markmap-code-bg: #fff;
--markmap-code-color: #555;
--markmap-circle-open-bg: #fff;
--markmap-text-color: #333;
}
html[data-theme=dark] {
.markmap {
--markmap-code-bg: #1a1b26;
--markmap-code-color: #ddd;
--markmap-circle-open-bg: #444;
--markmap-text-color: #dddbdb;
}
}
* {
margin: 0;
padding: 0;
}
#mindmap {
display: block;
width: 100vw;
height: 100vh;
}
.mm-toolbar {display:flex;-webkit-user-select:none;-moz-user-select:none;user-select:none;align-items:center;border-width:1px;--un-border-opacity:1;border-color:rgb(212 212 216 / var(--un-border-opacity));border-radius:0.25rem;border-style:solid;--un-bg-opacity:1;background-color:rgb(255 255 255 / var(--un-bg-opacity));padding:0.25rem;line-height:1; }
.mm-toolbar:hover {--un-border-opacity:1;border-color:rgb(161 161 170 / var(--un-border-opacity)); }
.mm-toolbar svg {display:block; }
.mm-toolbar a {display:inline-block;text-decoration:none; }
.mm-toolbar-brand > img {width:1rem;height:1rem;vertical-align:middle; }
.mm-toolbar-brand > span {padding-left:0.25rem;padding-right:0.25rem; }
.mm-toolbar-brand:not(:first-child), .mm-toolbar-item:not(:first-child) {margin-left:0.25rem; }
.mm-toolbar-brand > *, .mm-toolbar-item > * {min-width:1rem;cursor:pointer;text-align:center;font-size:0.75rem;line-height:1rem;--un-text-opacity:1;color:rgb(161 161 170 / var(--un-text-opacity)); }
.mm-toolbar-brand.active,
.mm-toolbar-brand:hover,
.mm-toolbar-item.active,
.mm-toolbar-item:hover {border-radius:0.25rem;--un-bg-opacity:1;background-color:rgb(228 228 231 / var(--un-bg-opacity)); }
.mm-toolbar-brand.active > *, .mm-toolbar-brand:hover > *, .mm-toolbar-item.active > *, .mm-toolbar-item:hover > * {--un-text-opacity:1;color:rgb(39 39 42 / var(--un-text-opacity)); }
.mm-toolbar-brand.active, .mm-toolbar-item.active {--un-bg-opacity:1;background-color:rgb(212 212 216 / var(--un-bg-opacity)); }
.markmap-dark .mm-toolbar {--un-border-opacity:1;border-color:rgb(82 82 91 / var(--un-border-opacity));--un-bg-opacity:1;background-color:rgb(39 39 42 / var(--un-bg-opacity));--un-text-opacity:1;color:rgb(161 161 170 / var(--un-text-opacity)); }
.markmap-dark .mm-toolbar:hover {--un-border-opacity:1;border-color:rgb(113 113 122 / var(--un-border-opacity)); }
.markmap-dark .mm-toolbar > *:hover {--un-bg-opacity:1;background-color:rgb(82 82 91 / var(--un-bg-opacity)); }
.markmap-dark .mm-toolbar > *:hover > * {--un-text-opacity:1;color:rgb(228 228 231 / var(--un-text-opacity)); }
</style>
<div id="root" class="sb-preview">
<div class="sb-mindmap-toolbar no-print">
<button onclick="window.print()" title="Print">
🖨️
</button>
</div>
<svg id="mindmap"></svg>
</div>
```
## Changelog
* 2026-01-13: fix: multiple SVG visible on refresh
* 2025-12-01 fix: html duplicate inserts
## Community
[Silverbullet forum]([https://community.silverbullet.md/t/space-lua-addon-with-missing-git-commands-history-diff-restore/3539](https://community.silverbullet.md/t/mindmap-with-markmap-js/1556))

View File

@@ -0,0 +1,930 @@
---
author: malys
description: Automatically formats Markdown table cells based on hashtag column tags.
tags: userscript
name: "Library/Malys/MdTableRender"
share.uri: "https://github.com/malys/silverbullet-libraries/blob/main/src/MdTableRender.md"
share.hash: da8e2c70
share.mode: pull
---
# Md table column rendering
This script enhances Markdown tables inside SilverBullet by applying dynamic
formatting rules to columns marked with hashtag-style format tags (e.g. `#euro`,
`#percent`, `#stars`). It observes table changes in real time and transforms raw
text values into styled, formatted elements — such as currency, percentages,
booleans, dates, badges, emojis, trends, and star ratings — without altering the
original Markdown source. It is designed to be non-intrusive, editable-friendly,
and resilient thanks to mutation observers, debouncing, and a polling fallback.
## Disclaimer & Contributions
This code is provided **as-is**, **without any kind of support or warranty**.
I do **not** provide user support, bug-fixing on demand, or feature development.
If you detect a bug, please **actively participate in debugging it** (analysis,
proposed fix, or pull request) **before reporting it**. Bug reports without
investigation may be ignored.
🚫 **No new features will be added.**
**All types of contributions are welcome**, including bug fixes, refactoring,
documentation improvements, and optimizations.
By using or contributing to this project, you acknowledge and accept these
conditions.
## Supported renderers (via `#tag` in header)
| Tag | Effect |
| --------------- | --------------------------------------------------------- |
| **#euro** | Formats number as “12 345 €” |
| **#usd** | Formats number as “$12,345” |
| **#percent** | Converts decimal to percentage (0.15 → “15 %”) |
| **#gauge** | Graphical percentage representation ███░ |
| **#posneg** | Colored gauge -2 🟥🟥,0 ⬜, +1 🟩 |
| **#km** | Formats number as “12 345 km” |
| **#kg** | Formats number as “12 345 kg” |
| **#watt** | Formats number as “12 345 W” |
| **#int** | Parses and formats whole numbers with locale separators |
| **#float** | Forces 2 decimal places (e.g. “3.14”) |
| **#upper** | Forces uppercase |
| **#lower** | Forces lowercase |
| **#bold** | Wraps value in `<strong>` |
| **#italic** | Wraps value in `<em>` |
| **#link** | Turns URL into clickable link |
| **#date** | Formats dates (YYYY-MM-DD or ISO) |
| **#datetime** | Formats full timestamp |
| **#logical** | Converts truthy → `✅` / falsy → `❌` |
| **#stars** | Converts number to up to 10 ⭐ stars |
| **#evaluation** | Converts 05 into ★/☆ rating |
| **#badge** | Renders value as a blue pill badge |
| **#emoji** | Converts words like “happy”, “cool”, “neutral” → 😃 😎 😐 |
| **#mood** | Converts evaluation of mood to emoj 1:bad 5: very well |
| **#trend** | Converts + / - / = into 🔼 🔽 ➡️ |
| **#histo** | Converts number to █ |
Just add the renderer as a hashtag tag in your table header:
```md
| Product #wine | Euro #euro | Percent #percent | Logical #logical | Stars #stars | Evaluation #evaluation | Updated | Mood #emoji | Trend #trend |
| ------------- | ---------- | ---------------- | ---------------- | ------------ | ---------------------- | -------------------- | ----------- | ------------ |
| Widget | 12.99 | 0.15 | 0 | 3 | 4 | 2025-11-06T14:30:00Z | happy | + |
| Gadget | 8.50 | 0.23 | false | 5 | 2 | 2024-12-25T10:00:00Z | neutral | - |
| Thingamajig | 5.75 | 0.05 | true | 4 | 5 | 2023-05-10T08:15:00Z | cool | = |
```
![](https://community.silverbullet.md/uploads/default/original/2X/e/e2598b9faf8fb223eb5b68b9d03b0729384c5351.png)
![](https://community.silverbullet.md/uploads/default/original/2X/e/ec9b8a44f48b1854b94544da609e24fb1c9bf888.gif)
## How to
### Add new renderer
```lua
mls = mls or {}
mls.table = mls.table or {}
mls.table.renderer = mls.table.renderer or {}
mls.table.renderer["euro"] = {
completion = {
{
name = "one",
value = "1"
},
{
name = "two",
value = "2"
},
},
visual = [[isNaN(v) ? v : `${parseFloat(v).toLocaleString()} TEST`]],
validation = function(v){
--...
return true
}
}
```
## Code
```space-lua
-- Table Renderer (Formatter)
mls = mls or {}
mls.table = mls.table or {}
mls.table.renderer = mls.table.renderer or {}
local cfg = config.get("tableRenderer") or {}
local enabled = cfg.enabled ~= false
--------------------------------------------------
-- FUNCTION
--------------------------------------------------
function mls.table.cleanupRenderer()
local scriptId = "sb-table-renderer-runtime"
local existing = js.window.document.getElementById(scriptId)
if existing then
local ev = js.window.document.createEvent("Event")
ev.initEvent("sb-table-renderer-unload", true, true)
js.window.dispatchEvent(ev)
existing.remove()
print("Table Renderer: Disabled")
else
print("Table Renderer: Already inactive")
end
end
------------------------------------------------
-- Generic validators
------------------------------------------------
local function isNumber(v)
return tonumber(v) ~= nil
end
local function isBetween(v, min, max)
v = tonumber(v)
return v ~= nil and v >= min and v <= max
end
local function isInt(v)
v = tonumber(v)
return v ~= nil and math.floor(v) == v
end
------------------------------------------------
-- Renderers (JS visual + Lua validation)
------------------------------------------------
mls.table.renderer = {
euro = {
visual = [[isNaN(v) ? v : `${parseFloat(v).toLocaleString()} €`]],
validation = isNumber
},
usd = {
visual = [[isNaN(v) ? v : `$${parseFloat(v).toLocaleString()}`]],
validation = isNumber
},
kg = {
visual = [[isNaN(v) ? v : `${parseFloat(v).toLocaleString()} kg`]],
validation = isNumber
},
km = {
visual = [[isNaN(v) ? v : `${parseFloat(v).toLocaleString()} km`]],
validation = isNumber
},
watt = {
visual = [[isNaN(v) ? v : `${parseFloat(v).toLocaleString()} W`]],
validation = isNumber
},
percent = {
visual = [[isNaN(v) ? v : `${(parseFloat(v) * 100).toFixed(0)} %`]],
validation = isNumber
},
int = {
visual = [[isNaN(v) ? v : parseInt(v, 10).toLocaleString()]],
validation = isInt
},
float = {
visual = [[isNaN(v) ? v : parseFloat(v).toFixed(2)]],
validation = isNumber
},
upper = {
visual = [[v.toString().toUpperCase()]],
validation = function(v)
return v ~= nil
end
},
lower = {
visual = [[v.toString().toLowerCase()]],
validation = function(v)
return v ~= nil
end
},
bold = {
visual = [[`<strong>${v}</strong>`]],
validation = function(v)
return v ~= nil
end
},
italic = {
visual = [[`<em>${v}</em>`]],
validation = function(v)
return v ~= nil
end
},
link = {
visual = [[`<a href="${v}" target="_blank">${v.replace(/^https?:\/\//, '')}</a>`]],
validation = function(v)
return type(v) == "string" and v:match("^https?://")
end
},
logical = {
completion = {
{
name = "❌",
value = "false"
},
{
name = "✅",
value = "true"
},
},
visual = [[
if (v !== '✅' && v !== '❌') {
const val = v.toString().toLowerCase().trim();
return (val === '1' || val === 'true' || val === 'yes' || val === 'ok') ? '✅' : '❌';
}
return v;
]],
validation = function(v)
return v ~= nil
end
},
evaluation = {
completion = {
{
name = "🤍🤍🤍🤍🤍",
value = "0"
},
{
name = "❤️🤍🤍🤍🤍",
value = "1"
},
{
name = "❤️❤️🤍🤍🤍",
value = "2"
},
{
name = "❤️❤️❤️🤍🤍",
value = "3"
},
{
name = "❤️❤️❤️❤️🤍",
value = "4"
},
{
name = "❤️❤️❤️❤️❤️",
value = "5"
},
},
visual = [[
const n = parseInt(v, 10);
if (isNaN(n)) return v;
return '❤️'.repeat(Math.max(0, Math.min(n, 5)))
+ '🤍'.repeat(5 - Math.max(0, Math.min(n, 5)));
]],
validation = function(v)
return isBetween(v, 1, 5)
end
},
histo = {
visual = [[
const n = parseInt(v, 10);
return isNaN(n) ? v : '█'.repeat(n);
]],
validation = isInt
},
gauge = {
visual = [[
const a = 0;
const b = 100;
const val = parseInt(v, 10);
if (isNaN(val)) return v;
const clampedValue = Math.max(a, Math.min(val, b));
const percentage = (clampedValue - a) / (b - a);
const filled = Math.floor(percentage * 10);
const empty = 10 - filled;
return `[${'█'.repeat(filled)}${'░'.repeat(empty)}]`;
]],
validation = function(v)
return isBetween(v, 0, 100)
end
},
trend = {
completion = {
{
name = "🔼",
value = "+"
},
{
name = "🔽",
value = "-"
},
{
name = "➡️",
value = "="
}
},
visual = [[
const val = v.trim();
if (val === '+') return '🔼';
if (val === '-') return '🔽';
if (val === '=') return '➡️';
return val;
]],
validation = function(v)
return v == "+" or v == "-" or v == "="
end
},
emoji = {
completion = {
-- basic emotions
{
name = "happy 😃",
value = "happy"
},
{
name = "sad 😢",
value = "sad"
},
{
name = "angry 😠",
value = "angry"
},
{
name = "love ❤️",
value = "love"
},
{
name = "neutral 😐",
value = "neutral"
},
{
name = "cool 😎",
value = "cool"
},
-- positive / joyful
{
name = "smile 😊",
value = "smile"
},
{
name = "grin 😁",
value = "grin"
},
{
name = "laugh 😂",
value = "laugh"
},
{
name = "excited 🤩",
value = "excited"
},
{
name = "proud 😌",
value = "proud"
},
{
name = "relieved 😮‍💨",
value = "relieved"
},
{
name = "thankful 🙏",
value = "thankful"
},
{
name = "party 🥳",
value = "party"
},
{
name = "confident 😏",
value = "confident"
},
-- negative / difficult
{
name = "cry 😭",
value = "cry"
},
{
name = "disappointed 😞",
value = "disappointed"
},
{
name = "worried 😟",
value = "worried"
},
{
name = "anxious 😰",
value = "anxious"
},
{
name = "scared 😱",
value = "scared"
},
{
name = "tired 😴",
value = "tired"
},
{
name = "sick 🤒",
value = "sick"
},
{
name = "bored 😒",
value = "bored"
},
{
name = "frustrated 😤",
value = "frustrated"
},
{
name = "confused 😕",
value = "confused"
},
-- reactions
{
name = "surprised 😮",
value = "surprised"
},
{
name = "shocked 😲",
value = "shocked"
},
{
name = "thinking 🤔",
value = "thinking"
},
{
name = "facepalm 🤦",
value = "facepalm"
},
{
name = "shrug 🤷",
value = "shrug"
},
{
name = "eyeRoll 🙄",
value = "eyeroll"
},
-- social / playful
{
name = "wink 😉",
value = "wink"
},
{
name = "kiss 😘",
value = "kiss"
},
{
name = "hug 🤗",
value = "hug"
},
{
name = "teasing 😜",
value = "teasing"
},
{
name = "silly 🤪",
value = "silly"
},
-- approval / disapproval
{
name = "ok 👌",
value = "ok"
},
{
name = "thumbsUp 👍",
value = "thumbsup"
},
{
name = "thumbsDown 👎",
value = "thumbsdown"
},
{
name = "clap 👏",
value = "clap"
},
{
name = "respect 🫡",
value = "respect"
},
-- status / misc
{
name = "fire 🔥",
value = "fire"
},
{
name = "star ⭐",
value = "star"
},
{
name = "check ✅",
value = "check"
},
{
name = "cross ❌",
value = "cross"
},
{
name = "warning ⚠️",
value = "warning"
},
},
visual = [[
const map = {
// basic emotions
happy: '😃',
sad: '😢',
angry: '😠',
love: '❤️',
neutral: '😐',
cool: '😎',
// positive / joyful
smile: '😊',
grin: '😁',
laugh: '😂',
excited: '🤩',
proud: '😌',
relieved: '😮‍💨',
thankful: '🙏',
party: '🥳',
confident: '😏',
// negative / difficult
cry: '😭',
disappointed: '😞',
worried: '😟',
anxious: '😰',
scared: '😱',
tired: '😴',
sick: '🤒',
bored: '😒',
frustrated: '😤',
confused: '😕',
// reactions
surprised: '😮',
shocked: '😲',
thinking: '🤔',
facepalm: '🤦',
shrug: '🤷',
eyeRoll: '🙄',
// social / playful
wink: '😉',
kiss: '😘',
hug: '🤗',
teasing: '😜',
silly: '🤪',
// approval / disapproval
ok: '👌',
thumbsUp: '👍',
thumbsDown: '👎',
clap: '👏',
respect: '🫡',
// status / misc
fire: '🔥',
star: '⭐',
check: '✅',
cross: '❌',
warning: '⚠️',
};
const key = v.toString().toLowerCase();
return map[key] || v;
]],
validation = function(v)
return type(v) == "string"
end
},
posneg = {
completion = {
{
name = "-2 🟥🟥",
value = "-2"
},
{
name = "-1 🟥",
value = "-1"
},
{
name = "0 ⬜",
value = "0"
},
{
name = "1 🟩",
value = "1"
},
{
name = "2 🟩🟩",
value = "2"
},
},
visual = [[
if (isNaN(v)) return v;
const val = parseInt(v, 10);
if (val < 0) return "🟥".repeat(Math.abs(val));
if (val > 0) return "🟩".repeat(Math.abs(val));
return "⬜";
]],
validation = function(v)
return isBetween(v, -10, 10)
end
},
speed = {
visual = [[v + " km/h"]],
validation = function(v)
return isBetween(v, 0, 300)
end
},
mood = {
completion = {
{
name = "😞",
value = "1"
},
{
name = "🙁",
value = "2"
},
{
name = "😐",
value = "3"
},
{
name = "🙂",
value = "4"
},
{
name = "😄",
value = "5"
},
},
visual = [[
const n = parseInt(v, 10);
const moodScaleSoft = ['😔', '🙁', '😐', '🙂', '😄'];
return moodScaleSoft[(n - 1) % 5];
]],
validation = function(v)
return isBetween(v, 1, 5)
end
},
stars = {
completion = {
{
name = "1 ⭐",
value = "1"
},
{
name = "2 ⭐⭐",
value = "2"
},
{
name = "3 ⭐⭐⭐",
value = "3"
},
{
name = "4 ⭐⭐⭐⭐",
value = "4"
},
{
name = "5 ⭐⭐⭐⭐⭐",
value = "5"
},
{
name = "6 ⭐⭐⭐⭐⭐⭐",
value = "6"
},
{
name = "7 ⭐⭐⭐⭐⭐⭐⭐",
value = "7"
},
{
name = "8 ⭐⭐⭐⭐⭐⭐⭐⭐",
value = "8"
},
{
name = "9 ⭐⭐⭐⭐⭐⭐⭐⭐⭐",
value = "9"
},
{
name = "10 ⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐",
value = "10"
},
},
visual = [[
const n = parseInt(v, 10);
return isNaN(n) ? v : '⭐'.repeat(Math.max(0, Math.min(n, 10)));
]],
validation = function(v)
return isBetween(v, 1, 10)
end
},
badge = {
completion = {},
visual = [[
return `<span style="background:#2196f3;color:white;padding:2px 6px;border-radius:8px;font-size:0.9em;">${v}</span>`;
]],
validation = function(v)
return v ~= nil
end
},
}
------------------------------------------------
-- Dispatcher
------------------------------------------------
mls.table.render = function(label, rendererN)
local rendererName = rendererN
if (type(rendererN) == "table") then
for _, tag in ipairs(rendererN) do
if mls.table.renderer[tag] then
rendererName = tag
end
end
end
if label and rendererName and mls.table.renderer[rendererName] then
local renderer = mls.table.renderer[rendererName]
local input
if renderer.completion and # renderer.completion > 0 then
input = editor.filterBox(label, renderer.completion)
else
input = editor.prompt(label)
end
local value = input
if input and input.value then
value = input.value
end
if renderer.validation(value) then
return value
else
editor.flashNotification("Input not valid: " .. tostring(input), "error")
end
else
editor.flashNotification("Missing renderer: " .. tostring(rendererName), "error")
end
end
------------------------------------------------
-- JS generator
------------------------------------------------
local function exportJSFormatters(renderers)
local lines = {}
table.insert(lines, "const formatters = {")
for name, def in pairs(renderers) do
if def.visual then
local js = def.visual
-- single line or block
if string.match(js, "\n") then
table.insert(lines, " " .. name .. ": v => {")
table.insert(lines, js)
table.insert(lines, " },")
else
table.insert(lines, " " .. name .. ": v => " .. js .. ",")
end
end
end
table.insert(lines, "};")
return table.concat(lines, "\n")
end
--------------------------------------------------
-- ENABLE
--------------------------------------------------
function mls.table.enableTableRenderer()
local scriptId = "sb-table-renderer-runtime"
if js.window.document.getElementById(scriptId) then
print("Table Renderer: Already active")
return
end
local scriptEl = js.window.document.createElement("script")
scriptEl.id = scriptId
scriptEl.innerHTML = [[
(function () {
'use strict';
const DEBUG = false;
const log = (...a) => DEBUG && console.log('[sb-table-renderer]', ...a);
/* ---------------- FORMATTERS ---------------- */
]] .. exportJSFormatters(mls.table.renderer) .. [[
/* ---------------- CORE ---------------- */
function extractFormats(table) {
const formats = [];
const header =
table.querySelector('thead tr') ||
table.querySelector('tr');
if (!header) return formats;
[...header.cells].forEach((cell, idx) => {
formats[idx] = null;
const tags = cell.querySelectorAll('a.hashtag,[data-tag-name]');
for (const tag of tags) {
const name =
tag.dataset?.tagName ||
tag.textContent?.replace('#', '');
if (formatters[name]) {
formats[idx] = name;
tag.style.display = 'none';
break;
}
}
});
return formats;
}
function processTable(table) {
if (table.dataset.sbFormatted) return;
const formats = extractFormats(table);
const rows = table.tBodies[0]?.rows || [];
[...rows].forEach(row => {
[...row.cells].forEach((cell, idx) => {
const fmt = formats[idx];
if (!fmt) return;
const raw = cell.textContent.trim();
const out = formatters[fmt](raw);
if (out !== raw) {
cell.textContent = out;
cell.dataset.sbformatted = fmt;
}
});
});
table.dataset.sbFormatted = 'true';
}
function scan() {
document
.querySelectorAll('#sb-editor table')
.forEach(processTable);
}
/* ---------------- OBSERVER ---------------- */
const observer = new MutationObserver(scan);
observer.observe(document.body, { childList: true, subtree: true });
scan();
/* ---------------- CLEANUP ---------------- */
window.addEventListener('sb-table-renderer-unload', function cln() {
observer.disconnect();
document
.querySelectorAll('[data-sbformatted]')
.forEach(c => {
c.removeAttribute('data-sbformatted');
});
document
.querySelectorAll('table[data-sb-formatted]')
.forEach(t => delete t.dataset.sbFormatted);
window.removeEventListener('sb-table-renderer-unload', cln);
});
})()
]]
js.window.document.body.appendChild(scriptEl)
end
--------------------------------------------------
-- COMMANDS
--------------------------------------------------
command.define{
name = "Table: Enable Renderer",
run = function()
mls.table.enableTableRenderer()
end
}
command.define{
name = "Table: Disable Renderer",
run = function()
mls.table.cleanupRenderer()
end
}
--------------------------------------------------
-- AUTOSTART
--------------------------------------------------
if enabled then
mls.table.enableTableRenderer()
else
mls.table.cleanupRenderer()
end
```
## Changelog
- 2026-02-01
- feat: define renderers in lua
- feat: add validation mechanism
- feat: add completion mechanism
- 2026-01-24:
- feat: convert to space-lua
- feat: add renderers (mood, emoj)
- 2026-01-02 feat: add kg, km, watt, histo
## Community
[Silverbullet forum](https://community.silverbullet.md/t/md-table-renderers/3545/15)

424
Library/Malys/Utilities.md Normal file
View File

@@ -0,0 +1,424 @@
---
author: malys
description: List of reusable functions.
name: "Library/Malys/Utilities"
tags: meta/library
share.uri: "https://github.com/malys/silverbullet-libraries/blob/main/src/Utilities.md"
share.hash: 004bb007
share.mode: pull
---
# Utilities
* `mls.getmeetingTitle()`: Extracts meeting title from page URL.
* `mls.embedUrl(url, w, h)`: Embeds a URL using an iframe (width & height optional).
* `mls.debug(message, prefix)`: Prints debug message (if `LOG_ENABLE` is true).
* `mls.getCodeBlock(page, blockId, token, text)`: Retrieves code from a Markdown code block by ID, with optional token replacement.
* `mls.parseISODate(isoDate)`: Parses an ISO date string to a timestamp (potential error with `xoffset`).
* `mls.getStdlibInternal()`: Gets a list of internal API keys (cached).
* `mls.positionToLineColumn(text, pos)`: Converts a text position to line/column numbers.
* `table.appendArray(a, b)`: Appends array `b` to array `a`.
* `table.unique(array)`: Returns unique elements from an array.
* `table.uniqueKVBy(array, keyFn)`: Returns unique key-value pairs based on a key function.
* `table.mergeKV(t1, t2)`: Merges two tables (recursive for nested tables).
* `table.map(t, fn)`: Applies a function to each element of an array.
* `table.toMd(data)`: Converts a table (or JSON) to a Markdown table.
## Debug
### How to enable debug mode
* Create space-lua with:
```lua
LOG_ENABLE=true
```
* Reload system.
* Open Chrome Console
* Add filter “[Client] [DEBUG]“
## Code
```space-lua
-- priority: 20
mls=mls or {}
-- Convert meeting note title
-- Extracts the meeting title from the current page URL.
-- Assumes the URL format is like "namespace/Meeting_Note Title".
-- Splits the URL by "/", takes the last part, and then splits that by "_"
-- to remove the "Meeting" prefix and joins the remaining parts with a space.
function mls.getmeetingTitle()
local t=string.split(string.split(editor.getCurrentPage(),"/")[#string.split(editor.getCurrentPage(),"/")],"_")
table.remove(t,1)
t=table.concat(t, " ")
return t
end
-- Embed external resources
-- Creates an HTML iframe to embed an external URL within the current page.
-- Allows specifying width and height, defaulting to "100%" and "400px" respectively.
function mls.embedUrl(specOrUrl,w,h)
local width = w or "100%"
local height = h or "400px"
return widget.html(dom.iframe {
src=specOrUrl,
style="width: " .. width .. "; height: " .. height
})
end
---------------------------------------------
---- Debug ---
---------------------------------------------
-- Pretty-print any Lua value (tables included)
-- Recursively prints a Lua value, handling tables with indentation.
-- Prevents infinite recursion by limiting the depth to 5.
local function dump(value, depth)
--print("[DEBUG][TYPE]"..type(value)) -- commented out debug line
depth = depth or 0
if type(value) ~= "table" or (type(value) == "string" and value ~= "[object Object]") then
return value
end
-- Prevent going too deep (avoid infinite recursion)
if depth > 5 then
return "{ ... }"
end
local indent = string.rep(" ", depth)
local next_indent = string.rep(" ", depth + 1)
local parts = {}
table.insert(parts, "{")
for k, v in pairs(value) do
local key = tostring(k)
local val
if type(v) == "table" then
val = dump(v, depth + 1)
else
val = v
end
table.insert(parts, next_indent .. tostring(key) .. " = " .. tostring(val) .. ",")
end
table.insert(parts, indent .. "}")
return table.concat(parts, "\n")
end
-- Debug function
-- Prints a debug message to the console if LOG_ENABLE is true.
-- Uses the dump function to pretty-print the message.
-- Allows specifying a prefix for the debug message.
function mls.debug(message, prefix)
if not LOG_ENABLE then
return message
end
local log_message = dump(message)
local result = "[DEBUG]"
if prefix then
result = result .. "[" .. tostring(prefix) .. "]"
end
result = result .. " " .. tostring(log_message)
print(result)
return result
end
---------------------------------------------
---- Code Block code extraction ---
---------------------------------------------
-- Get child of node
-- Helper function to find a child node of a given type within a parent node.
local getChild = function(node, type)
for _, child in ipairs(node.children) do
if child.type == type then
return child
end
end
end
-- Get text of Node
-- Helper function to recursively extract the text content from a node.
local getText = function(node)
if not node then
return nil
end
if node.text then
return node.text
else
for _, child in ipairs(node.children) do
local text = getText(child)
if text then
return text
end
end
end
end
-- Find codeblock
-- Recursively searches for a code block (FencedCode node) with a specific blockId in the node's children.
local findMyFence = function(node,blockId)
if not node.children then
return nil
end
for _, child in ipairs(node.children) do
--mls.debug(child) -- commented out debug line
if child.type == "FencedCode" then
local info = getText(getChild(child, "CodeInfo"))
--mls.debug(info) -- commented out debug line
if info and info:find(blockId) then
mls.debug(info)
return getChild(child, "CodeText")
end
end
local result= findMyFence(child,blockId)
if result ~=nil then
return result
end
--break -- for loop
end --for
end
-- Get code source in md codeblock
-- Parses a Markdown page, finds a code block with the given blockId, and returns its content.
-- Allows replacing a token within the code block with a new text value.
function mls.getCodeBlock (page,blockId,token,text)
local tree = markdown.parseMarkdown(space.readPage(page))
--mls.debug(tree) -- commented out debug line
if tree then
local fence = findMyFence(tree,blockId)
--mls.debug(fence) -- commented out debug line
if fence then
local result=fence.children[1].text
if token == nil or text==nil then
return result
else
return string.gsub(result, token, text)
end
end
end
return "Error"
end
-- Parse ISO Date
-- Parses an ISO date string into a Unix timestamp.
-- This function appears incomplete and has a potential error in the offset calculation.
-- The `xoffset` variable is not defined.
function mls.parseISODate(isoDate)
local pattern = "(%d+)%-(%d+)%-(%d+)%a(%d+)%:%d+:%d+([Z%+%-])(%d?%d?)%:?(%d?%d?)"
local year, month, day, hour, minute,
seconds, offsetsign, offsethour, offsetmin = json_date:match(pattern)
local timestamp = os.time{year = year, month = month,
day = day, hour = hour, min = minute, sec = seconds}
local offset = 0
if offsetsign ~= 'Z' then
offset = tonumber(offsethour) * 60 + tonumber(offsetmin)
if xoffset == "-" then offset = offset * -1 end
end
return timestamp + offset
end
-- Get Stdlib Internal
-- Retrieves a list of internal API keys from a remote file.
-- Caches the results to avoid repeated fetching.
-- The URL points to a file in the silverbulletmd/silverbullet repository.
function mls.getStdlibInternal()
if _G ~=nil then
return table.keys(_G)
end
-- get list of internal api TODO: remove
local KEY="stdlib_internal"
local result=mls.cache.ttl.CacheManager.get(KEY)
if result == nil then
local url = "https://raw.githubusercontent.com/silverbulletmd/silverbullet/refs/heads/main/client/space_lua/stdlib.ts"
local resp = net.proxyFetch(url)
if resp.status ~= 200 then
error("Failed to fetch file: " .. resp.status)
end
local content = resp.body
local results = {}
for line in string.split(content,"\n") do
local key = string.match(string.trim(line), 'env%.set%("(.*)"')
if key then
table.insert(results, key)
end
end
result=table.sort(results)
mls.cache.ttl.CacheManager.set(KEY,result)
end
return table.sort(result)
end
-- Position to Line Column
-- Converts a character position within a text string to a line and column number.
function mls.positionToLineColumn(text, pos)
local line = 1
local column = 0
local lastNewline = -1
for i = 0, pos - 1 do
if string.sub(text, i + 1, i + 1) == "\n" then
line = line + 1
lastNewline = i
column = 0
else
column = column + 1
end
end
return { line = line, column = column }
end
-----------------------------------------
-- TABLE
-----------------------------------------
-- Append Array
-- Appends all elements from one array to another.
function table.appendArray(a, b)
if a~= nil and b ~= nil then
for i = 1, #b do
table.insert(a, b[i])
end
end
return a
end
-- Unique
-- Returns a new array containing only the unique elements from the input array.
function table.unique(array)
local seen = {}
local result = {}
for i = 1, #array do
local v = array[i]
if not seen[v] then
seen[v] = true
result[#result + 1] = v
end
end
return result
end
-- Unique KV By
-- Returns a new array containing only the unique key-value pairs from the input array,
-- based on a provided key function.
function table.uniqueKVBy(array, keyFn)
local seen = {}
local result = {}
for i = 1, #array do
local key = keyFn(array[i])
if not seen[key] then
seen[key] = true
result[#result + 1] = array[i]
end
end
return result
end
-- Merge KV
-- Merges two tables, recursively merging nested tables.
-- If a key exists in both tables and the values are both tables, the nested tables are merged.
-- Otherwise, the value from the second table overwrites the value from the first table.
function table.mergeKV(t1, t2)
for k, v in pairs(t2) do
if type(v) == "table" and type(t1[k]) == "table" then
mergeTablesRecursive(t1[k], v)
else
t1[k] = v
end
end
return t1
end
-- Map
-- Applies a function to each element of an array and returns a new array with the results.
function table.map(t, fn)
local result = {}
for i, v in ipairs(t) do
result[i] = fn(v, i)
end
return result
end
-- To Md
-- Converts a Lua table to a Markdown table string.
-- Handles both arrays of arrays and arrays of objects.
-- Can parse JSON or Lua strings as input.
function table.toMd(data)
local tbl
local input=string.trim(data)
-- If input is a string, try parsing as JSON
if string.startsWith(data,"{") then
-- Lua
tbl=spacelua.evalExpression(spacelua.parseExpression(data))
else
--JSON
tbl=js.tolua(js.window.JSON.parse(js.tojs(data)))
end
if #tbl == 0 then return "" end
local md = {}
-- Helper to convert a row to Markdown
local function rowToMd(row)
local cells = {}
for _, cell in ipairs(row) do
table.insert(cells, tostring(cell))
end
return "| " .. table.concat(cells, " | ") .. " |"
end
-- Handle array of objects
local first = tbl[1]
local headers
if type(first) == "table" and not (#first > 0) then
headers = {}
for k in pairs(first) do table.insert(headers, k) end
local rows = {headers}
for _, obj in ipairs(tbl) do
local row = {}
for _, h in ipairs(headers) do
table.insert(row, obj[h] or "")
end
table.insert(rows, row)
end
tbl = rows
end
-- Header
table.insert(md, rowToMd(tbl[1]))
-- Separator
local sep = {}
for _ = 1, #tbl[1] do table.insert(sep, "---") end
table.insert(md, "| " .. table.concat(sep, " | ") .. " |")
-- Data rows
for i = 2, #tbl do
table.insert(md, rowToMd(tbl[i]))
end
return table.concat(md, "\n")
end
```
## Changelog
* 2026-01-22:
* getStdlibInternal compatible with edge version https://community.silverbullet.md/t/risk-audit/3562/14
* 2026-01-20:
* feat: add table functions
* map
* mergeKV
* uniqueKVBy
* unique
* appendArray
* feat: add `mls.getStdlibInternal` fucntion

View File

@@ -0,0 +1,61 @@
---
author: malys
description: Beautify md file.
name: "Library/Malys/mdPrettier"
tags: meta/library
share.uri: "https://github.com/malys/silverbullet-libraries/blob/main/src/mdPrettier.md"
share.hash: f2473a28
share.mode: pull
---
# Md Prettier
Beautify markdown.
## Code
```space-lua
local prettier = js.import("https://cdn.jsdelivr.net/npm/prettier/standalone/+esm")
local prettierMarkdown = js.import("https://cdn.jsdelivr.net/npm/prettier/plugins/markdown/+esm")
function formatText(text)
return prettier.format(text, {
parser = "markdown",
plugins = { prettierMarkdown },
printWidth = 160,
proseWrap = "preserve",
-- These DO NOT affect markdown tables
useTabs = true,
tabWidth = 4,
})
end
function formatDocument()
local text = editor.getText()
local formattedText = formatText(text)
editor.setText(formattedText)
end
command.define {
name = "Beautify: markdown",
run = formatDocument,
}
```
**Important Notes:**
- **Placement:** `prettier-ignore` _must_ be the very first line within the code
fence. Any leading whitespace will cause it to be ignored.
- **Scope:** `prettier-ignore` applies to the entire code fence it's placed in.
- **Alternative:** If you want to disable formatting for a specific section of
code _within_ a code fence, you can use `prettier-ignore` on a single line:
## Changelog
- 2026-01-25:
- feat: add option and ignore code
## Community
[Silverbullet forum](https://community.silverbullet.md/t/markdown-formatter-for-silverbullet/3071)

View File

@@ -0,0 +1,190 @@
---
author: malys
description: Dark theme thought for readibility and productivity
name: "Library/Malys/theme-malys"
tags: meta/library
share.uri: "https://github.com/malys/silverbullet-libraries/blob/main/src/Theme/theme-malys.md"
share.hash: 0817db84
share.mode: pull
---
# Malys theme
Dark theme thought for readability and productivity.
## Example
# 1
## 2
### 3
#### 4
##### 5
###### 6
`code`
*emphasis*
**strong**
## Editor
```space-style
html {
--ui-font: firacode-nf, monospace !important;
--editor-font: firacode-nf, monospace !important;
--editor-width: 100% !important;
line-height: 1.4 !important;
font-variant-ligatures: none;
font-feature-settings: "liga" 0;
}
.markmap {
--markmap-text-color: #BBDEFB !important;
}
#sb-main .cm-editor {
font-size: 15px;
margin-top: 2rem;
}
.sb-line-h1 {
font-size: 1.8em !important;
color: #ee82ee !important;
}
.sb-line-h2 {
font-size: 1.6em !important;
color: #6a5acd !important;
}
.sb-line-h3 {
font-size: 1.4em !important;
color: #4169e1 !important;
}
.sb-line-h4 {
font-size: 1.2em !important;
color: #008000 !important;
}
.sb-line-h5 {
font-size: 1em !important;
color: #ffff00 !important;
}
.sb-line-h6 {
font-size: 1em !important;
color: #ffa500 !important;
}
.sb-line-h1::before {
content: "h1";
margin-right: 0.5em;
font-size: 0.5em !important;
}
.sb-line-h2::before {
content: "h2";
margin-right: 0.5em;
font-size: 0.5em !important;
}
.sb-line-h3::before {
content: "h3";
margin-right: 0.5em;
font-size: 0.5em !important;
}
.sb-line-h4::before {
content: "h4";
margin-right: 0.5em;
font-size: 0.5em !important;
}
.sb-line-h5::before {
content: "h5";
margin-right: 0.5em;
font-size: 0.5em !important;
}
.sb-line-h6::before {
content: "h6";
margin-right: 0.5em;
font-size: 0.5em !important;
}
.sb-code {
color: grey !important;
}
.sb-emphasis {
color: darkorange !important;
}
.sb-strong {
color: salmon !important;
}
html {
--treeview-phone-height: 25vh;
--treeview-tablet-width: 25vw;
--treeview-tablet-height: 100vh;
--treeview-desktop-width: 20vw;
}
.sb-bhs {
height: var(--treeview-phone-height);
}
.cm-diagnosticText {
color: black;
}
```
## Treeview
```space-style
.tree__label > span {
font-size: calc(11px + 0.1vh);
}
@media (min-width: 960px) {
#sb-root:has(.sb-lhs) #sb-main,
#sb-root:has(.sb-lhs) #sb-top {
margin-left: var(--treeview-tablet-width);
}
.sb-lhs {
position: fixed;
left: 0;
height: var(--treeview-tablet-height);
width: var(--treeview-tablet-width);
border-right: 1px solid var(--top-border-color);
}
}
@media (min-width: 1440px) {
#sb-root:has(.sb-lhs) #sb-main,
#sb-root:has(.sb-lhs) #sb-top {
margin-left: var(--treeview-desktop-width);
}
.sb-lhs {
width: var(--treeview-desktop-width);
}
}
```
.tree__label > span {
padding: 0 5px;
font-size: 11px;
line-height: 1.2;
}
.treeview-root {
--st-label-height: auto;
--st-subnodes-padding-left: 0.1rem;
--st-collapse-icon-height: 2.1rem;
--st-collapse-icon-width: 1.25rem;
--st-collapse-icon-size: 1rem;
}
## Outline
```space-style
div.cm-scroller {
scroll-behavior: smooth;
scrollbar-width: thin;
}
```

View File

@@ -0,0 +1,117 @@
---
name: Library/mrmugame/Silverbullet-Math
tags: meta/library
files:
- Silverbullet-Math/katex.mjs
- Silverbullet-Math/katex.min.css
- Silverbullet-Math/fonts/KaTeX_Typewriter-Regular.woff2
- Silverbullet-Math/fonts/KaTeX_Size4-Regular.woff2
- Silverbullet-Math/fonts/KaTeX_Size3-Regular.woff2
- Silverbullet-Math/fonts/KaTeX_Size2-Regular.woff2
- Silverbullet-Math/fonts/KaTeX_Size1-Regular.woff2
- Silverbullet-Math/fonts/KaTeX_Script-Regular.woff2
- Silverbullet-Math/fonts/KaTeX_SansSerif-Regular.woff2
- Silverbullet-Math/fonts/KaTeX_SansSerif-Italic.woff2
- Silverbullet-Math/fonts/KaTeX_SansSerif-Bold.woff2
- Silverbullet-Math/fonts/KaTeX_Math-Italic.woff2
- Silverbullet-Math/fonts/KaTeX_Math-BoldItalic.woff2
- Silverbullet-Math/fonts/KaTeX_Main-Regular.woff2
- Silverbullet-Math/fonts/KaTeX_Main-Italic.woff2
- Silverbullet-Math/fonts/KaTeX_Main-Bold.woff2
- Silverbullet-Math/fonts/KaTeX_Main-BoldItalic.woff2
- Silverbullet-Math/fonts/KaTeX_Fraktur-Regular.woff2
- Silverbullet-Math/fonts/KaTeX_Fraktur-Bold.woff2
- Silverbullet-Math/fonts/KaTeX_Caligraphic-Regular.woff2
- Silverbullet-Math/fonts/KaTeX_Caligraphic-Bold.woff2
- Silverbullet-Math/fonts/KaTeX_AMS-Regular.woff2
share.uri: "https://github.com/MrMugame/silverbullet-math/blob/main/Math.md"
share.hash: "13247895"
share.mode: pull
---
# Silverbullet Math
This library implements two new widgets
- `latex.block(...)` and
- `latex.inline(...)`,
which can be used to render block and inline level math respectively. Both use ${latex.inline[[\href{https://katex.org/}{\KaTeX}]]} under the hood
## Examples
Let ${latex.inline[[S]]} be a set and ${latex.inline[[\circ : S \times S \to S,\; (a, b) \mapsto a \cdot b]]} be a binary operation, then the pair ${latex.inline[[(S, \circ)]]} is called a *group* iff
1. ${latex.inline[[\forall a, b \in S, \; a \circ b \in S]]} (completeness),
2. ${latex.inline[[\forall a,b,c \in S, \; (ab)c = a(bc)]]} (associativity),
3. ${latex.inline[[\exists e \in S]]} such that ${latex.inline[[\forall a \in S,\; ae=a=ea]]} (identity) and
4. ${latex.inline[[\forall a \in S,\; \exists b \in S]]} such that ${latex.inline[[ab=e=ba]]} (inverse).
The Fourier transform of a complex-valued (Lebesgue) integrable function ${latex.inline[[f(x)]]} on the real line, is the complex valued function ${latex.inline[[\hat {f}(\xi )]]}, defined by the integral
${latex.block[[\widehat{f}(\xi) = \int_{-\infty}^{\infty} f(x)\ e^{-i 2\pi \xi x}\,dx, \quad \forall \xi \in \mathbb{R}.]]}
## Quality of life
There are two slash commands to make writing math a little easier,
- `/math` and
- `/equation`.
## Info
The current ${latex.inline[[\KaTeX]]} version is ${latex.katex.version}.
## Implementation
```space-lua
local location = "Library/mrmugame/Silverbullet-Math"
-- TODO: Remove the check for system.getURLPrefix as soon as the API has settled
latex = {
header = string.format("<link rel=\"stylesheet\" href=\".fs/%s/katex.min.css\">", location),
katex = js.import(string.format("%s.fs/%s/katex.mjs", system.getURLPrefix and system.getURLPrefix() or "/", location))
}
function latex.inline(expression)
local html = latex.katex.renderToString(expression, {
trust = true,
throwOnError = false,
displayMode = false
})
return widget.new {
display = "inline",
html = "<span>" .. latex.header .. html .. "</span>"
}
end
function latex.block(expression)
local html = latex.katex.renderToString(expression, {
trust = true,
throwOnError = false,
displayMode = true
})
return widget.new {
display = "block",
html = "<span>" .. latex.header .. html .. "</span>"
}
end
slashcommand.define {
name = "math",
run = function()
editor.insertAtCursor("${latex.inline[[]]}", false, true)
editor.moveCursor(editor.getCursor() - 3)
end
}
slashcommand.define {
name = "equation",
run = function()
editor.insertAtCursor("${latex.block[[]]}", false, true)
editor.moveCursor(editor.getCursor() - 3)
end
}
```
```space-style
.sb-lua-directive-inline:has(.katex-html) {
border: none !important;
}
```

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,23 @@
---
name: Library/mrmugame/Silverbullet-PDF
tags: meta/library
files:
- silverbullet-pdf.plug.js
share.uri: "ghr:MrMugame/silverbullet-pdf/PLUG.md"
share.hash: 3498d9f9
share.mode: pull
---
# Silverbullet PDF
This plug adds the ability to [Silverbullet](https://github.com/silverbulletmd/silverbullet) to view and annotate pdfs using a slightly modified version of the [pdfjs](https://github.com/mozilla/pdf.js) viewer. If used with [Silversearch](https://github.com/MrMugame/silversearch), Silverbullet PDF can extract text content from PDFs to help you search through them.
![screenshot](https://raw.githubusercontent.com/mrmugame/silverbullet-pdf/main/docs/preview.png)
## Installation
Silverbullet PDF is part of the [`Std`](https://silverbullet.md/Repositories/Std) repostitory and can by installed using the [Library Manager](https://silverbullet.md/Library%20Manager). You will have to navigate to `Library/Std/Pages/Library Manager` in *your* space and look for Silverbullet PDF under the available libraries and press `Install`.
## Internals
The build process of this plug is rather weird. The steps are as follows
1. Uing `deno task download` the pdfjs repo will be cloned and the `pdfjs.patch` patch will be applied. I opted for this approach, because I wanted to avoid an extra repo for the few changes
2. Using `deno task install` all npm install commands are run
3. Using `deno task build` the build process will be run. This will firstly build pdfjs, copy all the important files over and then do the ~~typical~~ vite (ui) + deno (worker) build.

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,50 @@
---
name: Library/silverbulletmd/basic-search/PLUG
tags: meta/library
files:
- search.plug.js
share.uri: "https://github.com/silverbulletmd/basic-search/blob/main/PLUG.md"
share.hash: 59d1e9ad
share.mode: pull
---
# Basic Full Text Search
Formerly a built-in plug for SilverBullet, now installable separately for those who dont want to (for whatever reason) use the far superior [Silversearch](https://github.com/MrMugame/silversearch) instead. Seriously, use Silversearch instead of this.
No? Alright then.
## Initial index
Perform a `Space: Reindex` after installing this plug.
## Commands
* `Search Space` (`Cmd-Shift-f`/`Ctrl-Shift-f`): performs a full text search across your space.
# Implementation
(part Lua, part Plug)
```space-lua
-- priority: 5
command.define {
name = "Search Space",
key = "Ctrl-Shift-f",
mac = "Cmd-Shift-f",
run = function()
local phrase = editor.prompt "Search for:"
if phrase then
editor.navigate("search:" .. phrase)
end
end
}
virtualPage.define {
pattern = "search:(.+)",
run = function(phrase)
-- These are implemented in the plug code
local results = search.ftsSearch(phrase)
local pageText = "# Search results for '" .. phrase .. "'\n"
for r in each(results) do
pageText = pageText .. spacelua.interpolate("* [[${r.id}|${r.id}]] (score ${r.score})\n", {r=r})
end
return pageText
end
}
```

File diff suppressed because one or more lines are too long

84
Notfall/Kontakte.md Normal file
View File

@@ -0,0 +1,84 @@
# 📞 Wichtige Kontakte & Adressbuch
<div class="is-danger">
<strong>IM NOTFALL:</strong><br>
🚑 <strong>Rettungsdienst / Feuerwehr:</strong> <a href="tel:112">112</a><br>
🚓 <strong>Polizei:</strong> <a href="tel:110">110</a><br>
☠️ <strong>Giftnotruf:</strong> <a href="tel:116117">116 117</a> (oder lokale Nummer: `[Nummer]`)<br>
🏥 <strong>Ärztlicher Bereitschaftsdienst:</strong> <a href="tel:116117">116 117</a> (Wenn Arzt zu hat)
</div>
---
## 👩‍⚕️ Ärzte & Gesundheit
| Fachrichtung | Name / Praxis | Telefon | Adresse / Notiz |
| :--- | :--- | :--- | :--- |
| **Hausarzt** | `[Name]` | `[Telefon]` | `[Adresse]` |
| **Kinderarzt** | `[Name]` | `[Telefon]` | `[Adresse]` |
| **Zahnarzt** | `[Name]` | `[Telefon]` | `[Adresse]` |
| **Apotheke (Stamm)** | `[Name]` | `[Telefon]` | `[Öffnungszeiten]` |
| **Tierarzt** | `[Name]` | `[Telefon]` | `[Adresse]` |
| **Krankenhaus** | `[Name Klinik]` | `[Telefon Pforte]` | `[Adresse Notaufnahme]` |
---
## 🛠️ Handwerker & Haus-Service
<div class="is-warning">
<strong>Tipp:</strong> Halte bei Anrufen immer die Kundennummer oder Modellnummer des defekten Geräts bereit.
</div>
| Gewerk | Firma / Name | Telefon (Notdienst) | Kundennummer / Notiz |
| :--- | :--- | :--- | :--- |
| **Heizung / Sanitär** | `[Firma]` | `[Telefon]` | Wartungsvertrag: `[Ja/Nein]` |
| **Elektriker** | `[Firma]` | `[Telefon]` | `[Notiz]` |
| **Schlüsseldienst** | `[Firma]` | `[Telefon]` | *Vorsicht vor Abzocke! Nur diesen anrufen.* |
| **Dachdecker** | `[Firma]` | `[Telefon]` | `[Notiz]` |
| **Kaminkehrer** | `[Name]` | `[Telefon]` | `[Kehrbezirk]` |
| **Hausverwaltung** | `[Name]` | `[Telefon]` | `[Ansprechpartner]` |
---
## 🏘️ Nachbarn & Familie (Privat)
| Rolle | Name | Telefon / Handy | Hat Hausschlüssel? |
| :--- | :--- | :--- | :--- |
| **Notfall-Kontakt 1** | `[Name]` | `[Nummer]` | ✅ Ja |
| **Notfall-Kontakt 2** | `[Name]` | `[Nummer]` | ❌ Nein |
| **Nachbar (Rechts)** | `[Name]` | `[Nummer]` | ❌ Nein |
| **Nachbar (Links)** | `[Name]` | `[Nummer]` | ❌ Nein |
---
## ⚡ Störungshotlines (Versorger)
Wenn der Strom weg ist oder das Internet streikt.
| Versorger | Anbieter | Störungs-Hotline (24h) | Kundennummer |
| :--- | :--- | :--- | :--- |
| **Stromnetz** | `[Netzbetreiber]` | `[Nummer]` | `[Zählernummer]` |
| **Wasserwerk** | `[Stadtwerke]` | `[Nummer]` | `[Zählernummer]` |
| **Internet / Telefon** | `[Anbieter]` | `[Nummer]` | `[Vertragsnummer]` |
| **Gasnetz** | `[Netzbetreiber]` | `[Nummer]` | `[Zählernummer]` |
---
## 🛡️ Versicherungen (Schadensmeldung)
| Versicherung | Gesellschaft | Hotline Schadensfall | Police-Nr. (Versicherungsschein) |
| :--- | :--- | :--- | :--- |
| **Gebäude** | `[Firma]` | `[Nummer]` | `[Nummer]` |
| **Hausrat** | `[Firma]` | `[Nummer]` | `[Nummer]` |
| **Haftpflicht** | `[Firma]` | `[Nummer]` | `[Nummer]` |
| **Rechtsschutz** | `[Firma]` | `[Nummer]` | `[Nummer]` |
---
## 🏫 Schule & Betreuung
| Einrichtung | Name | Telefon | Ansprechpartner / Klasse |
| :--- | :--- | :--- | :--- |
| **Kita / Kiga** | `[Name]` | `[Telefon]` | `[Gruppe]` |
| **Schule** | `[Name]` | `[Sekretariat]` | `[Klassenlehrer]` |
| **Hort** | `[Name]` | `[Telefon]` | `[Gruppe]` |

95
Notfall/Verhalten.md Normal file
View File

@@ -0,0 +1,95 @@
# 🚨 Notfall- & Verhaltenspläne
<div class="is-danger">
<strong>NOTRUF NUMMERN:</strong><br>
🚒 Feuerwehr / Rettungsdienst: <a href="tel:112">112</a><br>
🚓 Polizei: <a href="tel:110">110</a><br>
☠️ Giftnotruf: <a href="tel:116117">116 117</a> (oder lokale Nummer einfügen)
</div>
---
## 1. 🔥 Feuer & Rauch
**Oberste Regel:** Eigenschutz geht vor Löschversuch. Rauchgas ist tödlicher als Feuer (Kohlenmonoxid-Intoxikation).
### Vorgehen (R-A-S Regel)
1. **R**etten: Menschen aus dem Gefahrenbereich bringen.
2. **A**larmieren: **112** rufen. Alle Hausbewohner warnen (laut rufen!).
3. **S**chließen: Fenster und Türen schließen (Sauerstoffzufuhr unterbinden), aber nicht abschließen.
### Löschversuch (Nur bei Entstehungsbränden!)
* **Fettbrand (Küche):** NIEMALS Wasser! (Fettexplosion). Deckel drauf oder Löschdecke nutzen.
* **Elektrobrand:** Sicherung raus, dann CO2- oder Pulverlöscher.
### Standorte Feuerlöscher & Decken
| Etage | Ort | Typ (Schaum/Pulver/CO2) |
| :--- | :--- | :--- |
| EG | *z.B. Küche, neben Kühlschrank* | Löschdecke |
| EG | *z.B. Flur, Eingangstür* | Schaumlöscher 6L |
| OG | *z.B. Treppenaufgang* | Pulverlöscher |
---
## 2. 💧 Wasserrohrbruch / Überflutung
<div class="is-warning">
<strong>Gefahr durch Stromschlag!</strong> Wasser leitet. Bevor du den Raum betrittst: Sicherungen prüfen/aussschalten.
</div>
### Sofortmaßnahmen
1. **Wasser stoppen:** Hauptwasserhahn sofort schließen.
* 📍 **Ort:** *[Hier Ort einfügen, z.B. Keller, Raum HR 2]*
* 🔗 [Details & Foto siehe Haustechnik](/technik/wasser)
2. **Strom aus:** Betroffene Stromkreise am Sicherungskasten abschalten.
* 📍 **Ort:** *[Hier Ort einfügen]*
3. **Abpumpen:** Wenn Wasserpegel steigt, Feuerwehr (112) nur bei Gefahr rufen. Sonst Sanitär-Notdienst.
---
## 3. 👃 Gasgeruch
<div class="is-danger">
<strong>EXPLOSIONSGEFAHR!</strong> Schon der kleinste Funke (Lichtschalter, Telefon, Klingel) reicht für die Zündung des Gas-Luft-Gemisches.
</div>
### Protokoll
1. **Keine Schalter betätigen:** Kein Licht an/aus. Nicht telefonieren (Handy auslassen). Nicht rauchen.
2. **Lüften:** Fenster und Türen weit öffnen (Durchzug herstellen, Gaskonzentration senken).
3. **Hahn zu:** Gashaupthahn schließen (nur wenn gefahrlos erreichbar).
* 📍 **Ort:** *[Z.B. Gelber Hebel an der Therme/Keller]*
4. **Raus:** Haus sofort verlassen.
5. **Alarmieren:** Polizei/Feuerwehr von **draußen** (beim Nachbarn oder Handy weit weg vom Haus) rufen.
---
## 4. ⚡ Stromausfall (Blackout)
### Checkliste
1. **Sicherungskasten prüfen:** Ist nur der FI-Schalter (RCD) geflogen? Oder ist der ganze Straßenzug dunkel?
* *Nur Haus:* Defektes Gerät suchen.
* *Ganze Straße:* Ruhe bewahren. Kühlschrank/Gefriertruhe **nicht öffnen** (Kältebrücke hält ca. 12-24h).
2. **Lichtquelle:** Taschenlampen nutzen (Kerzen nur unter Aufsicht wegen Brandgefahr).
3. **Wasser:** Bei langem Ausfall (wenn Hauswasserwerk/Pumpe elektrisch ist): Wasservorrat prüfen.
**Standort Notfall-Box (Taschenlampen/Batterien):**
* 📍 *[Ort einfügen, z.B. Schublade im Flur]*
---
## 5. 🏥 Medizinischer Notfall (Akut)
1. **Bewusstsein prüfen:** Ansprechen, Schultern rütteln.
2. **Atmung prüfen:** Sehen, Hören, Fühlen.
3. **Handeln:**
* *Keine Atmung:* **112** -> Sofort Herzdruckmassage (30x drücken, 2x beatmen). Rhythmus: "Stayin' Alive".
* *Bewusstlos aber Atmung:* Stabile Seitenlage.
🔗 **[Zur Medikamentenliste & Erste-Hilfe-Inventar](/notfall/medizin)**
---
## 📍 Sammelpunkt (Evakuierung)
Wenn das Haus verlassen werden muss (Feuer/Gas), treffen wir uns hier, um Vollzähligkeit zu prüfen:
* **Ort:** *[z.B. Bei der großen Eiche beim Nachbarn gegenüber / Am Straßenschild X]*

160
Repositories/malys.md Normal file
View File

@@ -0,0 +1,160 @@
---
name: "Repositories/malys"
tags: meta/repository
pageDecoration.prefix: "🦩"
share.uri: "https://github.com/malys/silverbullet-libraries/blob/main/Repositories/malys.md"
share.hash: 9d911bb0
share.mode: pull
---
```#meta/library/remote
name: "Breadcrumb"
uri: https://github.com/malys/silverbullet-libraries/blob/main/src/Breadcrumb.md
website: https://github.com/malys/silverbullet-libraries/blob/main/src/Breadcrumb.md
description: "Generate breadcrumbs for a page"
---
name: "Lru"
uri: https://github.com/malys/silverbullet-libraries/blob/main/src/cache/LRU.md
website: https://github.com/malys/silverbullet-libraries/blob/main/src/cache/LRU.md
description: "LRU cache leveraging @isaacs/lrucache"
---
name: "Ttl"
uri: https://github.com/malys/silverbullet-libraries/blob/main/src/cache/TTL.md
website: https://github.com/malys/silverbullet-libraries/blob/main/src/cache/TTL.md
description: "TTL cache leveraging @isaacs/ttlcache"
---
name: "Configcode"
uri: https://github.com/malys/silverbullet-libraries/blob/main/src/ConfigCode.md
website: https://github.com/malys/silverbullet-libraries/blob/main/src/ConfigCode.md
description: "Quickly insert config code."
---
name: "Cursorposition"
uri: https://github.com/malys/silverbullet-libraries/blob/main/src/CursorPosition.md
website: https://github.com/malys/silverbullet-libraries/blob/main/src/CursorPosition.md
description: "Generate and copy links to specific cursor positions and headers in markdown documents"
---
name: "Customslashcommand"
uri: https://github.com/malys/silverbullet-libraries/blob/main/src/CustomSlashCommand.md
website: https://github.com/malys/silverbullet-libraries/blob/main/src/CustomSlashCommand.md
description: "custom slash commands."
---
name: "Externaltransclusion"
uri: https://github.com/malys/silverbullet-libraries/blob/main/src/ExternalTransclusion.md
website: https://github.com/malys/silverbullet-libraries/blob/main/src/ExternalTransclusion.md
description: "Transclude data form external resource."
---
name: "Fasttagexplorer"
uri: https://github.com/malys/silverbullet-libraries/blob/main/src/FastTagExplorer.md
website: https://github.com/malys/silverbullet-libraries/blob/main/src/FastTagExplorer.md
description: "Generate wall of children page tags"
---
name: "Githistory"
uri: https://github.com/malys/silverbullet-libraries/blob/main/src/GitHistory.md
website: https://github.com/malys/silverbullet-libraries/blob/main/src/GitHistory.md
description: "Implement Git commands (log, diff, revert)"
---
name: "Helpshortcuts"
uri: https://github.com/malys/silverbullet-libraries/blob/main/src/HelpShortcuts.md
website: https://github.com/malys/silverbullet-libraries/blob/main/src/HelpShortcuts.md
description: "Display most commun shortcuts."
---
name: "Llminstructions"
uri: https://github.com/malys/silverbullet-libraries/blob/main/src/LLMInstructions.md
website: https://github.com/malys/silverbullet-libraries/blob/main/src/LLMInstructions.md
description: "System prompt to pilot LLM in SB plugin coding."
---
name: "Markmapmindmap"
uri: https://github.com/malys/silverbullet-libraries/blob/main/src/MarkmapMindmap.md
website: https://github.com/malys/silverbullet-libraries/blob/main/src/MarkmapMindmap.md
description: "MarkMap mindmap integration."
---
name: "Marpslides"
uri: https://github.com/malys/silverbullet-libraries/blob/main/src/MarpSlides.md
website: https://github.com/malys/silverbullet-libraries/blob/main/src/MarpSlides.md
description: "Marp slides integration."
---
name: "Mdprettier"
uri: https://github.com/malys/silverbullet-libraries/blob/main/src/mdPrettier.md
website: https://github.com/malys/silverbullet-libraries/blob/main/src/mdPrettier.md
description: "Beautify md file."
---
name: "Mdtablerender"
uri: https://github.com/malys/silverbullet-libraries/blob/main/src/MdTableRender.md
website: https://github.com/malys/silverbullet-libraries/blob/main/src/MdTableRender.md
description: "Automatically formats Markdown table cells based on hashtag column tags."
---
name: "Mdtablesheet"
uri: https://github.com/malys/silverbullet-libraries/blob/main/src/MdTableSheet.md
website: https://github.com/malys/silverbullet-libraries/blob/main/src/MdTableSheet.md
description: "Integrate FormulaJS in markdown table (table = sheet)."
---
name: "Organization Chart"
uri: https://github.com/malys/silverbullet-libraries/blob/main/src/Organization/Organization-Chart.md
website: https://github.com/malys/silverbullet-libraries/blob/main/src/Organization/Organization-Chart.md
description: "Organization chart create [Plantuml](https://plantuml.com/fr/) organization chart."
---
name: "Organization Company"
uri: https://github.com/malys/silverbullet-libraries/blob/main/src/Organization/Organization-Company.md
website: https://github.com/malys/silverbullet-libraries/blob/main/src/Organization/Organization-Company.md
description: "Organization Company card template."
---
name: "Organization Employee"
uri: https://github.com/malys/silverbullet-libraries/blob/main/src/Organization/Organization-Employee.md
website: https://github.com/malys/silverbullet-libraries/blob/main/src/Organization/Organization-Employee.md
description: "Organization employee template"
---
name: "Organization Vcfexport"
uri: https://github.com/malys/silverbullet-libraries/blob/main/src/Organization/Organization-VCFExport.md
website: https://github.com/malys/silverbullet-libraries/blob/main/src/Organization/Organization-VCFExport.md
description: "Generate VCF of company's employees."
---
name: "Replaceplaceholders"
uri: https://github.com/malys/silverbullet-libraries/blob/main/src/ReplacePlaceholders.md
website: https://github.com/malys/silverbullet-libraries/blob/main/src/ReplacePlaceholders.md
description: "Replace Placeholders with specific values"
---
name: "Riskaudit"
uri: https://github.com/malys/silverbullet-libraries/blob/main/src/RiskAudit.md
website: https://github.com/malys/silverbullet-libraries/blob/main/src/RiskAudit.md
description: "Risk audit (scripts analyzor)"
---
name: "Taiga"
uri: https://github.com/malys/silverbullet-libraries/blob/main/src/Taiga.md
website: https://github.com/malys/silverbullet-libraries/blob/main/src/Taiga.md
description: "Taiga project management tool"
---
name: "Theme Malys"
uri: https://github.com/malys/silverbullet-libraries/blob/main/src/Theme/theme-malys.md
website: https://github.com/malys/silverbullet-libraries/blob/main/src/Theme/theme-malys.md
description: "Dark theme thought for readibility and productivity"
---
name: "Utilities"
uri: https://github.com/malys/silverbullet-libraries/blob/main/src/Utilities.md
website: https://github.com/malys/silverbullet-libraries/blob/main/src/Utilities.md
description: "List of reusable functions."
---
name: "Debugger"
uri: https://github.com/malys/silverbullet-libraries/blob/main/src/Utilities/Debugger.md
website: https://github.com/malys/silverbullet-libraries/blob/main/src/Utilities/Debugger.md
description: "Tooling to debug (linter, postion, beautify)"
---
name: "Luacheck"
uri: https://github.com/malys/silverbullet-libraries/blob/main/src/Utilities/Luacheck.md
website: https://github.com/malys/silverbullet-libraries/blob/main/src/Utilities/Luacheck.md
description: "Lua linter."
---
name: "Utilitycode"
uri: https://github.com/malys/silverbullet-libraries/blob/main/src/UtilityCode.md
website: https://github.com/malys/silverbullet-libraries/blob/main/src/UtilityCode.md
description: "Quickly insert utility code."
---
name: "Vikunja"
uri: https://github.com/malys/silverbullet-libraries/blob/main/src/Vikunja.md
website: https://github.com/malys/silverbullet-libraries/blob/main/src/Vikunja.md
description: "Vikunja, open-source project management tool, integration."
---
name: "Vscodepalette"
uri: https://github.com/malys/silverbullet-libraries/blob/main/src/VSCodePalette.md
website: https://github.com/malys/silverbullet-libraries/blob/main/src/VSCodePalette.md
description: "DEPRECATED universal palette (as VScode Palette), use '>' to execute commands"
---
```

4
SETTINGS.md Normal file
View File

@@ -0,0 +1,4 @@
treeview:
exclusions:
- type: "space-function"
name: "filterOldDailyNotes"

38
_plug/treeview.plug.js Normal file

File diff suppressed because one or more lines are too long

76
index.md Normal file
View File

@@ -0,0 +1,76 @@
# HIHI
[[IT/Ports]]🔌
[[IT/Services]]🖥️
Hello 👋
Welcome to the wondrous world of SilverBullet. A world that once you discover and appreciate, youll never want to leave.
_One of us!_
You can go ahead and delete this placeholder content in a second, but before you do, let me quickly show you around.
Well do this through a list of **silver bullets**.
_Ah, so that explains the name!_
* Click on the page picker (book icon) icon at the top right, or hit `Cmd-k` (Mac) or `Ctrl-k` (Linux and Windows) to open the **page picker**.
* Type the name of a non-existent page to create it.
* Folders are implicitly created by putting slashes (`/`) in the name (even on Windows), e.g. `My Folder/My Page`. Dont worry about folders existing, SilverBullet will automatically create them if they dont.
* Click on the terminal icon (top right), or hit `Cmd-/` (Mac) or `Ctrl-/` (Linux and Windows) to open the **command palette**. From here you can run various useful and perhaps less useful commands.
* Select some text and hit `Cmd-b` (Mac) or `Ctrl-b` (Windows/Linux) to make it **bold**, or `Cmd-i` (Mac) or `Ctrl-i` (Windows/Linux) to make it _italic_.
* You can create links to pages using the `[[other page]]` syntax, for instance: `[[aspiring page]]`. When you link to a non-existent page it will initially show up in orange (to indicate it does not yet exist), but once you click it — you will create the page automatically (only for real when you actually enter some text).
* Start typing `:party` to trigger the emoji picker 🎉
* Type `/` somewhere in the text to invoke a **slash command**.
* If this matches your personality type, there is also an `Editor: Toggle Vim Mode` command to switch to Vim mode. If you cannot figure out how to exit it (classic vim issue), just run that same command again. _Phew!_
* As you may have noticed, while SilverBullet uses [markdown](https://www.markdownguide.org/) underneath, it also “live previews” it to give a bit more of a WYSIWYG feel. You can always move your cursor “into” the underlying code by `Alt-clicking` it (even links and widgets, which well get to later).
While SilverBullet implements (most) of [CommonMark](https://commonmark.org/), it also adds a few extensions that are SilverBullet-specific. Most notably, it adds the `${Lua expression}` syntax to render Lua expressions inline.
Using SilverBullets Lua APIs, you can do all kinds of cool stuff. For instance, query your space for the last 3 modified pages. _Exciting!_
${query[[from index.tag "page" order by lastModified desc limit 3]]}
Theres a whole world out there to explore, but lets not get ahead of ourselves. First, have some fun and add some content to your fresh space.
Then well talk.
# What next?
You can find more information on SilverBullets feature set on its [official website](https://silverbullet.md/). Also, be sure to join the [SilverBullet community](https://community.silverbullet.md/) to interact with fellow SilverBullet explorers.

41
technik/wasser.md Normal file
View File

@@ -0,0 +1,41 @@
# ⚡ Elektrik & Sicherungskasten
<div class="is-danger">
<strong>Sicherheitsregel:</strong> Arbeiten an der Elektrik nur durch Fachpersonal. Vor Arbeiten immer: <strong>Freischalten, gegen Wiedereinschalten sichern, Spannungsfreiheit feststellen.</strong>
</div>
## 📍 Hauptverteilung (Sicherungskasten)
**Ort:** `[z.B. Flur EG / Keller]`
### FI-Schutzschalter (RCD)
Der FI-Schalter schützt Personen vor Stromschlag.
* **Test-Intervall:** 2x jährlich (Drücken der "T"-Taste).
* **Auslöser:** `30mA` Differenzstrom.
### Belegungsplan (Sicherungen)
| Nr. | Typ | Ampere | Zuständig für (Räume / Großgeräte) |
| :--- | :--- | :--- | :--- |
| **1** | B16 | 16A | Wohnzimmer (Licht & Steckdosen) |
| **2** | B16 | 16A | Küche (Allgemein) |
| **3** | B16 | 16A | *Kühlschrank (Separat)* |
| **4** | B16 | 16A | Waschmaschine |
| **5-7** | **3-Phasen** | 16A | E-Herd / Backofen (Drehstrom) |
| **8** | B16 | 16A | Außenbereich / Garage |
---
## 💡 Leuchtmittel-Inventar
Damit man im Baumarkt weiß, welche Fassung man braucht.
| Raum | Lampe | Fassung (Sockel) | Watt / Lumen | Farbtemp. (Kelvin) |
| :--- | :--- | :--- | :--- | :--- |
| WZ | Decke | `E27` | LED 10W | 2700K (Warmweiß) |
| Küche | Spots | `GU10` | LED 5W | 4000K (Neutral) |
| Bad | Spiegel | `E14` | LED 4W | 3000K |
---
## 🔌 Spezielle Anschlüsse
* **Starkstrom (CEE):** Vorhanden in Garage? `[Ja/Nein]` (z.B. 16A oder 32A rot).
* **Außensteckdosen:** Schaltbar von innen? `[Ja/Nein]` (Schalterort: `...`).