feat(notion-writer): materialize local images via upload walk
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -83,3 +83,54 @@ def upload(path: Path) -> str:
|
||||
first_line = result.stdout.strip().splitlines()[0]
|
||||
upload_id = first_line.split("\t")[0].strip()
|
||||
return upload_id
|
||||
|
||||
|
||||
_REMOTE_PREFIXES = ("http://", "https://")
|
||||
|
||||
|
||||
def _resolve_local(url: str, base_dir: Path) -> Optional[Path]:
|
||||
"""Return the resolved path for a local media url, or None if remote."""
|
||||
if url.startswith(_REMOTE_PREFIXES):
|
||||
return None
|
||||
p = Path(url)
|
||||
return p if p.is_absolute() else Path(base_dir) / p
|
||||
|
||||
|
||||
def materialize_local_media(
|
||||
blocks: List[Dict[str, Any]],
|
||||
base_dir: Path,
|
||||
upload_fn: Callable[[Path], str] = upload,
|
||||
) -> List[Dict[str, Any]]:
|
||||
"""Walk blocks (and nested children); upload local image files and
|
||||
rewrite them to file_upload shape. Remote images are left as-is."""
|
||||
for block in blocks:
|
||||
if block.get("type") == "image":
|
||||
img = block["image"]
|
||||
if img.get("type") == "external":
|
||||
url = img.get("external", {}).get("url", "")
|
||||
resolved = _resolve_local(url, base_dir)
|
||||
if resolved is not None:
|
||||
if not resolved.is_file():
|
||||
raise NtnUploadError(
|
||||
f"image references missing file: {url}",
|
||||
path=str(resolved),
|
||||
)
|
||||
upload_id = upload_fn(resolved)
|
||||
caption = img.get("caption")
|
||||
new_img: Dict[str, Any] = {
|
||||
"type": "file_upload",
|
||||
"file_upload": {"id": upload_id},
|
||||
}
|
||||
if caption:
|
||||
new_img["caption"] = caption
|
||||
block["image"] = new_img
|
||||
# Recurse into any nested children list.
|
||||
btype = block.get("type")
|
||||
nested = block.get(btype, {}) if isinstance(block.get(btype), dict) else {}
|
||||
if isinstance(nested.get("children"), list):
|
||||
materialize_local_media(nested["children"], base_dir, upload_fn)
|
||||
if btype == "column_list":
|
||||
for col in nested.get("children", []):
|
||||
col_children = col.get("column", {}).get("children", [])
|
||||
materialize_local_media(col_children, base_dir, upload_fn)
|
||||
return blocks
|
||||
|
||||
Reference in New Issue
Block a user