Skip to content

Pin default image-mode contract: -f markdown keeps direct links; flags work uniformly#132

Merged
konard merged 7 commits into
mainfrom
issue-112-53d54c67d8bb
May 30, 2026
Merged

Pin default image-mode contract: -f markdown keeps direct links; flags work uniformly#132
konard merged 7 commits into
mainfrom
issue-112-53d54c67d8bb

Conversation

@konard
Copy link
Copy Markdown
Collaborator

@konard konard commented May 30, 2026

Summary

Fixes #112.

Pins the default image-mode contract and introduces a single image-handling
chokepoint so the same flag behaves identically regardless of capture method
(browser vs API, CLI vs server). Previously the default differed across paths
(API md silently inlined a 5.9 MB base64 blob; browser md ignored --embed-images
and --keep-original-links entirely).

The pinned contract

Mode Flag Result
Direct links (default) none / --keep-original-links Remote images stay as direct https://… URLs. Inline base64 (no remote URL to restore) is stripped to a visible placeholder with a warning — never silently kept as a multi-megabyte blob. No images/ folder.
Embed --embed-images Base64 kept inline → single self-contained file.
Extract --extract-images[=DIR] Inline base64 and remote images written to DIR/images/ (defaults next to the output); markdown rewritten to local files. On download failure the original remote URL is restored so references never break.

--archive always bundles images into the archive's images/ folder (issue #113, already merged).

Implementation

The single chokepoint is apply_image_mode (Rust, rust/src/extract_images.rs)
/ applyImageMode (JS, js/src/extract-images.js). Every CLI/server markdown
path now routes through it:

  • Rust CLI (rust/src/main.rs): new --extract-images[=DIR] flag;
    resolve_image_mode (precedence embed > extract > default),
    process_output_markdown, and download_pending_remote helpers; browser- and
    gdocs-api-derived markdown writes routed through the chokepoint.
  • Rust server /markdown: routed through apply_image_mode.
  • JS CLI (js/bin/web-capture.js): new --extract-images flag;
    resolveImageMode / processOutputMarkdown / downloadPendingRemote helpers;
    both markdown branches routed through them.
  • JS server /markdown (js/src/markdown.js): routed through applyImageMode.
  • Docs + CLI help (README.md, js/README.md, flag descriptions) updated to the
    three-mode contract.

Tests

The exact reproducible tests from the issue (adapted only to avoid the
unavailable tempfile dev-dep, using the repo's existing manual temp_dir()
helper — assertions unchanged):

  • rust/tests/integration/image_mode_defaults.rs — 5 tests
  • js/tests/unit/image-mode-defaults.test.js — 4 tests

How to reproduce / verify

# Rust
cd rust && cargo test --test integration image_mode

# JS
cd js && node --experimental-vm-modules ./node_modules/.bin/jest image-mode-defaults

All 5 Rust + 4 JS contract tests pass. Full suites green except pre-existing
browser/Docker integration tests that require a Chrome binary / Docker not
available in this environment (unrelated to these changes).

Release

  • Added changeset js/.changeset/pin-image-mode-contract.md (minor).
  • Rust version is auto-bumped on main by the existing auto-release workflow.

Adding .gitkeep for PR creation (default mode).
This file will be removed when the task is complete.

Issue: #112
@konard konard self-assigned this May 30, 2026
konard added 4 commits May 30, 2026 08:07
…+ contract tests

Implements the single image-handling entry point pinned by issue #112:
- Rust: ImageMode enum (Default/Embed/Extract) + apply_image_mode()
- JS: applyImageMode({ mode, dir, subdir })
- Default: keep remote URLs as direct links, strip inline base64
- Embed: keep base64 inline
- Extract: base64 -> files + localize remote refs (pending download)
- Adds the contract tests from the issue (Rust + JS), all passing
…oint

Wire the unified image-mode chokepoint into every capture path so the same
flag behaves identically regardless of capture method (browser vs API, CLI vs
server), per issue #112:

- Rust CLI: add --extract-images[=DIR]; resolve_image_mode (embed > extract >
  default) + process_output_markdown + download_pending_remote helpers; route
  browser- and gdocs-api-derived markdown writes through process_output_markdown.
- Rust server /markdown: route through apply_image_mode (Default vs Embed).
- JS CLI: add --extractImages; resolveImageMode + processOutputMarkdown +
  downloadPendingRemote helpers; route both markdown branches through them.
- JS server /markdown: route through applyImageMode.
- Docs + CLI help: pin the three-mode contract (direct links default, embed,
  extract) in README, js/README, and flag descriptions.
@konard konard changed the title [WIP] Pin default image-mode contract: -f markdown keeps direct links; -f archive bundles images; flags work uniformly Pin default image-mode contract: -f markdown keeps direct links; flags work uniformly May 30, 2026
@konard konard marked this pull request as ready for review May 30, 2026 08:36
@konard
Copy link
Copy Markdown
Collaborator Author

konard commented May 30, 2026

Working session summary

The work is complete. Here's a summary of what was accomplished for issue #112:

Done — PR #132 is ready for review

PR: #132 (no longer draft, title de-WIP'd)

What was solved

Pinned the default image-mode contract and routed every CLI/server markdown path (JS & Rust × browser & API) through a single image-handling chokepointapply_image_mode (Rust) / applyImageMode (JS) — so flags behave identically regardless of capture method:

  • Default -f markdown → keeps remote images as direct URLs; inline base64 (no URL to restore) is stripped to a placeholder with a warning instead of being silently kept as a multi-MB blob.
  • --embed-images → keeps base64 inline (self-contained file).
  • --extract-images[=DIR] (new flag) → writes inline base64 and downloads remote images to DIR/images/, rewriting markdown; restores the original URL on download failure.
  • --keep-original-links → back-compat alias for the default.

Verification

  • The issue's exact test files were added verbatim (adapted only to avoid the unavailable tempfile dev-dep): rust/tests/integration/image_mode_defaults.rs (5 tests) and js/tests/unit/image-mode-defaults.test.js (4 tests) — all pass.
  • CI green on the latest commit 23850d6: both "Rust Checks and Release" and "JavaScript Checks and Release" passed (Rust clippy/fmt, JS lint/format/test, changeset check).

Final fixes this session

  • Wrote the proper PR description (contract table, reproduction, chokepoint routing, changeset).
  • Fixed the only CI failure — a prettier --check alignment issue in js/README.md — committed as style(js): prettier-format README image-mode table and pushed.

Release prep is in place: a single minor changeset (js/.changeset/pin-image-mode-contract.md) for JS; Rust auto-bumps on merge to main.


This summary was automatically extracted from the AI working session output.

@konard
Copy link
Copy Markdown
Collaborator Author

konard commented May 30, 2026

🤖 Solution Draft Log

This log file contains the complete execution trace of the AI solution draft process.

💰 Cost: $10.562374

📊 Context and tokens usage:

Claude Opus 4.8: (3 sub-sessions)

  1. 115.5K / 1M (12%) input tokens, 41.3K / 128K (32%) output tokens
  2. 114.9K / 1M (11%) input tokens, 37.0K / 128K (29%) output tokens
  3. 44.2K / 1M (4%) input tokens, 3.7K / 128K (3%) output tokens

Total: (24.3K new + 302.4K cache writes + 12.3M cache reads) input tokens, 95.6K output tokens, $10.562374 cost

🤖 Models used:

  • Tool: Anthropic Claude Code
  • Requested: opus
  • Model: Claude Opus 4.8 (claude-opus-4-8)

📎 Log file uploaded as Gist (5363KB)


Now working session is ended, feel free to review and add any feedback on the solution draft.

@konard
Copy link
Copy Markdown
Collaborator Author

konard commented May 30, 2026

✅ Ready to merge

This pull request is now ready to be merged:

  • All CI checks have passed
  • No merge conflicts
  • No pending changes

Monitored by hive-mind with --auto-restart-until-mergeable flag

@konard konard merged commit 8fe502d into main May 30, 2026
16 checks passed
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.

Pin default image-mode contract: -f markdown keeps direct links; -f archive bundles images; flags work uniformly

1 participant