token-resolver 1.0.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.
@@ -0,0 +1,93 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Token
4
+ module Resolver
5
+ # Resolves tokens in a parsed Document using a replacement map.
6
+ #
7
+ # Text nodes pass through unchanged. Token nodes are looked up in the
8
+ # replacement map by their key. Missing tokens are handled according
9
+ # to the `on_missing` policy.
10
+ #
11
+ # @example Resolve all tokens
12
+ # doc = Document.new("Hello {KJ|NAME}!")
13
+ # resolver = Resolve.new
14
+ # resolver.resolve(doc, {"KJ|NAME" => "World"})
15
+ # # => "Hello World!"
16
+ #
17
+ # @example Keep unresolved tokens
18
+ # resolver = Resolve.new(on_missing: :keep)
19
+ # resolver.resolve(doc, {})
20
+ # # => "Hello {KJ|NAME}!"
21
+ #
22
+ # @example Remove unresolved tokens
23
+ # resolver = Resolve.new(on_missing: :remove)
24
+ # resolver.resolve(doc, {})
25
+ # # => "Hello !"
26
+ #
27
+ class Resolve
28
+ VALID_ON_MISSING = %i[raise keep remove].freeze
29
+
30
+ # @return [Symbol] Policy for unresolved tokens (:raise, :keep, :remove)
31
+ attr_reader :on_missing
32
+
33
+ # @param on_missing [Symbol] Behavior for unresolved tokens
34
+ # @raise [ArgumentError] If on_missing is invalid
35
+ def initialize(on_missing: :raise)
36
+ unless VALID_ON_MISSING.include?(on_missing)
37
+ raise ArgumentError,
38
+ "Invalid on_missing: #{on_missing.inspect}. Must be one of: #{VALID_ON_MISSING.map(&:inspect).join(", ")}"
39
+ end
40
+
41
+ @on_missing = on_missing
42
+ end
43
+
44
+ # Resolve tokens in a document or node array using a replacement map.
45
+ #
46
+ # Resolution is single-pass — replacement values are NOT re-scanned for tokens.
47
+ #
48
+ # @param document_or_nodes [Document, Array<Node::Text, Node::Token>] Parsed input
49
+ # @param replacements [Hash{String => String}] Map of token keys to replacement values
50
+ # @return [String] Resolved text
51
+ #
52
+ # @raise [UnresolvedTokenError] If on_missing is :raise and a token has no replacement
53
+ def resolve(document_or_nodes, replacements)
54
+ nodes = case document_or_nodes
55
+ when Document
56
+ document_or_nodes.nodes
57
+ when Array
58
+ document_or_nodes
59
+ else
60
+ raise ArgumentError, "Expected Document or Array of nodes, got #{document_or_nodes.class}"
61
+ end
62
+
63
+ result = +""
64
+ nodes.each do |node|
65
+ if node.token?
66
+ replacement = replacements[node.key]
67
+ if replacement
68
+ result << replacement
69
+ else
70
+ handle_missing(node, result)
71
+ end
72
+ else
73
+ result << node.to_s
74
+ end
75
+ end
76
+ result
77
+ end
78
+
79
+ private
80
+
81
+ def handle_missing(token_node, result)
82
+ case @on_missing
83
+ when :raise
84
+ raise UnresolvedTokenError.new(token_node.key)
85
+ when :keep
86
+ result << token_node.to_s
87
+ when :remove
88
+ # emit nothing
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,100 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "parslet"
4
+
5
+ module Token
6
+ module Resolver
7
+ # Transforms the raw parslet parse tree into Node::Text and Node::Token objects.
8
+ #
9
+ # The grammar produces one `:text` entry per character and `:token` entries
10
+ # with `:seg` captures. This transform converts those into proper node objects
11
+ # and coalesces adjacent Text nodes into single nodes.
12
+ #
13
+ # @example
14
+ # config = Config.default
15
+ # tree = Grammar.build(config).new.parse("Hi {KJ|X}!")
16
+ # nodes = Transform.apply(tree, config)
17
+ # # => [Node::Text("Hi "), Node::Token(["KJ", "X"]), Node::Text("!")]
18
+ #
19
+ class Transform
20
+ class << self
21
+ # Transform a parslet tree into an array of Text and Token nodes.
22
+ #
23
+ # @param tree [Array<Hash>] Raw parslet parse tree
24
+ # @param config [Config] Token configuration
25
+ # @return [Array<Node::Text, Node::Token>] Coalesced node array
26
+ def apply(tree, config)
27
+ return [] if tree.nil? || (tree.respond_to?(:empty?) && tree.empty?)
28
+
29
+ # Convert raw parslet entries to node objects
30
+ raw_nodes = tree.map { |entry| convert_entry(entry, config) }
31
+
32
+ # Coalesce adjacent Text nodes
33
+ coalesce(raw_nodes)
34
+ end
35
+
36
+ private
37
+
38
+ def convert_entry(entry, config)
39
+ if entry.key?(:token)
40
+ convert_token(entry[:token], config)
41
+ elsif entry.key?(:text)
42
+ Node::Text.new(slice_to_s(entry[:text]))
43
+ else
44
+ # Shouldn't happen with our grammar, but be safe
45
+ Node::Text.new(entry.to_s)
46
+ end
47
+ end
48
+
49
+ def convert_token(token_data, config)
50
+ # token_data contains :seg captures
51
+ # It can be a single seg hash or an array of seg hashes
52
+ segments = extract_segments(token_data)
53
+ Node::Token.new(segments, config)
54
+ end
55
+
56
+ def extract_segments(token_data)
57
+ # Parslet returns different structures depending on repetition:
58
+ # - Single segment match: {:seg => "value"}
59
+ # - Multiple segments: [{:seg => "val1"}, {:seg => "val2"}] or {:seg => [...]}
60
+ case token_data
61
+ when Hash
62
+ if token_data[:seg].is_a?(Array)
63
+ token_data[:seg].map { |s| slice_to_s(s) }
64
+ else
65
+ [slice_to_s(token_data[:seg])]
66
+ end
67
+ when Array
68
+ token_data.flat_map { |item|
69
+ if item.is_a?(Hash) && item.key?(:seg)
70
+ [slice_to_s(item[:seg])]
71
+ else
72
+ [slice_to_s(item)]
73
+ end
74
+ }
75
+ else
76
+ [slice_to_s(token_data)]
77
+ end
78
+ end
79
+
80
+ def slice_to_s(value)
81
+ value.to_s
82
+ end
83
+
84
+ def coalesce(nodes)
85
+ return nodes if nodes.length <= 1
86
+
87
+ nodes.chunk { |node| node.is_a?(Node::Text) }
88
+ .flat_map { |is_text, group|
89
+ if is_text
90
+ combined = group.map(&:content).join
91
+ [Node::Text.new(combined)]
92
+ else
93
+ group
94
+ end
95
+ }
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Token
4
+ module Resolver
5
+ # Version information for Token::Resolver
6
+ module Version
7
+ # Current version of the token-resolver gem
8
+ VERSION = "1.0.0"
9
+ end
10
+ VERSION = Version::VERSION # traditional location
11
+ end
12
+ end
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ # External gems
4
+ require "version_gem"
5
+
6
+ # This gem - only version can be required (never autoloaded)
7
+ require_relative "resolver/version"
8
+
9
+ module Token
10
+ # Token::Resolver provides configurable PEG-based (parslet) parsing and resolution
11
+ # of structured tokens in arbitrary text.
12
+ #
13
+ # Tokens are configurable structured patterns like `{KJ|GEM_NAME}` that can be
14
+ # detected in any file format and resolved against a replacement map.
15
+ #
16
+ # @example Parse a document to find tokens
17
+ # doc = Token::Resolver.parse("Hello {KJ|NAME}!")
18
+ # doc.token_keys # => ["KJ|NAME"]
19
+ #
20
+ # @example Resolve tokens in one step
21
+ # result = Token::Resolver.resolve(
22
+ # "Hello {KJ|NAME}, welcome to {KJ|PROJECT}!",
23
+ # {"KJ|NAME" => "World", "KJ|PROJECT" => "token-resolver"}
24
+ # )
25
+ # # => "Hello World, welcome to token-resolver!"
26
+ #
27
+ module Resolver
28
+ # Base error class for all token-resolver operations.
29
+ # @api public
30
+ class Error < StandardError; end
31
+
32
+ # Raised when a token has no replacement value and on_missing is :raise.
33
+ # @api public
34
+ class UnresolvedTokenError < Error
35
+ # @return [String] The token key that was not found
36
+ attr_reader :token_key
37
+
38
+ # @param token_key [String] The unresolved token key
39
+ # @param message [String, nil] Optional custom message
40
+ def initialize(token_key, message = nil)
41
+ @token_key = token_key
42
+ super(message || "Unresolved token: #{token_key}")
43
+ end
44
+ end
45
+
46
+ # Autoload all classes
47
+ autoload :Config, "token/resolver/config"
48
+ autoload :Document, "token/resolver/document"
49
+ autoload :Grammar, "token/resolver/grammar"
50
+ autoload :Node, "token/resolver/node"
51
+ autoload :Resolve, "token/resolver/resolve"
52
+ autoload :Transform, "token/resolver/transform"
53
+
54
+ class << self
55
+ # Parse input text and return a Document.
56
+ #
57
+ # @param input [String] Text to parse for tokens
58
+ # @param config [Config] Token configuration (default: Config.default)
59
+ # @return [Document] Parsed document with text and token nodes
60
+ #
61
+ # @example
62
+ # doc = Token::Resolver.parse("Hello {KJ|NAME}!")
63
+ # doc.tokens.first.key # => "KJ|NAME"
64
+ def parse(input, config: Config.default)
65
+ Document.new(input, config: config)
66
+ end
67
+
68
+ # Parse and resolve tokens in one step.
69
+ #
70
+ # @param input [String] Text containing tokens to resolve
71
+ # @param replacements [Hash{String => String}] Map of token keys to replacement values
72
+ # @param config [Config] Token configuration (default: Config.default)
73
+ # @param on_missing [Symbol] Behavior for unresolved tokens (:raise, :keep, :remove)
74
+ # @return [String] Resolved text with tokens replaced
75
+ #
76
+ # @example
77
+ # Token::Resolver.resolve("{KJ|NAME}", {"KJ|NAME" => "World"})
78
+ # # => "World"
79
+ def resolve(input, replacements, config: Config.default, on_missing: :raise)
80
+ doc = parse(input, config: config)
81
+ resolver = Resolve.new(on_missing: on_missing)
82
+ resolver.resolve(doc, replacements)
83
+ end
84
+ end
85
+ end
86
+ end
87
+
88
+ Token::Resolver::Version.class_eval do
89
+ extend VersionGem::Basic
90
+ end
@@ -0,0 +1,4 @@
1
+ # For technical reasons, if we move to Zeitwerk, this cannot be require_relative.
2
+ # See: https://github.com/fxn/zeitwerk#for_gem_extension
3
+ # Hook for other libraries to load this library (e.g. via bundler)
4
+ require "token/resolver"
@@ -0,0 +1,6 @@
1
+ module Token
2
+ module Resolver
3
+ VERSION: String
4
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
5
+ end
6
+ end
data.tar.gz.sig ADDED
@@ -0,0 +1,2 @@
1
+ ?<"�˽��(���S��wzӈ�_�B�+7�i�H�nxv���ۨ��t"��Y9��u��0Ti��P�]/�Z�03�vh���ڸ�B�8*�v�@�
2
+ �v-�Y5[�Q�3fG�)8T{)+����C[2������ъ�ߌ �q��a��_��9���,��:�D�6���A����i�5i�@��Uv��e�?�����d��$�Bí�%y ���d�2/9�
metadata ADDED
@@ -0,0 +1,314 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: token-resolver
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Peter H. Boling
8
+ bindir: exe
9
+ cert_chain:
10
+ - |
11
+ -----BEGIN CERTIFICATE-----
12
+ MIIEgDCCAuigAwIBAgIBATANBgkqhkiG9w0BAQsFADBDMRUwEwYDVQQDDAxwZXRl
13
+ ci5ib2xpbmcxFTATBgoJkiaJk/IsZAEZFgVnbWFpbDETMBEGCgmSJomT8ixkARkW
14
+ A2NvbTAeFw0yNTA1MDQxNTMzMDlaFw00NTA0MjkxNTMzMDlaMEMxFTATBgNVBAMM
15
+ DHBldGVyLmJvbGluZzEVMBMGCgmSJomT8ixkARkWBWdtYWlsMRMwEQYKCZImiZPy
16
+ LGQBGRYDY29tMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAruUoo0WA
17
+ uoNuq6puKWYeRYiZekz/nsDeK5x/0IEirzcCEvaHr3Bmz7rjo1I6On3gGKmiZs61
18
+ LRmQ3oxy77ydmkGTXBjruJB+pQEn7UfLSgQ0xa1/X3kdBZt6RmabFlBxnHkoaGY5
19
+ mZuZ5+Z7walmv6sFD9ajhzj+oIgwWfnEHkXYTR8I6VLN7MRRKGMPoZ/yvOmxb2DN
20
+ coEEHWKO9CvgYpW7asIihl/9GMpKiRkcYPm9dGQzZc6uTwom1COfW0+ZOFrDVBuV
21
+ FMQRPswZcY4Wlq0uEBLPU7hxnCL9nKK6Y9IhdDcz1mY6HZ91WImNslOSI0S8hRpj
22
+ yGOWxQIhBT3fqCBlRIqFQBudrnD9jSNpSGsFvbEijd5ns7Z9ZMehXkXDycpGAUj1
23
+ to/5cuTWWw1JqUWrKJYoifnVhtE1o1DZ+LkPtWxHtz5kjDG/zR3MG0Ula0UOavlD
24
+ qbnbcXPBnwXtTFeZ3C+yrWpE4pGnl3yGkZj9SMTlo9qnTMiPmuWKQDatAgMBAAGj
25
+ fzB9MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQWBBQE8uWvNbPVNRXZ
26
+ HlgPbc2PCzC4bjAhBgNVHREEGjAYgRZwZXRlci5ib2xpbmdAZ21haWwuY29tMCEG
27
+ A1UdEgQaMBiBFnBldGVyLmJvbGluZ0BnbWFpbC5jb20wDQYJKoZIhvcNAQELBQAD
28
+ ggGBAJbnUwfJQFPkBgH9cL7hoBfRtmWiCvdqdjeTmi04u8zVNCUox0A4gT982DE9
29
+ wmuN12LpdajxZONqbXuzZvc+nb0StFwmFYZG6iDwaf4BPywm2e/Vmq0YG45vZXGR
30
+ L8yMDSK1cQXjmA+ZBKOHKWavxP6Vp7lWvjAhz8RFwqF9GuNIdhv9NpnCAWcMZtpm
31
+ GUPyIWw/Cw/2wZp74QzZj6Npx+LdXoLTF1HMSJXZ7/pkxLCsB8m4EFVdb/IrW/0k
32
+ kNSfjtAfBHO8nLGuqQZVH9IBD1i9K6aSs7pT6TW8itXUIlkIUI2tg5YzW6OFfPzq
33
+ QekSkX3lZfY+HTSp/o+YvKkqWLUV7PQ7xh1ZYDtocpaHwgxe/j3bBqHE+CUPH2vA
34
+ 0V/FwdTRWcwsjVoOJTrYcff8pBZ8r2MvtAc54xfnnhGFzeRHfcltobgFxkAXdE6p
35
+ DVjBtqT23eugOqQ73umLcYDZkc36vnqGxUBSsXrzY9pzV5gGr2I8YUxMqf6ATrZt
36
+ L9nRqA==
37
+ -----END CERTIFICATE-----
38
+ date: 1980-01-02 00:00:00.000000000 Z
39
+ dependencies:
40
+ - !ruby/object:Gem::Dependency
41
+ name: parslet
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '2.0'
47
+ type: :runtime
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '2.0'
54
+ - !ruby/object:Gem::Dependency
55
+ name: version_gem
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '1.1'
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: 1.1.9
64
+ type: :runtime
65
+ prerelease: false
66
+ version_requirements: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - "~>"
69
+ - !ruby/object:Gem::Version
70
+ version: '1.1'
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: 1.1.9
74
+ - !ruby/object:Gem::Dependency
75
+ name: kettle-dev
76
+ requirement: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - "~>"
79
+ - !ruby/object:Gem::Version
80
+ version: '1.2'
81
+ type: :development
82
+ prerelease: false
83
+ version_requirements: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - "~>"
86
+ - !ruby/object:Gem::Version
87
+ version: '1.2'
88
+ - !ruby/object:Gem::Dependency
89
+ name: bundler-audit
90
+ requirement: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - "~>"
93
+ - !ruby/object:Gem::Version
94
+ version: 0.9.2
95
+ type: :development
96
+ prerelease: false
97
+ version_requirements: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - "~>"
100
+ - !ruby/object:Gem::Version
101
+ version: 0.9.2
102
+ - !ruby/object:Gem::Dependency
103
+ name: rake
104
+ requirement: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - "~>"
107
+ - !ruby/object:Gem::Version
108
+ version: '13.0'
109
+ type: :development
110
+ prerelease: false
111
+ version_requirements: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - "~>"
114
+ - !ruby/object:Gem::Version
115
+ version: '13.0'
116
+ - !ruby/object:Gem::Dependency
117
+ name: require_bench
118
+ requirement: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - "~>"
121
+ - !ruby/object:Gem::Version
122
+ version: '1.0'
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ version: 1.0.4
126
+ type: :development
127
+ prerelease: false
128
+ version_requirements: !ruby/object:Gem::Requirement
129
+ requirements:
130
+ - - "~>"
131
+ - !ruby/object:Gem::Version
132
+ version: '1.0'
133
+ - - ">="
134
+ - !ruby/object:Gem::Version
135
+ version: 1.0.4
136
+ - !ruby/object:Gem::Dependency
137
+ name: appraisal2
138
+ requirement: !ruby/object:Gem::Requirement
139
+ requirements:
140
+ - - "~>"
141
+ - !ruby/object:Gem::Version
142
+ version: '3.0'
143
+ - - "~>"
144
+ - !ruby/object:Gem::Version
145
+ version: 3.0.6
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - "~>"
151
+ - !ruby/object:Gem::Version
152
+ version: '3.0'
153
+ - - "~>"
154
+ - !ruby/object:Gem::Version
155
+ version: 3.0.6
156
+ - !ruby/object:Gem::Dependency
157
+ name: kettle-test
158
+ requirement: !ruby/object:Gem::Requirement
159
+ requirements:
160
+ - - "~>"
161
+ - !ruby/object:Gem::Version
162
+ version: '1.0'
163
+ - - ">="
164
+ - !ruby/object:Gem::Version
165
+ version: 1.0.10
166
+ type: :development
167
+ prerelease: false
168
+ version_requirements: !ruby/object:Gem::Requirement
169
+ requirements:
170
+ - - "~>"
171
+ - !ruby/object:Gem::Version
172
+ version: '1.0'
173
+ - - ">="
174
+ - !ruby/object:Gem::Version
175
+ version: 1.0.10
176
+ - !ruby/object:Gem::Dependency
177
+ name: ruby-progressbar
178
+ requirement: !ruby/object:Gem::Requirement
179
+ requirements:
180
+ - - "~>"
181
+ - !ruby/object:Gem::Version
182
+ version: '1.13'
183
+ type: :development
184
+ prerelease: false
185
+ version_requirements: !ruby/object:Gem::Requirement
186
+ requirements:
187
+ - - "~>"
188
+ - !ruby/object:Gem::Version
189
+ version: '1.13'
190
+ - !ruby/object:Gem::Dependency
191
+ name: stone_checksums
192
+ requirement: !ruby/object:Gem::Requirement
193
+ requirements:
194
+ - - "~>"
195
+ - !ruby/object:Gem::Version
196
+ version: '1.0'
197
+ - - ">="
198
+ - !ruby/object:Gem::Version
199
+ version: 1.0.3
200
+ type: :development
201
+ prerelease: false
202
+ version_requirements: !ruby/object:Gem::Requirement
203
+ requirements:
204
+ - - "~>"
205
+ - !ruby/object:Gem::Version
206
+ version: '1.0'
207
+ - - ">="
208
+ - !ruby/object:Gem::Version
209
+ version: 1.0.3
210
+ - !ruby/object:Gem::Dependency
211
+ name: gitmoji-regex
212
+ requirement: !ruby/object:Gem::Requirement
213
+ requirements:
214
+ - - "~>"
215
+ - !ruby/object:Gem::Version
216
+ version: '1.0'
217
+ - - ">="
218
+ - !ruby/object:Gem::Version
219
+ version: 1.0.3
220
+ type: :development
221
+ prerelease: false
222
+ version_requirements: !ruby/object:Gem::Requirement
223
+ requirements:
224
+ - - "~>"
225
+ - !ruby/object:Gem::Version
226
+ version: '1.0'
227
+ - - ">="
228
+ - !ruby/object:Gem::Version
229
+ version: 1.0.3
230
+ description: "\U0001FA99 Token::Resolver provides configurable PEG-based (parslet)
231
+ parsing and resolution of structured tokens (e.g., {KJ|GEM_NAME}) in arbitrary text.
232
+ Useful for template ETL pipelines where tokens in template files must be resolved
233
+ before format-specific merging."
234
+ email:
235
+ - floss@galtzo.com
236
+ executables: []
237
+ extensions: []
238
+ extra_rdoc_files:
239
+ - CHANGELOG.md
240
+ - CITATION.cff
241
+ - CODE_OF_CONDUCT.md
242
+ - CONTRIBUTING.md
243
+ - FUNDING.md
244
+ - LICENSE.txt
245
+ - README.md
246
+ - REEK
247
+ - RUBOCOP.md
248
+ - SECURITY.md
249
+ files:
250
+ - CHANGELOG.md
251
+ - CITATION.cff
252
+ - CODE_OF_CONDUCT.md
253
+ - CONTRIBUTING.md
254
+ - FUNDING.md
255
+ - LICENSE.txt
256
+ - README.md
257
+ - REEK
258
+ - RUBOCOP.md
259
+ - SECURITY.md
260
+ - lib/token-resolver.rb
261
+ - lib/token/resolver.rb
262
+ - lib/token/resolver/config.rb
263
+ - lib/token/resolver/document.rb
264
+ - lib/token/resolver/grammar.rb
265
+ - lib/token/resolver/node.rb
266
+ - lib/token/resolver/node/text.rb
267
+ - lib/token/resolver/node/token.rb
268
+ - lib/token/resolver/resolve.rb
269
+ - lib/token/resolver/transform.rb
270
+ - lib/token/resolver/version.rb
271
+ - sig/token/resolver.rbs
272
+ homepage: https://github.com/kettle-rb/token-resolver
273
+ licenses:
274
+ - MIT
275
+ metadata:
276
+ homepage_uri: https://token-resolver.galtzo.com/
277
+ source_code_uri: https://github.com/kettle-rb/token-resolver/tree/v1.0.0
278
+ changelog_uri: https://github.com/kettle-rb/token-resolver/blob/v1.0.0/CHANGELOG.md
279
+ bug_tracker_uri: https://github.com/kettle-rb/token-resolver/issues
280
+ documentation_uri: https://www.rubydoc.info/gems/token-resolver/1.0.0
281
+ funding_uri: https://github.com/sponsors/pboling
282
+ wiki_uri: https://github.com/kettle-rb/token-resolver/wiki
283
+ news_uri: https://www.railsbling.com/tags/token-resolver
284
+ discord_uri: https://discord.gg/3qme4XHNKN
285
+ rubygems_mfa_required: 'true'
286
+ rdoc_options:
287
+ - "--title"
288
+ - "token-resolver - \U0001FA99 Configurable PEG-based token parser and resolver for
289
+ structured token detection and replacement in arbitrary text"
290
+ - "--main"
291
+ - README.md
292
+ - "--exclude"
293
+ - "^sig/"
294
+ - "--line-numbers"
295
+ - "--inline-source"
296
+ - "--quiet"
297
+ require_paths:
298
+ - lib
299
+ required_ruby_version: !ruby/object:Gem::Requirement
300
+ requirements:
301
+ - - ">="
302
+ - !ruby/object:Gem::Version
303
+ version: 3.2.0
304
+ required_rubygems_version: !ruby/object:Gem::Requirement
305
+ requirements:
306
+ - - ">="
307
+ - !ruby/object:Gem::Version
308
+ version: '0'
309
+ requirements: []
310
+ rubygems_version: 4.0.5
311
+ specification_version: 4
312
+ summary: "\U0001FA99 Configurable PEG-based token parser and resolver for structured
313
+ token detection and replacement in arbitrary text"
314
+ test_files: []
metadata.gz.sig ADDED
Binary file