node_query 1.3.0 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8c7363cd71167f293f046d95014611ceb1f695c6639036a3cc0e202ab0ae5b2b
4
- data.tar.gz: 161c5784daae011699a1300b0cedc2f18bdc7235f71b7e89e1b1dce41caef71a
3
+ metadata.gz: 526c6ef0b0f58f1a8f1f7aff14e147ce4220cd6366bea5d5108db29591e0ab02
4
+ data.tar.gz: 347fc60e4f3629871356757349c5a126235a192049eefa713fb15890d26033d0
5
5
  SHA512:
6
- metadata.gz: 356e94651bf61cb5c244399bbfe0aa353aafe3a3506fc7e6b1efba9cc4c853a0b963850c9d64e9b9de26dd3986f10967b2752a3dc7ec627dfd7466ddcf9a70f8
7
- data.tar.gz: 0fdacf2a86292f60968a02054ce43e02a131d3a1da7c528d1e6df2e8279afd5de19afe714a80bd1b9ab17143c433b4e219c7be2cf8b55e3f28e45ff82a25d274
6
+ metadata.gz: b94b5f913b63824d89211dc6156add8ada6963a0122cf5d6adafc60fcf20af62a4f9a239f2bd341ef12167adcf8a5785b96b9c1b6bbad41d2ebe3f0eb90b498f
7
+ data.tar.gz: 2a9613221d35553af7e91e1e2a20792dbee63572634e254633cb0951180adb48b582454dee93f6c817d870ec16962af346bb1ce4ea253b253da10cb7e78ada49
data/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 1.5.0 (2022-09-15)
4
+
5
+ * Add `Helper.to_string`
6
+ * Only check the current node if `including_self` is true and `recursive` is false
7
+ * Fix `Regexp#match?` and `String#match?`
8
+ * Rename `stop_on_match` to `stop_at_first_match`
9
+
10
+ ## 1.4.0 (2022-09-14)
11
+
12
+ * Add options `including_self`, `stop_on_match` and `recursive`
13
+ * Fix regex to match evaluated value
14
+
3
15
  ## 1.3.0 (2022-09-13)
4
16
 
5
17
  * Rename `NodeQuery#parse` to `NodeQuery#query_nodes`
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- node_query (1.3.0)
4
+ node_query (1.5.0)
5
5
  activesupport (< 7.0.0)
6
6
 
7
7
  GEM
data/README.md CHANGED
@@ -62,7 +62,7 @@ It provides two apis: `query_nodes` and `match_node?`
62
62
 
63
63
  ```ruby
64
64
  node_query = NodeQuery.new(nqlOrRules: String | Hash) # Initialize NodeQuery
65
- node_query.query_nodes(node: Node, including_self = true): Node[] # Get the matching nodes.
65
+ node_query.query_nodes(node: Node, options = { including_self: true, stop_at_first_match: false, recursive: true }): Node[] # Get the matching nodes.
66
66
  node_query.match_node?(node: Node): boolean # Check if the node matches nql or rules.
67
67
  ```
68
68
 
@@ -13,14 +13,17 @@ module NodeQuery::Compiler
13
13
 
14
14
  # Query nodes by the selector and the rest expression.
15
15
  # @param node [Node] node to match
16
- # @params including_self [boolean] if query the current node.
16
+ # @param options [Hash] if query the current node
17
+ # @option options [boolean] :including_self if query the current node, default is ture
18
+ # @option options [boolean] :stop_at_first_match if stop at first match, default is false
19
+ # @option options [boolean] :recursive if recursively query child nodes, default is true
17
20
  # @return [Array<Node>] matching nodes.
18
- def query_nodes(node, including_self = true)
19
- matching_nodes = @selector.query_nodes(node, including_self)
21
+ def query_nodes(node, options = {})
22
+ matching_nodes = @selector.query_nodes(node, options)
20
23
  return matching_nodes if @rest.nil?
21
24
 
22
25
  matching_nodes.flat_map do |matching_node|
23
- @rest.query_nodes(matching_node, including_self)
26
+ @rest.query_nodes(matching_node, options)
24
27
  end
25
28
  end
26
29
 
@@ -13,13 +13,16 @@ module NodeQuery::Compiler
13
13
 
14
14
  # Query nodes by the current and the rest expression.
15
15
  # @param node [Node] node to match
16
- # @params including_self [boolean] if query the current node.
16
+ # @param options [Hash] if query the current node
17
+ # @option options [boolean] :including_self if query the current node, default is ture
18
+ # @option options [boolean] :stop_at_first_match if stop at first match, default is false
19
+ # @option options [boolean] :recursive if recursively query child nodes, default is true
17
20
  # @return [Array<Node>] matching nodes.
18
- def query_nodes(node, including_self = true)
19
- matching_nodes = @expression.query_nodes(node, including_self)
21
+ def query_nodes(node, options = {})
22
+ matching_nodes = @expression.query_nodes(node, options)
20
23
  return matching_nodes if @rest.nil?
21
24
 
22
- matching_nodes + @rest.query_nodes(node, including_self)
25
+ matching_nodes + @rest.query_nodes(node, options)
23
26
  end
24
27
 
25
28
  # Check if the node matches the expression list.
@@ -13,13 +13,16 @@ module NodeQuery::Compiler
13
13
 
14
14
  # Check if the regexp value matches the node value.
15
15
  # @param node [Node] the node
16
- # @return [Boolean] true if the regexp value matches the node value.
17
- def is_equal?(node)
18
- if NodeQuery.adapter.is_node?(node)
19
- @value.match(NodeQuery.adapter.get_source(node))
20
- else
21
- @value.match(node.to_s)
22
- end
16
+ # @param operator [String] the operator
17
+ # @return [Boolean] true if the regexp value matches the node value, otherwise, false.
18
+ def match?(node, operator = '=~')
19
+ match =
20
+ if NodeQuery.adapter.is_node?(node)
21
+ @value.match(NodeQuery.adapter.get_source(node))
22
+ else
23
+ @value.match(node.to_s)
24
+ end
25
+ operator == '=~' ? match : !match
23
26
  end
24
27
 
25
28
  # Get valid operators.
@@ -33,9 +33,13 @@ module NodeQuery::Compiler
33
33
  # * If relationship is next sibling, it try to match next sibling node.
34
34
  # * If relationship is subsequent sibling, it will match in all sibling nodes.
35
35
  # @param node [Node] node to match
36
- # @params including_self [boolean] if query the current node.
36
+ # @param options [Hash] if query the current node
37
+ # @option options [boolean] :including_self if query the current node, default is ture
38
+ # @option options [boolean] :stop_at_first_match if stop at first match, default is false
39
+ # @option options [boolean] :recursive if recursively query child nodes, default is true
37
40
  # @return [Array<Node>] matching nodes.
38
- def query_nodes(node, including_self = true)
41
+ def query_nodes(node, options = {})
42
+ options = { including_self: true, stop_at_first_match: false, recursive: true }.merge(options)
39
43
  return find_nodes_by_relationship(node) if @relationship
40
44
 
41
45
  if node.is_a?(::Array)
@@ -44,13 +48,30 @@ module NodeQuery::Compiler
44
48
 
45
49
  return find_nodes_by_goto_scope(node) if @goto_scope
46
50
 
51
+ if options[:including_self] && !options[:recursive]
52
+ return match?(node) ? [node] : []
53
+ end
54
+
47
55
  nodes = []
48
- if including_self && match?(node)
56
+ if options[:including_self] && match?(node)
49
57
  nodes << node
58
+ return nodes if options[:stop_at_first_match]
50
59
  end
51
60
  if @basic_selector
52
- NodeQuery::Helper.handle_recursive_child(node) do |child_node|
53
- nodes << child_node if match?(child_node)
61
+ if options[:recursive]
62
+ NodeQuery::Helper.handle_recursive_child(node) do |child_node|
63
+ if match?(child_node)
64
+ nodes << child_node
65
+ break if options[:stop_at_first_match]
66
+ end
67
+ end
68
+ else
69
+ NodeQuery.adapter.get_children(node).each do |child_node|
70
+ if match?(child_node)
71
+ nodes << child_node
72
+ break if options[:stop_at_first_match]
73
+ end
74
+ end
54
75
  end
55
76
  end
56
77
  nodes
@@ -27,7 +27,7 @@ module NodeQuery::Compiler
27
27
  # @param node [Node] the node
28
28
  # @return [Boolean] true if the actual value equals the node value.
29
29
  def is_equal?(node)
30
- actual_value(node).to_s == expected_value
30
+ NodeQuery::Helper.to_string(actual_value(node)) == expected_value
31
31
  end
32
32
 
33
33
  # Get valid operators.
@@ -48,11 +48,19 @@ class NodeQuery::Helper
48
48
  # @param str [String] string to be evaluated
49
49
  # @return [String] evaluated string
50
50
  def evaluate_node_value(node, str)
51
- str.scan(/{{(.*)}}/).each do |match_data|
51
+ str.scan(/{{(.*?)}}/).each do |match_data|
52
52
  target_node = NodeQuery::Helper.get_target_node(node, match_data.first)
53
- str = str.sub("{{#{match_data.first}}}", NodeQuery.adapter.get_source(target_node))
53
+ str = str.sub("{{#{match_data.first}}}", to_string(target_node))
54
54
  end
55
55
  str
56
56
  end
57
+
58
+ def to_string(node)
59
+ if NodeQuery.adapter.is_node?(node)
60
+ return NodeQuery.adapter.get_source(node)
61
+ end
62
+
63
+ node.to_s
64
+ end
57
65
  end
58
66
  end
@@ -11,16 +11,35 @@ class NodeQuery::NodeRules
11
11
 
12
12
  # Query nodes by the rules.
13
13
  # @param node [Node] node to query
14
- # @params including_self [boolean] if query the current node.
14
+ # @param options [Hash] if query the current node
15
+ # @option options [boolean] :including_self if query the current node, default is ture
16
+ # @option options [boolean] :stop_at_first_match if stop at first match, default is false
17
+ # @option options [boolean] :recursive if recursively query child nodes, default is true
15
18
  # @return [Array<Node>] matching nodes.
16
- def query_nodes(node, including_self = true)
19
+ def query_nodes(node, options = {})
20
+ options = { including_self: true, stop_at_first_match: false, recursive: true }.merge(options)
21
+ if options[:including_self] && !options[:recursive]
22
+ return match_node?(node) ? [node] : []
23
+ end
24
+
17
25
  matching_nodes = []
18
- if (including_self && match_node?(node))
26
+ if options[:including_self] && match_node?(node)
19
27
  matching_nodes.push(node)
28
+ return matching_nodes if options[:stop_at_first_match]
20
29
  end
21
- NodeQuery::Helper.handle_recursive_child(node) do |child_node|
22
- if (match_node?(child_node))
23
- matching_nodes.push(child_node)
30
+ if options[:recursive]
31
+ NodeQuery::Helper.handle_recursive_child(node) do |child_node|
32
+ if match_node?(child_node)
33
+ matching_nodes.push(child_node)
34
+ break if options[:stop_at_first_match]
35
+ end
36
+ end
37
+ else
38
+ NodeQuery.adapter.get_children(node).each do |child_node|
39
+ if match_node?(child_node)
40
+ matching_nodes.push(child_node)
41
+ break if options[:stop_at_first_match]
42
+ end
24
43
  end
25
44
  end
26
45
  matching_nodes
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class NodeQuery
4
- VERSION = "1.3.0"
4
+ VERSION = "1.5.0"
5
5
  end
data/lib/node_query.rb CHANGED
@@ -38,13 +38,16 @@ class NodeQuery
38
38
 
39
39
  # Query matching nodes.
40
40
  # @param node [Node] ast node
41
- # @param including_self [boolean] if check the node itself
41
+ # @param options [Hash] if query the current node
42
+ # @option options [boolean] :including_self if query the current node, default is ture
43
+ # @option options [boolean] :stop_at_first_match if stop at first match, default is false
44
+ # @option options [boolean] :recursive if recursively query child nodes, default is true
42
45
  # @return [Array<Node>] matching child nodes
43
- def query_nodes(node, including_self = true)
46
+ def query_nodes(node, options = {})
44
47
  if @expression
45
- @expression.query_nodes(node, including_self)
48
+ @expression.query_nodes(node, options)
46
49
  elsif @rules
47
- @rules.query_nodes(node, including_self)
50
+ @rules.query_nodes(node, options)
48
51
  else
49
52
  []
50
53
  end
data/sig/node_query.rbs CHANGED
@@ -7,7 +7,7 @@ class NodeQuery[T]
7
7
 
8
8
  def initialize: (nqlOrRues: String | Hash) -> NodeQuery
9
9
 
10
- def query_nodes: (node: T, including_self: boolean) -> Array[T]
10
+ def query_nodes: (node: T, options: Hash) -> Array[T]
11
11
 
12
12
  def match_node?: (node: T) -> boolean
13
13
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: node_query
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Richard Huang
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-09-13 00:00:00.000000000 Z
11
+ date: 2022-09-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport