From d3c3dbc98433da87589009296b2eb01d30e879e7 Mon Sep 17 00:00:00 2001 From: BoSuY0 Date: Tue, 12 May 2026 04:24:47 +0300 Subject: [PATCH] Ensure scrape output ends with newline Normalize non-empty scrape output before it is written to stdout or an --output file, so generated text content behaves like a regular POSIX text stream. Constraint: Preserve empty output as empty and avoid duplicating an existing trailing newline. Rejected: Per-path stdout/file special cases because a single normalization point covers both sinks. Confidence: High. Scope-risk: Low; affects only scrape command output formatting plus test imports. Directive: PlatformNetwork/bounty-challenge#53315. Tested: cargo test -p cortex-cli. Tested: Local smoke verified stdout and --output bytes end in 0a. Not-tested: Full workspace test suite. --- src/cortex-cli/src/agent_cmd/tests.rs | 5 ++--- src/cortex-cli/src/scrape_cmd/command.rs | 8 ++++++++ src/cortex-cli/src/scrape_cmd/tests.rs | 15 ++++++++++++++- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/cortex-cli/src/agent_cmd/tests.rs b/src/cortex-cli/src/agent_cmd/tests.rs index e2ff07f9f..18f7ba753 100644 --- a/src/cortex-cli/src/agent_cmd/tests.rs +++ b/src/cortex-cli/src/agent_cmd/tests.rs @@ -3,10 +3,9 @@ #[cfg(test)] mod tests { use crate::agent_cmd::cli::{CopyArgs, ExportArgs}; - use crate::agent_cmd::loader::{ - load_builtin_agents, parse_frontmatter, read_file_with_encoding, - }; + use crate::agent_cmd::loader::{load_builtin_agents, parse_frontmatter}; use crate::agent_cmd::types::AgentMode; + use crate::utils::file::read_file_with_encoding; #[test] fn test_read_file_with_utf8() { diff --git a/src/cortex-cli/src/scrape_cmd/command.rs b/src/cortex-cli/src/scrape_cmd/command.rs index 238724a2a..e518ac780 100644 --- a/src/cortex-cli/src/scrape_cmd/command.rs +++ b/src/cortex-cli/src/scrape_cmd/command.rs @@ -306,6 +306,7 @@ impl ScrapeCommand { // Parse and convert HTML self.process_html(&body, format)? }; + let output = ensure_trailing_newline(output); // Write output match &self.output { @@ -373,3 +374,10 @@ impl ScrapeCommand { Ok(output) } } + +pub(super) fn ensure_trailing_newline(mut output: String) -> String { + if !output.is_empty() && !output.ends_with('\n') { + output.push('\n'); + } + output +} diff --git a/src/cortex-cli/src/scrape_cmd/tests.rs b/src/cortex-cli/src/scrape_cmd/tests.rs index bd8b39509..7b0a8eb70 100644 --- a/src/cortex-cli/src/scrape_cmd/tests.rs +++ b/src/cortex-cli/src/scrape_cmd/tests.rs @@ -6,7 +6,7 @@ mod tests { use cortex_engine::create_client_builder; - use crate::scrape_cmd::command::ScrapeCommand; + use crate::scrape_cmd::command::{ScrapeCommand, ensure_trailing_newline}; use crate::scrape_cmd::html::{html_to_markdown, html_to_text, normalize_whitespace}; use crate::scrape_cmd::http::parse_headers; use crate::scrape_cmd::types::OutputFormat; @@ -145,6 +145,19 @@ mod tests { assert!("invalid".parse::().is_err()); } + #[test] + fn test_ensure_trailing_newline() { + assert_eq!( + ensure_trailing_newline("scraped content".to_string()), + "scraped content\n" + ); + assert_eq!( + ensure_trailing_newline("already terminated\n".to_string()), + "already terminated\n" + ); + assert_eq!(ensure_trailing_newline(String::new()), ""); + } + #[test] fn test_normalize_whitespace() { // normalize_whitespace collapses multiple whitespace into single space