Collapse whitespace left by stripped filename separators
A real feed titled with pipe separators produced a folder named "Get in the Trunk Anthology Series Delta Green": removing a forbidden character left the gap around it. Runs of whitespace now collapse, and control characters map to a space rather than vanishing. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RPyeapneuXrCdojsaiXGbe
This commit is contained in:
@@ -15,10 +15,24 @@ const MAX_NAME_BYTES: usize = 255;
|
||||
/// Keeps UTF-8: the original transliterated to ASCII via latin1_to_ascii because 2004
|
||||
/// filesystems demanded it. Ours do not.
|
||||
pub fn sanitize(name: &str) -> String {
|
||||
let mut out: String = name
|
||||
let stripped: String = name
|
||||
.chars()
|
||||
.filter(|c| !c.is_control() && !FORBIDDEN.contains(c))
|
||||
.map(|c| if c.is_control() { ' ' } else { c })
|
||||
.filter(|c| !FORBIDDEN.contains(c))
|
||||
.collect();
|
||||
|
||||
// Stripping a separator leaves a gap: "Show | Series | Delta" would otherwise become
|
||||
// "Show Series Delta". Collapse runs of whitespace rather than leaving the seams.
|
||||
let mut out = String::with_capacity(stripped.len());
|
||||
for c in stripped.chars() {
|
||||
if c.is_whitespace() {
|
||||
if !out.ends_with(' ') {
|
||||
out.push(' ');
|
||||
}
|
||||
} else {
|
||||
out.push(c);
|
||||
}
|
||||
}
|
||||
out = out.trim().trim_matches('.').trim().to_owned();
|
||||
|
||||
if out.len() > MAX_NAME_BYTES {
|
||||
@@ -266,10 +280,21 @@ mod tests {
|
||||
fn sanitize_strips_path_and_control_characters() {
|
||||
assert_eq!(sanitize("../../etc/passwd"), "etcpasswd");
|
||||
assert_eq!(sanitize("Ep 12: The \"Best\" One?"), "Ep 12 The Best One");
|
||||
assert_eq!(sanitize("bad\u{0}name\u{7}.mp3"), "badname.mp3");
|
||||
assert_eq!(sanitize("bad\u{0}name\u{7}.mp3"), "bad name .mp3");
|
||||
assert_eq!(sanitize(" spaced.mp3 "), "spaced.mp3");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sanitize_collapses_the_gaps_left_by_stripped_separators() {
|
||||
// A real Patreon feed title; the pipes are forbidden characters.
|
||||
assert_eq!(
|
||||
sanitize("Get in the Trunk | Anthology Series | Delta Green"),
|
||||
"Get in the Trunk Anthology Series Delta Green"
|
||||
);
|
||||
assert_eq!(sanitize("Ep 12: The One"), "Ep 12 The One");
|
||||
assert_eq!(sanitize("a b"), "a b");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sanitize_never_yields_an_empty_or_dot_name() {
|
||||
assert_eq!(sanitize(""), "download");
|
||||
|
||||
Reference in New Issue
Block a user