Skip to content

Commit

Permalink
fix(lib): Support jekyll sorting by subproperties
Browse files Browse the repository at this point in the history
  • Loading branch information
epage committed Jun 6, 2024
1 parent 5e5925e commit 53580ed
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 8 deletions.
10 changes: 10 additions & 0 deletions crates/core/src/parser/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,16 @@ pub fn parse(text: &str, options: &Language) -> Result<Vec<Box<dyn Renderable>>>
Ok(renderables)
}

/// Given a `Variable` as a string, parses it into a `Variable`.
pub fn parse_variable(text: &str) -> Result<Variable> {
let variable = LiquidParser::parse(Rule::Variable, text)
.map_err(convert_pest_error)?
.next()
.expect("Parsing a variable failed.");

Ok(parse_variable_pair(variable))
}

/// Parses a `Scalar` from a `Pair` with a literal value.
/// This `Pair` must be `Rule::Literal`.
fn parse_literal(literal: Pair) -> Value {
Expand Down
24 changes: 17 additions & 7 deletions crates/lib/src/jekyll/array.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
use std::cmp;
use std::fmt::Write;

use liquid_core::model::try_find;
use liquid_core::model::KStringCow;
use liquid_core::model::ValueViewCmp;
use liquid_core::parser::parse_variable;
use liquid_core::Expression;
use liquid_core::Result;
use liquid_core::Runtime;
use liquid_core::ValueCow;
use liquid_core::{
Display_filter, Filter, FilterParameters, FilterReflection, FromFilterParameters, ParseFilter,
};
Expand Down Expand Up @@ -45,11 +49,17 @@ enum NilsOrder {
Last,
}

fn safe_property_getter<'a>(value: &'a Value, property: &str) -> &'a dyn ValueView {
value
.as_object()
.and_then(|obj| obj.get(property))
.unwrap_or(&Value::Nil)
fn safe_property_getter<'v>(
value: &'v Value,
property: &KStringCow,
runtime: &dyn Runtime,
) -> ValueCow<'v> {
let variable = parse_variable(property).expect("Failed to parse variable");
if let Some(path) = variable.try_evaluate(runtime) {
try_find(value, path.as_slice()).unwrap_or(ValueCow::Borrowed(&Value::Nil))
} else {
ValueCow::Borrowed(&Value::Nil)
}
}

fn nil_safe_compare(
Expand Down Expand Up @@ -114,8 +124,8 @@ impl Filter for SortFilter {
// Using unwrap is ok since all of the elements are objects
sorted.sort_by(|a, b| {
nil_safe_compare(
safe_property_getter(a, property),
safe_property_getter(b, property),
safe_property_getter(a, property, runtime).as_view(),
safe_property_getter(b, property, runtime).as_view(),
nils,
)
.unwrap_or(cmp::Ordering::Equal)
Expand Down
2 changes: 1 addition & 1 deletion crates/lib/tests/conformance_jekyll/test_filters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ mod sort_filter {
#[test]
fn return_sorted_by_subproperty_array() {
assert_eq!(
liquid_core::value!([{ "a": { "b": 2 } }, { "a": { "b": 1 } },
liquid_core::value!([{ "a": { "b": 1 } }, { "a": { "b": 2 } },
{ "a": { "b": 3 } },]),
liquid_core::call_filter!(
jekyll::Sort,
Expand Down

0 comments on commit 53580ed

Please sign in to comment.