File: css.rb

package info (click to toggle)
ruby-nokogiri 1.18.2%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 8,076 kB
  • sloc: ansic: 38,893; xml: 27,665; ruby: 27,285; java: 15,348; cpp: 7,107; yacc: 244; sh: 208; makefile: 154; sed: 14
file content (132 lines) | stat: -rw-r--r-- 5,325 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# coding: utf-8
# frozen_string_literal: true

module Nokogiri
  # Translate a CSS selector into an XPath 1.0 query
  module CSS
    class << self
      # TODO: Deprecate this method ahead of 2.0 and delete it in 2.0.
      # It is not used by Nokogiri and shouldn't be part of the public API.
      def parse(selector) # :nodoc:
        warn("Nokogiri::CSS.parse is deprecated and will be removed in a future version of Nokogiri. Use Nokogiri::CSS::Parser#parse instead.", uplevel: 1, category: :deprecated)
        Parser.new.parse(selector)
      end

      # :call-seq:
      #   xpath_for(selector_list) → Array<String>
      #   xpath_for(selector_list [, prefix:] [, ns:] [, visitor:] [, cache:]) → Array<String>
      #
      # Translate a CSS selector list to the equivalent XPath expressions.
      #
      # 💡 Note that translated queries are cached by default for performance concerns.
      #
      # ⚠ Users should prefer Nokogiri::XML::Searchable#css, which is mixed into all document and
      # node classes, for querying documents with CSS selectors. This method is the underlying
      # mechanism used by XML::Searchable and is provided solely for advanced users to translate
      # \CSS selectors to XPath directly.
      #
      # Also see Nokogiri::XML::Searchable#css for documentation on supported CSS selector features,
      # some extended syntax that Nokogiri supports, and advanced CSS features like pseudo-class
      # functions.
      #
      # [Parameters]
      # - +selector_list+ (String)
      #
      #   The CSS selector to be translated into XPath. This is always a String, but that string
      #   value may be a {selector list}[https://www.w3.org/TR/selectors-4/#grouping] (see
      #   examples).
      #
      # [Keyword arguments]
      # - +prefix:+ (String)
      #
      #   The XPath expression prefix which determines the search context. See Nokogiri::XML::XPath
      #   for standard options. Default is +XPath::GLOBAL_SEARCH_PREFIX+.
      #
      # - +ns:+ (Hash<String ⇒ String>, nil)
      #
      #   Namespaces that are referenced in the query, if any. This is a hash where the keys are the
      #   namespace prefix and the values are the namespace URIs. Default is +nil+ indicating an
      #   empty set of namespaces.
      #
      # - +visitor:+ (Nokogiri::CSS::XPathVisitor)
      #
      #   Use this XPathVisitor object to transform the CSS AST into XPath expressions. See
      #   Nokogiri::CSS::XPathVisitor for more information on some of the complex behavior that can
      #   be customized for your document type. Default is +Nokogiri::CSS::XPathVisitor.new+.
      #
      #   ⚠ Note that this option is mutually exclusive with +prefix+ and +ns+. If +visitor+ is
      #   provided, +prefix+ and +ns+ must not be present.
      #
      # - +cache:+ (Boolean)
      #
      #   Whether to use the SelectorCache for the translated query to ensure that repeated queries
      #   don't incur the overhead of re-parsing the selector. Default is +true+.
      #
      # [Returns] (Array<String>) The equivalent set of XPath expressions for +selector_list+
      #
      # *Example* with a simple selector:
      #
      #   Nokogiri::CSS.xpath_for("div") # => ["//div"]
      #
      # *Example* with a compound selector:
      #
      #   Nokogiri::CSS.xpath_for("div.xl") # => ["//div[contains(concat(' ',normalize-space(@class),' '),' xl ')]"]
      #
      # *Example* with a complex selector:
      #
      #   Nokogiri::CSS.xpath_for("h1 + div") # => ["//h1/following-sibling::*[1]/self::div"]
      #
      # *Example* with a selector list:
      #
      #   Nokogiri::CSS.xpath_for("h1, h2, h3") # => ["//h1", "//h2", "//h3"]
      #
      def xpath_for(
        selector, options = nil,
        prefix: options&.delete(:prefix),
        visitor: options&.delete(:visitor),
        ns: options&.delete(:ns),
        cache: true
      )
        unless options.nil?
          warn("Nokogiri::CSS.xpath_for: Passing options as an explicit hash is deprecated. Use keyword arguments instead. This will become an error in a future release.", uplevel: 1, category: :deprecated)
        end

        raise(TypeError, "no implicit conversion of #{selector.inspect} to String") unless selector.respond_to?(:to_str)

        selector = selector.to_str
        raise(Nokogiri::CSS::SyntaxError, "empty CSS selector") if selector.empty?

        if visitor
          raise ArgumentError, "cannot provide both :prefix and :visitor" if prefix
          raise ArgumentError, "cannot provide both :ns and :visitor" if ns
        end

        visitor ||= begin
          visitor_kw = {}
          visitor_kw[:prefix] = prefix if prefix
          visitor_kw[:namespaces] = ns if ns

          Nokogiri::CSS::XPathVisitor.new(**visitor_kw)
        end

        if cache
          key = SelectorCache.key(selector: selector, visitor: visitor)
          SelectorCache[key] ||= Parser.new.xpath_for(selector, visitor)
        else
          Parser.new.xpath_for(selector, visitor)
        end
      end
    end
  end
end

require_relative "css/selector_cache"
require_relative "css/node"
require_relative "css/xpath_visitor"
x = $-w
$-w = false
require_relative "css/parser"
$-w = x

require_relative "css/tokenizer"
require_relative "css/syntax_error"