-module(lustre@dev@query). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). -define(FILEPATH, "src/lustre/dev/query.gleam"). -export([element/1, child/2, descendant/2, 'and'/2, tag/1, namespaced/2, attribute/2, class/1, style/2, id/1, data/2, test_id/1, aria/2, text/1, matches/2, to_readable_string/1, find_all/2, find_path/4, find/2, has/2]). -export_type(['query'/0, selector/0]). -if(?OTP_RELEASE >= 27). -define(MODULEDOC(Str), -moduledoc(Str)). -define(DOC(Str), -doc(Str)). -else. -define(MODULEDOC(Str), -compile([])). -define(DOC(Str), -compile([])). -endif. -opaque 'query'() :: {find_element, selector()} | {find_child, 'query'(), selector()} | {find_descendant, 'query'(), selector()}. -opaque selector() :: {all, list(selector())} | {type, binary(), binary()} | {has_attribute, binary(), binary()} | {has_class, binary()} | {has_style, binary(), binary()} | {contains, binary()}. -file("src/lustre/dev/query.gleam", 41). ?DOC(" Find any elements in a view that match the given [`Selector`](#Selector).\n"). -spec element(selector()) -> 'query'(). element(Selector) -> {find_element, Selector}. -file("src/lustre/dev/query.gleam", 49). ?DOC( " Given a `Query` that finds an element, find any of that element's _direct_\n" " children that match the given [`Selector`](#Selector). This is similar to the\n" " CSS `>` combinator.\n" ). -spec child('query'(), selector()) -> 'query'(). child(Parent, Selector) -> {find_child, Parent, Selector}. -file("src/lustre/dev/query.gleam", 57). ?DOC( " Given a `Query` that finds an element, find any of that element's _descendants_\n" " that match the given [`Selector`](#Selector). This will walk the entire tree\n" " from the matching parent.\n" ). -spec descendant('query'(), selector()) -> 'query'(). descendant(Parent, Selector) -> {find_descendant, Parent, Selector}. -file("src/lustre/dev/query.gleam", 95). ?DOC( " Combine two selectors into one that must match both. For example, if you have\n" " a selector for div elements and a selector for elements with the class \"wibble\"\n" " then they can be combined into a selector that matches only div elements with\n" " the class \"wibble\".\n" "\n" " ```gleam\n" " import lustre/dev/query\n" "\n" " pub fn example() {\n" " let div = query.tag(\"div\")\n" " let wibble = query.class(\"wibble\")\n" "\n" " query.element(matching: div |> query.and(wibble))\n" " }\n" " ```\n" "\n" " You can chain multiple `and` calls together to combine many selectors into\n" " something more specific.\n" "\n" " ```gleam\n" " import lustre/dev/query\n" "\n" " pub fn example() {\n" " query.tag(\"div\")\n" " |> query.and(query.class(\"wibble\"))\n" " |> query.and(query.data(\"open\", \"true\"))\n" " }\n" " ```\n" "\n" " > **Note**: if you find yourself crafting complex selectors, consider using\n" " > a test id on the element(s) you want to find instead.\n" ). -spec 'and'(selector(), selector()) -> selector(). 'and'(First, Second) -> case First of {all, []} -> {all, [Second]}; {all, Others} -> {all, [Second | Others]}; _ -> {all, [First, Second]} end. -file("src/lustre/dev/query.gleam", 107). ?DOC( " Select elements based on their tag name, like `\"div\"`, `\"span\"`, or `\"a\"`.\n" " To select elements with an XML namespace - such as SVG elements - use the\n" " [`namespaced`](#namespaced) selector instead.\n" ). -spec tag(binary()) -> selector(). tag(Value) -> {type, <<""/utf8>>, Value}. -file("src/lustre/dev/query.gleam", 125). ?DOC( " Select elements based on their tag name and XML namespace. This is useful\n" " for selecting SVG elements or other XML elements that have a namespace.\n" " For example, to select an SVG circle element, you would use:\n" "\n" " ```gleam\n" " import lustre/dev/query\n" "\n" " pub fn example() {\n" " let svg = \"http://www.w3.org/2000/svg\"\n" "\n" " query.element(matching: query.namespaced(svg, \"circle\"))\n" " }\n" " ```\n" ). -spec namespaced(binary(), binary()) -> selector(). namespaced(Namespace, Tag) -> {type, Namespace, Tag}. -file("src/lustre/dev/query.gleam", 154). ?DOC( " Select elements that have the specified attribute with the given value. If\n" " the value is left blank, this selector will match any element that has the\n" " attribute, _regardless of its value_.\n" "\n" " For example, to select a form input with the name \"username\", you would\n" " use:\n" "\n" " ```gleam\n" " import lustre/dev/query\n" "\n" " pub fn example() {\n" " query.element(matching: query.attribute(\"name\", \"username\"))\n" " }\n" " ```\n" "\n" " Or to select elements with the `disabled` attribute:\n" "\n" " ```gleam\n" " import lustre/dev/query\n" "\n" " pub fn example() {\n" " query.element(matching: query.attribute(\"disabled\", \"\"))\n" " }\n" " ```\n" ). -spec attribute(binary(), binary()) -> selector(). attribute(Name, Value) -> {has_attribute, Name, Value}. -file("src/lustre/dev/query.gleam", 169). ?DOC( " Select elements that include the given space-separated class name(s). For\n" " example given the element `
Hello, Joe!
\n" " ```\n" "\n" " The selector `query.text(\"Hello, Joe!\")` would match the `` element because\n"
" the text content of the inline `` element is included in the paragraph's\n"
" text content.\n"
"\n"
" Whitespace must match exactly, so the selector `query.text(\"Hello, Joe!\")`\n"
" would not match an element like:\n"
"\n"
" ```gleam\n"
" html.p([], [html.text(\"Hello, Joe!\")])\n"
" ```\n"
"\n"
" > **Note**: while this selector makes a best-effort attempt to include the\n"
" > text content of inline children, this cannot account for block elements that\n"
" > are styled as inline by CSS stylesheets.\n"
"\n"
" > **Note**: often it is better to use more precise selectors such as\n"
" > [`id`](#id), [`class`](#class), or [`test_id`](#test_id). You should reach\n"
" > for this selector only when you want to assert that an element contains\n"
" > some specific text, such as in a hero banner or a copyright notice.\n"
).
-spec text(binary()) -> selector().
text(Content) ->
{contains, Content}.
-file("src/lustre/dev/query.gleam", 610).
-spec text_content(lustre@vdom@vnode:element(any()), boolean(), binary()) -> binary().
text_content(Element, Inline, Content) ->
case Element of
{fragment, _, _, _, _, _} ->
gleam@list:fold(
erlang:element(5, Element),
Content,
fun(Content@1, Child) ->
text_content(Child, true, Content@1)
end
);
{element, _, _, _, _, _, _, _, _, _, _} when not Inline orelse (erlang:element(
5,
Element
) =/= <<""/utf8>>) ->
gleam@list:fold(
erlang:element(8, Element),
Content,
fun(Content@2, Child@1) ->
text_content(Child@1, true, Content@2)
end
);
{element, _, _, _, _, <<"a"/utf8>>, _, _, _, _, _} ->
gleam@list:fold(
erlang:element(8, Element),
Content,
fun(Content@3, Child@2) ->
text_content(Child@2, true, Content@3)
end
);
{element, _, _, _, _, <<"abbr"/utf8>>, _, _, _, _, _} ->
gleam@list:fold(
erlang:element(8, Element),
Content,
fun(Content@3, Child@2) ->
text_content(Child@2, true, Content@3)
end
);
{element, _, _, _, _, <<"acronym"/utf8>>, _, _, _, _, _} ->
gleam@list:fold(
erlang:element(8, Element),
Content,
fun(Content@3, Child@2) ->
text_content(Child@2, true, Content@3)
end
);
{element, _, _, _, _, <<"b"/utf8>>, _, _, _, _, _} ->
gleam@list:fold(
erlang:element(8, Element),
Content,
fun(Content@3, Child@2) ->
text_content(Child@2, true, Content@3)
end
);
{element, _, _, _, _, <<"bdo"/utf8>>, _, _, _, _, _} ->
gleam@list:fold(
erlang:element(8, Element),
Content,
fun(Content@3, Child@2) ->
text_content(Child@2, true, Content@3)
end
);
{element, _, _, _, _, <<"big"/utf8>>, _, _, _, _, _} ->
gleam@list:fold(
erlang:element(8, Element),
Content,
fun(Content@3, Child@2) ->
text_content(Child@2, true, Content@3)
end
);
{element, _, _, _, _, <<"br"/utf8>>, _, _, _, _, _} ->
gleam@list:fold(
erlang:element(8, Element),
Content,
fun(Content@3, Child@2) ->
text_content(Child@2, true, Content@3)
end
);
{element, _, _, _, _, <<"button"/utf8>>, _, _, _, _, _} ->
gleam@list:fold(
erlang:element(8, Element),
Content,
fun(Content@3, Child@2) ->
text_content(Child@2, true, Content@3)
end
);
{element, _, _, _, _, <<"cite"/utf8>>, _, _, _, _, _} ->
gleam@list:fold(
erlang:element(8, Element),
Content,
fun(Content@3, Child@2) ->
text_content(Child@2, true, Content@3)
end
);
{element, _, _, _, _, <<"code"/utf8>>, _, _, _, _, _} ->
gleam@list:fold(
erlang:element(8, Element),
Content,
fun(Content@3, Child@2) ->
text_content(Child@2, true, Content@3)
end
);
{element, _, _, _, _, <<"dfn"/utf8>>, _, _, _, _, _} ->
gleam@list:fold(
erlang:element(8, Element),
Content,
fun(Content@3, Child@2) ->
text_content(Child@2, true, Content@3)
end
);
{element, _, _, _, _, <<"em"/utf8>>, _, _, _, _, _} ->
gleam@list:fold(
erlang:element(8, Element),
Content,
fun(Content@3, Child@2) ->
text_content(Child@2, true, Content@3)
end
);
{element, _, _, _, _, <<"i"/utf8>>, _, _, _, _, _} ->
gleam@list:fold(
erlang:element(8, Element),
Content,
fun(Content@3, Child@2) ->
text_content(Child@2, true, Content@3)
end
);
{element, _, _, _, _, <<"img"/utf8>>, _, _, _, _, _} ->
gleam@list:fold(
erlang:element(8, Element),
Content,
fun(Content@3, Child@2) ->
text_content(Child@2, true, Content@3)
end
);
{element, _, _, _, _, <<"input"/utf8>>, _, _, _, _, _} ->
gleam@list:fold(
erlang:element(8, Element),
Content,
fun(Content@3, Child@2) ->
text_content(Child@2, true, Content@3)
end
);
{element, _, _, _, _, <<"kbd"/utf8>>, _, _, _, _, _} ->
gleam@list:fold(
erlang:element(8, Element),
Content,
fun(Content@3, Child@2) ->
text_content(Child@2, true, Content@3)
end
);
{element, _, _, _, _, <<"label"/utf8>>, _, _, _, _, _} ->
gleam@list:fold(
erlang:element(8, Element),
Content,
fun(Content@3, Child@2) ->
text_content(Child@2, true, Content@3)
end
);
{element, _, _, _, _, <<"map"/utf8>>, _, _, _, _, _} ->
gleam@list:fold(
erlang:element(8, Element),
Content,
fun(Content@3, Child@2) ->
text_content(Child@2, true, Content@3)
end
);
{element, _, _, _, _, <<"object"/utf8>>, _, _, _, _, _} ->
gleam@list:fold(
erlang:element(8, Element),
Content,
fun(Content@3, Child@2) ->
text_content(Child@2, true, Content@3)
end
);
{element, _, _, _, _, <<"output"/utf8>>, _, _, _, _, _} ->
gleam@list:fold(
erlang:element(8, Element),
Content,
fun(Content@3, Child@2) ->
text_content(Child@2, true, Content@3)
end
);
{element, _, _, _, _, <<"q"/utf8>>, _, _, _, _, _} ->
gleam@list:fold(
erlang:element(8, Element),
Content,
fun(Content@3, Child@2) ->
text_content(Child@2, true, Content@3)
end
);
{element, _, _, _, _, <<"samp"/utf8>>, _, _, _, _, _} ->
gleam@list:fold(
erlang:element(8, Element),
Content,
fun(Content@3, Child@2) ->
text_content(Child@2, true, Content@3)
end
);
{element, _, _, _, _, <<"script"/utf8>>, _, _, _, _, _} ->
gleam@list:fold(
erlang:element(8, Element),
Content,
fun(Content@3, Child@2) ->
text_content(Child@2, true, Content@3)
end
);
{element, _, _, _, _, <<"select"/utf8>>, _, _, _, _, _} ->
gleam@list:fold(
erlang:element(8, Element),
Content,
fun(Content@3, Child@2) ->
text_content(Child@2, true, Content@3)
end
);
{element, _, _, _, _, <<"small"/utf8>>, _, _, _, _, _} ->
gleam@list:fold(
erlang:element(8, Element),
Content,
fun(Content@3, Child@2) ->
text_content(Child@2, true, Content@3)
end
);
{element, _, _, _, _, <<"span"/utf8>>, _, _, _, _, _} ->
gleam@list:fold(
erlang:element(8, Element),
Content,
fun(Content@3, Child@2) ->
text_content(Child@2, true, Content@3)
end
);
{element, _, _, _, _, <<"strong"/utf8>>, _, _, _, _, _} ->
gleam@list:fold(
erlang:element(8, Element),
Content,
fun(Content@3, Child@2) ->
text_content(Child@2, true, Content@3)
end
);
{element, _, _, _, _, <<"sub"/utf8>>, _, _, _, _, _} ->
gleam@list:fold(
erlang:element(8, Element),
Content,
fun(Content@3, Child@2) ->
text_content(Child@2, true, Content@3)
end
);
{element, _, _, _, _, <<"sup"/utf8>>, _, _, _, _, _} ->
gleam@list:fold(
erlang:element(8, Element),
Content,
fun(Content@3, Child@2) ->
text_content(Child@2, true, Content@3)
end
);
{element, _, _, _, _, <<"textarea"/utf8>>, _, _, _, _, _} ->
gleam@list:fold(
erlang:element(8, Element),
Content,
fun(Content@3, Child@2) ->
text_content(Child@2, true, Content@3)
end
);
{element, _, _, _, _, <<"time"/utf8>>, _, _, _, _, _} ->
gleam@list:fold(
erlang:element(8, Element),
Content,
fun(Content@3, Child@2) ->
text_content(Child@2, true, Content@3)
end
);
{element, _, _, _, _, <<"tt"/utf8>>, _, _, _, _, _} ->
gleam@list:fold(
erlang:element(8, Element),
Content,
fun(Content@3, Child@2) ->
text_content(Child@2, true, Content@3)
end
);
{element, _, _, _, _, <<"var"/utf8>>, _, _, _, _, _} ->
gleam@list:fold(
erlang:element(8, Element),
Content,
fun(Content@3, Child@2) ->
text_content(Child@2, true, Content@3)
end
);
{element, _, _, _, _, _, _, _, _, _, _} ->
Rule = <<"display:inline"/utf8>>,
Is_inline = gleam@list:any(
erlang:element(7, Element),
fun(Attribute) -> case Attribute of
{attribute, _, <<"style"/utf8>>, Value} ->
gleam_stdlib:contains_string(Value, Rule);
_ ->
false
end end
),
case Is_inline of
true ->
gleam@list:fold(
erlang:element(8, Element),
Content,
fun(Content@4, Child@3) ->
text_content(Child@3, true, Content@4)
end
);
false ->
Content
end;
{text, _, _, _, _} ->
<