Skip to content

feat(block): --image-file / --image-upload (and friends) for append/insert#30

Merged
4ier merged 1 commit into
mainfrom
feat/media-blocks-by-upload
Apr 30, 2026
Merged

feat(block): --image-file / --image-upload (and friends) for append/insert#30
4ier merged 1 commit into
mainfrom
feat/media-blocks-by-upload

Conversation

@4ier
Copy link
Copy Markdown
Owner

@4ier 4ier commented Apr 30, 2026

What

Add first-class CLI paths to embed uploaded files as Notion blocks — no more hand-written notion api PATCH /v1/blocks/... JSON for the upload-then-embed flow.

Why

Tracked in #23. After notion file upload, there was no way to insert the result as an image / file / video / audio / pdf block. Existing --image-url only took external http(s) URLs. The workaround was to drop to notion api with a hand-written block spec. Agent workflows that produce charts/diagrams hit this constantly.

Changes

Symmetric triple for every media kind:

flag behavior
--<kind>-url <URL> external URL (unchanged semantics)
--<kind>-file <path> upload local file then embed
--<kind>-upload <id> embed existing file_upload id

…where <kind> is one of image, file, video, audio, pdf. --caption works with all of them.

New file cmd/media_source.go:

  • registerMediaFlags(cmd) — adds the 15 flags + --caption in one call.
  • resolveMediaSource(cmd, filePath, text) — picks the single active source, validates mutual exclusion and conflicts with --file / positional text, rejects non-http(s) URLs.
  • mediaSource.Build(c) — performs any upload step and returns the final block map.

The legacy --image-url and its helpers are now thin back-compat wrappers around the new plumbing, so existing tests and invocations stay byte-for-byte identical.

Examples

notion block append <page-id> --image-file ./chart.png --caption "heap usage"
notion block append <page-id> --pdf-upload 351d45fb-... --caption "spec v2"
notion block insert <page-id> --after <block-id> --video-file ./demo.mp4

Test plan

  • Table-driven tests covering all 15 flag combinations.
  • Mutual-exclusion / conflict tests.
  • TestMediaSource_Build_File_UploadsAndReferences verifies that --image-file performs exactly one POST /v1/file_uploads and does not patch the parent (the caller's append/insert path is responsible for that).

Closes #23

…nsert

Before this change there was no first-class CLI path to turn an uploaded
file into a block. Users had to run `notion file upload`, capture the
id, then hand-craft a PATCH /v1/blocks/<id>/children JSON body and send
it via `notion api`. The existing --image-url only accepted external
http(s) links.

This PR adds a symmetric triple for every media type Notion supports:

  --image-url / --image-file / --image-upload
  --file-url  / --file-file  / --file-upload
  --video-url / --video-file / --video-upload
  --audio-url / --audio-file / --audio-upload
  --pdf-url   / --pdf-file   / --pdf-upload

Semantics:
  --<kind>-url     http(s) external URL           → block.<kind>.type = external
  --<kind>-file    local path                     → upload then embed
  --<kind>-upload  existing file_upload id        → embed directly

Flags are mutually exclusive with each other and with --file/positional
text. --caption works with any of them.

Implementation lives in cmd/media_source.go:
  - registerMediaFlags: adds the 15 flags + --caption to a cobra command.
  - resolveMediaSource: validates, returns the single active source.
  - mediaSource.Build: performs the upload (for --*-file) and assembles
    the final block map.

The legacy --image-url flag and its validator/builder are now thin
back-compat wrappers around the new helpers, so existing tests and
usage keep working byte-for-byte.

Closes #23
@4ier 4ier force-pushed the feat/media-blocks-by-upload branch from 1ddb106 to dec1330 Compare April 30, 2026 04:59
@4ier 4ier merged commit 7d0d5f8 into main Apr 30, 2026
@4ier 4ier deleted the feat/media-blocks-by-upload branch April 30, 2026 05:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

No first-class CLI path to embed a file upload as a block (no --image-file / --image-upload)

1 participant