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
18
.editorconfig
Normal file
18
.editorconfig
Normal 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
12
.env.example
Normal 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
44
.gitignore
vendored
Normal 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
82
CONTRIBUTING.md
Normal 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
21
LICENSE
Normal 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
257
README.md
Normal 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
435
docs/ARCHITECTURE.md
Normal 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
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)
|
||||
50
package.json
Normal file
50
package.json
Normal 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"
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue