mirror of
https://github.com/storytold/figcraft.git
synced 2026-10-31 13:56:54 -06:00
#1408: match a Greek final sigma in node.find filters
Lowercasing a name ending in Σ gives ς, while a query Σ on its own lowercases to σ, so the substring check missed it (CodeRabbit). Both sides now fold ς to σ. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
57c1133a34
commit
9d7c435f6b
@@ -46,10 +46,16 @@ const LAYER_TYPES: [&str; 16] = [
|
||||
"SLICE",
|
||||
];
|
||||
|
||||
/// Lowercase for `node.find`'s substring filters. Greek final sigma becomes σ on both sides, so a
|
||||
/// query lowercased on its own (`Σ` to `σ`) still matches a name ending in it (`ΟΣ` to `ος`).
|
||||
fn fold(s: &str) -> String {
|
||||
s.to_lowercase().replace('ς', "σ")
|
||||
}
|
||||
|
||||
fn node_find(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
let cmd = "node.find";
|
||||
let filter = |key| -> Result<Option<String>> {
|
||||
get(p, key).map(|v| v.as_str().map(str::to_lowercase).ok_or_else(|| bad(cmd, format!("`{key}` must be a string")))).transpose()
|
||||
get(p, key).map(|v| v.as_str().map(fold).ok_or_else(|| bad(cmd, format!("`{key}` must be a string")))).transpose()
|
||||
};
|
||||
let name = filter("name")?;
|
||||
let text = filter("text")?;
|
||||
@@ -77,12 +83,12 @@ fn node_find(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
};
|
||||
let n = doc.get(id)?;
|
||||
stack.push(n.children.iter());
|
||||
if name.as_ref().is_some_and(|q| !n.name.to_lowercase().contains(q))
|
||||
if name.as_ref().is_some_and(|q| !fold(&n.name).contains(q))
|
||||
|| kind.as_ref().is_some_and(|q| !n.kind.type_name().eq_ignore_ascii_case(q))
|
||||
|| text.as_ref().is_some_and(|q| !matches!(&n.kind, NodeKind::Text(t) if t.characters.to_lowercase().contains(q)))
|
||||
|| component.as_ref().is_some_and(|q| {
|
||||
!matches!(&n.kind, NodeKind::Instance { component, .. } if doc.node(*component).is_some_and(|c| c.name.to_lowercase().contains(q)))
|
||||
})
|
||||
|| text.as_ref().is_some_and(|q| !matches!(&n.kind, NodeKind::Text(t) if fold(&t.characters).contains(q)))
|
||||
|| component.as_ref().is_some_and(
|
||||
|q| !matches!(&n.kind, NodeKind::Instance { component, .. } if doc.node(*component).is_some_and(|c| fold(&c.name).contains(q))),
|
||||
)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -35,6 +35,16 @@ fn node_find_filters_are_literal_case_insensitive_and_anded() {
|
||||
found(&mut s, json!({"name": ".*"}), &[]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn node_find_matches_a_greek_final_sigma_both_ways() {
|
||||
let mut s = Session::new();
|
||||
let page = s.page().unwrap();
|
||||
let os = add(&mut s, page, NodeKind::Text(TextData::new("ΛΟΓΟΣ")), "ΟΣ");
|
||||
found(&mut s, json!({"name": "Σ"}), &[os]);
|
||||
found(&mut s, json!({"name": "ς"}), &[os]);
|
||||
found(&mut s, json!({"text": "λογοσ"}), &[os]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn node_find_scope_is_preorder_strict_descendants_in_stored_order() {
|
||||
let mut s = Session::new();
|
||||
|
||||
Reference in New Issue
Block a user