diff --git a/src/decoder.rs b/src/decoder.rs index 132f657..be652ce 100644 --- a/src/decoder.rs +++ b/src/decoder.rs @@ -12,8 +12,6 @@ use crate::jsontypes::RawSourceMap; use crate::types::{DecodedMap, RawToken, SourceMap, SourceMapIndex, SourceMapSection}; use crate::vlq::parse_vlq_segment_into; -const DATA_PREAMBLE: &str = "data:application/json;base64,"; - #[derive(PartialEq, Eq)] enum HeaderState { Undecided, @@ -339,12 +337,22 @@ pub fn decode_slice(slice: &[u8]) -> Result { decode_common(rsm) } -/// Loads a sourcemap from a data URL +/// Loads a sourcemap from a data URL. +/// +/// The URL should match the regex +/// `data:application/json;(charset=utf-?8;)?base64,(?.+)`. pub fn decode_data_url(url: &str) -> Result { - if !url.starts_with(DATA_PREAMBLE) { - return Err(Error::InvalidDataUrl); - } - let data_b64 = &url[DATA_PREAMBLE.len()..]; + let rest = url + .strip_prefix("data:application/json") + .ok_or(Error::InvalidDataUrl)?; + let rest = match rest.strip_prefix(";charset=") { + Some(rest) => rest + .strip_prefix("utf-8") + .or_else(|| rest.strip_prefix("utf8")) + .ok_or(Error::InvalidDataUrl)?, + None => rest, + }; + let data_b64 = rest.strip_prefix(";base64,").ok_or(Error::InvalidDataUrl)?; let data = data_encoding::BASE64 .decode(data_b64.as_bytes()) .map_err(|_| Error::InvalidDataUrl)?; diff --git a/tests/test_decoder.rs b/tests/test_decoder.rs index 9f89802..beaed42 100644 --- a/tests/test_decoder.rs +++ b/tests/test_decoder.rs @@ -116,11 +116,11 @@ fn test_basic_sourcemap_source_root_logic() { #[test] fn test_sourcemap_data_url() { - let url = "data:application/json;base64,\ + let base64 = "\ eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImNvb2xzdHVmZi5qcyJdLCJzb3VyY2VSb290I\ joieCIsIm5hbWVzIjpbIngiLCJhbGVydCJdLCJtYXBwaW5ncyI6IkFBQUEsR0FBSUEsR0\ FBSSxFQUNSLElBQUlBLEdBQUssRUFBRyxDQUNWQyxNQUFNIn0="; - match decode_data_url(url).unwrap() { + let test_url = |prefix: &str| match decode_data_url(&[prefix, base64].concat()).unwrap() { DecodedMap::Regular(sm) => { let mut iter = sm.tokens().filter(Token::has_name); assert_eq!( @@ -140,7 +140,10 @@ fn test_sourcemap_data_url() { _ => { panic!("did not get sourcemap"); } - } + }; + test_url("data:application/json;base64,"); + test_url("data:application/json;charset=utf-8;base64,"); + test_url("data:application/json;charset=utf8;base64,"); } #[test]