feat: output module — Markdown file writer with slugified filenames
This commit is contained in:
@@ -0,0 +1,50 @@
|
|||||||
|
import os
|
||||||
|
import re
|
||||||
|
import unicodedata
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
|
||||||
|
def slugify(text: str) -> str:
|
||||||
|
for src, dst in [("ä","a"),("ö","o"),("ü","u"),("Ä","a"),("Ö","o"),("Ü","u"),("ß","ss")]:
|
||||||
|
text = text.replace(src, dst)
|
||||||
|
text = unicodedata.normalize("NFKD", text)
|
||||||
|
text = "".join(c for c in text if unicodedata.category(c) != "Mn")
|
||||||
|
text = text.lower()
|
||||||
|
text = re.sub(r"[^a-z0-9]+", "-", text)
|
||||||
|
return text.strip("-")
|
||||||
|
|
||||||
|
|
||||||
|
def save_transcript(
|
||||||
|
title: str,
|
||||||
|
content: str,
|
||||||
|
output_dir: str,
|
||||||
|
dt: datetime | None = None,
|
||||||
|
) -> str:
|
||||||
|
if dt is None:
|
||||||
|
dt = datetime.now()
|
||||||
|
slug = slugify(title)[:60]
|
||||||
|
filename = f"{dt.strftime('%Y-%m-%d-%H%M')}-{slug}.md"
|
||||||
|
os.makedirs(output_dir, exist_ok=True)
|
||||||
|
path = os.path.join(output_dir, filename)
|
||||||
|
with open(path, "w", encoding="utf-8") as f:
|
||||||
|
f.write(f"---\ndate: {dt.isoformat(timespec='seconds')}\ntags: [transkript]\n---\n\n")
|
||||||
|
f.write(f"# {title}\n\n")
|
||||||
|
f.write(content)
|
||||||
|
if not content.endswith("\n"):
|
||||||
|
f.write("\n")
|
||||||
|
return path
|
||||||
|
|
||||||
|
|
||||||
|
def list_transcripts(output_dir: str, limit: int = 20) -> list[dict]:
|
||||||
|
if not os.path.exists(output_dir):
|
||||||
|
return []
|
||||||
|
files = sorted(
|
||||||
|
[f for f in os.listdir(output_dir) if f.endswith(".md")],
|
||||||
|
reverse=True,
|
||||||
|
)[:limit]
|
||||||
|
result = []
|
||||||
|
for f in files:
|
||||||
|
full = os.path.join(output_dir, f)
|
||||||
|
stat = os.stat(full)
|
||||||
|
result.append({"filename": f, "path": full, "size": stat.st_size, "mtime": stat.st_mtime})
|
||||||
|
return result
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
import os
|
||||||
|
import tempfile
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
|
||||||
|
def test_save_transcript_creates_file():
|
||||||
|
with tempfile.TemporaryDirectory() as tmpdir:
|
||||||
|
from output import save_transcript
|
||||||
|
path = save_transcript(
|
||||||
|
title="Test Aufnahme",
|
||||||
|
content="Dies ist ein Test.",
|
||||||
|
output_dir=tmpdir,
|
||||||
|
dt=datetime(2026, 4, 1, 14, 32, 0),
|
||||||
|
)
|
||||||
|
assert os.path.exists(path)
|
||||||
|
|
||||||
|
|
||||||
|
def test_save_transcript_filename_format():
|
||||||
|
with tempfile.TemporaryDirectory() as tmpdir:
|
||||||
|
from output import save_transcript
|
||||||
|
path = save_transcript(
|
||||||
|
title="Mein erstes Diktat",
|
||||||
|
content="Inhalt.",
|
||||||
|
output_dir=tmpdir,
|
||||||
|
dt=datetime(2026, 4, 1, 14, 32, 0),
|
||||||
|
)
|
||||||
|
assert os.path.basename(path) == "2026-04-01-1432-mein-erstes-diktat.md"
|
||||||
|
|
||||||
|
|
||||||
|
def test_save_transcript_contains_frontmatter():
|
||||||
|
with tempfile.TemporaryDirectory() as tmpdir:
|
||||||
|
from output import save_transcript
|
||||||
|
path = save_transcript(
|
||||||
|
title="Test",
|
||||||
|
content="Inhalt.",
|
||||||
|
output_dir=tmpdir,
|
||||||
|
dt=datetime(2026, 4, 1, 14, 32, 0),
|
||||||
|
)
|
||||||
|
text = open(path).read()
|
||||||
|
assert "---" in text
|
||||||
|
assert "date:" in text
|
||||||
|
assert "transkript" in text
|
||||||
|
|
||||||
|
|
||||||
|
def test_save_transcript_contains_content():
|
||||||
|
with tempfile.TemporaryDirectory() as tmpdir:
|
||||||
|
from output import save_transcript
|
||||||
|
path = save_transcript(
|
||||||
|
title="Test",
|
||||||
|
content="Das ist der Inhalt.",
|
||||||
|
output_dir=tmpdir,
|
||||||
|
dt=datetime(2026, 4, 1, 14, 32, 0),
|
||||||
|
)
|
||||||
|
assert "Das ist der Inhalt." in open(path).read()
|
||||||
|
|
||||||
|
|
||||||
|
def test_slugify():
|
||||||
|
from output import slugify
|
||||||
|
assert slugify("Mein erstes Diktat") == "mein-erstes-diktat"
|
||||||
|
assert slugify("test -- foo") == "test-foo"
|
||||||
Reference in New Issue
Block a user