implement and test string.split #95 (#96)

Co-authored-by: David James <xpe@ixm.local>
This commit is contained in:
David James 2024-05-11 15:30:41 -04:00 committed by GitHub
parent c887e17e2e
commit 8d3258dcd4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 77 additions and 1 deletions

View File

@ -115,6 +115,53 @@ pub(crate) fn str_slice(mut args: ArgumentResult, visitor: &mut Visitor) -> Sass
} }
} }
/// https://sass-lang.com/documentation/modules/string/#split
///
/// Returns a bracketed, comma-separated list of substrings of $string
/// that are separated by $separator. The $separators arent included
/// in these substrings.
///
/// If $limit is a number 1 or higher, this splits on at most that many
/// $separators (and so returns at most $limit + 1 strings). The last
/// substring contains the rest of the string, including any remaining
/// $separators.
pub(crate) fn str_split(mut args: ArgumentResult, visitor: &mut Visitor) -> SassResult<Value> {
args.max_args(3)?;
let s1 = args
.get_err(0, "string")?
.assert_string_with_name("string", args.span())?
.0;
let separator = args
.get_err(1, "separator")?
.assert_string_with_name("separator", args.span())?
.0;
let limit = args.default_arg(2, "limit", Value::Null);
let vec = if matches!(limit, Value::Null) {
s1.split(&separator)
.map(|s| Value::String(s.to_string(), QuoteKind::Quoted))
.collect()
} else {
let limit = limit.assert_number_with_name("limit", args.span())?;
let limit_int = limit.assert_int_with_name("limit", args.span())?;
if limit_int < 1 {
return Err((
format!("$limit: Must be greater than 1, was {}.", limit_int),
args.span(),
)
.into());
}
// note: `1 + limit_int` is required to match dart-sass
s1.splitn(1 + limit_int as usize, &separator)
.map(|s| Value::String(s.to_string(), QuoteKind::Quoted))
.collect()
};
Ok(Value::List(vec, ListSeparator::Comma, Brackets::Bracketed))
}
pub(crate) fn str_index(mut args: ArgumentResult, visitor: &mut Visitor) -> SassResult<Value> { pub(crate) fn str_index(mut args: ArgumentResult, visitor: &mut Visitor) -> SassResult<Value> {
args.max_args(2)?; args.max_args(2)?;
let s1 = args let s1 = args

View File

@ -1,7 +1,8 @@
use crate::builtin::{ use crate::builtin::{
modules::Module, modules::Module,
string::{ string::{
quote, str_index, str_insert, str_length, str_slice, to_lower_case, to_upper_case, unquote, quote, str_index, str_insert, str_length, str_slice, str_split, to_lower_case,
to_upper_case, unquote,
}, },
}; };
@ -14,6 +15,7 @@ pub(crate) fn declare(f: &mut Module) {
f.insert_builtin("insert", str_insert); f.insert_builtin("insert", str_insert);
f.insert_builtin("length", str_length); f.insert_builtin("length", str_length);
f.insert_builtin("slice", str_slice); f.insert_builtin("slice", str_slice);
f.insert_builtin("split", str_split);
f.insert_builtin("to-lower-case", to_lower_case); f.insert_builtin("to-lower-case", to_lower_case);
f.insert_builtin("to-upper-case", to_upper_case); f.insert_builtin("to-upper-case", to_upper_case);
#[cfg(feature = "random")] #[cfg(feature = "random")]

View File

@ -308,3 +308,30 @@ test!(
", ",
"a {\n color: \"aaa\";\n}\n" "a {\n color: \"aaa\";\n}\n"
); );
test!(
str_split_abc_space,
"@use 'sass:string';
foo {
bar: string.split('a b c', ' ');
}
",
"foo {\n bar: [\"a\", \"b\", \"c\"];\n}\n"
);
test!(
str_split_abc_space_1,
"@use 'sass:string';
foo {
bar: string.split('a b c', ' ', 1);
}
",
"foo {\n bar: [\"a\", \"b c\"];\n}\n"
);
test!(
str_split_rgb_comma,
"@use 'sass:string';
foo {
bar: string.split('red,green,blue', ',');
}
",
"foo {\n bar: [\"red\", \"green\", \"blue\"];\n}\n"
);