quartz build

This commit is contained in:
Ignacio Ballesteros
2026-02-14 18:00:32 +01:00
parent 23aa2f4dc4
commit 79e93c167e
15 changed files with 710 additions and 19 deletions

View File

@@ -11,18 +11,26 @@ from .citations import CitationResolver
def find_org_files(input_dir: Path) -> list[Path]:
"""Find all .org files in directory (non-recursive)."""
return list(input_dir.glob("*.org"))
"""Find all .org files in directory (recursive)."""
return list(input_dir.rglob("*.org"))
def convert_file(
org_path: Path,
input_dir: Path,
output_dir: Path,
citation_resolver: CitationResolver | None,
verbose: bool = False,
) -> Path | None:
"""Convert a single org file to Quartz markdown.
Args:
org_path: Path to the org file
input_dir: Root input directory (for computing relative paths)
output_dir: Root output directory
citation_resolver: Optional citation resolver
verbose: Enable verbose output
Returns:
Path to created note directory, or None on error
"""
@@ -33,8 +41,21 @@ def convert_file(
if verbose:
print(f" Parsed: {doc.title or org_path.stem}")
# Compute relative path from input dir to preserve directory structure
relative_path = org_path.relative_to(input_dir)
# Special case: root index.org becomes content/index.md directly
if relative_path.stem == "index" and relative_path.parent == Path("."):
note_dir = output_dir
output_path = output_dir / "index.md"
else:
# Replace .org with directory containing index.md
# e.g., concepts/zettelkasten.org -> concepts/zettelkasten/index.md
note_relative_dir = relative_path.parent / relative_path.stem
note_dir = output_dir / note_relative_dir
output_path = note_dir / "index.md"
# Create output directory for this note
note_dir = output_dir / doc.slug
note_dir.mkdir(parents=True, exist_ok=True)
# Copy images first (before conversion, to get path mapping)
@@ -50,7 +71,6 @@ def convert_file(
md_content = update_image_paths(md_content, image_mapping)
# Write output
output_path = note_dir / "index.md"
output_path.write_text(md_content, encoding="utf-8")
return note_dir
@@ -123,7 +143,7 @@ def main() -> int:
for org_path in org_files:
print(f"Converting: {org_path.name}")
result = convert_file(org_path, args.output_dir, citation_resolver, args.verbose)
result = convert_file(org_path, args.input_dir, args.output_dir, citation_resolver, args.verbose)
if result:
success_count += 1
if args.verbose:

View File

@@ -57,7 +57,8 @@ def process_wikilinks(content: str) -> str:
Pandoc converts org links to markdown links:
- [[roam:Title]] -> [roam:Title](roam:Title) -> [[Title]]
- [[id:uuid][Desc]] -> [Desc](id:uuid) -> [[Desc]]
- [[file:x.org][Desc]] -> [Desc](file:x.org) -> [[Desc]]
- [[file:x.org][Desc]] -> [Desc](x) (relative link)
- [[file:../dir/x.org][Desc]] -> [Desc](../dir/x) (relative link)
"""
# [roam:Title](roam:Title) -> [[Title]]
content = re.sub(r"\[roam:([^\]]+)\]\(roam:[^)]+\)", r"[[\1]]", content)
@@ -65,8 +66,21 @@ def process_wikilinks(content: str) -> str:
# [Description](id:uuid) -> [[Description]]
content = re.sub(r"\[([^\]]+)\]\(id:[a-f0-9-]+\)", r"[[\1]]", content)
# [Description](file:something.org) -> [[Description]]
content = re.sub(r"\[([^\]]+)\]\(file:[^)]+\.org\)", r"[[\1]]", content)
# [Description](file:path/to/something.org) -> [Description](/path/to/something)
# Convert org file links to proper Quartz paths
def convert_file_link(match):
description = match.group(1)
path = match.group(2)
# Remove file: prefix and .org suffix, convert to Quartz path
# ../concepts/foo.org -> ../concepts/foo
clean_path = re.sub(r"\.org$", "", path)
return f"[{description}]({clean_path})"
content = re.sub(r"\[([^\]]+)\]\(file:([^)]+\.org)\)", convert_file_link, content)
# Also handle relative paths without file: prefix (pandoc sometimes drops it)
# [Description](../something.org) -> [Description](../something)
content = re.sub(r"\[([^\]]+)\]\(([^):]+\.org)\)", convert_file_link, content)
return content