use forge::signal::compactor;
const MAX_JSON_LINES: usize = 80;
pub fn compress_jq(raw: &str) -> String {
let cleaned = compactor::normalise(raw);
let lines: Vec<&str> = cleaned.lines().collect();
if lines.len() <= MAX_JSON_LINES {
return cleaned;
}
let omitted = lines.len() - MAX_JSON_LINES;
format!(
"{}\n... [{} more lines — pipe through `jq -c` or add a filter to narrow output] ...",
lines[..MAX_JSON_LINES].join("\n"),
omitted
)
}
pub fn compress_json_compact(raw: &str) -> String {
let cleaned = compactor::normalise(raw);
let kept: Vec<&str> = cleaned
.lines()
.filter(|l| {
let t = l.trim();
!t.ends_with(": null,")
&& !t.ends_with(": null")
&& !t.ends_with(": \"\",")
&& !t.ends_with(": \"\"")
&& !t.ends_with(": [],")
&& !t.ends_with(": []")
&& !t.ends_with(": {},")
&& !t.ends_with(": {}")
})
.collect();
let result = kept.join("\n");
compress_jq(&result)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn jq_passthrough_small() {
let raw = "{\n \"foo\": 1\n}\n";
let out = compress_jq(raw);
assert!(out.contains("foo"), "{out}");
assert!(!out.contains("more lines"), "{out}");
}
#[test]
fn jq_truncates_large_output() {
let raw = (0..100)
.map(|i| format!(" \"key{i}\": \"value{i}\""))
.collect::<Vec<_>>()
.join("\n");
let out = compress_jq(&raw);
assert!(out.contains("more lines"), "{out}");
}
#[test]
fn json_compact_strips_nulls() {
let raw = "{\n \"id\": 1,\n \"name\": null,\n \"tags\": [],\n \"meta\": {}\n}\n";
let out = compress_json_compact(raw);
assert!(!out.contains("null"), "{out}");
assert!(!out.contains("\"tags\": []"), "{out}");
assert!(out.contains("\"id\": 1"), "{out}");
}
}