Module: Dommy::Internal
- Defined in:
- lib/dommy/internal/idna.rb,
lib/dommy/internal/punycode.rb,
lib/dommy/internal/idna_data.rb,
lib/dommy/internal/cookie_jar.rb,
lib/dommy/internal/namespaces.rb,
lib/dommy/internal/url_parser.rb,
lib/dommy/internal/ipv4_parser.rb,
lib/dommy/internal/parent_node.rb,
lib/dommy/internal/dom_matching.rb,
lib/dommy/internal/node_equality.rb,
lib/dommy/internal/node_traversal.rb,
lib/dommy/internal/selector_parser.rb,
lib/dommy/internal/global_functions.rb,
lib/dommy/internal/observer_manager.rb,
lib/dommy/internal/observer_matcher.rb,
lib/dommy/internal/scope_resolution.rb,
lib/dommy/internal/node_wrapper_cache.rb,
lib/dommy/internal/css_pseudo_handlers.rb,
lib/dommy/internal/observable_callback.rb,
lib/dommy/internal/mutation_coordinator.rb,
lib/dommy/internal/reflected_attributes.rb,
lib/dommy/internal/shadow_root_registry.rb,
lib/dommy/internal/range_text_serializer.rb,
lib/dommy/internal/template_content_registry.rb
Defined Under Namespace
Modules: DomMatching, GlobalFunctions, IDNA, IDNAData, Ipv4Parser, Namespaces, NodeEquality, NodeTraversal, ObservableCallback, ParentNode, Punycode, ReflectedAttributes, ScopeResolution, SelectorParser, UrlParser Classes: CSSPseudoHandlers, CookieJar, MutationCoordinator, NodeWrapperCache, ObserverManager, ObserverMatcher, RangeTextSerializer, ScopedCSSPseudoHandlers, ShadowRootRegistry, TemplateContentRegistry
Constant Summary collapse
- CSS_PSEUDO_HANDLERS =
CSSPseudoHandlers.new
- KNOWN_PSEUDOS =
The complete set of CSS pseudo-classes (+ the four legacy single-colon pseudo-elements). A ‘:identifier` outside this set is an unknown selector token → SyntaxError, whereas a known-but-unimplemented one (`:hover`) is a valid selector that simply matches nothing.
%w[ active any-link autofill blank checked current default defined disabled empty enabled first first-child first-of-type focus focus-visible focus-within fullscreen future has host hover in-range indeterminate invalid is lang last-child last-of-type left link local-link modal not nth-child nth-col nth-last-child nth-last-col nth-last-of-type nth-of-type only-child only-of-type optional out-of-range past placeholder-shown playing paused read-only read-write required right root scope target target-within user-invalid user-valid valid visited where dir before after first-line first-letter ].to_set.freeze
- ATTR_ESCAPED_COLON =
Nokogiri’s CSS→XPath compiler chokes on an escaped colon INSIDE an attribute selector (‘[xlink:href]`, a namespaced/SVG attribute → “Invalid predicate”), though it handles escaped colons in class/id selectors fine (`.md:flex`, `#a:b` — Tailwind). Those attribute selectors target XML-namespaced attributes the HTML backend doesn’t model, so drop just the comma-clauses that use them; the rest of the selector list is preserved. (Real frameworks hit this constantly — Turbo’s click handler matches ‘a, a` on every click.) Returns a backend-safe selector; if every clause was unsupported, returns one that compiles but never matches.
/\[[^\]]*\\:[^\]]*\]/
Class Method Summary collapse
- .backend_safe_selector(selector) ⇒ Object
-
.css_query_arg!(args) ⇒ Object
Coerce the JS argument of a query method (querySelector/All) per WebIDL: the selector is a non-nullable DOMString, so JS ‘null` → “null” and `undefined` → “undefined” (which then match `<null>` / `<undefined>` typed elements rather than returning nothing), while a missing argument is a TypeError.
- .scoped_pseudo_handlers(scope_node) ⇒ Object
-
.split_selector_list(selector) ⇒ Object
Split a selector list on top-level commas only (commas inside […], (…), or quotes are part of a single complex selector and must not split it).
-
.validate_selector!(selector) ⇒ Object
Validate a non-null CSS selector for ‘querySelector`/`matches`/`closest`, raising SyntaxError for syntactically invalid selectors.
Class Method Details
.backend_safe_selector(selector) ⇒ Object
99 100 101 102 103 104 105 106 107 108 |
# File 'lib/dommy/internal/css_pseudo_handlers.rb', line 99 def self.backend_safe_selector(selector) # First drop clauses whose subject is a pseudo-element (`::before`, # `:first-line`) — they match no element, and the backend can't compile # `::`. Then drop the escaped-colon attribute clauses below. s = SelectorParser.matchable_selector(selector.to_s) return s unless s.include?('\\') && s.match?(ATTR_ESCAPED_COLON) kept = split_selector_list(s).reject { |clause| clause.match?(ATTR_ESCAPED_COLON) } kept.empty? ? ":not(*)" : kept.join(", ") end |
.css_query_arg!(args) ⇒ Object
Coerce the JS argument of a query method (querySelector/All) per WebIDL: the selector is a non-nullable DOMString, so JS ‘null` → “null” and `undefined` → “undefined” (which then match `<null>` / `<undefined>` typed elements rather than returning nothing), while a missing argument is a TypeError. Used at every JS dispatch site so the behaviour is uniform.
78 79 80 81 82 83 84 85 86 |
# File 'lib/dommy/internal/css_pseudo_handlers.rb', line 78 def self.css_query_arg!(args) raise ::Dommy::Bridge::TypeError, "1 argument required, but only 0 present" if args.empty? value = args[0] return "null" if value.nil? return "undefined" if defined?(::Dommy::Bridge::UNDEFINED) && value.equal?(::Dommy::Bridge::UNDEFINED) value end |
.scoped_pseudo_handlers(scope_node) ⇒ Object
43 44 45 |
# File 'lib/dommy/internal/css_pseudo_handlers.rb', line 43 def self.scoped_pseudo_handlers(scope_node) ScopedCSSPseudoHandlers.new(scope_node) end |
.split_selector_list(selector) ⇒ Object
Split a selector list on top-level commas only (commas inside […], (…), or quotes are part of a single complex selector and must not split it).
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
# File 'lib/dommy/internal/css_pseudo_handlers.rb', line 112 def self.split_selector_list(selector) clauses = [] depth = 0 quote = nil current = +"" selector.each_char do |ch| if quote quote = nil if ch == quote elsif ch == '"' || ch == "'" quote = ch elsif ch == "[" || ch == "(" depth += 1 elsif ch == "]" || ch == ")" depth -= 1 if depth.positive? elsif ch == "," && depth.zero? clauses << current.strip current = +"" next end current << ch end clauses << current.strip clauses.reject(&:empty?) end |
.validate_selector!(selector) ⇒ Object
Validate a non-null CSS selector for ‘querySelector`/`matches`/`closest`, raising SyntaxError for syntactically invalid selectors. Delegates to the full grammar parser (SelectorParser), which catches everything the old heuristic did (empty string, leading combinator, unknown pseudo-class) plus the rest of the Selectors grammar (`[*=v]`, `..x`, `div % p`, unknown pseudo-elements, undeclared namespaces, …) that Nokogiri silently accepts.
69 70 71 |
# File 'lib/dommy/internal/css_pseudo_handlers.rb', line 69 def self.validate_selector!(selector) SelectorParser.validate!(selector.to_s) end |