Skip to content

add support for multiple output formats#2

Merged
dhth merged 10 commits into
mainfrom
add-support-for-multiple-output-formats
May 25, 2026
Merged

add support for multiple output formats#2
dhth merged 10 commits into
mainfrom
add-support-for-multiple-output-formats

Conversation

@dhth
Copy link
Copy Markdown
Owner

@dhth dhth commented May 24, 2026

Add a dedicated output module that renders deterministic output in four formats: html, plain, markdown, and terminal.

Each renderer relies on a shared EventPresentation shape that describes an event in display terms. This keeps event wording, link targets, and format-specific metadata in one place while letting each renderer decide how to present the final output.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 24, 2026

📝 Walkthrough

Walkthrough

This PR introduces a multi-format output rendering system for the ghlog CLI. It adds --output and --html-template options to the run subcommand, allowing users to select between HTML (with four template choices), Markdown, plain text, or colored terminal output. The implementation lifts event data into a presentation layer of human-readable fragments and event kinds, routes all formatting through a centralized dispatcher, and refactors the run handler to use the new output system instead of inline per-event formatting. Four new HTML template assets provide different visual styles for HTML output.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% 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
Title check ✅ Passed The title 'add support for multiple output formats' accurately and clearly summarizes the main objective of the changeset, which introduces four output format renderers.
Description check ✅ Passed The description directly addresses the core change: adding a dedicated output module with four format renderers (html, plain, markdown, terminal) that share an EventPresentation abstraction.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


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 and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (1)
src/domain/events.rs (1)

111-113: ⚡ Quick win

Remove DeleteEvent::ref_path() since it’s unused and yields misleading tree/{ref_name} paths for deleted refs.

src/output/presentation.rs renders deletions with text(delete.ref_name()) and the only .ref_path() call sites are push.ref_path() / create.ref_path()—so DeleteEvent::ref_path() is currently dead code and a future footgun.

🧹 Proposed fix
 impl DeleteEvent {
     pub fn ref_name(&self) -> &str {
         strip_git_ref_prefix(&self.git_ref)
     }
-
-    pub fn ref_path(&self) -> String {
-        format!("tree/{}", self.ref_name())
-    }
 }
🤖 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/domain/events.rs` around lines 111 - 113, Remove the unused and
misleading DeleteEvent::ref_path() method from the DeleteEvent implementation;
delete the entire fn ref_path(&self) -> String { ... } for DeleteEvent and
ensure no call sites rely on it (only PushEvent::ref_path() and
CreateEvent::ref_path() should remain); verify presentation code renders
deletions via delete.ref_name() so behavior is unchanged and no other types
expect a ref_path on DeleteEvent.
🤖 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/cmds/run.rs`:
- Around line 17-19: The early return on events.is_empty() unconditionally skips
all rendering (including HTML), so change the logic to only short-circuit for
non-HTML outputs: instead of returning immediately when events.is_empty(), check
the selected output format (the variable representing the format, e.g., format
or output_format) and only return Ok(()) when events.is_empty() AND the format
is not HTML (e.g., Format::Html); otherwise continue into the HTML rendering
path so an empty document/shell is produced. Ensure you update the branch around
events.is_empty() where it currently returns to reference the format enum/flag
and preserve the existing render_html/render() call flow for HTML.

In `@src/output/markdown.rs`:
- Around line 24-27: The fragment renderer inserts raw part.text into Markdown
which can break formatting; implement a helper like escape_markdown(text: &str)
-> String that escapes Markdown-sensitive characters (at minimum: \, `, *, _, {,
}, [, ], (, ), #, +, -, ., !) and converts newlines to spaces or escaped
newlines, then call this helper inside render_fragment for both the link label
and the plain text branch (i.e., replace uses of part.text.clone() with
escape_markdown(&part.text)); ensure the function is referenced from
render_fragment and named so it’s easy to find.

In `@src/output/terminal.rs`:
- Around line 33-37: render_fragment currently injects raw fragment.text into
OSC/ANSI sequences, enabling control-sequence injection; add a sanitizer and use
it before any terminal rendering. Implement a helper (e.g.,
sanitize_for_terminal) that removes or escapes terminal-control characters (ESC
0x1B, BEL, C0 controls, and any OSC/ST sequences) or percent-encodes unsafe
bytes, then call it on fragment.text inside render_fragment (both the Some(url)
branch and None branch) so only the sanitized string is embedded in format! and
returned.

---

Nitpick comments:
In `@src/domain/events.rs`:
- Around line 111-113: Remove the unused and misleading DeleteEvent::ref_path()
method from the DeleteEvent implementation; delete the entire fn ref_path(&self)
-> String { ... } for DeleteEvent and ensure no call sites rely on it (only
PushEvent::ref_path() and CreateEvent::ref_path() should remain); verify
presentation code renders deletions via delete.ref_name() so behavior is
unchanged and no other types expect a ref_path on DeleteEvent.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ee2f0f5c-f7e3-4bbf-8439-2db64a0ccd6b

📥 Commits

Reviewing files that changed from the base of the PR and between 477451b and 6a2bae8.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (16)
  • Cargo.toml
  • src/cli.rs
  • src/cmds/command.rs
  • src/cmds/run.rs
  • src/domain/events.rs
  • src/main.rs
  • src/output/assets/templates/editorial.html
  • src/output/assets/templates/notebook.html
  • src/output/assets/templates/terminal.html
  • src/output/assets/templates/zine.html
  • src/output/html.rs
  • src/output/markdown.rs
  • src/output/mod.rs
  • src/output/plain.rs
  • src/output/presentation.rs
  • src/output/terminal.rs

Comment thread src/cmds/run.rs
Comment thread src/output/markdown.rs
Comment thread src/output/terminal.rs
@dhth dhth merged commit fe582c6 into main May 25, 2026
8 checks passed
@dhth dhth deleted the add-support-for-multiple-output-formats branch May 25, 2026 08:44
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