openapi3_parser 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +2 -0
- data/CHANGELOG.md +8 -0
- data/README.md +1 -1
- data/TODO.md +4 -4
- data/lib/openapi3_parser/array_sentence.rb +12 -0
- data/lib/openapi3_parser/cautious_dig.rb +39 -0
- data/lib/openapi3_parser/context.rb +53 -1
- data/lib/openapi3_parser/context/location.rb +1 -0
- data/lib/openapi3_parser/context/pointer.rb +67 -5
- data/lib/openapi3_parser/document.rb +45 -4
- data/lib/openapi3_parser/error.rb +9 -0
- data/lib/openapi3_parser/node/array.rb +14 -4
- data/lib/openapi3_parser/node/map.rb +45 -3
- data/lib/openapi3_parser/node/object.rb +25 -5
- data/lib/openapi3_parser/node_factory.rb +0 -150
- data/lib/openapi3_parser/node_factory/array.rb +198 -0
- data/lib/openapi3_parser/node_factory/callback.rb +24 -0
- data/lib/openapi3_parser/{node_factories → node_factory}/components.rb +24 -25
- data/lib/openapi3_parser/{node_factories → node_factory}/contact.rb +5 -6
- data/lib/openapi3_parser/{node_factories → node_factory}/discriminator.rb +6 -7
- data/lib/openapi3_parser/{node_factories → node_factory}/encoding.rb +6 -8
- data/lib/openapi3_parser/{node_factories → node_factory}/example.rb +4 -5
- data/lib/openapi3_parser/{node_factories → node_factory}/external_documentation.rb +4 -5
- data/lib/openapi3_parser/node_factory/field.rb +129 -0
- data/lib/openapi3_parser/node_factory/fields/reference.rb +54 -18
- data/lib/openapi3_parser/{node_factories → node_factory}/header.rb +4 -5
- data/lib/openapi3_parser/{node_factories → node_factory}/info.rb +6 -7
- data/lib/openapi3_parser/{node_factories → node_factory}/license.rb +4 -5
- data/lib/openapi3_parser/{node_factories → node_factory}/link.rb +6 -8
- data/lib/openapi3_parser/node_factory/map.rb +206 -21
- data/lib/openapi3_parser/{node_factories → node_factory}/media_type.rb +17 -16
- data/lib/openapi3_parser/{node_factories → node_factory}/oauth_flow.rb +2 -4
- data/lib/openapi3_parser/{node_factories → node_factory}/oauth_flows.rb +4 -6
- data/lib/openapi3_parser/node_factory/object.rb +66 -63
- data/lib/openapi3_parser/node_factory/object_factory/dsl.rb +50 -0
- data/lib/openapi3_parser/node_factory/object_factory/field_config.rb +88 -0
- data/lib/openapi3_parser/node_factory/object_factory/node_builder.rb +96 -0
- data/lib/openapi3_parser/node_factory/object_factory/validator.rb +172 -0
- data/lib/openapi3_parser/node_factory/openapi.rb +65 -0
- data/lib/openapi3_parser/node_factory/operation.rb +87 -0
- data/lib/openapi3_parser/node_factory/optional_reference.rb +7 -3
- data/lib/openapi3_parser/{node_factories → node_factory}/parameter.rb +16 -22
- data/lib/openapi3_parser/node_factory/parameter_like.rb +42 -0
- data/lib/openapi3_parser/{node_factories → node_factory}/path_item.rb +27 -29
- data/lib/openapi3_parser/{node_factories → node_factory}/paths.rb +21 -27
- data/lib/openapi3_parser/node_factory/recursive_pointer.rb +17 -0
- data/lib/openapi3_parser/node_factory/reference.rb +48 -0
- data/lib/openapi3_parser/{node_factories → node_factory}/request_body.rb +15 -19
- data/lib/openapi3_parser/{node_factories → node_factory}/response.rb +18 -21
- data/lib/openapi3_parser/node_factory/responses.rb +51 -0
- data/lib/openapi3_parser/{node_factories → node_factory}/schema.rb +33 -33
- data/lib/openapi3_parser/node_factory/security_requirement.rb +21 -0
- data/lib/openapi3_parser/{node_factories → node_factory}/security_scheme.rb +4 -6
- data/lib/openapi3_parser/{node_factories → node_factory}/server.rb +6 -8
- data/lib/openapi3_parser/{node_factories → node_factory}/server_variable.rb +10 -12
- data/lib/openapi3_parser/{node_factories → node_factory}/tag.rb +4 -6
- data/lib/openapi3_parser/node_factory/type_checker.rb +103 -0
- data/lib/openapi3_parser/{node_factories → node_factory}/xml.rb +4 -5
- data/lib/openapi3_parser/source/reference_resolver.rb +3 -3
- data/lib/openapi3_parser/validation/error.rb +9 -0
- data/lib/openapi3_parser/validation/input_validator.rb +18 -0
- data/lib/openapi3_parser/validation/validatable.rb +44 -0
- data/lib/openapi3_parser/validators/mutually_exclusive_fields.rb +121 -0
- data/lib/openapi3_parser/validators/required_fields.rb +37 -0
- data/lib/openapi3_parser/validators/unexpected_fields.rb +52 -0
- data/lib/openapi3_parser/version.rb +1 -1
- metadata +48 -38
- data/lib/openapi3_parser/node_factories/array.rb +0 -114
- data/lib/openapi3_parser/node_factories/callback.rb +0 -27
- data/lib/openapi3_parser/node_factories/map.rb +0 -120
- data/lib/openapi3_parser/node_factories/openapi.rb +0 -62
- data/lib/openapi3_parser/node_factories/operation.rb +0 -84
- data/lib/openapi3_parser/node_factories/parameter/parameter_like.rb +0 -41
- data/lib/openapi3_parser/node_factories/reference.rb +0 -35
- data/lib/openapi3_parser/node_factories/responses.rb +0 -60
- data/lib/openapi3_parser/node_factories/security_requirement.rb +0 -26
- data/lib/openapi3_parser/node_factory/field_config.rb +0 -88
- data/lib/openapi3_parser/node_factory/object/node_builder.rb +0 -97
- data/lib/openapi3_parser/node_factory/object/validator.rb +0 -176
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0e48a69a367595cb50a68fbfef79e0d9fc925c61
|
4
|
+
data.tar.gz: a53afad6f342b79d622201e9b87cd014be1eeac8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2d772db41130444cbb1bfae66508ec1bde2ae21ba583da15b9cf3776d68dee5864f061e5e333a7cd2676361f9ac3bd6362efc4afaccaa0967b47c1fcbc00c781
|
7
|
+
data.tar.gz: 79df18c70a0e16b3d509c669a37be4b421b8b2504e36ff97b4144cbb982123c6d146c77a190eda794abb7ecd8282d41397006ba3284452ba65220e2952f6b6a4
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
# Unreleased
|
2
|
+
|
3
|
+
- Support for recursive references - fixes: https://github.com/kevindew/openapi3_parser/issues/4
|
4
|
+
- `node_at` method on nodes and document to allow looking up nodes by string
|
5
|
+
paths
|
6
|
+
- Refactor of the node factory classes to use simpler inheritance rather than
|
7
|
+
the mixins in mixins approach.
|
8
|
+
|
1
9
|
# 0.4.0
|
2
10
|
|
3
11
|
- Determine the OpenAPI specification version and store it in document.
|
data/README.md
CHANGED
data/TODO.md
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
These are the steps defined to reach 1.0. Assistance is very welcome.
|
4
4
|
|
5
5
|
- [x] Handle mutually exclusive fields
|
6
|
-
- [
|
6
|
+
- [x] Refactor the various NodeFactory modules to be a less confusing
|
7
7
|
hierachical structure. Consider having factories subclass instead of use
|
8
8
|
mixin
|
9
9
|
- [x] Decouple Document class for the source file. Consider a source file class
|
@@ -18,16 +18,16 @@ These are the steps defined to reach 1.0. Assistance is very welcome.
|
|
18
18
|
- [ ] Reach parity with OpenAPI specification for validation
|
19
19
|
- [ ] Consider a lenient mode for a document to only have to comply with type
|
20
20
|
based validation
|
21
|
-
- [
|
21
|
+
- [x] Improve test coverage
|
22
22
|
- [ ] Publish documentation of the interface through the structure
|
23
23
|
- [x] Consider a resolved context class for representing context with a node
|
24
24
|
that can handle scenarios where a node is represented by both a reference
|
25
25
|
and resolved context
|
26
|
-
- [
|
26
|
+
- [x] Create error classes for various scenarios
|
27
27
|
- [ ] Associate/resolve operation id / operation references
|
28
28
|
- [ ] Do something to model expressions
|
29
29
|
- [x] Improve the modelling of namespace
|
30
|
-
- [
|
30
|
+
- [x] Set up nicer string representations of key classes to help them be
|
31
31
|
debugged
|
32
32
|
- [x] Ensure Array and Map nodes return empty ones by default rather than nil
|
33
33
|
- [ ] Make JSON pointer public access to be consistent accepting string, array
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Openapi3Parser
|
4
|
+
class CautiousDig
|
5
|
+
private_class_method :new
|
6
|
+
|
7
|
+
def self.call(*args)
|
8
|
+
new.call(*args)
|
9
|
+
end
|
10
|
+
|
11
|
+
def call(collection, *segments)
|
12
|
+
segments.inject(collection) do |next_depth, segment|
|
13
|
+
break unless next_depth
|
14
|
+
|
15
|
+
if next_depth.respond_to?(:keys)
|
16
|
+
hash_like(next_depth, segment)
|
17
|
+
elsif next_depth.respond_to?(:[])
|
18
|
+
array_like(next_depth, segment)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def hash_like(item, segment)
|
26
|
+
key = item.keys.find { |k| segment == k || segment.to_s == k.to_s }
|
27
|
+
item[key]
|
28
|
+
end
|
29
|
+
|
30
|
+
def array_like(item, segment)
|
31
|
+
index = if segment.is_a?(String) && segment =~ /\A\d+\z/
|
32
|
+
segment.to_i
|
33
|
+
else
|
34
|
+
segment
|
35
|
+
end
|
36
|
+
index.is_a?(Integer) ? item[index] : nil
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -38,6 +38,18 @@ module Openapi3Parser
|
|
38
38
|
referenced_by: pc.referenced_by)
|
39
39
|
end
|
40
40
|
|
41
|
+
# Convert a context into one that knows that is a reference
|
42
|
+
#
|
43
|
+
# @param [Context] current_context
|
44
|
+
# @return [Context]
|
45
|
+
def self.as_reference(current_context)
|
46
|
+
new(current_context.input,
|
47
|
+
document_location: current_context.document_location,
|
48
|
+
source_location: current_context.source_location,
|
49
|
+
referenced_by: current_context.referenced_by,
|
50
|
+
is_reference: true)
|
51
|
+
end
|
52
|
+
|
41
53
|
# Creates the context for a field that is referenced by a context.
|
42
54
|
# In this scenario the context of the document is the same but we are in
|
43
55
|
# a different part of the source file, or even a different source file
|
@@ -63,14 +75,25 @@ module Openapi3Parser
|
|
63
75
|
# @param [Context::Location] document_location
|
64
76
|
# @param [Context::Location, nil] source_location
|
65
77
|
# @param [Context, nil] referenced_by
|
78
|
+
# @param [Boolean] is_reference
|
66
79
|
def initialize(input,
|
67
80
|
document_location:,
|
68
81
|
source_location: nil,
|
69
|
-
referenced_by: nil
|
82
|
+
referenced_by: nil,
|
83
|
+
is_reference: false)
|
70
84
|
@input = input
|
71
85
|
@document_location = document_location
|
72
86
|
@source_location = source_location || document_location
|
73
87
|
@referenced_by = referenced_by
|
88
|
+
@is_reference = is_reference
|
89
|
+
end
|
90
|
+
|
91
|
+
# @return [Boolean]
|
92
|
+
def ==(other)
|
93
|
+
input == other.input &&
|
94
|
+
document_location == other.document_location &&
|
95
|
+
source_location == other.source_location &&
|
96
|
+
referenced_by == other.referenced_by
|
74
97
|
end
|
75
98
|
|
76
99
|
# @return [Document]
|
@@ -93,6 +116,11 @@ module Openapi3Parser
|
|
93
116
|
document_location.pointer.segments
|
94
117
|
end
|
95
118
|
|
119
|
+
# @return [Boolean]
|
120
|
+
def reference?
|
121
|
+
@is_reference
|
122
|
+
end
|
123
|
+
|
96
124
|
def inspect
|
97
125
|
%{#{self.class.name}(document_location: #{document_location}, } +
|
98
126
|
%{source_location: #{source_location}), referenced_by: } +
|
@@ -108,5 +136,29 @@ module Openapi3Parser
|
|
108
136
|
def to_s
|
109
137
|
location_summary
|
110
138
|
end
|
139
|
+
|
140
|
+
def resolved_input
|
141
|
+
# The resolved input for a reference is at the segment before the
|
142
|
+
# reference
|
143
|
+
pointer = if reference?
|
144
|
+
document_location.pointer.segments[0...-1]
|
145
|
+
else
|
146
|
+
document_location.pointer
|
147
|
+
end
|
148
|
+
|
149
|
+
document.resolved_input_at(pointer)
|
150
|
+
end
|
151
|
+
|
152
|
+
def node
|
153
|
+
# The created node for a reference is at the segment before the
|
154
|
+
# reference
|
155
|
+
pointer = if reference?
|
156
|
+
document_location.pointer.segments[0...-1]
|
157
|
+
else
|
158
|
+
document_location.pointer
|
159
|
+
end
|
160
|
+
|
161
|
+
document.node_at(pointer)
|
162
|
+
end
|
111
163
|
end
|
112
164
|
end
|
@@ -7,11 +7,28 @@ module Openapi3Parser
|
|
7
7
|
# A class to decorate the array of fields that make up a pointer and
|
8
8
|
# provide common means to convert it into different representations.
|
9
9
|
class Pointer
|
10
|
-
|
10
|
+
def self.from_fragment(fragment)
|
11
|
+
fragment = fragment[1..-1] if fragment.start_with?("#")
|
12
|
+
absolute = fragment[0] == "/"
|
13
|
+
segments = fragment.split("/").map do |part|
|
14
|
+
next if part == ""
|
15
|
+
unescaped = CGI.unescape(part.gsub("%20", "+"))
|
16
|
+
unescaped =~ /\A\d+\z/ ? unescaped.to_i : unescaped
|
17
|
+
end
|
18
|
+
new(segments.compact, absolute)
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.merge_pointers(base_pointer, new_pointer)
|
22
|
+
MergePointers.call(base_pointer, new_pointer)
|
23
|
+
end
|
24
|
+
|
25
|
+
attr_reader :segments, :absolute
|
11
26
|
|
12
27
|
# @param [::Array] segments
|
13
|
-
|
28
|
+
# @param [Boolean] absolute
|
29
|
+
def initialize(segments, absolute = true)
|
14
30
|
@segments = segments.freeze
|
31
|
+
@absolute = absolute
|
15
32
|
end
|
16
33
|
|
17
34
|
def ==(other)
|
@@ -19,9 +36,9 @@ module Openapi3Parser
|
|
19
36
|
end
|
20
37
|
|
21
38
|
def fragment
|
22
|
-
segments.map { |s| CGI.escape(s.to_s).gsub("+", "%20") }
|
23
|
-
|
24
|
-
|
39
|
+
fragment = segments.map { |s| CGI.escape(s.to_s).gsub("+", "%20") }
|
40
|
+
.join("/")
|
41
|
+
"#" + (absolute ? fragment.prepend("/") : fragment)
|
25
42
|
end
|
26
43
|
|
27
44
|
def to_s
|
@@ -31,6 +48,51 @@ module Openapi3Parser
|
|
31
48
|
def inspect
|
32
49
|
%{#{self.class.name}(segments: #{segments}, fragment: "#{fragment}")}
|
33
50
|
end
|
51
|
+
|
52
|
+
class MergePointers
|
53
|
+
private_class_method :new
|
54
|
+
|
55
|
+
def self.call(*args)
|
56
|
+
new(*args).call
|
57
|
+
end
|
58
|
+
|
59
|
+
def initialize(base_pointer, new_pointer)
|
60
|
+
@base_pointer = create_pointer(base_pointer)
|
61
|
+
@new_pointer = create_pointer(new_pointer)
|
62
|
+
end
|
63
|
+
|
64
|
+
def call
|
65
|
+
return base_pointer if new_pointer.nil?
|
66
|
+
return new_pointer if base_pointer.nil? || new_pointer.absolute
|
67
|
+
|
68
|
+
merge_pointers(base_pointer, new_pointer)
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
attr_reader :base_pointer, :new_pointer
|
74
|
+
|
75
|
+
def create_pointer(pointer_like)
|
76
|
+
case pointer_like
|
77
|
+
when Pointer then pointer_like
|
78
|
+
when ::Array then Pointer.new(pointer_like, false)
|
79
|
+
when ::String then Pointer.from_fragment(pointer_like)
|
80
|
+
when nil then nil
|
81
|
+
else raise Openapi3Parser::Error, "Unexpected type for pointer"
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def merge_pointers(pointer_a, pointer_b)
|
86
|
+
fragment_a = pointer_a.fragment.gsub(%r{\A#?/?}, "")
|
87
|
+
fragment_b = pointer_b.fragment.gsub(%r{\A#?/?}, "")
|
88
|
+
|
89
|
+
joined = File.expand_path("/#{fragment_a}/#{fragment_b}", "/")
|
90
|
+
|
91
|
+
joined = joined[1..-1] unless pointer_a.absolute
|
92
|
+
|
93
|
+
Pointer.from_fragment("##{joined}")
|
94
|
+
end
|
95
|
+
end
|
34
96
|
end
|
35
97
|
end
|
36
98
|
end
|
@@ -1,9 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "openapi3_parser/cautious_dig"
|
3
4
|
require "openapi3_parser/context"
|
5
|
+
require "openapi3_parser/context/pointer"
|
4
6
|
require "openapi3_parser/document/reference_register"
|
5
7
|
require "openapi3_parser/error"
|
6
|
-
require "openapi3_parser/
|
8
|
+
require "openapi3_parser/node_factory/openapi"
|
7
9
|
require "openapi3_parser/source"
|
8
10
|
require "openapi3_parser/validation/error_collection"
|
9
11
|
|
@@ -79,9 +81,11 @@ module Openapi3Parser
|
|
79
81
|
# @return Object
|
80
82
|
# @!method each
|
81
83
|
# Iterate through the attributes of the root object
|
82
|
-
#
|
84
|
+
# @!method keys
|
85
|
+
# Access keys of the root object
|
83
86
|
def_delegators :root, :openapi, :info, :servers, :paths, :components,
|
84
|
-
:security, :tags, :external_docs, :extension, :[], :each
|
87
|
+
:security, :tags, :external_docs, :extension, :[], :each,
|
88
|
+
:keys
|
85
89
|
|
86
90
|
# @param [SourceInput] source_input
|
87
91
|
def initialize(source_input)
|
@@ -132,10 +136,47 @@ module Openapi3Parser
|
|
132
136
|
sources.find { |source| source.source_input == source_input }
|
133
137
|
end
|
134
138
|
|
139
|
+
# Look up the resolved input for an address in the OpenAPI document,
|
140
|
+
# resolved_input refers to the input with references resolevd and all
|
141
|
+
# optional fields existing
|
142
|
+
#
|
143
|
+
# @param [Context::Pointer, String, Array] pointer
|
144
|
+
# @param [Context::Pointer, String, Array, nil] relative_to
|
145
|
+
# @return anything
|
146
|
+
def resolved_input_at(pointer, relative_to = nil)
|
147
|
+
look_up_pointer(pointer, relative_to, factory.resolved_input)
|
148
|
+
end
|
149
|
+
|
150
|
+
# Look up a node at a particular location in the OpenAPI docuemnt
|
151
|
+
#
|
152
|
+
# Examples:
|
153
|
+
#
|
154
|
+
# document.node_at("#/components/schemas")
|
155
|
+
# document.node_at(%w[components schemas])
|
156
|
+
#
|
157
|
+
# @param [Context::Pointer, String, Array] pointer
|
158
|
+
# @param [Context::Pointer, String, Array, nil] relative_to
|
159
|
+
# @return anything
|
160
|
+
def node_at(pointer, relative_to = nil)
|
161
|
+
look_up_pointer(pointer, relative_to, root)
|
162
|
+
end
|
163
|
+
|
164
|
+
# @return [String]
|
165
|
+
def inspect
|
166
|
+
%{#{self.class.name}(openapi_version: #{openapi_version}, } +
|
167
|
+
%{root_source: #{root_source.inspect})}
|
168
|
+
end
|
169
|
+
|
135
170
|
private
|
136
171
|
|
137
172
|
attr_reader :reference_register, :built, :build_in_progress
|
138
173
|
|
174
|
+
def look_up_pointer(pointer, relative_pointer, subject)
|
175
|
+
merged_pointer = Context::Pointer.merge_pointers(relative_pointer,
|
176
|
+
pointer)
|
177
|
+
CautiousDig.call(subject, *merged_pointer.segments)
|
178
|
+
end
|
179
|
+
|
139
180
|
def add_warning(text)
|
140
181
|
@warnings << text
|
141
182
|
end
|
@@ -144,7 +185,7 @@ module Openapi3Parser
|
|
144
185
|
return if build_in_progress || built
|
145
186
|
@build_in_progress = true
|
146
187
|
context = Context.root(root_source.data, root_source)
|
147
|
-
@factory =
|
188
|
+
@factory = NodeFactory::Openapi.new(context)
|
148
189
|
reference_register.freeze
|
149
190
|
@warnings.freeze
|
150
191
|
@build_in_progress = false
|
@@ -27,5 +27,14 @@ module Openapi3Parser
|
|
27
27
|
# Used when there are extra fields that are not expected in the data for
|
28
28
|
# a node
|
29
29
|
class UnexpectedFields < Error; end
|
30
|
+
# Used when a method we expect to be able to call (through symbol or proc)
|
31
|
+
# is not callable
|
32
|
+
class NotCallable < Error; end
|
33
|
+
# Raised when we in a recursive data structure and can't perform an
|
34
|
+
# operation
|
35
|
+
class InRecursiveStructure < Error; end
|
36
|
+
# Used when we're trying to validate that a type is something that is not
|
37
|
+
# validatable, most likely a sign that we're in a bug
|
38
|
+
class UnvalidatableType < Error; end
|
30
39
|
end
|
31
40
|
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "forwardable"
|
4
|
+
|
3
5
|
require "openapi3_parser/node/map"
|
4
6
|
|
5
7
|
module Openapi3Parser
|
@@ -11,8 +13,10 @@ module Openapi3Parser
|
|
11
13
|
# The contents of the data will be dependent on where this document is in
|
12
14
|
# the document hierachy.
|
13
15
|
class Array
|
16
|
+
extend Forwardable
|
14
17
|
include Enumerable
|
15
18
|
|
19
|
+
def_delegators :node_data, :each, :[], :empty?
|
16
20
|
attr_reader :node_data, :node_context
|
17
21
|
|
18
22
|
# @param [::Array] data data used to populate this node
|
@@ -22,12 +26,18 @@ module Openapi3Parser
|
|
22
26
|
@node_context = context
|
23
27
|
end
|
24
28
|
|
25
|
-
|
26
|
-
|
29
|
+
# Used to access a node relative to this node
|
30
|
+
# @param [Context::Pointer, ::Array, ::String] pointer_like
|
31
|
+
# @return anything
|
32
|
+
def node_at(pointer_like)
|
33
|
+
current_pointer = node_context.document_location.pointer
|
34
|
+
node_context.document.node_at(pointer_like, current_pointer)
|
27
35
|
end
|
28
36
|
|
29
|
-
|
30
|
-
|
37
|
+
# @return [String]
|
38
|
+
def inspect
|
39
|
+
fragment = node_context.document_location.pointer.fragment
|
40
|
+
%{#{self.class.name}(#{fragment})}
|
31
41
|
end
|
32
42
|
end
|
33
43
|
end
|