Skip to content

Commit

Permalink
Add :has selector
Browse files Browse the repository at this point in the history
  • Loading branch information
jbhoot committed Apr 17, 2024
1 parent 277e9d9 commit bc8d3d0
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 2 deletions.
6 changes: 6 additions & 0 deletions src/soup.ml
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,7 @@ struct
| OnlyOfType
| Empty
| Content of string
| Has of simple_selector
| Not of simple_selector

and simple_selector =
Expand Down Expand Up @@ -595,6 +596,8 @@ struct
| OnlyOfType -> element_count_with_name (name node) node = 1
| Empty -> no_children node
| Content s -> texts node |> String.concat "" |> has_substring s
| Has selector ->
let matching_nodes = filter (fun n -> matches_simple_selector n selector) (descendants node) in count matching_nodes > 0
| Not selector -> not (matches_simple_selector node selector)

and matches_simple_selector node = function
Expand Down Expand Up @@ -921,6 +924,9 @@ struct
let s = parse_parenthesized_value parse_quoted_string stream in
Content s
| "empty" -> Empty
| "has" ->
let selector = parse_parenthesized_value parse_simple_selector stream in
Has selector
| "not" ->
let selector = parse_parenthesized_value parse_simple_selector stream in
Not selector
Expand Down
16 changes: 14 additions & 2 deletions test/performance/performance.ml
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,20 @@ let () =

let selector = "form[action*=search]" in
assert (soup $ selector |> name = "form");
measure 1000 "select" (fun () -> soup $ selector |> ignore);
measure 1000 ("select " ^ selector) (fun () -> soup $ selector |> ignore);

let selector = ":has([id=mngb])" in
assert (soup $$ selector |> count = 2);
measure 1000 ("select_all " ^ selector) (fun () -> soup $$ selector |> count |> ignore);

let selector = ":has([action*=search])" in
assert (soup $$ selector |> count = 3);
measure 1000 ("select_all " ^ selector) (fun () -> soup $$ selector |> count |> ignore);

let selector = ":has([name=gbv])" in
assert (soup $$ selector |> count = 4);
measure 1000 ("select_all " ^ selector) (fun () -> soup $$ selector |> count |> ignore);

let selector = "*" in
assert (soup $$ selector |> count > 10);
measure 1000 "select_all" (fun () -> soup $$ selector |> count |> ignore)
measure 1000 ("select_all " ^ selector) (fun () -> soup $$ selector |> count |> ignore)

0 comments on commit bc8d3d0

Please sign in to comment.