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:
Jörg Lohrer 2025-10-01 15:28:30 +02:00
commit fbd6630f6d
9 changed files with 1263 additions and 0 deletions

18
.editorconfig Normal file
View file

@ -0,0 +1,18 @@
# EditorConfig is awesome: https://EditorConfig.org
root = true
[*]
charset = utf-8
end_of_line = lf
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true
[*.md]
trim_trailing_whitespace = false
max_line_length = off
[*.json]
indent_size = 2

12
.env.example Normal file
View file

@ -0,0 +1,12 @@
# Forgejo/Gitea API Configuration
FORGEJO_API_BASE_URL=https://git.rpi-virtuell.de/api/v1
FORGEJO_OWNER=Comenius-Institut
FORGEJO_REPO=FOERBICO_und_rpi-virtuell
FORGEJO_BRANCH=main
FORGEJO_TOKEN=
# Optional: API Rate Limiting
API_RATE_LIMIT_DELAY_MS=100
# Logging
LOG_LEVEL=info

44
.gitignore vendored Normal file
View file

@ -0,0 +1,44 @@
# Node.js
node_modules/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
package-lock.json
.pnpm-debug.log*
# Environment variables
.env
.env.local
.env.*.local
# IDE / Editor
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/extensions.json
.idea/
*.swp
*.swo
*~
.DS_Store
# Build / Distribution
dist/
build/
*.tgz
# Test coverage
coverage/
.nyc_output/
# Logs
logs/
*.log
# Temporary files
tmp/
temp/
*.tmp
# OS
Thumbs.db

82
CONTRIBUTING.md Normal file
View file

@ -0,0 +1,82 @@
# Contributing to MDParser
Vielen Dank für dein Interesse an MDParser! 🎉
## 🚀 Quick Start
1. **Fork & Clone**
```bash
git clone https://git.rpi-virtuell.de/dein-username/mdparser.git
cd mdparser
```
2. **Dependencies installieren**
```bash
npm install
```
3. **Branch erstellen**
```bash
git checkout -b feature/mein-feature
```
4. **Entwickeln & Testen**
```bash
npm test
npm run lint
```
5. **Commit & Push**
```bash
git commit -m "feat: beschreibung"
git push origin feature/mein-feature
```
6. **Pull Request erstellen**
## 📝 Code-Style
- **ESLint** für Linting
- **Prettier** für Formatierung
- **ESM** (ES Modules) verwenden
- **JSDoc** für Funktions-Dokumentation
```javascript
/**
* Parst eine Markdown-Datei mit YAML Front Matter
* @param {string} filePath - Pfad zur Markdown-Datei
* @param {Object} options - Optionale Konfiguration
* @returns {Promise<Object>} Parsed result
*/
export async function parseMarkdownFile(filePath, options = {}) {
// ...
}
```
## 🧪 Testing
- Alle neuen Features benötigen Tests
- Tests mit `npm test` ausführen
- Test-Fixtures in `test/fixtures/` ablegen
## 📦 Commit-Conventions
Wir verwenden [Conventional Commits](https://www.conventionalcommits.org/):
- `feat:` - Neues Feature
- `fix:` - Bugfix
- `docs:` - Dokumentation
- `test:` - Tests
- `refactor:` - Code-Refactoring
- `chore:` - Maintenance
Beispiele:
```
feat: add WordPress transformer
fix: handle missing YAML gracefully
docs: update API documentation
```
## 📄 Lizenz
MIT - siehe [LICENSE](LICENSE)

21
LICENSE Normal file
View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2025 Jörg Lohrer, Comenius-Institut
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

257
README.md Normal file
View file

@ -0,0 +1,257 @@
# 📚 MDParser - Markdown to JSON Parser
Ein modularer Parser für Markdown-Dateien mit YAML Front Matter, optimiert für AMB-Metadatenstandard (schema.org) und Transformation zu WordPress & Nostr.
## 🎯 Features
- ✅ **YAML Front Matter Parsing** - Volle Unterstützung für komplexe YAML-Strukturen
- ✅ **AMB-Metadaten** - Schema.org-konforme Metadaten-Extraktion
- ✅ **Forgejo/Gitea API** - Direkter Zugriff auf Git-Repository-Inhalte
- ✅ **AST-basiert** - Strukturierte Markdown-Verarbeitung mit unified/remark
- ✅ **Isomorph** - Funktioniert in Node.js und im Browser
- ✅ **Erweiterbar** - Modulare Architektur für Custom-Transformationen
- 🚧 **WordPress REST API v2** - Transformer (geplant)
- 🚧 **Nostr NIP-23** - Long-form Content Transformer (geplant)
## 📦 Installation
```bash
# Repository klonen
git clone https://git.rpi-virtuell.de/Comenius-Institut/mdparser.git
cd mdparser
# Dependencies installieren
npm install
# Environment-Variablen konfigurieren
cp .env.example .env
# .env bearbeiten und API-Zugangsdaten eintragen
```
## 🚀 Quick Start
```javascript
import { parseMarkdownFile } from './src/parser.js';
// Markdown mit YAML Front Matter parsen
const result = await parseMarkdownFile('./content/posts/example/index.md');
console.log(result.metadata); // Schema.org Metadaten
console.log(result.content); // Markdown AST
console.log(result.html); // HTML-Output (optional)
```
## 🏗️ Projekt-Struktur
```
mdparser/
├── src/
│ ├── index.js # Haupteinstiegspunkt
│ ├── parser.js # Core Parser (unified/remark)
│ ├── forgejo-client.js # Forgejo API Client
│ ├── extractors/
│ │ ├── yaml-extractor.js # YAML Front Matter Parsing
│ │ └── amb-extractor.js # AMB/Schema.org Metadaten
│ └── transformers/ # (geplant)
│ ├── wordpress.js
│ └── nostr.js
├── examples/
│ ├── parse-forgejo.js # Beispiel: Forgejo API
│ ├── parse-local.js # Beispiel: Lokale Datei
│ └── parse-url.js # Beispiel: HTTP URL
├── test/
│ └── parser.test.js
├── docs/
│ ├── ARCHITECTURE.md # Architektur-Dokumentation
│ ├── API.md # API-Referenz
│ └── DECISIONS.md # Design-Entscheidungen
├── .env.example
├── .gitignore
├── .editorconfig
├── package.json
└── README.md
```
## 🔧 Konfiguration
### Environment-Variablen (`.env`)
```bash
# Forgejo/Gitea API
FORGEJO_API_BASE_URL=https://git.rpi-virtuell.de/api/v1
FORGEJO_OWNER=Comenius-Institut
FORGEJO_REPO=FOERBICO_und_rpi-virtuell
FORGEJO_BRANCH=main
FORGEJO_TOKEN= # Optional für private Repos
# API Rate Limiting
API_RATE_LIMIT_DELAY_MS=100
# Logging
LOG_LEVEL=info
```
## 📖 Verwendung
### 1. Lokale Markdown-Datei parsen
```javascript
import { parseMarkdownFile } from './src/parser.js';
const result = await parseMarkdownFile('./content/post/index.md');
console.log(result);
```
### 2. Forgejo API verwenden
```javascript
import { ForgejoClient } from './src/forgejo-client.js';
const client = new ForgejoClient({
baseUrl: 'https://git.rpi-virtuell.de/api/v1',
owner: 'Comenius-Institut',
repo: 'FOERBICO_und_rpi-virtuell'
});
// Einzelne Datei abrufen
const content = await client.getFileContent(
'Website/content/posts/2025-04-20-OER-und-Symbole/index.md'
);
// Alle Posts auflisten
const posts = await client.listPosts('Website/content/posts');
```
### 3. AMB-Metadaten extrahieren
```javascript
import { extractAMBMetadata } from './src/extractors/amb-extractor.js';
const ambData = extractAMBMetadata(result.yaml);
// Ausgabe: Schema.org-konforme Struktur
console.log(ambData.name); // Titel
console.log(ambData.creator); // Autoren
console.log(ambData.license); // Lizenz
console.log(ambData.about); // Themen/Tags
```
## 🎓 AMB-Metadatenstandard
Dieses Projekt unterstützt den **AMB-Standard** (Metadaten für Bildungsressourcen) basierend auf schema.org:
**Unterstützte Felder:**
- `@context`, `type`, `name`, `description`
- `creator` (Person/Organization mit ORCID/ROR)
- `license`, `inLanguage`, `datePublished`
- `about` (Hochschulfächersystematik)
- `learningResourceType`, `educationalLevel`
- `image`, `id` (URL)
Siehe [AMB-Dokumentation](https://dini-ag-kim.github.io/amb/) für Details.
## 🔌 API-Referenz
### `parseMarkdownFile(filePath, options)`
Parst eine Markdown-Datei mit YAML Front Matter.
**Parameter:**
- `filePath` (string) - Pfad zur Markdown-Datei
- `options` (object) - Optionale Konfiguration
- `extractYaml` (boolean) - YAML extrahieren (default: true)
- `parseGfm` (boolean) - GitHub Flavored Markdown (default: true)
- `toHtml` (boolean) - HTML-Output generieren (default: false)
**Rückgabe:**
```javascript
{
yaml: { /* YAML Front Matter als Objekt */ },
metadata: { /* Extrahierte AMB-Metadaten */ },
ast: { /* Markdown Abstract Syntax Tree */ },
content: { /* Reiner Content ohne Front Matter */ },
html: "..." // Optional
}
```
Siehe [docs/API.md](./docs/API.md) für vollständige API-Dokumentation.
## 🧪 Tests
```bash
# Tests ausführen
npm test
# Mit Watch-Mode während Entwicklung
npm run dev
```
## 🤝 Entwicklung
### Technologie-Stack
| Bereich | Bibliothek | Begründung |
|---------|-----------|------------|
| **Markdown Parser** | unified + remark-parse | AST-basiert, erweiterbar, isomorph |
| **YAML Parser** | yaml | Robust, spec-compliant |
| **Front Matter** | remark-frontmatter | Nahtlose Integration mit remark |
| **GFM Support** | remark-gfm | Tabellen, Task Lists, etc. |
| **HTTP Client** | native fetch | Standard, keine Dependencies |
### Warum unified/remark?
**Isomorph** - Node.js + Browser
**AST-basiert** - Präzise Manipulation
**Erweiterbar** - Riesiges Plugin-Ökosystem
**Standard** - MDAST ist De-facto-Standard
**Aktiv** - Große Community, gute Wartung
Siehe [docs/DECISIONS.md](./docs/DECISIONS.md) für detaillierte Design-Entscheidungen.
## 📋 Roadmap
### Phase 1: Core Parser (aktuell)
- [x] Projekt-Setup mit Git, npm, Dokumentation
- [ ] Markdown + YAML Parser implementieren
- [ ] Forgejo API Client
- [ ] AMB-Metadaten-Extraktor
- [ ] Beispiele und Tests
### Phase 2: Transformers (nächster Schritt)
- [ ] WordPress REST API v2 Transformer
- title, content, excerpt, featured_media
- tags, categories, custom fields
- author mapping
- [ ] Nostr NIP-23 Transformer
- d (identifier), title, summary
- published_at, image
- t (tags), e/a/p (references)
### Phase 3: Erweiterte Features
- [ ] Browser-Build (ESM)
- [ ] CLI-Tool
- [ ] Batch-Processing
- [ ] Caching-Strategie
- [ ] Error-Handling & Logging
## 📄 Lizenz
MIT License - siehe [LICENSE](./LICENSE) für Details.
## 👥 Autoren
- **Jörg Lohrer** - [ORCID](https://orcid.org/0000-0002-9282-0406)
- Comenius-Institut - [ROR](https://ror.org/025e8aw85)
## 🔗 Links
- **Projekt-Repository**: https://git.rpi-virtuell.de/Comenius-Institut/mdparser
- **Forgejo API**: https://git.rpi-virtuell.de/api/swagger
- **AMB-Standard**: https://dini-ag-kim.github.io/amb/
- **unified/remark**: https://unifiedjs.com/
- **WordPress REST API**: https://developer.wordpress.org/rest-api/
- **Nostr NIPs**: https://github.com/nostr-protocol/nips
---
**Status:** 🚧 In aktiver Entwicklung - Phase 1

435
docs/ARCHITECTURE.md Normal file
View file

@ -0,0 +1,435 @@
# 🏛️ Architektur-Dokumentation
## Überblick
MDParser ist ein modularer, erweiterbarer Parser für Markdown-Dateien mit YAML Front Matter, optimiert für die Verarbeitung von AMB-konformen Bildungsressourcen.
## 📐 Architektur-Diagramm
```mermaid
flowchart TB
subgraph "Datenquellen"
File["📄 Lokale Datei"]
URL["🌐 HTTP/HTTPS URL"]
API["🔌 Forgejo/Gitea API"]
end
subgraph "Core Parser"
Fetch["Fetch Module<br/>Daten abrufen"]
Unified["unified Pipeline<br/>remark-parse<br/>remark-frontmatter<br/>remark-gfm"]
YAMLParser["YAML Parser<br/>yaml library"]
end
subgraph "Extraction Layer"
FrontMatter["Front Matter<br/>Extractor"]
AMBExtract["AMB Metadata<br/>Extractor<br/>(schema.org)"]
ContentExtract["Content<br/>Extractor<br/>(AST)"]
end
subgraph "Output Formats"
JSON["📦 JSON<br/>Structured Data"]
AST["🌲 MDAST<br/>Abstract Syntax Tree"]
HTML["📝 HTML<br/>(optional)"]
end
subgraph "Transformers (Phase 2)"
WP["WordPress<br/>REST API v2"]
Nostr["Nostr<br/>NIP-23"]
end
File --> Fetch
URL --> Fetch
API --> Fetch
Fetch --> Unified
Unified --> YAMLParser
Unified --> FrontMatter
FrontMatter --> AMBExtract
FrontMatter --> ContentExtract
AMBExtract --> JSON
ContentExtract --> AST
ContentExtract --> HTML
JSON --> WP
JSON --> Nostr
AST --> WP
AST --> Nostr
style Unified fill:#e1f5ff,stroke:#01579b
style AMBExtract fill:#f3e5f5,stroke:#4a148c
style JSON fill:#e8f5e9,stroke:#1b5e20
```
## 🎯 Design-Prinzipien
### 1. **Modularität**
- Jede Komponente hat eine klare Verantwortung
- Lose Kopplung zwischen Modulen
- Einfach erweiterbar durch Plugin-System
### 2. **Isomorphie**
- Code funktioniert in Node.js **und** Browser
- Keine Node.js-spezifischen APIs im Core
- Native `fetch` für HTTP-Requests
### 3. **Standards-Konformität**
- AMB-Metadatenstandard (schema.org)
- MDAST (Markdown Abstract Syntax Tree)
- CommonMark + GFM (GitHub Flavored Markdown)
### 4. **Fehlertoleranz**
- Graceful Degradation bei fehlenden Metadaten
- Validierung mit aussagekräftigen Fehlermeldungen
- Optionale Felder werden sauber behandelt
## 📦 Modul-Struktur
### Core Module
#### 1. **Parser (`src/parser.js`)**
```javascript
export async function parseMarkdownFile(filePath, options) {
// Haupteinstiegspunkt für Markdown-Parsing
// Orchestriert unified Pipeline
return {
yaml: {}, // Rohes YAML Front Matter
metadata: {}, // Extrahierte AMB-Metadaten
ast: {}, // Markdown AST
content: "", // Reiner Content
html: "" // Optional: HTML-Output
}
}
```
**Technologie:** unified + remark Ökosystem
**Plugins:**
- `remark-parse` - Markdown → AST
- `remark-frontmatter` - YAML Front Matter Support
- `remark-gfm` - GitHub Flavored Markdown
- `remark-stringify` - AST → Markdown (optional)
- `remark-html` - AST → HTML (optional)
#### 2. **Forgejo Client (`src/forgejo-client.js`)**
```javascript
export class ForgejoClient {
constructor(config) { /* ... */ }
async getFileContent(path) { /* ... */ }
async listDirectory(path) { /* ... */ }
async listPosts(postsDir) { /* ... */ }
async getRepository() { /* ... */ }
}
```
**API-Endpoints:**
- `/repos/{owner}/{repo}/contents/{path}` - Dateiinhalt
- `/repos/{owner}/{repo}/git/trees/{sha}` - Verzeichnis-Listing
- Content wird Base64-dekodiert
#### 3. **YAML Extractor (`src/extractors/yaml-extractor.js`)**
```javascript
export function extractYAML(markdownContent) {
// Extrahiert YAML Front Matter
// Parst mit yaml library
return yamlObject
}
```
**Technologie:** `yaml` library (v2.x)
**Features:**
- Komplexe YAML-Strukturen
- Arrays, nested Objects
- Multi-line Strings
- Datum-Parsing
#### 4. **AMB Metadata Extractor (`src/extractors/amb-extractor.js`)**
```javascript
export function extractAMBMetadata(yamlObject) {
// Transformiert YAML → Schema.org
// Validiert AMB-Konformität
return ambMetadata
}
```
**Mapping:**
```javascript
{
"@context": "https://schema.org/",
"type": "LearningResource",
"name": yaml.commonMetadata.name,
"description": yaml.commonMetadata.description,
"creator": mapCreators(yaml.commonMetadata.creator),
"license": yaml.commonMetadata.license,
"inLanguage": yaml.commonMetadata.inLanguage,
"datePublished": yaml.commonMetadata.datePublished,
"about": yaml.commonMetadata.about,
"image": yaml.commonMetadata.image,
"id": yaml.commonMetadata.id,
"learningResourceType": yaml.commonMetadata.learningResourceType,
"educationalLevel": yaml.commonMetadata.educationalLevel
}
```
### Transformation Layer (Phase 2)
#### 5. **WordPress Transformer (`src/transformers/wordpress.js`)**
```javascript
export function transformToWordPress(parsedData) {
return {
title: "",
content: "",
excerpt: "",
featured_media: 0,
tags: [],
categories: [],
meta: {},
author: 0
}
}
```
**WordPress REST API v2 Format**
#### 6. **Nostr Transformer (`src/transformers/nostr.js`)**
```javascript
export function transformToNostr(parsedData) {
return {
kind: 30023, // NIP-23 Long-form
tags: [
["d", ""], // unique identifier
["title", ""],
["summary", ""],
["published_at", ""],
["image", ""],
["t", ""], // hashtags
["e", ""], // event refs
["a", ""], // article refs
["p", ""] // pubkey refs
],
content: "" // Markdown content
}
}
```
## 🔄 Datenfluss
### 1. Parsing-Pipeline
```mermaid
sequenceDiagram
participant Client
participant Parser
participant Unified
participant YAML
participant AMB
Client->>Parser: parseMarkdownFile(path)
Parser->>Unified: process(markdown)
Unified->>YAML: extract front matter
YAML-->>Parser: yamlObject
Parser->>AMB: extractAMBMetadata(yaml)
AMB-->>Parser: ambMetadata
Unified-->>Parser: ast
Parser-->>Client: { yaml, metadata, ast, content }
```
### 2. Forgejo API Integration
```mermaid
sequenceDiagram
participant Client
participant ForgejoClient
participant API as Forgejo API
participant Parser
Client->>ForgejoClient: getFileContent(path)
ForgejoClient->>API: GET /repos/.../contents/...
API-->>ForgejoClient: { content: base64, ... }
ForgejoClient->>ForgejoClient: decode base64
ForgejoClient-->>Client: markdown string
Client->>Parser: parseMarkdownFile(markdown)
Parser-->>Client: parsed data
```
### 3. Transformation (Phase 2)
```mermaid
flowchart LR
Parse["Parsed Data<br/>{yaml, metadata, ast}"]
WPT["WordPress<br/>Transformer"]
NostrT["Nostr<br/>Transformer"]
WPAPI["WordPress<br/>REST API"]
NostrRelay["Nostr<br/>Relay"]
Parse --> WPT
Parse --> NostrT
WPT --> WPAPI
NostrT --> NostrRelay
style Parse fill:#e8f5e9
style WPT fill:#fff3e0
style NostrT fill:#f3e5f5
```
## 🛠️ Technologie-Entscheidungen
### Warum unified/remark?
| Alternative | Pro | Contra | Entscheidung |
|-------------|-----|--------|--------------|
| **marked** | ✅ Sehr populär<br/>✅ Einfach | ❌ HTML-fokussiert<br/>❌ Kein AST | ❌ Abgelehnt |
| **markdown-it** | ✅ Erweiterbar<br/>✅ Performance | ❌ Komplexe API<br/>❌ HTML-fokussiert | ❌ Abgelehnt |
| **unified/remark** | ✅ AST-basiert<br/>✅ Isomorph<br/>✅ Plugin-System<br/>✅ Standard | ⚠️ Lernkurve | ✅ **GEWÄHLT** |
| **gray-matter + marked** | ✅ Einfach | ❌ Weniger strukturiert | ⚠️ Fallback |
### Warum `yaml` library?
| Alternative | Pro | Contra | Entscheidung |
|-------------|-----|--------|--------------|
| **js-yaml** | ✅ Populär | ❌ Größere Bundle-Size | ❌ Abgelehnt |
| **yaml** | ✅ Modern<br/>✅ Spec-compliant<br/>✅ Klein | - | ✅ **GEWÄHLT** |
| JSON.parse | ✅ Native | ❌ Kein YAML-Support | ❌ Nicht geeignet |
### Warum native `fetch`?
- ✅ Standard in Node.js 18+
- ✅ Identische API im Browser
- ✅ Keine Dependencies
- ✅ Async/await Support
## 📊 Performance-Überlegungen
### Caching-Strategie
```javascript
// Optional: Cache für häufig abgerufene Dateien
const cache = new Map()
async function parseWithCache(path, options) {
const cacheKey = `${path}-${JSON.stringify(options)}`
if (cache.has(cacheKey)) {
return cache.get(cacheKey)
}
const result = await parseMarkdownFile(path, options)
cache.set(cacheKey, result)
return result
}
```
### Rate Limiting für APIs
```javascript
// Forgejo API: Max. 10 Requests/Sekunde
const rateLimiter = new RateLimiter({
tokensPerInterval: 10,
interval: 1000
})
```
## 🔒 Sicherheit
### Input-Validierung
- YAML-Bombing-Schutz (max. depth/size)
- Path-Traversal-Schutz bei Dateizugriffen
- Content-Type-Validierung bei API-Requests
### Sanitization
- XSS-Schutz bei HTML-Output (optional mit DOMPurify)
- SQL-Injection-Schutz bei DB-Integration (Phase 2)
## 🧪 Testing-Strategie
### Unit Tests
```
test/
├── parser.test.js
├── yaml-extractor.test.js
├── amb-extractor.test.js
├── forgejo-client.test.js
└── transformers/
├── wordpress.test.js
└── nostr.test.js
```
### Integration Tests
- End-to-End mit echtem Forgejo-Repository
- Mocking der API-Responses
### Test-Fixtures
```
test/fixtures/
├── valid-amb.md
├── missing-metadata.md
├── complex-yaml.md
└── github-flavored.md
```
## 🚀 Deployment-Szenarien
### 1. **Node.js CLI**
```bash
npm install -g mdparser
mdparser parse ./content/post.md
```
### 2. **Node.js Library**
```javascript
import { parseMarkdownFile } from 'mdparser'
const result = await parseMarkdownFile('./post.md')
```
### 3. **Browser (ESM)**
```html
<script type="module">
import { parseMarkdownFile } from './mdparser.js'
// ...
</script>
```
### 4. **Serverless Function**
```javascript
// Vercel/Netlify Function
export default async function handler(req, res) {
const result = await parseMarkdownFile(req.body.url)
res.json(result)
}
```
## 📈 Roadmap & Erweiterungen
### Phase 1: Core Parser ✅ (aktuell)
- [x] Projekt-Setup
- [ ] Parser-Implementierung
- [ ] Forgejo-Client
- [ ] AMB-Extraktor
- [ ] Tests & Dokumentation
### Phase 2: Transformers 🚧
- [ ] WordPress-Integration
- [ ] Nostr-Integration
- [ ] Batch-Processing
### Phase 3: Advanced Features 🔮
- [ ] Browser-Build
- [ ] CLI-Tool
- [ ] Webhook-Support
- [ ] Real-time Sync
- [ ] GraphQL-API
## 🤝 Contribution Guidelines
Siehe [CONTRIBUTING.md](../CONTRIBUTING.md) für Details zu:
- Code-Style (ESLint + Prettier)
- Commit-Conventions
- Pull-Request-Prozess
- Testing-Requirements

344
docs/DECISIONS.md Normal file
View 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)

50
package.json Normal file
View file

@ -0,0 +1,50 @@
{
"name": "mdparser",
"version": "0.1.0",
"description": "Markdown Parser für AMB-konforme Inhalte mit YAML Front Matter - optimiert für Forgejo/Gitea API und Transformation zu WordPress/Nostr",
"type": "module",
"main": "src/index.js",
"scripts": {
"start": "node src/index.js",
"dev": "node --watch src/index.js",
"test": "node --test",
"lint": "eslint src/",
"format": "prettier --write 'src/**/*.js'",
"example": "node examples/parse-forgejo.js"
},
"keywords": [
"markdown",
"parser",
"yaml",
"frontmatter",
"AMB",
"schema.org",
"forgejo",
"gitea",
"wordpress",
"nostr",
"oer",
"education"
],
"author": "Jörg Lohrer",
"license": "MIT",
"dependencies": {
"unified": "^11.0.5",
"remark-parse": "^11.0.0",
"remark-frontmatter": "^5.0.0",
"remark-gfm": "^4.0.0",
"yaml": "^2.4.5",
"dotenv": "^16.4.5"
},
"devDependencies": {
"eslint": "^9.9.0",
"prettier": "^3.3.3"
},
"engines": {
"node": ">=18.0.0"
},
"repository": {
"type": "git",
"url": "git+https://git.rpi-virtuell.de/Comenius-Institut/mdparser.git"
}
}