Skip to content

Conversation

@ayuxsec
Copy link

@ayuxsec ayuxsec commented Dec 26, 2025

  • Introduce MarkDownOutput flag and CLI option (-markdown / -md).
  • Implement Result.MarkdownOutput to generate a formatted Markdown table with optional title and CDN columns, and a response body preview.
  • Add markdown escaping helper.
  • Update runner to create .md output file, handle markdown generation per result, and write to file or stdout.
  • Adjust option parsing and related logic to include markdown handling.

Preview:

Screenshot from 2025-12-26 17-42-23

Summary by CodeRabbit

  • New Features
    • Added Markdown output via --markdown (-md). Results can be exported as formatted Markdown tables to file and stdout.
    • Tables include a header (written once per stream) and per-result rows showing URL, status, method, IP, content length, words, lines, and optional Title/CDN.
    • Title values are safely escaped for Markdown display.

✏️ Tip: You can customize this high-level summary in your review settings.

- Introduce `MarkDownOutput` flag and CLI option (`-markdown` / `-md`).
- Implement `Result.MarkdownOutput` to generate a formatted Markdown table with optional title and CDN columns, and a response body preview.
- Add markdown escaping helper.
- Update runner to create `.md` output file, handle markdown generation per result, and write to file or stdout.
- Adjust option parsing and related logic to include markdown handling.
@auto-assign auto-assign bot requested a review from dogancanbakir December 26, 2025 12:13
@coderabbitai
Copy link

coderabbitai bot commented Dec 26, 2025

Walkthrough

Adds Markdown table output: new header/row renderers in runner/md_output.go, a --markdown flag and MarkDownOutput option in runner/options.go, and integration in runner/runner.go to create/write/close a .md file and emit per-response Markdown rows.

Changes

Cohort / File(s) Summary
Markdown rendering
\runner/md_output.go``
New exported MarkdownHeader(r Result) string, method func (r Result) MarkdownRow(scanopts *ScanOptions) string, and private escapeMarkdown(s string) string to build Markdown table header and rows; handles optional Title/CDN columns and escapes pipes/newlines.
CLI option
\runner/options.go``
Adds MarkDownOutput bool to Options and registers --markdown (short -md) flag to enable Markdown output.
Runner integration
\runner/runner.go``
When MarkDownOutput is enabled, opens Output+".md", writes header once (guarded), appends per-response MarkdownRow to file and optionally stdout, and closes the .md file on exit; integrates with existing JSON/CSV output logic.

Sequence Diagram(s)

sequenceDiagram
  %%{init: {"themeVariables": {"actorBorder":"#374151","actorBackground":"#F8FAFC","noteBackground":"#EEF2FF"}}}%%
  participant Runner
  participant MDFile as "MD File\n(filesystem)"
  participant Stdout
  participant Result as "Result → MarkdownRow"

  Runner->>MDFile: Open Output + ".md" (if MarkDownOutput)
  Note right of MDFile: file handle created\nmarkdownHeaderWritten=false
  Runner->>MDFile: Write MarkdownHeader (once)
  Runner->>Stdout: Optionally print header

  loop per response
    Runner->>Result: Build MarkdownRow(scanopts)
    Result-->>Runner: MarkdownRow string
    Runner->>MDFile: Append MarkdownRow
    Runner->>Stdout: Optionally print row
  end

  Runner->>MDFile: Close file (deferred on exit)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐇 I nibble pipes and tame each line,

Titles tidy, rows align in time.
I hop to disk — Output.md appears,
Quiet rows, and tiny cheers.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Add Markdown output support' accurately summarizes the main change—introducing Markdown table output functionality with new flags, rendering methods, and file handling throughout the codebase.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cabc1ae and b1f4809.

📒 Files selected for processing (1)
  • runner/runner.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • runner/runner.go

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

@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: 1

🧹 Nitpick comments (2)
runner/md_output.go (1)

61-67: Consider additional Markdown escaping for edge cases.

The current implementation escapes pipes and newlines, which covers the primary cases for table cell content. However, consider whether these additional characters should be escaped:

  • Backticks ` (could break inline code blocks if used in title)
  • Square brackets [ and ] (could create unintended links)

For the current use case (table cells), the existing escaping is likely sufficient, but be aware of potential edge cases.

runner/runner.go (1)

845-845: Consider renaming jsonOrCsv variable for clarity.

The variable now includes Markdown output but retains the name jsonOrCsv, which is misleading. Consider renaming to something like structuredOutput or jsonOrCsvOrMarkdown for better maintainability.

This is used on lines 847 and 1105 to control output behavior, so the rename would affect those locations as well.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7f9403e and f53b945.

📒 Files selected for processing (3)
  • runner/md_output.go
  • runner/options.go
  • runner/runner.go
🔇 Additional comments (5)
runner/options.go (2)

225-225: LGTM!

The MarkDownOutput field is properly positioned alongside other output format flags and follows existing conventions.


482-482: LGTM!

The CLI flag binding is properly configured and follows the same pattern as other output format flags.

runner/runner.go (3)

818-818: LGTM!

The mdFile variable declaration follows the existing pattern for other output file handles.


835-843: LGTM!

The markdown file opening logic correctly follows the pattern established for JSON and CSV outputs, including proper resume support and cleanup.


1241-1249: Markdown output integration is correctly implemented.

The markdown output logic properly integrates with the existing output flow and mirrors the JSON/CSV patterns. However, note the table structure issue flagged in runner/md_output.go: each result generates its own complete table rather than contributing rows to a unified table.

Unlike CSV (lines 889-897), which writes one header then rows for all results, the current markdown implementation writes a complete table (header + separator + row) per result. This is correctly implemented given the current design of MarkdownOutput(), but results in multiple separate tables in the output file.

Suggestion: If a unified table is desired (similar to CSV), consider writing a markdown table header once at the beginning (similar to CSV header on lines 889-897), then have MarkdownOutput() return only the data row without header/separator.

- Split Markdown generation into `MarkdownHeader` and `MarkdownRow` for clearer separation.
- Remove body‑preview block from Markdown rows.
- Add guard in runner to write the header only once per run.
Copy link

@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: 0

♻️ Duplicate comments (2)
runner/md_output.go (2)

9-31: Table structure still inconsistent: conditional columns break Markdown rendering.

The header conditionally includes Title and CDN columns based on a single Result instance's field values. This creates mismatched tables when different results have different fields populated.

Problem scenario:

  1. First result has Title="" → header generated with 7 columns (no Title column)
  2. Second result has Title="Hello" → row written with 8 cells (includes Title)
  3. Result: broken table with mismatched column counts

The split into MarkdownHeader/MarkdownRow (addressing the past review comment) solves the repeated-header issue but not the column consistency problem.

To ensure consistent table structure, always include Title and CDN columns regardless of whether individual results have those values populated. Write empty cells when values are blank.

🔎 Proposed fix to always include Title and CDN columns
 func MarkdownHeader(r Result) string {
 	var b strings.Builder
 
-	b.WriteString("| URL | Status | Method | IP | Size | Words | Lines |")
-	if r.Title != "" {
-		b.WriteString(" Title |")
-	}
-	if r.CDNName != "" {
-		b.WriteString(" CDN |")
-	}
+	b.WriteString("| URL | Status | Method | IP | Size | Words | Lines | Title | CDN |")
 	b.WriteString("\n")
 
-	b.WriteString("|---|---|---|---|---|---|---|")
-	if r.Title != "" {
-		b.WriteString("---|")
-	}
-	if r.CDNName != "" {
-		b.WriteString("---|")
-	}
+	b.WriteString("|---|---|---|---|---|---|---|---|---|")
 	b.WriteString("\n")
 
 	return b.String()
 }

Then update MarkdownRow to always write Title and CDN cells (see separate comment).


33-54: Critical: URL field not escaped; conditional cells break table structure.

Two issues in this function:

  1. The URL field (line 37) is not escaped, which will break the table if it contains pipe characters (e.g., https://example.com?param=value|other). This was flagged in the past review comment and remains unresolved.

  2. Conditional Title and CDN cells (lines 45-50) create mismatched column counts when different results have different field values. Must always write these cells (empty if blank) to match the header's column structure.

🔎 Proposed fix for URL escaping and consistent cells
 func (r Result) MarkdownRow(scanopts *ScanOptions) string {
 	var b strings.Builder
 
 	fmt.Fprintf(&b, "| %s | `%d %s` | `%s` | `%s` | %d | %d | %d |",
-		r.URL,
+		escapeMarkdown(r.URL),
 		r.StatusCode, http.StatusText(r.StatusCode),
 		r.Method,
 		r.HostIP,
 		r.ContentLength,
 		r.Words,
 		r.Lines)
 
-	if r.Title != "" {
+	if r.Title != "" {
 		fmt.Fprintf(&b, " %s |", escapeMarkdown(r.Title))
+	} else {
+		b.WriteString(" |")
 	}
-	if r.CDNName != "" {
+	if r.CDNName != "" {
 		fmt.Fprintf(&b, " `%s` |", r.CDNName)
+	} else {
+		b.WriteString(" |")
 	}
 	b.WriteString("\n")
 
 	return b.String()
 }
🧹 Nitpick comments (1)
runner/md_output.go (1)

33-33: Consider removing or documenting the unused scanopts parameter.

The scanopts parameter is declared but never used in the function body. If it's reserved for future functionality (e.g., conditionally formatting fields based on scan options), consider adding a comment explaining its purpose. Otherwise, remove it to keep the signature clean.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f53b945 and 1517710.

📒 Files selected for processing (2)
  • runner/md_output.go
  • runner/runner.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • runner/runner.go
🧰 Additional context used
🧬 Code graph analysis (1)
runner/md_output.go (1)
runner/types.go (1)
  • Result (35-105)
🔇 Additional comments (1)
runner/md_output.go (1)

56-62: LGTM: Basic escaping logic is sound.

The function correctly escapes pipe characters and replaces newlines, which are the primary concerns for Markdown table structure. The main issue is that it's not being applied to the URL field (covered in the previous comment).

…d` flag

* Consolidate output‑type checks into a single `jsonOrCsvOrMD` variable.
* Adjust file‑opening logic to add the “.md” suffix only when needed.
* Update related conditionals to respect the new combined flag handling.
* Ensure markdown output is correctly written without creating “.md.md” files.
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