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.
- checksums.yaml +7 -0
- checksums.yaml.gz.sig +0 -0
- data/CHANGELOG.md +48 -0
- data/CITATION.cff +20 -0
- data/CODE_OF_CONDUCT.md +134 -0
- data/CONTRIBUTING.md +227 -0
- data/FUNDING.md +74 -0
- data/LICENSE.txt +21 -0
- data/README.md +645 -0
- data/REEK +0 -0
- data/RUBOCOP.md +71 -0
- data/SECURITY.md +21 -0
- data/lib/token/resolver/config.rb +134 -0
- data/lib/token/resolver/document.rb +82 -0
- data/lib/token/resolver/grammar.rb +122 -0
- data/lib/token/resolver/node/text.rb +63 -0
- data/lib/token/resolver/node/token.rb +107 -0
- data/lib/token/resolver/node.rb +11 -0
- data/lib/token/resolver/resolve.rb +93 -0
- data/lib/token/resolver/transform.rb +100 -0
- data/lib/token/resolver/version.rb +12 -0
- data/lib/token/resolver.rb +90 -0
- data/lib/token-resolver.rb +4 -0
- data/sig/token/resolver.rbs +6 -0
- data.tar.gz.sig +2 -0
- metadata +314 -0
- metadata.gz.sig +0 -0
|
@@ -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
|
data.tar.gz.sig
ADDED
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
|