fn0-ski 0.1.8

Minimal Winter CG Compatible Runtime
use base64::prelude::*;

const SOURCE_MAP_MARKER: &[u8] = b"//# sourceMappingURL=";

pub fn extract_source_map(code: &[u8]) -> Option<Vec<u8>> {
    let range = last_non_blank_line_range(code)?;
    let base64_data = base64_payload(&code[range])?;
    BASE64_STANDARD.decode(base64_data).ok()
}

fn base64_payload(source_map_comment: &[u8]) -> Option<&[u8]> {
    let url = source_map_comment.strip_prefix(SOURCE_MAP_MARKER)?;
    let rest = strip_prefix_ignore_ascii_case(url, b"data:application/json")?;
    let rest = strip_prefix_ignore_ascii_case(rest, b";charset=utf-8").unwrap_or(rest);
    strip_prefix_ignore_ascii_case(rest, b";base64,")
}

fn strip_prefix_ignore_ascii_case<'a>(data: &'a [u8], prefix: &[u8]) -> Option<&'a [u8]> {
    let (head, tail) = data.split_at_checked(prefix.len())?;
    head.eq_ignore_ascii_case(prefix).then_some(tail)
}

fn last_non_blank_line_range(code: &[u8]) -> Option<std::ops::Range<usize>> {
    let mut hit_non_whitespace = false;
    let mut end = code.len();
    for i in (0..code.len()).rev() {
        let is_whitespace =
            code[i] == b' ' || code[i] == b'\t' || code[i] == b'\r' || code[i] == b'\n';
        if !hit_non_whitespace && is_whitespace {
            end = i;
        }
        hit_non_whitespace = hit_non_whitespace || !is_whitespace;
        if hit_non_whitespace && code[i] == b'\n' {
            return Some(i + 1..end);
        }
    }
    if hit_non_whitespace {
        return Some(0..end);
    }
    None
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_extract_source_map() {
        let code = b"console.log('hello');\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozfQ==";
        let result = extract_source_map(code);
        assert!(result.is_some());
        let decoded = result.unwrap();
        assert_eq!(decoded, b"{\"version\":3}");
    }

    #[test]
    fn test_with_charset() {
        let code = b"console.log('hello');\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozfQ==";
        let result = extract_source_map(code);
        assert_eq!(result.unwrap(), b"{\"version\":3}");
    }

    #[test]
    fn test_media_type_case_insensitive() {
        let code = b"console.log('hello');\n//# sourceMappingURL=data:Application/JSON;Charset=UTF-8;Base64,eyJ2ZXJzaW9uIjozfQ==";
        let result = extract_source_map(code);
        assert_eq!(result.unwrap(), b"{\"version\":3}");
    }

    #[test]
    fn test_no_source_map() {
        let code = b"console.log('hello');";
        let result = extract_source_map(code);
        assert!(result.is_none());
    }

    #[test]
    fn test_other_media_type() {
        let code =
            b"console.log('hello');\n//# sourceMappingURL=data:text/plain;base64,eyJ2ZXJzaW9uIjozfQ==";
        let result = extract_source_map(code);
        assert!(result.is_none());
    }

    #[test]
    fn test_with_trailing_newline() {
        let code = b"console.log('hello');\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozfQ==\n";
        let result = extract_source_map(code);
        assert!(result.is_some());
    }
}