use tree_sitter::Node;
pub fn truncate_to_256_bytes(raw: String) -> String {
if raw.len() <= 256 {
return raw;
}
let end = raw
.char_indices()
.take_while(|(i, c)| *i + c.len_utf8() <= 256)
.last()
.map(|(i, c)| i + c.len_utf8())
.unwrap_or(0);
raw[..end].to_string()
}
pub fn js_string_content(string_node: Node<'_>, source: &[u8]) -> Option<String> {
for i in 0..string_node.child_count() {
let Some(child) = string_node.child(i) else {
continue;
};
if child.kind() == "string_fragment" {
return child
.utf8_text(source)
.ok()
.map(|s| s.to_string())
.filter(|s| !s.is_empty());
}
}
let text = string_node.utf8_text(source).ok()?;
let t = text.trim();
if t.len() >= 2 {
let q = &t[..1];
if (q == "\"" || q == "'") && t.ends_with(q) {
let inner = &t[1..t.len() - 1];
if !inner.is_empty() {
return Some(inner.to_string());
}
}
}
None
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn truncate_ascii_over_256() {
let s = "a".repeat(300);
let result = truncate_to_256_bytes(s);
assert_eq!(result.len(), 256);
}
#[test]
fn truncate_respects_char_boundaries() {
let s: String = "é".repeat(128); assert_eq!(s.len(), 256);
let result = truncate_to_256_bytes(s.clone());
assert_eq!(result, s);
let s: String = "é".repeat(129); let result = truncate_to_256_bytes(s);
assert_eq!(result.len(), 256);
assert!(result.is_char_boundary(result.len()));
}
}