chore: initial project setup
- Git repository mit .gitignore und .editorconfig - NPM-Projekt mit package.json und Dependencies - Projekt-Struktur (src/, docs/, examples/, test/) - Umfassende README.md mit Features und Roadmap - Architektur-Dokumentation mit Mermaid-Diagrammen - Design-Entscheidungen dokumentiert - .env.example für Forgejo API-Konfiguration - MIT Lizenz und Contributing Guidelines Status: Phase 1 - Core Parser (Setup abgeschlossen)
This commit is contained in:
commit
fbd6630f6d
9 changed files with 1263 additions and 0 deletions
344
docs/DECISIONS.md
Normal file
344
docs/DECISIONS.md
Normal file
|
|
@ -0,0 +1,344 @@
|
|||
# 🎯 Design-Entscheidungen
|
||||
|
||||
Dieses Dokument dokumentiert wichtige technische Entscheidungen und deren Begründungen.
|
||||
|
||||
## 1. Parser-Technologie: unified/remark
|
||||
|
||||
**Entscheidung:** unified + remark als Core-Parser
|
||||
|
||||
**Datum:** 2025-10-01
|
||||
|
||||
### Kontext
|
||||
Es wurden mehrere Markdown-Parser für die Verarbeitung von Bildungsressourcen mit YAML Front Matter evaluiert.
|
||||
|
||||
### Alternativen
|
||||
|
||||
| Parser | Vorteile | Nachteile | Score |
|
||||
|--------|----------|-----------|-------|
|
||||
| **marked** | Sehr populär (30k+ GitHub Stars)<br/>Einfache API<br/>Gute Performance | Fokus auf HTML-Output<br/>Kein AST-Zugriff<br/>Begrenzte Erweiterbarkeit | 6/10 |
|
||||
| **markdown-it** | Erweiterbar durch Plugins<br/>Sehr schnell<br/>CommonMark-konform | Komplexe API<br/>HTML-fokussiert<br/>Keine Browser-Isomorphie | 7/10 |
|
||||
| **unified/remark** | AST-basiert (MDAST)<br/>Isomorph (Node + Browser)<br/>Riesiges Plugin-Ökosystem<br/>De-facto Standard | Steilere Lernkurve<br/>Mehr Setup-Code | **9/10** |
|
||||
| **gray-matter + marked** | Sehr einfach<br/>Schneller Einstieg | Weniger strukturiert<br/>Begrenzte Flexibilität | 5/10 |
|
||||
|
||||
### Entscheidungskriterien
|
||||
|
||||
1. **AST-Zugriff** (Gewichtung: 30%)
|
||||
- ✅ unified: Voller MDAST-Zugriff für präzise Manipulation
|
||||
- ❌ marked: Kein AST, nur Token-Stream
|
||||
|
||||
2. **Isomorphie** (Gewichtung: 25%)
|
||||
- ✅ unified: Funktioniert identisch in Node.js und Browser
|
||||
- ⚠️ markdown-it: Primär Node.js-fokussiert
|
||||
|
||||
3. **Erweiterbarkeit** (Gewichtung: 20%)
|
||||
- ✅ unified: 200+ Plugins im Ökosystem
|
||||
- ⚠️ marked: Begrenzte Extension-API
|
||||
|
||||
4. **Standards** (Gewichtung: 15%)
|
||||
- ✅ unified: MDAST ist De-facto-Standard
|
||||
- ✅ markdown-it: CommonMark-konform
|
||||
|
||||
5. **Community & Wartung** (Gewichtung: 10%)
|
||||
- ✅ unified: Sehr aktiv, Teil von unifiedjs
|
||||
- ✅ marked: Aktiv maintained
|
||||
|
||||
### Konsequenzen
|
||||
|
||||
**Positiv:**
|
||||
- Maximale Flexibilität für zukünftige Features
|
||||
- AST-Transformationen für WordPress/Nostr
|
||||
- Browser-Support ohne Code-Änderungen
|
||||
- Plugin-System für Custom-Syntax
|
||||
|
||||
**Negativ:**
|
||||
- Mehr initialer Setup-Code erforderlich
|
||||
- Höhere Komplexität für einfache Use-Cases
|
||||
- Größere Learning-Curve für Contributors
|
||||
|
||||
### Code-Beispiel
|
||||
|
||||
```javascript
|
||||
import { unified } from 'unified'
|
||||
import remarkParse from 'remark-parse'
|
||||
import remarkFrontmatter from 'remark-frontmatter'
|
||||
import remarkGfm from 'remark-gfm'
|
||||
|
||||
const processor = unified()
|
||||
.use(remarkParse)
|
||||
.use(remarkFrontmatter, ['yaml'])
|
||||
.use(remarkGfm)
|
||||
|
||||
const ast = processor.parse(markdown)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. YAML-Parser: `yaml` library
|
||||
|
||||
**Entscheidung:** `yaml` (v2.x) statt `js-yaml`
|
||||
|
||||
**Datum:** 2025-10-01
|
||||
|
||||
### Kontext
|
||||
YAML Front Matter muss zuverlässig geparst werden, inkl. komplexer Strukturen (Arrays, nested Objects).
|
||||
|
||||
### Alternativen
|
||||
|
||||
| Library | Bundle Size | Spec-Konformität | Performance | Score |
|
||||
|---------|-------------|------------------|-------------|-------|
|
||||
| **yaml** | 42 KB | YAML 1.2 | Sehr gut | **9/10** |
|
||||
| **js-yaml** | 68 KB | YAML 1.2 | Gut | 7/10 |
|
||||
| JSON.parse | 0 KB (native) | N/A (nur JSON) | Exzellent | 3/10 |
|
||||
|
||||
### Entscheidung: `yaml`
|
||||
|
||||
**Gründe:**
|
||||
1. ✅ **Kleinere Bundle-Size** (42 KB vs. 68 KB)
|
||||
2. ✅ **Moderne API** (ESM-first, TypeScript-Typen)
|
||||
3. ✅ **Spec-compliant** (YAML 1.2)
|
||||
4. ✅ **Aktive Entwicklung**
|
||||
5. ✅ **Bessere Error-Messages**
|
||||
|
||||
### Konsequenzen
|
||||
|
||||
- Zuverlässiges Parsing komplexer YAML-Strukturen
|
||||
- Gute Performance auch bei großen Dateien
|
||||
- Kleinere Bundle-Size für Browser-Builds
|
||||
|
||||
---
|
||||
|
||||
## 3. HTTP-Client: Native `fetch`
|
||||
|
||||
**Entscheidung:** Native `fetch` API statt axios/node-fetch
|
||||
|
||||
**Datum:** 2025-10-01
|
||||
|
||||
### Kontext
|
||||
HTTP-Requests für Forgejo API und URL-basierte Markdown-Dateien.
|
||||
|
||||
### Alternativen
|
||||
|
||||
| Option | Vorteile | Nachteile | Score |
|
||||
|--------|----------|-----------|-------|
|
||||
| **native fetch** | In Node 18+ integriert<br/>Identisch im Browser<br/>Keine Dependencies | Erfordert Node.js 18+ | **10/10** |
|
||||
| **axios** | Feature-reich<br/>Interceptors<br/>Auto-Transform | Zusätzliche Dependency<br/>25 KB Bundle | 6/10 |
|
||||
| **node-fetch** | Populär | Zusätzliche Dependency<br/>Nicht identisch mit Browser | 5/10 |
|
||||
|
||||
### Entscheidung: Native `fetch`
|
||||
|
||||
**Gründe:**
|
||||
1. ✅ **Zero Dependencies**
|
||||
2. ✅ **Isomorphie** - Identische API in Node.js 18+ und Browser
|
||||
3. ✅ **Standard** - Web API Standard
|
||||
4. ✅ **Async/await** - Moderne Syntax
|
||||
|
||||
**Requirement:** Node.js >= 18.0.0
|
||||
|
||||
### Konsequenzen
|
||||
|
||||
- Keine zusätzlichen Dependencies
|
||||
- Code funktioniert ohne Änderungen im Browser
|
||||
- Einfachere Maintenance
|
||||
|
||||
---
|
||||
|
||||
## 4. Module-System: ESM (ES Modules)
|
||||
|
||||
**Entscheidung:** Pure ESM, kein CommonJS
|
||||
|
||||
**Datum:** 2025-10-01
|
||||
|
||||
### Kontext
|
||||
Wahl des Module-Systems für das Projekt.
|
||||
|
||||
### Entscheidung: ESM
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "module"
|
||||
}
|
||||
```
|
||||
|
||||
**Gründe:**
|
||||
1. ✅ **Standard** - ESM ist der JavaScript-Standard
|
||||
2. ✅ **Browser-kompatibel** - Direkt in Browsern lauffähig
|
||||
3. ✅ **Tree-Shaking** - Bessere Bundle-Optimierung
|
||||
4. ✅ **Zukunftssicher** - CommonJS ist Legacy
|
||||
|
||||
**Import-Syntax:**
|
||||
```javascript
|
||||
import { parseMarkdownFile } from './parser.js'
|
||||
// statt:
|
||||
// const { parseMarkdownFile } = require('./parser.js')
|
||||
```
|
||||
|
||||
### Konsequenzen
|
||||
|
||||
**Positiv:**
|
||||
- Moderne, zukunftssichere Codebasis
|
||||
- Bessere Bundle-Optimierung
|
||||
- Browser-Kompatibilität
|
||||
|
||||
**Negativ:**
|
||||
- Keine Kompatibilität mit alten CommonJS-only Tools
|
||||
- Erfordert `.js` Extension bei relativen Imports
|
||||
|
||||
---
|
||||
|
||||
## 5. Datenquelle-Priorität: API-First
|
||||
|
||||
**Entscheidung:** Primärer Fokus auf Forgejo API
|
||||
|
||||
**Datum:** 2025-10-01
|
||||
|
||||
### Kontext
|
||||
Verschiedene Datenquellen müssen unterstützt werden.
|
||||
|
||||
### Priorisierung
|
||||
|
||||
1. **Forgejo/Gitea API** (Priorität 1)
|
||||
- Primäre Datenquelle
|
||||
- Direkter API-Zugriff
|
||||
- No Git-Clone nötig
|
||||
|
||||
2. **HTTP/HTTPS URLs** (Priorität 2)
|
||||
- Einfacher Fallback
|
||||
- Für öffentliche Dateien
|
||||
|
||||
3. **Lokale Dateien** (Priorität 3)
|
||||
- Für Entwicklung und Tests
|
||||
- Node.js-only
|
||||
|
||||
### Implementation
|
||||
|
||||
```javascript
|
||||
// src/index.js
|
||||
export async function parseMarkdown(source, options = {}) {
|
||||
if (isForgejoURL(source)) {
|
||||
return parseFromForgejo(source, options)
|
||||
} else if (isHTTPURL(source)) {
|
||||
return parseFromURL(source, options)
|
||||
} else {
|
||||
return parseFromFile(source, options)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. Error-Handling: Graceful Degradation
|
||||
|
||||
**Entscheidung:** Fehlertolerante Metadaten-Extraktion
|
||||
|
||||
**Datum:** 2025-10-01
|
||||
|
||||
### Prinzip
|
||||
|
||||
Fehlende oder ungültige Metadaten führen nicht zu Fehler, sondern zu Warnings.
|
||||
|
||||
```javascript
|
||||
{
|
||||
metadata: {
|
||||
name: "Unbekannt", // Fallback
|
||||
_warnings: [
|
||||
"Fehlendes Feld: commonMetadata.name"
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Gründe:**
|
||||
1. ✅ Robustheit gegenüber unvollständigen Daten
|
||||
2. ✅ Bessere User Experience
|
||||
3. ✅ Ermöglicht partielle Verarbeitung
|
||||
|
||||
---
|
||||
|
||||
## 7. Browser-Build: Phase 2
|
||||
|
||||
**Entscheidung:** Browser-Build wird in Phase 2 implementiert
|
||||
|
||||
**Datum:** 2025-10-01
|
||||
|
||||
### Kontext
|
||||
Browser-Unterstützung ist wichtig, aber nicht im ersten Release.
|
||||
|
||||
### Phasen-Plan
|
||||
|
||||
**Phase 1 (jetzt):**
|
||||
- Node.js-kompatibel
|
||||
- Isomorpher Code (aber kein Build)
|
||||
- Tests in Node.js
|
||||
|
||||
**Phase 2:**
|
||||
- ESM Browser-Build
|
||||
- Bundling mit Rollup/esbuild
|
||||
- Browser-Tests
|
||||
|
||||
**Grund:**
|
||||
- Fokus auf Core-Funktionalität
|
||||
- Vermeidung von Over-Engineering
|
||||
- Schnelleres Initial-Release
|
||||
|
||||
---
|
||||
|
||||
## 8. Testing: Node.js Native Test Runner
|
||||
|
||||
**Entscheidung:** Node.js `--test` statt Jest/Mocha
|
||||
|
||||
**Datum:** 2025-10-01
|
||||
|
||||
### Alternativen
|
||||
|
||||
| Test-Framework | Vorteile | Nachteile | Score |
|
||||
|----------------|----------|-----------|-------|
|
||||
| **Node.js native** | Keine Dependencies<br/>Schnell<br/>ESM-Support | Weniger Features | **8/10** |
|
||||
| **Jest** | Feature-reich<br/>Snapshots | Langsam<br/>ESM-Probleme | 6/10 |
|
||||
| **Vitest** | Schnell<br/>ESM-first | Weitere Dependency | 7/10 |
|
||||
|
||||
### Entscheidung: Node.js Native
|
||||
|
||||
```javascript
|
||||
// test/parser.test.js
|
||||
import { test } from 'node:test'
|
||||
import assert from 'node:assert'
|
||||
|
||||
test('parses markdown with YAML', async () => {
|
||||
const result = await parseMarkdownFile('./fixtures/test.md')
|
||||
assert.ok(result.yaml)
|
||||
})
|
||||
```
|
||||
|
||||
**Gründe:**
|
||||
- ✅ Zero Dependencies für Tests
|
||||
- ✅ Schnelle Ausführung
|
||||
- ✅ Native ESM-Support
|
||||
- ✅ Ausreichend für unsere Zwecke
|
||||
|
||||
---
|
||||
|
||||
## Zusammenfassung: Technologie-Stack
|
||||
|
||||
| Kategorie | Technologie | Begründung |
|
||||
|-----------|-------------|------------|
|
||||
| **Parser** | unified + remark | AST-basiert, isomorph, erweiterbar |
|
||||
| **YAML** | yaml (v2.x) | Klein, modern, spec-compliant |
|
||||
| **HTTP** | native fetch | Zero deps, isomorph |
|
||||
| **Modules** | ESM | Standard, zukunftssicher |
|
||||
| **Testing** | Node.js native | Zero deps, schnell |
|
||||
| **Code Style** | Prettier + ESLint | Standard, automatisierbar |
|
||||
|
||||
---
|
||||
|
||||
## Änderungshistorie
|
||||
|
||||
| Datum | Entscheidung | Autor |
|
||||
|-------|--------------|-------|
|
||||
| 2025-10-01 | Initial: unified/remark | Jörg Lohrer |
|
||||
| 2025-10-01 | YAML library | Jörg Lohrer |
|
||||
| 2025-10-01 | Native fetch | Jörg Lohrer |
|
||||
| 2025-10-01 | ESM-only | Jörg Lohrer |
|
||||
|
||||
---
|
||||
|
||||
**Fragen oder Vorschläge?** → [Issue erstellen](https://git.rpi-virtuell.de/Comenius-Institut/mdparser/issues)
|
||||
Loading…
Add table
Add a link
Reference in a new issue