Skip to content

Commit

Permalink
implement and test string.split #95 (#96)
Browse files Browse the repository at this point in the history
Co-authored-by: David James <xpe@ixm.local>
  • Loading branch information
xpe and David James committed May 11, 2024
1 parent c887e17 commit 8d3258d
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 1 deletion.
47 changes: 47 additions & 0 deletions crates/compiler/src/builtin/functions/string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 aren’t 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> {
args.max_args(2)?;
let s1 = args
Expand Down
4 changes: 3 additions & 1 deletion crates/compiler/src/builtin/modules/string.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use crate::builtin::{
modules::Module,
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,
},
};

Expand All @@ -14,6 +15,7 @@ pub(crate) fn declare(f: &mut Module) {
f.insert_builtin("insert", str_insert);
f.insert_builtin("length", str_length);
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-upper-case", to_upper_case);
#[cfg(feature = "random")]
Expand Down
27 changes: 27 additions & 0 deletions crates/lib/tests/strings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -308,3 +308,30 @@ test!(
",
"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"
);

0 comments on commit 8d3258d

Please sign in to comment.