Skip to content

feat(render): add configurable long image layouts#87

Merged
69gg merged 5 commits into
mainfrom
feature/long-picture
Jul 14, 2026
Merged

feat(render): add configurable long image layouts#87
69gg merged 5 commits into
mainfrom
feature/long-picture

Conversation

@69gg

@69gg 69gg commented Jul 13, 2026

Copy link
Copy Markdown
Owner

变更摘要

  • 为 render.render_html 和 render.render_markdown 新增长图布局,以及可配置的输出宽度和内边距。
  • 使用 CSS 像素截图缩放保证长图最终宽度准确,并让缓存键区分截图缩放与样式参数。
  • 支持显式配置浏览器可执行文件;Playwright 内置浏览器缺失时可回退到系统 Chrome / Chromium。
  • 同步配置、环境变量、热更新边界、使用与部署文档,并补充相关回归测试。
  • 新增 v3.8.1 changelog,并同步 Python、Console、Chat、Tauri 与 lock 文件版本。

验证

  • uv run pytest tests/:2524 passed, 1 skipped
  • uv run pytest tests/test_bump_version_script.py tests/test_release_notes_script.py:17 passed
  • uv run ruff check .
  • uv run ruff format --check .
  • uv run mypy .
  • uv build --wheel
  • Console:Biome、TypeScript、Cargo fmt/check 通过
  • Chat:Biome、TypeScript、Vitest unit/e2e、Cargo fmt/check/test 通过
  • 实际 HTML、Markdown 长图渲染及系统 Chrome 回退验证通过

Summary by CodeRabbit

  • New Features
    • Added layout=long rendering for HTML/Markdown single long images with configurable defaults (width/padding) and controls for screenshot_scale/screenshot_style.
    • Added browser_executable_path configuration with auto fallback to system Chrome/Chromium and new env overrides for long-image defaults and browser path.
  • Bug Fixes
    • Improved long-image sizing (reduced whitespace and better canvas fill) and aligned screenshot capture to the requested width.
    • Strengthened browser startup and render-cache key distinctness (now varies by screenshot scale/style and relevant render inputs).
  • Security
    • HTML rendering now forces offline mode, blocks service workers, and terminates external requests (allowing data:/blob: resources); LaTeX rendering is local-only with no external fallback.
  • Documentation
    • Updated render configuration, deployment, and usage docs for layout=long and the new offline behavior.
  • Tests / Release
    • Added render/layout, cache, config/env, and LaTeX regression tests; bumped version to 3.8.1.

69gg and others added 2 commits July 13, 2026 10:56
Co-authored-by: GPT-5 Codex <noreply@openai.com>
Co-authored-by: GPT-5 Codex <noreply@openai.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 01dcf7dc-f84b-47d5-b161-a4c6a58893a7

📥 Commits

Reviewing files that changed from the base of the PR and between 31ef973 and 0678832.

📒 Files selected for processing (1)
  • src/Undefined/render.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/Undefined/render.py

📝 Walkthrough

Walkthrough

Changes

Long-image rendering adds layout, width, and padding support for HTML and Markdown tools. Configuration adds defaults and browser executable selection; rendering adds browser fallback, offline resource blocking, screenshot options, cache-key updates, and local-only LaTeX handling. Tests, documentation, and version metadata are updated.

Rendering and release update

Layer / File(s) Summary
Render configuration and reload wiring
src/Undefined/config/..., config.toml.example, docs/configuration.md, tests/test_config_*
Adds browser executable and long-image defaults, environment mappings, bounds handling, hot-reload behavior, and configuration coverage.
Long-layout resolution and tool integration
src/Undefined/skills/toolsets/render/..., docs/usage.md, src/Undefined/skills/toolsets/README.md, tests/test_render_layout_tools.py
Adds layout contracts, validation, generated styles, tool schemas, handler integration, and HTML/Markdown layout tests.
Browser fallback and protected screenshot rendering
src/Undefined/render.py, src/Undefined/utils/render_cache.py, src/Undefined/utils/io.py, tests/test_render.py, tests/test_render_cache.py
Adds browser fallback, screenshot scale/style forwarding, offline request blocking, cache-key inputs, executable helpers, and regression tests.
Local LaTeX rendering
src/Undefined/skills/toolsets/render/render_latex/..., tests/test_render_latex_tool.py
Replaces the MathJax and Playwright fallback with local mathtext rendering and unsupported-content error coverage.
3.8.1 release metadata and deployment documentation
CHANGELOG.md, pyproject.toml, src/Undefined/__init__.py, apps/undefined-*/..., docs/deployment.md
Updates project, module, application, Tauri, and changelog versions and documents revised rendering runtime behavior.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Tool
  participant resolve_render_layout
  participant render_html_to_image
  participant Playwright
  Tool->>resolve_render_layout: resolve layout, width, and padding
  resolve_render_layout-->>Tool: return render kwargs and screenshot style
  Tool->>render_html_to_image: render HTML or Markdown with layout kwargs
  render_html_to_image->>Playwright: capture screenshot with scale and style
  Playwright-->>render_html_to_image: return image
Loading

Possibly related PRs

  • 69gg/Undefined#61: Introduces the configuration and environment-mapping structure extended by this rendering configuration update.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 23.08% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately captures the main change: configurable long image layouts for render output.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/long-picture

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/Undefined/config/load_sections/network.py`:
- Around line 26-28: Add explicit integer type annotations to
_LONG_IMAGE_MIN_WIDTH, _LONG_IMAGE_MAX_WIDTH, and _LONG_IMAGE_MAX_PADDING in the
network configuration module, preserving their existing values and names.

In `@src/Undefined/render.py`:
- Around line 100-130: Move browser-path filesystem discovery out of the event
loop: update _resolve_configured_browser_executable to perform
Path.resolve/is_file through the project async I/O utility (or its
asyncio.to_thread-backed helper), and update _find_system_browser_executable to
run shutil.which through the same utility. Make the callers, including
_get_browser, await these asynchronous helpers before launching Chromium while
preserving configured-path precedence and validation behavior.

In `@tests/test_render_layout_tools.py`:
- Around line 75-81: Update the async test helpers around _fake_render and the
schema-loading code to route all artifact writes and schema reads through the
project utilities in utils/io.py. Replace direct Path.write_bytes and schema
file reads with the established async-safe, atomic I/O helpers, preserving the
existing test data and behavior.

In `@tests/test_render.py`:
- Around line 220-225: Update test_get_browser_uses_configured_executable to
create the executable fixture through the repository’s async-safe helper in
utils/io.py instead of calling Path.write_bytes directly. Preserve the existing
executable path and binary contents while ensuring disk I/O does not block the
event loop.
- Around line 441-484: Update render_html_with_page and its test
test_render_html_with_page_keeps_html_and_javascript_enabled so
caller-controlled HTML is not rendered with unrestricted JavaScript or network
access by default. Add an explicit trusted mode or enforce request
interception/egress blocking for loopback and private-network targets, then
revise the test to assert the secure default rather than requiring JavaScript to
remain enabled.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 2493ad00-7312-4169-90be-930bfb30107e

📥 Commits

Reviewing files that changed from the base of the PR and between 4f94b63 and c711e6d.

⛔ Files ignored due to path filters (5)
  • apps/undefined-chat/package-lock.json is excluded by !**/package-lock.json
  • apps/undefined-chat/src-tauri/Cargo.lock is excluded by !**/*.lock
  • apps/undefined-console/package-lock.json is excluded by !**/package-lock.json
  • apps/undefined-console/src-tauri/Cargo.lock is excluded by !**/*.lock
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (33)
  • CHANGELOG.md
  • apps/undefined-chat/package.json
  • apps/undefined-chat/src-tauri/Cargo.toml
  • apps/undefined-chat/src-tauri/tauri.conf.json
  • apps/undefined-console/package.json
  • apps/undefined-console/src-tauri/Cargo.toml
  • apps/undefined-console/src-tauri/tauri.conf.json
  • config.toml.example
  • docs/configuration.md
  • docs/deployment.md
  • docs/usage.md
  • pyproject.toml
  • src/Undefined/__init__.py
  • src/Undefined/config/config_class.py
  • src/Undefined/config/env_registry.py
  • src/Undefined/config/hot_reload.py
  • src/Undefined/config/load_sections/network.py
  • src/Undefined/render.py
  • src/Undefined/skills/toolsets/README.md
  • src/Undefined/skills/toolsets/render/README.md
  • src/Undefined/skills/toolsets/render/layout.py
  • src/Undefined/skills/toolsets/render/render_html/config.json
  • src/Undefined/skills/toolsets/render/render_html/handler.py
  • src/Undefined/skills/toolsets/render/render_markdown/config.json
  • src/Undefined/skills/toolsets/render/render_markdown/handler.py
  • src/Undefined/utils/render_cache.py
  • tests/test_config_api.py
  • tests/test_config_env_only.py
  • tests/test_config_env_registry.py
  • tests/test_config_hot_reload.py
  • tests/test_render.py
  • tests/test_render_cache.py
  • tests/test_render_layout_tools.py

Comment thread src/Undefined/config/load_sections/network.py Outdated
Comment thread src/Undefined/render.py Outdated
Comment thread tests/test_render_layout_tools.py Outdated
Comment thread tests/test_render.py Outdated
Comment thread tests/test_render.py Outdated
Co-authored-by: GPT-5 Codex <noreply@openai.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/Undefined/render.py`:
- Around line 406-413: Update the render sandbox networking flow around the
hostname/IP validation guard to prevent DNS rebinding: route browser render
traffic through an egress proxy that resolves and validates destination IPs, or
disable external networking entirely. Do not rely on the current normalized_host
hostname-only check as the security boundary.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 4297e7d5-f7e6-48c5-85a4-ed003df72ea5

📥 Commits

Reviewing files that changed from the base of the PR and between c711e6d and 562409f.

📒 Files selected for processing (9)
  • CHANGELOG.md
  • docs/configuration.md
  • docs/usage.md
  • src/Undefined/config/load_sections/network.py
  • src/Undefined/render.py
  • src/Undefined/skills/toolsets/render/README.md
  • src/Undefined/utils/io.py
  • tests/test_render.py
  • tests/test_render_layout_tools.py
🚧 Files skipped from review as they are similar to previous changes (6)
  • src/Undefined/skills/toolsets/render/README.md
  • docs/usage.md
  • CHANGELOG.md
  • src/Undefined/config/load_sections/network.py
  • docs/configuration.md
  • tests/test_render_layout_tools.py

Comment thread src/Undefined/render.py Outdated
Co-authored-by: GPT-5 Codex <noreply@openai.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/Undefined/render.py (1)

337-344: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Document or remove the now-unused proxy parameter in render_html_with_page.

Since proxy was removed from context_kwargs, it's no longer used in the function body. It's still passed from render_html_to_image (line 329) and documented there (line 290) as retained for call compatibility and cache isolation, but render_html_with_page's own docstring doesn't mention this. Consider either adding a note to the docstring or removing the parameter if no other callers depend on it.

♻️ Optional: document the unused parameter
 async def render_html_with_page(
     html_content: str,
     callback: Callable[[Page], Awaitable[_RenderResult]],
     *,
     viewport_width: int = 1280,
     timeout_ms: int = 60000,
     proxy: str | None = None,
 ) -> _RenderResult:
-    """在共享浏览器实例中打开 HTML 页面并交给调用方渲染。"""
+    """在共享浏览器实例中打开 HTML 页面并交给调用方渲染。
+
+    proxy 参数保留用于调用兼容,离线上下文不会发出网络请求。
+    """
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Undefined/render.py` around lines 337 - 344, Document the intentionally
unused proxy parameter in render_html_with_page, noting that it is retained for
call compatibility and cache isolation after removal from context_kwargs. Keep
the existing parameter and render_html_to_image call path unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/Undefined/render.py`:
- Around line 337-344: Document the intentionally unused proxy parameter in
render_html_with_page, noting that it is retained for call compatibility and
cache isolation after removal from context_kwargs. Keep the existing parameter
and render_html_to_image call path unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: e9927819-8748-41ac-9344-0c67d867a798

📥 Commits

Reviewing files that changed from the base of the PR and between 562409f and 31ef973.

📒 Files selected for processing (13)
  • CHANGELOG.md
  • config.toml.example
  • docs/build.md
  • docs/configuration.md
  • docs/deployment.md
  • docs/usage.md
  • src/Undefined/render.py
  • src/Undefined/skills/toolsets/render/README.md
  • src/Undefined/skills/toolsets/render/render_html/config.json
  • src/Undefined/skills/toolsets/render/render_latex/config.json
  • src/Undefined/skills/toolsets/render/render_latex/handler.py
  • tests/test_render.py
  • tests/test_render_latex_tool.py
🚧 Files skipped from review as they are similar to previous changes (4)
  • config.toml.example
  • src/Undefined/skills/toolsets/render/render_html/config.json
  • docs/configuration.md
  • tests/test_render.py

Co-authored-by: GPT-5 Codex <noreply@openai.com>
@69gg
69gg merged commit d80819d into main Jul 14, 2026
4 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.

1 participant