Merge branch 'main' of ssh://local.ionivation.com:2222/realAscot/adminslog

This commit is contained in:
Adam Skotarczak 2025-06-27 10:55:55 +02:00
commit d28fc84bae
24 changed files with 2341 additions and 28 deletions

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
.vscode/
node_modules/
dist/

16
CHANGELOG.md Normal file
View File

@ -0,0 +1,16 @@
# Changelog
- **25/06/15** - commit: v0.2.0
- **Hinzugefügt:**
- [X] git submodule erstellt
- [X] Rust Toolchain Einrichtung
- [X] Rust offline-installation
- **25/06/15** - commit: v0.1.0
- **Hinzugefügt:**
- [X] helix
- [x] desktop.ini
---
- **initial commit**

View File

@ -1 +1 @@
(C) - 2025 Adam Skotarczak
(C) 2025 - Adam Skotarczak <adam@skotarczak.net

134
README.md
View File

@ -1,25 +1,42 @@
# Admin´s Log
# -= Admin´s Log =-
Kleine Sammlung von Gedächnissstützen für den privaten und persönlichen Gebrauch.
![Logo Adam Skotarczak](./media/realAscotLogo_128x128.png)
Kleine Sammlung von Gedächnissstützen für den privaten und persönlichen Gebrauch.
Ausserdem befinden sich hier auch viele Artikel die von mir noch nicht vollständig verwertet worden sind.
Die Artikel sind auch zur Vorbereitung für neue Artikel auf <https://www.ionivation.com> vorgesehen.
**origin:** <https://local.ionivation.com/realAscot/adminslog>
## Inhalt
- [Admin´s Log](#admins-log)
- [-= Admin´s Log =-](#--admins-log--)
- [Inhalt](#inhalt)
- [Informationen](#informationen)
- [Themen](#themen)
- [AsciiDoc](#asciidoc)
- [Editoren/ IDE´s](#editoren-ides)
- [Helix](#helix)
- [Git](#git)
- [Markdown](#markdown)
- [Mermaid](#mermaid)
- [Mechanik](#mechanik)
- [Server](#server)
- [Plesk](#plesk)
- [Webserver](#webserver)
- [Windows](#windows)
- [Programmierung](#programmierung)
- [Rust](#rust)
- [ts - js - node](#ts---js---node)
- [Projektinhalt](#projektinhalt)
- [Neue Dokumente](#neue-dokumente)
---
## Informationen
Unter `./tools/` befinden sich Programme/ Skripte (aktuell in Typescript und Python) die Markdown-Dateien suchen und daraus ein Verzeichnis erstellen.
---
## Themen
@ -28,32 +45,131 @@ Kleine Sammlung von Gedächnissstützen für den privaten und persönlichen Gebr
### AsciiDoc
- [Asciidoctor PDF: Kapitel bleibt „Chapter“ Fehleranalyse & Workaround](dokus/asciidoc/asciidoctor-theme-bug-workaround.md)
- [Asciidoctor PDF: Kapitel bleibt „Chapter“ Fehleranalyse & Workaround](dokus/asciidoc/asciidoctor-theme-bug-workaround.md)
---
### Editoren/ IDE´s
#### Helix
- [Helix Editor Ein umfassender Einstieg für Anfänger (Deutsch)](dokus/helix__editor_einfuehrung_de.md)
---
### Git
- [Artikel: git](dokus/git/git.md)
- [SSH-Zugriff auf Git-Repository in WSL einrichten](dokus/git/git-ssh-remote.md)
- [SSH-Zugriff auf Git-Repository in WSL einrichten](dokus/git/git-ssh-remote.md)
- [Git Remote-Branches: Häufige Aufgaben und Lösungen](dokus/git/git-remote-branch.md)
- [Git-Submodule: Der umfassende Praxisleitfaden](dokus/git/git-submodule-leitfaden.md)
### Markdown
#### Mermaid
- [mermaidPockedGuide](https://dns.lan:3000/realAscot/mermaidPockedGuide/src/branch/main/README.md) **EXTERN**
- [mermaidPockedGuide](https://local.ionivation.com/realAscot/mermaidPockedGuide) **EXTERN** 🚀
### Mechanik
- [Gewindetabellen](dokus/mechanik/gewindetabellen.md)
---
### Server
#### Plesk
- [Plesk ausgesperrt bei Rechnerwechsel](dokus/plesk/plesk-benutzer-schon-vorhanden.md)
#### Webserver
- [Let's Encrypt: Fehlerbehebung bei Challenge-Timeout unter Plesk](dokus/apache-plesk/lets-encrypt-plesk.md)
- [Let's Encrypt: Fehlerbehebung bei Challenge-Timeout unter Plesk](dokus/apache-plesk/lets-encrypt-plesk.md)
---
### Windows
- [Einführung in die `desktop.ini`-Datei: Verwendung und Anpassung von Ordnern in Windows](dokus/windows/desktop_ini.md)
---
### Programmierung
#### Rust
- [Rust-Toolchain mit MSVC unter Windows einrichten](dokus/rust/rust-toolchain-msvc.md)
- [Erstellung eines Installationsmediums für Rust + MSVC (Offline)](dokus/rust/rust-offline-installation.md)
---
#### ts - js - node
- [Einstieg in JavaScript-Dialekte und TypeScript-Konfiguration](dokus/js-ts/js-ts-dialekte.md)
---
## Projektinhalt
*Erstellt mit [treescanner](https://github.com/realAscot/treeScanner)*
```plaintext
📁 ./
├── 📁 dokus
│ ├── 📁 apache-plesk
│ │ └── 📄 lets-encrypt-plesk.md
│ ├── 📁 asciidoc
│ │ └── 📄 asciidoctor-theme-bug-workaround.md
│ ├── 📁 git
│ │ ├── 📄 git-remote-branch.md
│ │ ├── 📄 git-ssh-remote.md
│ │ ├── 📄 git-submodule-leitfaden.md
│ │ └── 📄 git.md
│ ├── 📁 js-ts
│ │ └── 📄 js-ts-dialekte.md
│ ├── 📁 mechanik
│ │ └── 📄 gewindetabellen.md
│ ├── 📁 plesk
│ │ └── 📄 plesk-benutzer-schon-vorhanden.md
│ ├── 📁 rust
│ │ ├── 📄 rust-offline-installation.md
│ │ └── 📄 rust-toolchain-msvc.md
│ ├── 📁 windows
│ │ └── 📄 desktop_ini.md
│ └── 📄 helix__editor_einfuehrung_de.md
├── 📁 media
│ └── 📄 realAscotLogo_128x128.png
├── 📁 tools
│ ├── 📁 collector
│ │ ├── 📄 config.jsonc
│ │ ├── 📄 link_collector.js
│ │ ├── 📄 link_collector.py
│ │ └── 📄 processed.log
│ ├── 📁 dist
│ │ ├── 📁 collector
│ │ ├── 📄 fscopy.js
│ │ └── 📄 fsdel.js
│ └── 📁 src
│ ├── 📁 collector
│ │ ├── 📄 config.jsonc.template
│ │ └── 📄 link_collector.ts
│ ├── 📄 fscopy.ts
│ └── 📄 fsdel.ts
├── 📄 .gitignore
├── 📄 CHANGELOG.md
├── 📄 LICENSE
├── 📄 package-lock.json
├── 📄 package.json
├── 📄 README.md
├── 📄 scan.cmd
├── 📄 tsconfig.json
└── 📄 VERSION
```
---
## Neue Dokumente
> führe `scan.cmd` oder [`link_collector.py`](./tools/collector/link_collector.py) aus um nach neuen Dateien zu suchen!
> führe `scan.cmd` oder [`link_collector.py`](./tools/collector/link_collector.py) oder `npm run scan` aus um nach neuen Dateien zu suchen!
**NEUE EINTRÄGE AUS './tools/collector/link_collector.py'->**
**NEUE EINTRÄGE AUS 'link_collector'->**

2
VERSION Normal file
View File

@ -0,0 +1,2 @@
0.2.0
15.06.2025

View File

@ -0,0 +1,203 @@
# Git-Submodule: Der umfassende Praxisleitfaden
## Inhalt
- [Git-Submodule: Der umfassende Praxisleitfaden](#git-submodule-der-umfassende-praxisleitfaden)
- [Inhalt](#inhalt)
- [🔰 Was ist ein Git-Submodul?](#-was-ist-ein-git-submodul)
- [🧱 Grundlagen](#-grundlagen)
- [📌 `.gitmodules`](#-gitmodules)
- [🧠 Merksatz](#-merksatz)
- [🛠️ Submodul hinzufügen](#-submodul-hinzufügen)
- [🔄 Submodule aktualisieren](#-submodule-aktualisieren)
- [📥 Klonen mit Submodulen](#-klonen-mit-submodulen)
- [Methode 1: Inklusive Submodule](#methode-1-inklusive-submodule)
- [Methode 2: Nachträglich initialisieren](#methode-2-nachträglich-initialisieren)
- [🔃 Submodul-Synchronisation](#-submodul-synchronisation)
- [📂 Weitere Remotes im Submodul](#-weitere-remotes-im-submodul)
- [❗ Stolperfallen und Besonderheiten](#-stolperfallen-und-besonderheiten)
- [🔄 Remote-URL wechseln](#-remote-url-wechseln)
- [🚀 Push \& Pull Verhalten](#-push--pull-verhalten)
- [🧼 Submodul löschen](#-submodul-löschen)
- [🧰 Best Practices](#-best-practices)
- [📎 Nützliche Kommandos](#-nützliche-kommandos)
- [📑 Beispiel `.gitmodules` mit kommentierter Remote-Auswahl](#-beispiel-gitmodules-mit-kommentierter-remote-auswahl)
- [🧭 Alternative: Subtree statt Submodul?](#-alternative-subtree-statt-submodul)
- [📚 Fazit](#-fazit)
- [🔗 Weiterführende Links](#-weiterführende-links)
---
## 🔰 Was ist ein Git-Submodul?
Ein **Submodul** ist ein Git-Repository innerhalb eines anderen Git-Repositories. Es erlaubt, einen festen Commit eines externen Repositories als Teilprojekt einzubinden, ohne dessen Dateien direkt zu übernehmen.
Beispielhafte Struktur:
```plaintext
hauptprojekt/
├── .gitmodules
├── modul1/ ← eingebundenes Submodul
└── modul2/
```
## 🧱 Grundlagen
### 📌 `.gitmodules`
Diese Datei beschreibt Pfad und Remote-URL aller eingebundenen Submodule:
```ini
[submodule "modul1"]
path = modul1
url = git@github.com:user/modul1.git
```
### 🧠 Merksatz
> Submodule sind **Pointer auf einen bestimmten Commit** eines anderen Repositories.
## 🛠️ Submodul hinzufügen
```bash
git submodule add <repo-url> <zielpfad>
git commit -m "📦 Submodul hinzugefügt"
```
Beispiel:
```bash
git submodule add git@github.com:user/libmath.git extern/libmath
```
Erzeugt:
- `.gitmodules`
- Verzeichniseintrag im Git-Index
- Initialer Checkout des Submoduls (HEAD auf Remote-Commit)
## 🔄 Submodule aktualisieren
```bash
cd extern/libmath
git pull origin main
cd ../..
git add extern/libmath
git commit -m "🔄 Submodul libmath aktualisiert"
```
> Nur das **Hauptrepo speichert den Commit-Zeiger**, nicht den Submodul-Inhalt selbst.
## 📥 Klonen mit Submodulen
### Methode 1: Inklusive Submodule
```bash
git clone --recurse-submodules <url>
```
### Methode 2: Nachträglich initialisieren
```bash
git clone <url>
git submodule update --init
```
## 🔃 Submodul-Synchronisation
Wenn sich `.gitmodules` ändert (z.B. Remote-URL):
```bash
git submodule sync
```
## 📂 Weitere Remotes im Submodul
```bash
cd modul1
git remote add backup git@backup.server:repo.git
```
> Diese Remotes sind **lokal**, nicht versioniert. `.gitmodules` kennt nur den Haupt-Remote.
## ❗ Stolperfallen und Besonderheiten
| Problem | Erklärung |
|--------|-----------|
| Submodul wird nicht mitgeclont | `--recurse-submodules` vergessen |
| Änderungen im Submodul nicht sichtbar | Submodul-Commit im Hauptrepo nicht geupdated |
| `.gitmodules` zeigt nicht funktionierende URL | z.B. lokale URL nach GitHub-Push muss angepasst werden |
| Submodul zeigt „detached HEAD“ | normaler Zustand, wenn Submodul auf festen Commit gesetzt ist |
## 🔄 Remote-URL wechseln
```bash
# In .gitmodules ändern oder per Befehl:
git config -f .gitmodules submodule.modul1.url git@github.com:newuser/libmath.git
git submodule sync
```
## 🚀 Push & Pull Verhalten
| Aktion | Wirkung |
|---------------------|---------|
| `git push` im Hauptrepo | Pusht nur Zeiger auf Submodul-Commit |
| `git push` im Submodul | Muss separat erfolgen |
| `git pull` im Hauptrepo | Holt *nicht* automatisch neuen Submodul-Stand |
## 🧼 Submodul löschen
```bash
# Schritt 1: Entfernen
git submodule deinit -f pfad/zum/modul
git rm -f pfad/zum/modul
rm -rf .git/modules/pfad/zum/modul
git commit -m "❌ Submodul entfernt"
```
## 🧰 Best Practices
- **Nur stabile Submodul-Commits einchecken**, keine laufenden Branches.
- **Submodule niemals blind aktualisieren** Änderungen genau prüfen.
- **Remote-Umschaltung dokumentieren oder automatisieren**, z.B. per Script.
- **Submodule klein halten** große, tief verschachtelte Strukturen vermeiden.
- Für wiederverwendbare Bibliotheken oder Assets ideal (CAD, Snippets, Markdown, etc.).
## 📎 Nützliche Kommandos
```bash
git submodule status # Überblick über alle Submodule
git submodule update --init # Submodule initial holen
git submodule update --remote # Auf neuesten Remote-Stand updaten
git config -f .gitmodules ... # .gitmodules direkt bearbeiten
```
## 📑 Beispiel `.gitmodules` mit kommentierter Remote-Auswahl
```ini
[submodule "modul1"]
path = modul1
url = ssh://git@local.example.com:2222/myorg/modul1.git
# url = git@github.com:myorg/modul1.git
```
## 🧭 Alternative: Subtree statt Submodul?
Subtree ist einfacher zu verwalten, aber:
- kein fester Commit-Zeiger,
- kein Remote-Wechsel ohne Umweg,
- gemergte Historie im Hauptrepo.
**Submodul = getrennte Repos**
**Subtree = eingemergter Inhalt**
## 📚 Fazit
Git-Submodule sind mächtig, aber erfordern **Disziplin und Überblick**. Für wiederverwendbare Komponenten, zentral gepflegte Inhalte oder externe Bibliotheken sind sie oft die bessere Wahl als Duplikate oder Copy-Paste.
## 🔗 Weiterführende Links
- [Git Book: Submodules](https://git-scm.com/book/en/v2/Git-Tools-Submodules)
- [git-scm Doku: submodule](https://git-scm.com/docs/git-submodule)
- [Vergleich Submodule vs. Subtree](https://www.atlassian.com/git/tutorials/git-submodule)

View File

@ -0,0 +1,182 @@
# Helix Editor Ein umfassender Einstieg für Anfänger (Deutsch)
## Inhalt
- [Helix Editor Ein umfassender Einstieg für Anfänger (Deutsch)](#helix-editor--ein-umfassender-einstieg-für-anfänger-deutsch)
- [Inhalt](#inhalt)
- [✨ Was ist Helix?](#-was-ist-helix)
- [🔧 Installation](#-installation)
- [Linux (Fedora, Arch, Debian)](#linux-fedora-arch-debian)
- [GitHub Release (empfohlen für aktuellste Version)](#github-release-empfohlen-für-aktuellste-version)
- [📁 Erstes Projekt starten](#-erstes-projekt-starten)
- [Beispiel: Rust-Projekt](#beispiel-rust-projekt)
- [Beispiel: JavaScript-Projekt](#beispiel-javascript-projekt)
- [⌨ Bedienkonzept von Helix](#-bedienkonzept-von-helix)
- [Modale Steuerung (ähnlich wie Vim)](#modale-steuerung-ähnlich-wie-vim)
- [Wechsel der Modi](#wechsel-der-modi)
- [⚖️ Wichtige Tastenkombinationen](#-wichtige-tastenkombinationen)
- [🪨 Sprachserver (LSP)](#-sprachserver-lsp)
- [Rust](#rust)
- [JavaScript/TypeScript](#javascripttypescript)
- [C / C++](#c--c)
- [⚖️ LSP-Befehle in Helix](#-lsp-befehle-in-helix)
- [📂 Konfiguration](#-konfiguration)
- [Beispiel-Inhalt](#beispiel-inhalt)
- [🌍 Weitere Ressourcen](#-weitere-ressourcen)
## ✨ Was ist Helix?
Helix ist ein moderner, terminalbasierter Code-Editor mit Fokus auf Produktivität, Effizienz und minimalistische Bedienung. Er verwendet **modale Eingabe** (wie Vim), bietet jedoch eine eigene, einsteigerfreundlichere Philosophie mit moderner Technologie wie **LSP**, **Tree-sitter**, und Syntax-Highlighting direkt aus dem Terminal.
---
## 🔧 Installation
### Linux (Fedora, Arch, Debian)
```bash
# Fedora
sudo dnf install helix
# Arch (via pacman)
sudo pacman -S helix
# Debian/Ubuntu (nur in neueren Versionen oder via GitHub)
```
### GitHub Release (empfohlen für aktuellste Version)
1. Gehe zu: [https://github.com/helix-editor/helix/releases](https://github.com/helix-editor/helix/releases)
2. Lade das passende Paket für dein System herunter
3. Entpacken:
```bash
tar -xvf helix-*-x86_64-linux.tar.xz
sudo cp helix-*/helix/hx /usr/local/bin/
```
---
## 📁 Erstes Projekt starten
### Beispiel: Rust-Projekt
```bash
cargo new hallo_helix
cd hallo_helix
hx src/main.rs
```
### Beispiel: JavaScript-Projekt
```bash
mkdir node_hello && cd node_hello
echo 'console.log("Hallo, Welt!");' > index.js
hx index.js
```
---
## ⌨ Bedienkonzept von Helix
### Modale Steuerung (ähnlich wie Vim)
- **Normalmodus**: Standardmodus zum Navigieren und Bearbeiten
- **Einfügemodus (Insert)**: `i` drücken zum Schreiben
- **Auswahlmodus (Select)**: `v` für Zeichenweise, `V` für Zeilenweise Auswahl
### Wechsel der Modi
| Modus | Taste | Funktion |
| ----------- | ----- | ----------------------- |
| Normal | `Esc` | Zur Steuerung & Befehle |
| Insert | `i` | Einfügen / Tippen |
| Select | `v` | Auswahl ab Cursor |
| Line-Select | `V` | Ganze Zeile auswählen |
---
## ⚖️ Wichtige Tastenkombinationen
| Tastenkombi | Bedeutung |
| ----------- | --------------------------------- |
| `:w` | Datei speichern |
| `:q` | Editor beenden |
| `:wq` | Speichern und beenden |
| `g g` | Zum Anfang der Datei |
| `G` | Zum Ende der Datei |
| `d d` | Aktuelle Zeile löschen |
| `u` | Letzte Änderung rückgängig machen |
| `space + /` | Fuzzy-Dateisuche starten |
| `space + g` | Git-Diff anzeigen |
---
## 🪨 Sprachserver (LSP)
Helix erkennt automatisch den Dateityp und startet den passenden Sprachserver:
### Rust
```bash
rustup component add rust-analyzer
```
### JavaScript/TypeScript
```bash
npm install -g typescript typescript-language-server
```
### C / C++
```bash
sudo dnf install clang clang-tools-extra
```
---
## ⚖️ LSP-Befehle in Helix
| Taste | Bedeutung |
| ----- | ------------------------------- |
| `g d` | Gehe zur Definition |
| `g r` | Gehe zu Referenzen |
| `K` | Hover-Info anzeigen (Typ, Doku) |
| `=` | Formatieren |
---
## 📂 Konfiguration
Helix-Konfiguration liegt unter:
```bash
~/.config/helix/config.toml
```
Zum Öffnen:
```bash
:config-open
```
### Beispiel-Inhalt
```toml
theme = "base16_default_dark"
[keys.normal]
"C-s" = ":w"
"C-q" = ":wq"
```
---
## 🌍 Weitere Ressourcen
- Offizielle Seite: [https://helix-editor.com](https://helix-editor.com)
- GitHub: [https://github.com/helix-editor/helix](https://github.com/helix-editor/helix)
- Tastenkombis: [https://docs.helix-editor.com/](https://docs.helix-editor.com/)
---

View File

@ -0,0 +1,345 @@
# Einstieg in JavaScript-Dialekte und TypeScript-Konfiguration
## ✨ Ziel dieses Dokuments
Diese Anleitung richtet sich an Anfänger, die lernen wollen, wann sie welchen JavaScript-Dialekt (CommonJS vs. ESM) verwenden sollten, wie sie TypeScript korrekt konfigurieren und worauf sie bei modernen Projekten achten müssen.
## Inhalt
- [Einstieg in JavaScript-Dialekte und TypeScript-Konfiguration](#einstieg-in-javascript-dialekte-und-typescript-konfiguration)
- [✨ Ziel dieses Dokuments](#-ziel-dieses-dokuments)
- [Inhalt](#inhalt)
- [🔢 Begriffe erklärt](#-begriffe-erklärt)
- [JavaScript-Dialekte (Modulsysteme)](#javascript-dialekte-modulsysteme)
- [Was ist TypeScript?](#was-ist-typescript)
- [🔍 Wann verwende ich was?](#-wann-verwende-ich-was)
- [🔧 TypeScript richtig konfigurieren](#-typescript-richtig-konfigurieren)
- [📦 Was ist ESM?](#-was-ist-esm)
- [✅ Wann kann/sollte/muss man **ESM** verwenden?](#-wann-kannsolltemuss-man-esm-verwenden)
- [🟢 **Du kannst ESM verwenden**, wenn](#-du-kannst-esm-verwenden-wenn)
- [🟡 **Du solltest ESM verwenden**, wenn](#-du-solltest-esm-verwenden-wenn)
- [🔴 **Du musst ESM verwenden**, wenn](#-du-musst-esm-verwenden-wenn)
- [⚙️ TypeScript-Konfiguration für ESM](#-typescript-konfiguration-für-esm)
- [📌 Merkmale von ESM](#-merkmale-von-esm)
- [⚠️ Besonderheiten und Stolperfallen](#-besonderheiten-und-stolperfallen)
- [✅ Fazit ESM](#-fazit-esm)
- [🌐 CommonJS-Konfiguration CJS (Alternative)](#-commonjs-konfiguration-cjs-alternative)
- [📦 Was ist CommonJS?](#-was-ist-commonjs)
- [✅ Wann kann/sollte/muss man **CommonJS** verwenden?](#-wann-kannsolltemuss-man-commonjs-verwenden)
- [🟢 **Du kannst CJS verwenden**, wenn](#-du-kannst-cjs-verwenden-wenn)
- [🟡 **Du solltest CJS verwenden**, wenn](#-du-solltest-cjs-verwenden-wenn)
- [🔴 **Du musst CJS verwenden**, wenn](#-du-musst-cjs-verwenden-wenn)
- [⚙️ TypeScript-Konfiguration für CJS](#-typescript-konfiguration-für-cjs)
- [📌 Merkmale von CommonJS](#-merkmale-von-commonjs)
- [✅ Fazit CommonJS](#-fazit-commonjs)
- [📄 Fazit: Empfehlungen](#-fazit-empfehlungen)
- [📁 Dateiendungen in Node.js](#-dateiendungen-in-nodejs)
- [⚠️ Typische Fehler vermeiden](#-typische-fehler-vermeiden)
- [🚀 CLI-Build-Tipps (tsc)](#-cli-build-tipps-tsc)
- [📍 Weiterführende Themen](#-weiterführende-themen)
---
## 🔢 Begriffe erklärt
### JavaScript-Dialekte (Modulsysteme)
| Name | Kürzel | Typ | Verwendung heute |
| ------------------ | ------ | ----------- | ----------------------- |
| CommonJS | CJS | `require()` | Ältere Node.js-Projekte |
| ECMAScript Modules | ESM | `import` | Browser, moderne Tools |
- **CommonJS:** Nutzt `require()` und `module.exports`. Standard bis Node 12.
- **ESM:** Nutzt `import`/`export`. Standard im Browser und in Node ab Version 14+.
### Was ist TypeScript?
TypeScript ist eine statisch typisierte Obermenge von JavaScript, die zu normalem JS kompiliert wird.
---
## 🔍 Wann verwende ich was?
| Ziel | Modulformat | Empfehlung | Grund |
| -------------------------- | ------------ | -------------- | ------------------------------------------ |
| 📅 Moderne Webanwendung | ESM | Ja | Browser erwartet ESM |
| 📄 Node.js CLI-Tool | ESM oder CJS | Beides möglich | ESM zukunftssicher, CJS maximal kompatibel |
| 🔐 Legacy-Node-Integration | CJS | Ja | Viele NPM-Pakete sind CJS-only |
| 🔌 Electron Renderer | ESM | Ja (Pflicht) | Chromium-only, kein CJS |
| 🔁 Vite/Webpack-Projekt | ESM | Ja | Toolchain basiert auf ESM |
---
## 🔧 TypeScript richtig konfigurieren
Eine vollständige Zusammenfassung zu **ESM (ECMAScript Modules)** wann du es **verwenden kannst**, **solltest** oder **musst**, sowie alle wesentlichen technischen Eigenschaften. Stil und Umfang entsprechen exakt der vorherigen CommonJS-Zusammenfassung.
---
### 📦 Was ist ESM?
**ESM (ECMAScript Modules)** ist das moderne Modulsystem von JavaScript:
- verwendet `import`/`export`-Syntax
- wird nativ von allen modernen Browsern und Node.js (ab v14+) unterstützt
- ist Standard in allen modernen JS-Toolchains (Vite, Webpack, esbuild, etc.)
```js
// ESM-Stil
import fs from 'node:fs/promises';
export function read(path) {
return fs.readFile(path, 'utf-8');
}
```
---
### ✅ Wann kann/sollte/muss man **ESM** verwenden?
#### 🟢 **Du kannst ESM verwenden**, wenn
- du mit **modernen Node.js-Versionen (v16+)** arbeitest
- du ein **Frontend-Tool** oder ein **Browser-kompatibles Projekt** baust
- du Tree-Shaking oder Dynamic `import()` nutzen willst
- du Typkonsistenz mit dem Browser willst (gleiche Syntax wie dort)
#### 🟡 **Du solltest ESM verwenden**, wenn
| Situation | Grund |
| ------------------------------------------------------------------- | ---------------------------- |
| 🌐 Du entwickelst Webanwendungen mit Vite, Nuxt, Webpack o. ä. | Diese Tools basieren auf ESM |
| 💡 Du möchtest moderne Syntax und Tooling nutzen | ESM ist Standard |
| 🔄 Du willst `import()` dynamisch verwenden | Nur in ESM verfügbar |
| 📚 Du schreibst eine wiederverwendbare Bibliothek für neue Projekte | Zukunftssicherheit |
| 🧩 Du verwendest Deno, Bun oder moderne Plattformen | ESM only |
#### 🔴 **Du musst ESM verwenden**, wenn
- du im **Browser** arbeitest (ohne Bundler) → dort ist `import` Pflicht
- du in **Electron-Renderer-Prozessen** arbeitest
- du ein Projekt hast mit `"type": "module"` und `.js`-Dateien → dann interpretiert Node sie nur als ESM
- du ESM-only-Dependencies nutzt (z.B. `chalk@5`, `node-fetch@3`)
---
### ⚙️ TypeScript-Konfiguration für ESM
```jsonc
{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"moduleResolution": "node",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true
}
}
```
Und in der `package.json`:
```json
{
"type": "module"
}
```
**Wichtig:** Ohne `"type": "module"` behandelt Node deine `.js`-Dateien **nicht als ESM**, sondern als CommonJS.
---
### 📌 Merkmale von ESM
| Merkmal | ESM |
| ------------------------- | -------------------------------------------- |
| Import-Syntax | `import`, `export` |
| Export-Syntax | `export default`, `export {...}` |
| Dateiendung `.js` | **.js** nur mit `"type": "module"` |
| `.mjs` | explizit ESM |
| `__dirname`, `__filename` | ❌ nicht vorhanden, nur via `import.meta.url` |
| Dynamische Imports | ✅ `await import('...')` |
| Tree Shaking | ✅ möglich |
| Browser-kompatibel | ✅ nativ |
| CommonJS-Interop | ❗ mit Einschränkungen (`createRequire`) |
---
### ⚠️ Besonderheiten und Stolperfallen
| Problem | Lösung |
| --------------------------------------------- | ------------------------------------------- |
| ❌ `__dirname`/`__filename` fehlen | nutze `import.meta.url` + `fileURLToPath()` |
| ❌ `require()` nicht verfügbar | verwende `import`, oder `createRequire()` |
| ❌ `.js` muss beim Import angegeben werden | z.B. `import './utils.js'` |
| ❌ viele alte Pakete sind nicht ESM-kompatibel | ggf. CommonJS verwenden |
---
### ✅ Fazit ESM
> **ESM ist der offizielle Standard für moderne JavaScript-Entwicklung** sowohl im Browser als auch in modernen Node.js-Umgebungen.
Du solltest ESM verwenden, wenn du:
- neue Projekte startest,
- moderne Toolchains nutzt,
- oder langfristige Kompatibilität willst.
In Zweifelsfällen gilt: **Wenn du mit aktuellen Tools und Node-Versionen arbeitest, nimm ESM.**
Nur bei Problemen mit alten Paketen oder Tooling solltest du temporär auf CommonJS zurückfallen.
---
## 🌐 CommonJS-Konfiguration CJS (Alternative)
### 📦 Was ist CommonJS?
**CommonJS (CJS)** ist das ursprüngliche Modulsystem von Node.js:
- verwendet `require()` zum Importieren
- verwendet `module.exports` oder `exports` zum Exportieren
- keine native Unterstützung für `import`/`export`
- funktioniert nur in Node.js (nicht im Browser ohne Bundler)
```js
// CommonJS-Stil
const fs = require('fs');
module.exports = { read: fs.readFileSync };
```
---
### ✅ Wann kann/sollte/muss man **CommonJS** verwenden?
#### 🟢 **Du kannst CJS verwenden**, wenn
- du ein CLI-Tool oder Node.js-Skript erstellst
- du maximale **Kompatibilität** ohne ESM-Komplikationen willst
- du keine modernen ESM-Features brauchst
- du auf Build-Tools verzichtest und direkt `.js`-Dateien startest
#### 🟡 **Du solltest CJS verwenden**, wenn
| Situation | Grund |
| ------------------------------------------------------------------- | ------------------------------------------------------ |
| 🔄 Du arbeitest mit älteren Node.js-Versionen (z.B. v12 oder v10) | ESM ist dort nicht stabil |
| 📦 Du nutzt NPM-Pakete, die **kein ESM unterstützen** | `require()` wird erwartet |
| 🧪 Du verwendest alte Tools, Tests oder Konfigurationen | z.B. alte `mocha`, `gulpfile.js`, `webpack.config.js` |
| 🧱 Du brauchst direkten Zugriff auf `__dirname`, `__filename` | Diese fehlen in ESM |
| 📜 Du möchtest `.js`-Dateien ohne `.mjs` oder `type: module` nutzen | CommonJS macht keine Vorgaben für Dateiendungen |
#### 🔴 **Du musst CJS verwenden**, wenn
- das Node.js-Modul, das du importieren willst, **nur `module.exports` exportiert** (kein ESM-Support)
- dein Projekt oder Tool **nicht mit ESM kompatibel ist** (ältere Tooling oder NPM-Module)
- du `require()` oder dynamisches Laden (`require(dynamicPath)`) verwendest, was in ESM nicht geht
---
### ⚙️ TypeScript-Konfiguration für CJS
```jsonc
{
"compilerOptions": {
"target": "ES2020",
"module": "CommonJS",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true
}
}
```
Und in der `package.json`:
```json
{
"type": "commonjs"
}
```
**Hinweis:** Das `"type"`-Feld ist für Node wichtig, nicht für TypeScript.
---
### 📌 Merkmale von CommonJS
| Merkmal | CommonJS |
| ------------------------- | -------------------------- |
| Import-Syntax | `require()` |
| Export-Syntax | `module.exports = …` |
| Dateiendung | `.js` (keine `.mjs` nötig) |
| Direkt ausführbar | ✅ Ohne zusätzliche Flags |
| `__dirname`, `__filename` | ✅ verfügbar |
| Browserkompatibilität | ❌ Nur mit Bundler möglich |
| Dynamische Importe | ✅ `require(dynamicPath)` |
| Tree Shaking | ❌ nicht möglich |
---
### ✅ Fazit CommonJS
> **CommonJS ist stabil, weit verbreitet und maximal kompatibel.**
> Wenn du **einfach nur ein Node-Tool oder CLI-Skript baust** und keine besonderen Build-Prozesse oder Browser-Kompatibilität brauchst: **Nutze CommonJS.**
Für moderne ESM-Projekte im Web oder wenn du zukunftssicher entwickeln willst, solltest du auf ESM setzen aber CJS bleibt in vielen Fällen die einfachste und robusteste Wahl.
---
## 📄 Fazit: Empfehlungen
- **Neue Projekte:** Nutze ESM mit `"type": "module"`
- **Bestehende Tools nutzen `require()`?** Dann CJS
- **Browser + Node gemeinsam nutzen?** ESM-only + klare Trennung von `shared/`, `client/`, `server/`
- **Tooling wie Vite, Nuxt, Webpack?** Immer ESM
---
## 📁 Dateiendungen in Node.js
| Dateiendung | Verhalten |
| ----------- | ------------------- |
| `.js` | Hängt von `type` ab |
| `.mjs` | Immer ESM |
| `.cjs` | Immer CommonJS |
---
## ⚠️ Typische Fehler vermeiden
- **`SyntaxError: Cannot use import statement outside a module`**
`type` fehlt in `package.json`
- **`Cannot find module` bei relativen Imports**
`.js` fehlt am Ende beim ESM-Import
- **`__dirname` ist not defined**
→ Du nutzt ESM, verwende `import.meta.url`
---
## 🚀 CLI-Build-Tipps (tsc)
```bash
npx tsc # Kompiliert Projekt laut tsconfig.json
chmod +x dist/index.js # Macht CLI-Datei ausführbar
```
Header für CLI-Datei:
```ts
#!/usr/bin/env node
```
---
## 📍 Weiterführende Themen
- Dual-Exports für NPM (ESM + CJS gleichzeitig)
- "exports"-Feld in `package.json`
- Tools wie `tsup`, `vite`, `esbuild` als Alternativen zu `tsc`
- Einstieg in CLI-Tools: `commander`, `yargs`, `chalk`, `ora`

View File

@ -0,0 +1,64 @@
# Gewindetabellen
## 📏 **Praxis-Gewindetabelle (zöllig, G = BSPP)**
| Gewindebezeichnung | ⌀ Außengewinde (mm) | ⌀ Innengewinde (mm) | Typische Anwendung |
| ------------------ | ------------------- | ------------------- | ---------------------------------- |
| **G 1/8"** | \~9,7mm | \~8,5mm | Druckluft, Manometer |
| **G 1/4"** | \~13,2mm | \~11,5mm | Kleingeräte, Kaffeemaschinen |
| **G 3/8"** | \~16,6mm | \~14,5mm | Geräteventile, Mini-Zulaufschlauch |
| **G 1/2"** | \~20,95mm | \~18,6mm | Wasserhahn, Spülarmatur |
| **G 3/4"** | \~26,4mm | \~24,0mm | Waschmaschine, Gartenschlauch |
| **G 1"** | \~33,25mm | \~30,3mm | Gartenwasserleitungen, Heizkreise |
| **G 1 1/4"** | \~41,9mm | \~38,8mm | Hausanschluss, Regenwassernutzung |
---
### 📌 Hinweise
- Die Werte sind **gemittelte Praxiswerte**. Es gibt leichte Toleranzen je nach Hersteller.
- Es handelt sich um **zylindrische Whitworth-Rohrgewinde (BSPP / G)**, **nicht kegelig**.
- Zur **Identifikation** reicht in der Regel eine Schieblehre und ein Blick in diese Tabelle.
- Die Angabe „Zoll“ hat **nichts** mit dem Außendurchmesser zu tun das ist reine Gewindeklassifizierung aus der Rohrnorm.
---
Klar hier kommt eine **praxisorientierte Bohrtabelle für metrische ISO-Gewinde (M-Gewinde)** von **M1 bis M12**, wie sie beim Innengewindeschneiden (z.B. per Hand mit Schneideisen oder Gewindebohrer) verwendet wird.
---
## 📏 **Bohrtabelle für metrische ISO-Regelgewinde (M-Gewinde nach DIN 13-1)**
| Gewinde | Steigung (mm) | Kernloch-Ø (mm) (Bohrerdurchmesser) | Hinweis |
| ------- | ------------- | ----------------------------------- | ---------------------- |
| M1 | 0.25 | 0.75 | selten, Feinmechanik |
| M1.2 | 0.25 | 0.95 | z.B. Elektronik |
| M1.6 | 0.35 | 1.25 | sehr fein |
| M2 | 0.4 | 1.6 | Standard M2 |
| M2.5 | 0.45 | 2.05 | beliebt bei Modellbau |
| M3 | 0.5 | 2.5 | sehr verbreitet |
| M4 | 0.7 | 3.3 | Klassiker |
| M5 | 0.8 | 4.2 | oft bei Maschinen |
| M6 | 1.0 | 5.0 | Standardgröße |
| M7 | 1.0 | 6.0 | eher selten |
| M8 | 1.25 | 6.8 | Standard M8 |
| M9 | 1.25 | 7.8 | Sondermaß |
| M10 | 1.5 | 8.5 | Maschinenbau |
| M11 | 1.5 | 9.5 | selten |
| M12 | 1.75 | 10.2 | oft für tragende Teile |
---
### 📌 Hinweise Bohrtabelle
- Dies sind die **Regelgewinde** bei **Feingewinden** (z.B. M10x1) brauchst du kleinere Bohrer.
- Werte gelten für **100% Gewindeüberdeckung**. In der Praxis reicht oft eine leicht größere Bohrung für leichtere Schnitte (z.B. bei Alu oder weichen Werkstoffen).
- Bei harter Werkstoffwahl ggf. Spiralbohrer vorher anspitzen oder mit Zentrierbohrer vorbohren.
---
### 🧰 Beispiel zur Borhtabelle
Du willst ein **M6-Gewinde** schneiden? → **5,0mm Bohrer** nehmen → dann Gewindebohrer M6 einsetzen.
---

View File

@ -0,0 +1,52 @@
# Plesk ausgesperrt bei Rechnerwechsel
## Inhalt
- [Plesk ausgesperrt bei Rechnerwechsel](#plesk-ausgesperrt-bei-rechnerwechsel)
- [Inhalt](#inhalt)
- [Problembeschreibung](#problembeschreibung)
- [Workarround](#workarround)
- [Nachhaltige Lösung des Problems](#nachhaltige-lösung-des-problems)
## Problembeschreibung
Es kommt öfter vor, das ich aus der Plesk Weboberfläche automatisch ausgeloggt werde und ein erneuter Login anschliessend nicht mehr möglich ist.
Die genaue Ursache ist mir nicht eindeutig bekannt aber ich vermute das im Browser irgendwelche Sessions gelöscht werden.
Als erstes habe ich in meinem Brave-Browser den Schutz für explizit diese Seite deaktiviert.
Um mich wieder einloggen zu können, muss ich die Session auf dem Server von hand aus der Datenbank löschen.
### Workarround
**Plesk Version:** Plesk Obsidian Web Admin Edition 18.0.70
Bei Plesk gibt es manchmal die gloreiche Meldung:
> Sie konnten nicht angemeldet werden.
> **Ein anderer Benutzer mit demselben Benutzernamen (benutzername) ist bereits bei Plesk angemeldet.**
Ärgerlich wenn das gerade der Adminzugang ist.
Falls Du gerade noch SSH Zugang hast dann:
login und wechsel zum root, anschliessend:
```bash
plesk db "DELETE FROM sessions WHERE login = 'admin';"
```
**oder**
```bash
mysql -uadmin -p$(cat /etc/psa/.psa.shadow) psa -e "DELETE FROM sessions WHERE login = 'admin';"
```
anschliessend:
```bash
systemctl restart psa
```
und dann ganz normal Login wie gewohnt.
### Nachhaltige Lösung des Problems
aktuell nicht bekannt!

View File

@ -0,0 +1,152 @@
# Erstellung eines Installationsmediums für Rust + MSVC (Offline)
Dieser Artikel beschreibt, wie du ein **vollständiges Installationsmedium** für die **Rust-Toolchain mit MSVC** unter Windows vorbereitest, damit du Rust auf anderen Rechnern **ohne Internetzugang** einrichten kannst.
---
## Ziel
Ein USB-Stick oder Offline-Verzeichnis mit:
- Rust-Installer (offlinefähig)
- Visual Studio Build Tools (komplett inkl. MSVC)
- Optional: vorkompilierte Ziel-Toolchains
---
## 1. Rust Offline-Installer vorbereiten
### 1.1 Rustup Offline-Installer besorgen
Gehe auf:
https://forge.rust-lang.org/infra/release-archives.html
Lade von dort:
- `rust-<version>-x86_64-pc-windows-msvc.msi`
- `cargo-<version>-x86_64-pc-windows-msvc.msi` (optional)
Oder direkt über:
https://static.rust-lang.org/dist/
### 1.2 Installation ohne Internet
Auf dem Zielrechner:
- Führe `.msi`-Datei lokal aus
- Setze den `Path` manuell oder automatisch via Skript
---
## 2. Visual Studio Build Tools offline installieren
### 2.1 Installer herunterladen
Lade den **Visual Studio Installer** von:
https://visualstudio.microsoft.com/de/visual-cpp-build-tools/
Starte dann:
```cmd
vs_BuildTools.exe --layout C:\VSOffline --lang de-DE
```
Dieser Befehl erstellt einen vollständigen Offline-Installer im Verzeichnis `C:\VSOffline`.
### 2.2 Auswahl der Workloads
Wähle beim interaktiven Download (GUI oder CLI):
- **C++ Build Tools**
- Workload-Komponenten:
- MSVC v14.x (x64/x86)
- Windows 10/11 SDK
- CMake-Tools (optional)
> 💡 Achtung: Download-Größe ca. 46GB!
### 2.3 Installation auf Zielsystem (Offline)
Auf dem Zielrechner:
```cmd
C:\VSOffline\vs_BuildTools.exe --noweb --add Microsoft.VisualStudio.Workload.VCTools --includeRecommended --quiet --wait
```
Alternativ über `vs_setup.exe`, je nach Version.
---
## 3. Optional: Toolchains, Crates & Targets vorbereiten
Falls du zusätzliche Targets (z.B. Linux oder ARM) brauchst:
### 3.1 Ziel-Toolchain lokal laden
```cmd
rustup target add x86_64-unknown-linux-gnu --print
```
Lade die `.tar.gz` von:
https://static.rust-lang.org/dist/
Speichere diese im `dist/`-Ordner und installiere offline via:
```cmd
rustup toolchain link <name> <pfad_zur_toolchain>
```
---
## 4. Automatisierung via USB-Stick
### Dateistruktur auf Stick
```text
USB-STICK/
├── rust/
│ └── rust-1.xx.x-x86_64-pc-windows-msvc.msi
├── vsbuildtools/
│ └── setup + Offline-Daten
├── install.cmd
```
### Beispiel `install.cmd`
```cmd
@echo off
echo [1/2] Installiere Rust...
start /wait rust\rust-*.msi
echo [2/2] Installiere Visual Studio Build Tools...
start /wait vsbuildtools\vs_BuildTools.exe --noweb --add Microsoft.VisualStudio.Workload.VCTools --includeRecommended --quiet --wait
echo Fertig. Bitte PC neu starten!
pause
```
---
## 5. Validierung
Nach der Offline-Installation auf Zielsystem:
```cmd
cargo new testprojekt
cd testprojekt
cargo build --release
```
Ergebnis:
target\release\testprojekt.exe
---
## Fazit
Mit dieser Methode kannst du eine vollständige Rust- und MSVC-Umgebung offline auf jedem Windows-System aufsetzen ideal für abgeschottete Systeme ohne Internetverbindung.

View File

@ -0,0 +1,152 @@
# Rust-Toolchain mit MSVC unter Windows einrichten
Dieser Artikel beschreibt die vollständige Einrichtung einer produktionsfähigen Rust-Toolchain mit **MSVC (Microsoft Visual C++)** unter **Windows**, einschließlich Erstellung einer `.exe`-Datei aus einem Beispielprogramm.
## Inhalt
- [Rust-Toolchain mit MSVC unter Windows einrichten](#rust-toolchain-mit-msvc-unter-windows-einrichten)
- [Inhalt](#inhalt)
- [Voraussetzungen](#voraussetzungen)
- [1. Rust installieren](#1-rust-installieren)
- [2. Visual Studio Build Tools installieren](#2-visual-studio-build-tools-installieren)
- [Schritt-für-Schritt](#schritt-für-schritt)
- [3. Umgebungsvariablen setzen (optional)](#3-umgebungsvariablen-setzen-optional)
- [4. Beispielprojekt erstellen](#4-beispielprojekt-erstellen)
- [5. Projekt kompilieren](#5-projekt-kompilieren)
- [Debug-Build (schnell, nicht optimiert)](#debug-build-schnell-nicht-optimiert)
- [Release-Build (optimiert, kleine `.exe`)](#release-build-optimiert-kleine-exe)
- [6. Optional: `.exe` testen](#6-optional-exe-testen)
- [7. Troubleshooting](#7-troubleshooting)
- [8. Alternative: Toolchain in einem Offline-Installer vorbereiten](#8-alternative-toolchain-in-einem-offline-installer-vorbereiten)
- [Zusammenfassung](#zusammenfassung)
- [Weiterführende Themen](#weiterführende-themen)
---
## Voraussetzungen
- Windows 10 oder 11 (64 Bit)
- Administratorrechte
- Mindestens 2GB freier Speicherplatz
## 1. Rust installieren
Lade das offizielle Rust-Installationsprogramm herunter und führe es aus:
<https://rustup.rs>
Beim Setup:
- **Toolchain wählen**: `default host triple: x86_64-pc-windows-msvc`
- Folge dem Assistenten, um `rustc`, `cargo` und `rustup` zu installieren.
Verifiziere die Installation:
```shell
rustc --version
cargo --version
```
## 2. Visual Studio Build Tools installieren
Die Rust-Toolchain mit MSVC benötigt den **"C++ Build Tools"**-Teil von Visual Studio.
### Schritt-für-Schritt
1. Lade den **Visual Studio Installer**:
- <https://visualstudio.microsoft.com/de/visual-cpp-build-tools/>
2. Wähle bei der Installation:
- ✅ **C++ Build Tools**
- Und in der rechten Spalte:
- ✅ "MSVC v14.x - VS 2022 C++ x64/x86-Buildtools"
- ✅ "Windows 10 SDK" oder "Windows 11 SDK" (je nach Zielsystem)
- ✅ "C++ CMake-Tools für Windows" (optional für CMake-Projekte)
3. Installiere alles und starte das System neu, falls verlangt.
## 3. Umgebungsvariablen setzen (optional)
Falls du die Buildtools über Kommandozeile verwenden willst, öffne:
```cmd
"C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Auxiliary\Build\vcvars64.bat"
```
Das setzt temporär alle notwendigen Umgebungsvariablen für den Build-Prozess.
## 4. Beispielprojekt erstellen
```cmd
cargo new hello_world
cd hello_world
```
Beispielcode in `src/main.rs`:
```rust
fn main() {
println!("Hallo Welt kompiliert mit MSVC!");
}
```
## 5. Projekt kompilieren
### Debug-Build (schnell, nicht optimiert)
```cmd
cargo build
```
### Release-Build (optimiert, kleine `.exe`)
```cmd
cargo build --release
```
Die fertige `.exe` liegt unter:
.\target\release\hello_world.exe
## 6. Optional: `.exe` testen
```cmd
.\target\release\hello_world.exe
```
## 7. Troubleshooting
- **Fehlermeldung `link.exe not found`?**
→ Build-Tools sind nicht korrekt installiert (siehe Schritt 2)
- **Fehlermeldung zu fehlendem SDK?**
→ Stelle sicher, dass du das passende Windows SDK mit installiert hast
- **MSVC und GNU Toolchain gleichzeitig installiert?**
→ Du kannst über `rustup` zwischen beiden wechseln:
```cmd
rustup show
rustup default stable-x86_64-pc-windows-msvc
```
## 8. Alternative: Toolchain in einem Offline-Installer vorbereiten
Wenn du das Setup auf mehreren Rechnern ohne Internetzugang durchführen möchtest, siehe [separater Artikel zur Erstellung eines Installationsmediums](./rust-offline-installation.md).
## Zusammenfassung
| Komponente | Aufgabe |
|------------------|----------------------------------|
| Rustup | Verwaltung von Toolchains |
| Cargo | Buildsystem und Paketmanager |
| MSVC Build Tools | C++-Compiler/Linker für Windows |
| `vcvars64.bat` | Aktiviert Build-Umgebung |
| `cargo build` | Erstellt `.exe` mit Rust und MSVC |
## Weiterführende Themen
- Einbindung von Ressourcen und Icons in die `.exe`
- Verwendung von `cc`/`bindgen` für C-Bindings
- Cross-Kompilierung mit `x86_64-pc-windows-gnu` oder Linux-Zielsystemen
- Automatisierter Build via Makefile oder PowerShell

View File

@ -0,0 +1,177 @@
# Einführung in die `desktop.ini`-Datei: Verwendung und Anpassung von Ordnern in Windows
*2025 - Adam Skotarczak*
Die `desktop.ini`-Datei ist eine wichtige, jedoch wenig bekannte Datei in Windows, die zur Konfiguration und Anpassung von Ordnern verwendet wird. Sie ermöglicht es Benutzern, das Erscheinungsbild und Verhalten von Ordnern anzupassen, indem sie Einstellungen wie Symbole, Tooltips und Ordnerspezifikationen definiert. In diesem Artikel werden wir die Funktionsweise der `desktop.ini`-Datei ausführlich erklären und alle Optionen und Attribute vorstellen, die in dieser Datei verwendet werden können.
## Inhaltsverzeichnis
- [Einführung in die `desktop.ini`-Datei: Verwendung und Anpassung von Ordnern in Windows](#einführung-in-die-desktopini-datei-verwendung-und-anpassung-von-ordnern-in-windows)
- [Inhaltsverzeichnis](#inhaltsverzeichnis)
- [Was ist die `desktop.ini`-Datei?](#was-ist-die-desktopini-datei)
- [Grundlegende Struktur der `desktop.ini`](#grundlegende-struktur-der-desktopini)
- [Wichtige Optionen und Attribute](#wichtige-optionen-und-attribute)
- [Optionen in der `[General]`-Sektion](#optionen-in-der-general-sektion)
- [Optionen in der `[View]`-Sektion](#optionen-in-der-view-sektion)
- [Optionen in der `[Icon]`-Sektion](#optionen-in-der-icon-sektion)
- [Optionen in der `[LocalizedFileNames]`-Sektion](#optionen-in-der-localizedfilenames-sektion)
- [Optionen in der `[ShellClassInfo]`-Sektion](#optionen-in-der-shellclassinfo-sektion)
- [Kommentare in der `desktop.ini`](#kommentare-in-der-desktopini)
- [Die Bedeutung von Attributen und Rechten der `desktop.ini`](#die-bedeutung-von-attributen-und-rechten-der-desktopini)
- [Rechte für die `desktop.ini` unter Windows setzen](#rechte-für-die-desktopini-unter-windows-setzen)
- [Verwendung der `desktop.ini` auf NAS-Laufwerken](#verwendung-der-desktopini-auf-nas-laufwerken)
- [Fazit](#fazit)
## Was ist die `desktop.ini`-Datei?
Die `desktop.ini`-Datei ist eine Systemdatei in Microsoft Windows, die zur Anpassung von Ordnersymbolen, Tooltips und anderen Ordnerattributen verwendet wird. Diese Datei ermöglicht es, das Aussehen und Verhalten eines Ordners zu verändern, ohne dass zusätzliche Software erforderlich ist. Sie befindet sich normalerweise im Ordner, für den sie Einstellungen vornimmt, und beeinflusst nur diesen Ordner.
## Grundlegende Struktur der `desktop.ini`
Die `desktop.ini`-Datei ist eine INI-Datei, die aus verschiedenen Sektionen und Key-Value-Paaren besteht. Sie enthält spezifische Anweisungen für den Ordner, in dem sie sich befindet. Die wichtigsten Sektionen sind:
- `[General]`: Enthält grundlegende Informationen zum Ordner, wie den Namen und den Tooltip.
- `[View]`: Steuert die Anzeigeeinstellungen des Ordners.
- `[Icon]`: Definiert das Symbol des Ordners.
- `[LocalizedFileNames]`: Bietet die Möglichkeit, Ordnernamen in verschiedenen Sprachen anzuzeigen.
- `[ShellClassInfo]`: Beinhaltet erweiterte Einstellungen für den Ordner, wie das Symbol und zusätzliche Eigenschaften.
## Wichtige Optionen und Attribute
### Optionen in der `[General]`-Sektion
- **`Name`**: Der Name des Ordners, der im Windows Explorer angezeigt wird.
```ini
Name=Mein Ordner
```
- **`InfoTip`**: Ein Tooltip, der angezeigt wird, wenn der Benutzer mit der Maus über den Ordner fährt.
```ini
InfoTip=Dies ist ein wichtiger Ordner.
```
### Optionen in der `[View]`-Sektion
- **`Mode`**: Bestimmt die Ansicht des Ordners. Mögliche Werte:
- `0`: Liste
- `1`: Details
- `2`: Große Symbole
- `3`: Kleine Symbole
```ini
Mode=2 ; Setze den Ordner auf "Große Symbole"
```
- **`FolderType`**: Bestimmt den Typ des Ordners, z. B. `Documents`, `Music`, `Pictures`.
```ini
FolderType=Documents ; Ordnertyp auf Dokumente setzen
```
- **`IconAreaImage`**: Setzt ein Hintergrundbild für den Ordnerbereich.
```ini
IconAreaImage=C:\Bilder\Hintergrund.png
```
### Optionen in der `[Icon]`-Sektion
- **`IconFile`**: Der Pfad zu einer Datei, die das Ordnersymbol enthält (z. B. `.ico`, `.dll`, `.exe`).
```ini
IconFile=C:\Windows\System32\shell32.dll
```
- **`IconIndex`**: Der Index des Symbols in der Datei, wenn mehrere Symbole in einer Datei vorhanden sind.
```ini
IconIndex=5
```
### Optionen in der `[LocalizedFileNames]`-Sektion
- **`@`**: Erlaubt die Anzeige von Ordnernamen in verschiedenen Sprachen.
```ini
[LocalizedFileNames]
@="Projektordner"
```
### Optionen in der `[ShellClassInfo]`-Sektion
- **`NoSharing`**: Verhindert die Freigabe des Ordners über das Netzwerk.
```ini
NoSharing=1 ; Verhindert die Netzwerkfreigabe
```
- **`ConfirmFileOp`**: Steuert, ob eine Bestätigung beim Kopieren von Dateien erforderlich ist.
```ini
ConfirmFileOp=0 ; Keine Bestätigung erforderlich
```
- **`InfoTip`**: Eine zusätzliche Option zur Festlegung eines Tooltips.
```ini
InfoTip=Dieser Ordner enthält Projektdateien.
```
- **`IconFile` und `IconIndex`**: Wiederholung der Optionen zur Festlegung des Ordnersymbols.
```ini
IconFile=C:\Windows\System32\shell32.dll
IconIndex=5
```
## Kommentare in der `desktop.ini`
In der `desktop.ini`-Datei können **Kommentare** durch das Hinzufügen eines **Semikolons (`;`)** am Anfang einer Zeile eingefügt werden. Alles, was nach einem Semikolon in einer Zeile steht, wird von Windows ignoriert und dient lediglich der Dokumentation.
Beispiel:
```ini
; Dies ist ein Kommentar
[.ShellClassInfo]
IconFile=C:\Windows\System32\shell32.dll
IconIndex=23
```
## Die Bedeutung von Attributen und Rechten der `desktop.ini`
Die `desktop.ini`-Datei muss bestimmte **Dateiattribute** besitzen, damit sie korrekt funktioniert:
- **Schreibgeschützt (`+r`)**: Verhindert, dass die Datei überschrieben wird.
- **Versteckt (`+h`)**: Stellt sicher, dass die Datei im Windows Explorer nicht angezeigt wird.
- **System (`+s`)**: Kennzeichnet die Datei als Systemdatei, sodass Windows sie als Konfigurationsdatei erkennt.
Die `desktop.ini`-Datei sollte auch die entsprechenden **Dateisystemrechte** haben, um sicherzustellen, dass sie nicht versehentlich gelöscht oder verändert wird.
## Rechte für die `desktop.ini` unter Windows setzen
Damit die `desktop.ini`-Datei korrekt funktioniert, müssen unter Windows bestimmte **Dateirechte und Attribute** gesetzt werden:
- **Schreibschutz setzen**: Um zu verhindern, dass die Datei überschrieben wird, kann das Schreibschutz-Attribut aktiviert werden. Dies kann über die Eingabeaufforderung mit dem Befehl `attrib +r desktop.ini` erreicht werden.
- **Versteckt setzen**: Damit die Datei im Explorer nicht angezeigt wird, muss das versteckte Attribut gesetzt werden. Dies kann mit `attrib +h desktop.ini` erfolgen.
- **Systemdateiattribut setzen**: Um die Datei als Systemdatei zu kennzeichnen, sodass Windows sie korrekt als Konfigurationsdatei behandelt, muss das Systemattribut gesetzt werden. Verwenden Sie dazu `attrib +s desktop.ini`.
Die richtigen Attribute können alle auf einmal gesetzt werden, indem Sie den folgenden Befehl verwenden:
```cmd
attrib +r +h +s desktop.ini
```
## Verwendung der `desktop.ini` auf NAS-Laufwerken
Die `desktop.ini`-Datei kann auch auf **NAS-Laufwerken** verwendet werden, solange das Laufwerk ein **Windows-kompatibles Dateisystem** wie **NTFS** verwendet. Es gibt jedoch einige wichtige Aspekte zu beachten:
- Das NAS muss ein unterstütztes Dateisystem verwenden.
- Die Berechtigungen für die Datei und die Ordnersichtbarkeit müssen so konfiguriert werden, dass Windows sie korrekt lesen kann.
## Fazit
Die `desktop.ini`-Datei ist ein mächtiges Werkzeug zur Anpassung von Ordnern in Windows. Sie ermöglicht es, das Aussehen und Verhalten von Ordnern zu verändern, ohne zusätzliche Software zu benötigen. Durch die Verwendung von Kommentaren und Attributen können Benutzer ihre Ordnerspezifikationen einfach und effektiv anpassen. Ob auf lokalen Laufwerken oder NAS-Systemen die `desktop.ini` bleibt eine vielseitige Lösung für die Ordneranpassung in Windows.

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

499
package-lock.json generated
View File

@ -1,28 +1,502 @@
{
"name": "adminslog",
"name": "tools",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "tools",
"version": "1.0.0",
"dependencies": {
"fs": "^0.0.1-security",
"path": "^0.12.7",
"process": "^0.11.10"
"process": "^0.11.10",
"typescript": "^5.8.3"
},
"bin": {
"link-collector": "dist/index.js"
},
"devDependencies": {
"@types/node": "^22.15.21"
"@types/node": "^22.15.29",
"esbuild": "^0.25.5"
}
},
"node_modules/@esbuild/aix-ppc64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.5.tgz",
"integrity": "sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA==",
"cpu": [
"ppc64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"aix"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/android-arm": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.5.tgz",
"integrity": "sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA==",
"cpu": [
"arm"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/android-arm64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.5.tgz",
"integrity": "sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/android-x64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.5.tgz",
"integrity": "sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/darwin-arm64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.5.tgz",
"integrity": "sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/darwin-x64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.5.tgz",
"integrity": "sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/freebsd-arm64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.5.tgz",
"integrity": "sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/freebsd-x64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.5.tgz",
"integrity": "sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-arm": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.5.tgz",
"integrity": "sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw==",
"cpu": [
"arm"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-arm64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.5.tgz",
"integrity": "sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-ia32": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.5.tgz",
"integrity": "sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA==",
"cpu": [
"ia32"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-loong64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.5.tgz",
"integrity": "sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg==",
"cpu": [
"loong64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-mips64el": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.5.tgz",
"integrity": "sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg==",
"cpu": [
"mips64el"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-ppc64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.5.tgz",
"integrity": "sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ==",
"cpu": [
"ppc64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-riscv64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.5.tgz",
"integrity": "sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA==",
"cpu": [
"riscv64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-s390x": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.5.tgz",
"integrity": "sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ==",
"cpu": [
"s390x"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-x64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.5.tgz",
"integrity": "sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/netbsd-arm64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.5.tgz",
"integrity": "sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"netbsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/netbsd-x64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.5.tgz",
"integrity": "sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"netbsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/openbsd-arm64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.5.tgz",
"integrity": "sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"openbsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/openbsd-x64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.5.tgz",
"integrity": "sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"openbsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/sunos-x64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.5.tgz",
"integrity": "sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"sunos"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/win32-arm64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.5.tgz",
"integrity": "sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/win32-ia32": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.5.tgz",
"integrity": "sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ==",
"cpu": [
"ia32"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/win32-x64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.5.tgz",
"integrity": "sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@types/node": {
"version": "22.15.21",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.21.tgz",
"integrity": "sha512-EV/37Td6c+MgKAbkcLG6vqZ2zEYHD7bvSrzqqs2RIhbA6w3x+Dqz8MZM3sP6kGTeLrdoOgKZe+Xja7tUB2DNkQ==",
"version": "22.15.29",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.29.tgz",
"integrity": "sha512-LNdjOkUDlU1RZb8e1kOIUpN1qQUlzGkEtbVNo53vbrwDg5om6oduhm4SiUaPW5ASTXhAiP0jInWG8Qx9fVlOeQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"undici-types": "~6.21.0"
}
},
"node_modules/esbuild": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.5.tgz",
"integrity": "sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
"bin": {
"esbuild": "bin/esbuild"
},
"engines": {
"node": ">=18"
},
"optionalDependencies": {
"@esbuild/aix-ppc64": "0.25.5",
"@esbuild/android-arm": "0.25.5",
"@esbuild/android-arm64": "0.25.5",
"@esbuild/android-x64": "0.25.5",
"@esbuild/darwin-arm64": "0.25.5",
"@esbuild/darwin-x64": "0.25.5",
"@esbuild/freebsd-arm64": "0.25.5",
"@esbuild/freebsd-x64": "0.25.5",
"@esbuild/linux-arm": "0.25.5",
"@esbuild/linux-arm64": "0.25.5",
"@esbuild/linux-ia32": "0.25.5",
"@esbuild/linux-loong64": "0.25.5",
"@esbuild/linux-mips64el": "0.25.5",
"@esbuild/linux-ppc64": "0.25.5",
"@esbuild/linux-riscv64": "0.25.5",
"@esbuild/linux-s390x": "0.25.5",
"@esbuild/linux-x64": "0.25.5",
"@esbuild/netbsd-arm64": "0.25.5",
"@esbuild/netbsd-x64": "0.25.5",
"@esbuild/openbsd-arm64": "0.25.5",
"@esbuild/openbsd-x64": "0.25.5",
"@esbuild/sunos-x64": "0.25.5",
"@esbuild/win32-arm64": "0.25.5",
"@esbuild/win32-ia32": "0.25.5",
"@esbuild/win32-x64": "0.25.5"
}
},
"node_modules/fs": {
"version": "0.0.1-security",
"resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz",
@ -54,6 +528,19 @@
"node": ">= 0.6.0"
}
},
"node_modules/typescript": {
"version": "5.8.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
"integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
"license": "Apache-2.0",
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
},
"engines": {
"node": ">=14.17"
}
},
"node_modules/undici-types": {
"version": "6.21.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",

View File

@ -1,10 +1,24 @@
{
"name": "tools",
"version": "1.0.0",
"type": "module",
"bin": {
"link-collector": "./dist/index.js"
},
"scripts": {
"build": "tsc",
"postbuild": "node tools/dist/fscopy.js -s tools/dist/collector/link_collector.js -t tools/collector/link_collector.js && npm run clean",
"scan": "node tools/collector/link_collector.js",
"clean": "node ./tools/dist/fsdel.js ./tools/dist/collector/link_collector.js"
},
"dependencies": {
"fs": "^0.0.1-security",
"path": "^0.12.7",
"process": "^0.11.10"
"process": "^0.11.10",
"typescript": "^5.8.3"
},
"devDependencies": {
"@types/node": "^22.15.21"
"@types/node": "^22.15.29",
"esbuild": "^0.25.5"
}
}

View File

@ -1,8 +1,8 @@
{
// Verzeichnis relativ zum Script, das durchsucht wird
"root_dirs": [
"dokus"
],
"root_dirs": [
"dokus"
],
// Nur Dateien mit dieser Endung (wird erweitert)
"extensions": [".md"],
@ -10,6 +10,7 @@
// Zielpfad für die Linkausgabe (Markdown-Datei)
"output_file": "README.md",
// Optional: Log für bereits verarbeitete Dateien
// Optional: Log für bereits verarbeitete Dateien. Dateien die dort
// enthalten sind, werden nicht nochmals verabeitet.
"processed_log": "processed.log"
}

View File

@ -0,0 +1,188 @@
#!/usr/bin/env node
import * as fs from 'node:fs';
import * as path from 'node:path';
import { fileURLToPath } from 'node:url';
import { dirname } from 'node:path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
class ScriptInfo {
static dir() {
return path.dirname(__filename);
}
static cwd() {
return process.cwd();
}
}
class ConfigLoader {
static load(filename = 'config.jsonc') {
const configPath = path.join(ScriptInfo.dir(), filename);
if (!fs.existsSync(configPath)) {
console.error(` ⚠ Konfigurationsdatei nicht gefunden: ${configPath}`);
process.exit(1);
}
const raw = fs.readFileSync(configPath, 'utf8');
const clean = raw
.split('\n')
.filter(line => !line.trim().startsWith('//'))
.join('');
return JSON.parse(clean);
}
}
class ArgParser {
static parse() {
const argv = process.argv.slice(2);
const result = { scan: null, ignore: [], reset: false, hilfe: false };
while (argv.length) {
const arg = argv.shift();
if (!arg)
break;
if (arg === '-h' || arg === '--hilfe') {
result.hilfe = true;
}
else if (arg === '--reset') {
result.reset = true;
}
else if ((arg === '-s' || arg === '--scan') && argv.length) {
result.scan = argv.shift().split(',').map(x => x.trim()).filter(Boolean);
}
else if ((arg === '-x' || arg === '--ignore') && argv.length) {
result.ignore = argv.shift().split(',').map(x => x.trim()).filter(Boolean);
}
else {
console.warn(` ⚠ Unbekannter Parameter: ${arg}`);
result.hilfe = true;
break;
}
}
return result;
}
static showHelp() {
console.log(`
(C) 2025 - Adam Skotarczak (ionivation.com)
🛈 Tool das Verzeichnisse nach Markdown-Dateien durchsucht und diese an eine definierte Liste anhängt als Markdown-Link.
Verwendung: ts-node link_collector.ts [OPTIONEN]
-s, --scan Kommagetrennte Liste von Verzeichnissen zum Durchsuchen (relativ zum Aufrufpfad)
-x, --ignore Kommagetrennte Liste von Verzeichnissen, die ignoriert werden sollen
--reset Löscht das Logfile 'processed.log' und beendet sich
-h, --hilfe Zeigt diese Hilfe
Beispiel:
ts-node link_collector.ts -s docs,notes -x "docs/alt"
`);
}
}
class FileScanner {
static *find(rootDirs, ignoreDirs, extensions) {
for (const root of rootDirs) {
const absRoot = path.resolve(root);
const stack = [absRoot];
while (stack.length) {
const current = stack.pop();
const rel = path.relative(ScriptInfo.cwd(), current).replace(/\\/g, '/');
if (ignoreDirs.some(ignored => rel.startsWith(ignored)))
continue;
const entries = fs.readdirSync(current, { withFileTypes: true });
for (const entry of entries) {
const fullPath = path.join(current, entry.name);
if (entry.isDirectory()) {
stack.push(fullPath);
}
else if (extensions.some(ext => entry.name.endsWith(ext))) {
yield fullPath;
}
}
}
}
}
}
class TitleExtractor {
static extract(filepath) {
try {
const content = fs.readFileSync(filepath, 'utf8');
for (const line of content.split('\n')) {
if (line.trim().startsWith('#')) {
return line.replace(/^#+/, '').trim();
}
}
}
catch (e) {
console.error(`⚠ Fehler beim Lesen von ${filepath}: ${e}`);
}
return path.basename(filepath, path.extname(filepath));
}
}
class ProcessedLog {
constructor(filename) {
this.logPath = path.join(ScriptInfo.dir(), filename);
this.entries = new Set();
this.load();
}
load() {
if (!fs.existsSync(this.logPath))
return;
const lines = fs.readFileSync(this.logPath, 'utf8').split('\n').map(x => x.trim()).filter(Boolean);
this.entries = new Set(lines.map(p => p.replace(/\\/g, '/')));
}
has(posixPath) {
return this.entries.has(posixPath);
}
update(newPaths) {
const content = newPaths.map(p => p.replace(/\\/g, '/')).join('\n') + '\n';
fs.appendFileSync(this.logPath, content, 'utf8');
}
reset() {
if (fs.existsSync(this.logPath)) {
fs.unlinkSync(this.logPath);
console.log('🧹 Logfile gelöscht:', this.logPath);
}
else {
console.log(' Logfile existierte nicht:', this.logPath);
}
}
}
class MarkdownAppender {
static append(outputFile, links) {
const content = links.join('\n') + '\n';
fs.appendFileSync(outputFile, content, 'utf8');
}
}
// Einstiegspunkt
function main() {
const config = ConfigLoader.load();
const args = ArgParser.parse();
if (args.hilfe) {
ArgParser.showHelp();
return;
}
const log = new ProcessedLog(config.processed_log || 'processed.log');
if (args.reset) {
log.reset();
return;
}
const cwd = ScriptInfo.cwd();
const outputFile = path.resolve(cwd, config.output_file || 'output.md');
const rootDirs = (args.scan || config.root_dirs || []).map(d => path.resolve(d));
const ignoreDirs = (args.ignore || []).map(d => path.relative(cwd, path.resolve(d)).replace(/\\/g, '/'));
const extensions = config.extensions || ['.md'];
const newLinks = [];
const newProcessed = [];
for (const absPath of FileScanner.find(rootDirs, ignoreDirs, extensions)) {
const relPath = path.relative(cwd, absPath).replace(/\\/g, '/');
if (path.resolve(absPath) === outputFile || log.has(relPath))
continue;
const title = TitleExtractor.extract(absPath);
newLinks.push(`- [${title}](${relPath})`);
newProcessed.push(relPath);
}
if (newLinks.length > 0) {
MarkdownAppender.append(outputFile, newLinks);
log.update(newProcessed);
console.log(`${newLinks.length} neue Links hinzugefügt.`);
}
else {
console.log(' Keine neuen Dateien gefunden.');
}
}
main();

View File

@ -1,5 +1,13 @@
dokus/apache-plesk/lets-encrypt-plesk.md
dokus/asciidoc/asciidoctor-theme-bug-workaround.md
dokus/helix__editor_einfuehrung_de.md
dokus/windows/desktop_ini.md
dokus/plesk/plesk-benutzer-schon-vorhanden.md
dokus/mechanik/gewindetabellen.md
dokus/js-ts/js-ts-dialekte.md
dokus/git/git-remote-branch.md
dokus/git/git-ssh-remote.md
dokus/git/git.md
dokus/asciidoc/asciidoctor-theme-bug-workaround.md
dokus/apache-plesk/lets-encrypt-plesk.md
dokus/git/git-submodule-leitfaden.md
dokus/rust/rust-toolchain-msvc.md
dokus/rust/rust-offline-installation.md

View File

@ -0,0 +1,16 @@
{
// Verzeichnis relativ zum Script, das durchsucht wird
"root_dirs": [
"dokus"
],
// Nur Dateien mit dieser Endung (wird erweitert)
"extensions": [".md"],
// Zielpfad für die Linkausgabe (Markdown-Datei)
"output_file": "README.md",
// Optional: Log für bereits verarbeitete Dateien. Dateien die dort
// enthalten sind, werden nicht nochmals verabeitet.
"processed_log": "processed.log"
}

View File

@ -1,8 +1,13 @@
#!/usr/bin/env ts-node
#!/usr/bin/env node
import * as fs from 'fs';
import * as path from 'path';
import * as process from 'process';
import * as fs from 'node:fs';
import * as path from 'node:path';
import { fileURLToPath } from 'node:url';
import { dirname } from 'node:path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
type Config = {
root_dirs?: string[];

80
tools/src/fscopy.ts Normal file
View File

@ -0,0 +1,80 @@
#!/usr/bin/env ts-node
/**
* Robust plattformunabhängiger Dateikopierer
* Verwendung: node fscopy.ts -s <quelle> -t <ziel>
* Optionen: -h | --help
*/
import * as fs from "fs";
import * as path from "path";
function showHelp(): void {
console.log(`
Copy Files with node.js
Verwendung:
node fscopy.ts -s <quelle> -q <ziel>
Parameter:
-s, --source Pfad zur Quelldatei (z.B. static/.htaccess)
-t, --target Pfad zur Zieldatei (z.B. dist/app/.htaccess)
-h, --help Diese Hilfe anzeigen
`);
process.exit(0);
}
function parseArgs(): { source: string; ziel: string } {
const args = process.argv.slice(2);
let source = "";
let ziel = "";
for (let i = 0; i < args.length; i++) {
switch (args[i]) {
case "-s":
case "--source":
source = args[++i];
break;
case "-t":
case "--target":
ziel = args[++i];
break;
case "-h":
case "--help":
showHelp();
break;
default:
console.error(`Unbekannter Parameter: ${args[i]}`);
showHelp();
}
}
if (!source || !ziel) {
console.error("❌ Quelle und Ziel müssen angegeben werden.");
showHelp();
}
return { source, ziel };
}
function copyFile(source: string, ziel: string): void {
const zielVerzeichnis = path.dirname(ziel);
fs.mkdir(zielVerzeichnis, { recursive: true }, (mkdirErr) => {
if (mkdirErr) {
console.error(`❌ Zielverzeichnis konnte nicht erstellt werden: ${mkdirErr.message}`);
process.exit(1);
}
fs.copyFile(source, ziel, (copyErr) => {
if (copyErr) {
console.error(`❌ Fehler beim Kopieren: ${copyErr.message}`);
process.exit(1);
}
console.log(`✔ Datei erfolgreich kopiert: ${source}${ziel}`);
});
});
}
// Ausführung
const { source, ziel } = parseArgs();
copyFile(source, ziel);

41
tools/src/fsdel.ts Normal file
View File

@ -0,0 +1,41 @@
#!/usr/bin/env ts-node
import * as fs from 'fs';
import * as path from 'path';
/**
* Löscht eine Datei am angegebenen Pfad.
*
* @param filePath - Pfad zur Datei, die gelöscht werden soll
*/
function deleteFile(filePath: string): void {
const resolvedPath = path.resolve(filePath);
if (!fs.existsSync(resolvedPath)) {
console.error(`❌ Datei nicht gefunden: ${resolvedPath}`);
process.exit(1);
}
try {
fs.unlinkSync(resolvedPath);
console.log(`✔ Datei gelöscht: ${resolvedPath}`);
} catch (err) {
console.error(`❌ Fehler beim Löschen: ${(err as Error).message}`);
process.exit(1);
}
}
// Kommandozeilenargumente
const [, , arg] = process.argv;
if (!arg || arg === '-h' || arg === '--help') {
console.log(`Verwendung:
ts-node delete.ts <dateipfad>
Beispiel:
ts-node delete.ts ./log/output.txt`);
process.exit(0);
}
// Datei löschen
deleteFile(arg);

11
tsconfig.json Normal file
View File

@ -0,0 +1,11 @@
{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"moduleResolution": "node",
"outDir": "./tools/dist",
"rootDir": "./tools/src",
"strict": true
},
"include": ["tools/src"]
}