Files
傅洋 8e4cd813a2 feat(page): add 'page markdown' and 'page set-markdown' (#47)
Closes #37. Wraps the two 2025 Notion endpoints that do server-side
markdown I/O on a full page:

  GET   /v1/pages/:id/markdown     →  notion page markdown <id>
  PATCH /v1/pages/:id/markdown     →  notion page set-markdown <id>

### page markdown

Prints a page's content as markdown. Strictly better than `block list
--md` for page-level dumps: the server handles toggles, columns, synced
blocks, and databases-as-pages uniformly and always matches what the
Notion UI shows.

  notion page markdown <id>
  notion page markdown <id> > page.md
  notion page markdown <id> --out page.md
  notion page markdown <id> --format json   # full response incl. truncated flag

Surfaces Notion's 'truncated' flag and 'unknown_block_ids' as stderr
notes in default output so silent partial renders don't go unnoticed.

### page set-markdown

Updates a page from markdown in one API call. Supports all four
mutation modes Notion's PATCH endpoint accepts:

  --replace         (default) replace_content: overwrite whole page
  --append          insert_content at end
  --after <anchor>  insert_content after ellipsis anchor ("start...end")
  --range <anchor>  replace_content_range bounded by ellipsis anchor

  --file <path>     (use '-' for stdin)
  --text <str>      inline markdown
  --allow-deleting-content   pass allow flag for destructive modes

Because Notion handles the full markdown → blocks conversion server-side,
this is the cleanest way to write long documents — the 100-children
batching (#21) doesn't apply to set-markdown.

### Implementation

Two pure helpers isolate the fiddly bits for unit testing without network:
- buildSetMarkdownBody: produces the correct envelope for each mode;
  rejects ambiguous flag combinations up front.
- readMarkdownSource: picks the source (--file / --text / stdin); same
  mutual-exclusion rules as the rest of the CLI.

### Tests

- Exhaustive buildSetMarkdownBody coverage across all four modes +
  allow_deleting_content + multi-mode rejection.
- readMarkdownSource: required / conflict / file / stdin / file-missing.

### Smoke

Verified end-to-end against a real workspace: replace via --file,
append --text, markdown read with --out, stdin replace, and multi-mode
rejection all behave as documented.
2026-04-30 14:12:25 +08:00
..
2026-02-18 23:40:14 +08:00
2026-02-18 23:40:14 +08:00