curly_bracket_parser 0.0.1 → 0.9.9

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: 437e9b2cda38fa373852f4b2f67a35428f99d5c78928820b539ae8c5ecf77d09
4
- data.tar.gz: b11dd97f668eff6128b5ae0a9846189c7a8e6291953e7a475080fe705247e9f3
3
+ metadata.gz: c287b3fc82c91116b7c0ca2f982b81bac5c37e4ca286cd1ea8606de75e0c214f
4
+ data.tar.gz: 04f59765b1f59ea540d1e152bbc88c0294ca5adc681f30bf1efed3a117cb3afa
5
5
  SHA512:
6
- metadata.gz: d8286bc6b15346a2babed4de6894be8fadad6c84c9d51ad759fdae906ecec41fdc50d28cf294fb3f8f1b67b6745bf6206e95d337f743ed82fc488cd77b4c6bea
7
- data.tar.gz: 3aab318c0069bf40f73443eefb0245e53c35bbddfb6373883e921ae32e3ebd1b26050319ab24e6336baf98283023ee9232a36dd2655745ee3b018170836a490d
6
+ metadata.gz: 685345c3a8551e0749742550f2dae6784501fefa07318b8e76b2b30fd743c96d1571d2550bee0731a1c1609d82055ec39ff943a6aebf3c39db435d4686d8e01c
7
+ data.tar.gz: a19c4ffb4fe23ce4945023604aeb34ee28a88bd6f89cf2df08f5eab63151fbb0f1ec6b7ec337f6cc8c0b8d2b57c8dacbfec19cbec7b70b22d68cc8b4caf965c6
data/README.md CHANGED
@@ -1,9 +1,10 @@
1
1
  # curly_bracket_parser
2
2
 
3
- Simple parser to replace curly brackets {{like_this}} inside strings like URLs, Texts or even files easily.
3
+ Ruby gem providing a simple parser to replace curly brackets `{{like_this}}` inside strings like URLs, texts or even files easily.
4
4
 
5
- alpha version ... to be done ...
5
+ Additional support for build-in filters and custom filters make them more powerful. `{{example|my_filter}}`
6
6
 
7
+ Using [LuckyCase](https://github.com/magynhard/lucky_case), all its case formats are supported as filter by default.
7
8
 
8
9
 
9
10
 
@@ -12,7 +13,7 @@ alpha version ... to be done ...
12
13
  # Contents
13
14
 
14
15
  * [Installation](#installation)
15
- * [Usage](#usage)
16
+ * [Usage examples](#usage)
16
17
  * [Documentation](#documentation)
17
18
  * [Contributing](#contributing)
18
19
 
@@ -36,23 +37,13 @@ Or install it yourself as:
36
37
 
37
38
  $ gem install curly_bracket_parser
38
39
 
39
- ## Common information
40
-
41
- TODO
42
-
43
-
44
-
45
-
46
-
47
40
 
48
41
  <a name="usage"></a>
49
- ## Usage
42
+ ## Usage examples
50
43
 
51
- TODO
44
+ You can either parse variables inside strings or even directly in files.
52
45
 
53
- ### Examples
54
-
55
- #### Basic
46
+ ### Basic
56
47
 
57
48
  ```ruby
58
49
  url = "https://my-domain.com/items/{{item_id}}"
@@ -60,7 +51,7 @@ TODO
60
51
  # => "https://my-domain.com/items/123"
61
52
  ```
62
53
 
63
- #### Filters
54
+ ### Filters
64
55
 
65
56
  ```ruby
66
57
  url = "https://my-domain.com/catalog/{{item_name|snake_case}}"
@@ -68,9 +59,51 @@ TODO
68
59
  # => "https://my-domain.com/catalog/mega_super_item"
69
60
  ```
70
61
 
71
- #### Globals
62
+ For a list of built-in filters visit [LuckyCase](https://github.com/magynhard/lucky_case).
63
+
64
+ #### Define your custom filter
65
+
66
+ ```ruby
67
+ CurlyBracketParser.register_filter('7times') do |string|
68
+ string.to_s * 7
69
+ end
70
+
71
+ text = "Paul went out and screamed: A{{scream|7times}}h"
72
+ final_text = CurlyBracketParser.parse text, scream: 'a'
73
+ # => "Paul went out and screamed: Aaaaaaaah"
74
+ ```
75
+
76
+ ### Files
77
+
78
+ <ins>test.html</ins>
79
+ ```html
80
+ <h1>{{title|sentence_case}}</h1>
81
+ ```
82
+
83
+ ```ruby
84
+ parsed_file = CurlyBracketParser.parse_file './test.html', title: 'WelcomeAtHome'
85
+ # => "<h1>Welcome at home</h1>"
86
+ ```
87
+
88
+ Use `#parse_file!` instead to write the parsed string directly into the file!
89
+
90
+ ### Default variables
91
+
92
+ You can define default variables, which will be replaced automatically without passing them by parameters, but can be overwritten with parameters.
72
93
 
73
- TODO
94
+ Because of providing blocks, your variables can dynamically depend on other states (e.g. current date).
95
+
96
+ ```ruby
97
+ CurlyBracketParser.register_default_var('version') do
98
+ '1.0.2'
99
+ end
100
+
101
+ text = "You are running version {{version}}"
102
+ CurlyBracketParser.parse text
103
+ # => "You are running version 1.0.2"
104
+ CurlyBracketParser.parse text, version: '0.7.0'
105
+ # => "You are running version 0.7.0"
106
+ ```
74
107
 
75
108
 
76
109
 
@@ -1,7 +1,11 @@
1
1
  require 'lucky_case'
2
2
 
3
3
  require 'curly_bracket_parser/version'
4
+ require_relative 'custom_errors/filter_already_registered_error'
5
+ require_relative 'custom_errors/invalid_filter_error'
6
+ require_relative 'custom_errors/invalid_variable_error'
4
7
  require_relative 'custom_errors/unresolved_variables_error'
8
+ require_relative 'custom_errors/variable_already_registered_error'
5
9
 
6
10
  #
7
11
  # CurlyBracketParser
@@ -17,25 +21,37 @@ module CurlyBracketParser
17
21
  VARIABLE_DECODER_REGEX = /{{([^{}\|]+)\|?([^{}\|]*)}}/
18
22
  VARIABLE_REGEX = /{{[^{}]+}}/
19
23
 
20
- VALID_FILTERS = [
21
- LuckyCase::CASES.keys.map(&:to_s)
24
+ VALID_DEFAULT_FILTERS = [
25
+ LuckyCase::CASES.keys.map(&:to_s)
22
26
  ].flatten
23
27
 
24
28
  #----------------------------------------------------------------------------------------------------
25
29
 
30
+ # Parse given string and replace the included variables by the given variables
31
+ #
26
32
  # @param [String] string to parse
27
33
  # @param [Hash<Symbol => String>] variables <key: 'value'>
28
34
  # @param [Symbol] unresolved_vars :raise, :keep, :replace => define how to act when unresolved variables within the string are found.
29
- # @param [String] replace_pattern pattern used when param unresolved_vars is set to :replace. You can include the var name \\1 and filter \\1. Empty string to remove unresolved variables.
35
+ # @param [String] replace_pattern pattern used when param unresolved_vars is set to :replace. You can include the var name \\1 and filter \\2. Empty string to remove unresolved variables.
30
36
  # @return [String, UnresolvedVariablesError] parsed string
31
37
  def self.parse(string, variables, unresolved_vars: :raise, replace_pattern: "##\\1##")
38
+ variables ||= {}
32
39
  result_string = string.clone
33
40
  if CurlyBracketParser.any_variable_included? string
34
41
  loop do
35
42
  variables(string).each do |string_var|
36
- name, filter = decode_variable(string_var)
43
+ dec = decode_variable(string_var)
44
+ name = dec[:name]
45
+ filter = dec[:filter]
37
46
  if variables[name.to_sym]
38
- value = process_filter(variables[name.to_sym], filter)
47
+ value = if filter
48
+ process_filter(filter, variables[name.to_sym])
49
+ else
50
+ variables[name.to_sym]
51
+ end
52
+ result_string.gsub!(string_var, value)
53
+ elsif registered_default_var?(name.to_s)
54
+ value = process_default_var(name)
39
55
  result_string.gsub!(string_var, value)
40
56
  end
41
57
  end
@@ -56,45 +72,178 @@ module CurlyBracketParser
56
72
 
57
73
  #----------------------------------------------------------------------------------------------------
58
74
 
59
- def self.parse_file(path, variables, options = {})
60
- raise "NOT IMPLEMENTED YET!"
75
+ # Parse the content of the file of the given path with #parse and return it.
76
+ # The original file keeps unmodified.
77
+ #
78
+ # @param [String] string to parse
79
+ # @param [Hash<Symbol => String>] variables <key: 'value'>
80
+ # @param [Symbol] unresolved_vars :raise, :keep, :replace => define how to act when unresolved variables within the string are found.
81
+ # @param [String] replace_pattern pattern used when param unresolved_vars is set to :replace. You can include the var name \\1 and filter \\1. Empty string to remove unresolved variables.
82
+ # @return [String, UnresolvedVariablesError] parsed string
83
+ def self.parse_file(path, variables, unresolved_vars: :raise, replace_pattern: "##\\1##")
84
+ file_content = File.read path
85
+ parse(file_content, variables, unresolved_vars: unresolved_vars, replace_pattern: replace_pattern)
86
+ end
87
+
88
+ # Parse the content of the file of the given path with #parse and return it.
89
+ # The original file will be overwritten by the parsed content.
90
+ #
91
+ # @param [String] string to parse
92
+ # @param [Hash<Symbol => String>] variables <key: 'value'>
93
+ # @param [Symbol] unresolved_vars :raise, :keep, :replace => define how to act when unresolved variables within the string are found.
94
+ # @param [String] replace_pattern pattern used when param unresolved_vars is set to :replace. You can include the var name \\1 and filter \\1. Empty string to remove unresolved variables.
95
+ # @return [String, UnresolvedVariablesError] parsed string
96
+ def self.parse_file!(path, variables, unresolved_vars: :raise, replace_pattern: "##\\1##")
97
+ parsed_file = parse_file path, variables, unresolved_vars: unresolved_vars, replace_pattern: replace_pattern
98
+ File.write path, parsed_file
99
+ parsed_file
100
+ end
101
+
102
+ #----------------------------------------------------------------------------------------------------
103
+
104
+ # Register your custom filter to the filter list
105
+ #
106
+ # @param [String] filter name of the filter, also used then in your strings, e.g. {{var_name|my_filter_name}}
107
+ # @param [Lambda] function of the filter to run the variable against
108
+ # @raise [FilterAlreadyRegisteredError] if filter does already exist
109
+ # @return [Proc] given block
110
+ def self.register_filter(filter, &block)
111
+ @@registered_filters ||= {}
112
+ filter = filter.to_s
113
+ if valid_filter?(filter)
114
+ raise FilterAlreadyRegisteredError, "The given filter name '#{filter}' is already registered"
115
+ else
116
+ @@registered_filters[filter] = block
117
+ end
61
118
  end
62
119
 
63
- def self.parse_file!(path, variables, options = {})
64
- raise "NOT IMPLEMENTED YET!"
120
+ #----------------------------------------------------------------------------------------------------
121
+
122
+ # Process the given value with the given filter
123
+ #
124
+ # @param [String] filter name of the filter, also used then in your strings, e.g. {{var_name|my_filter_name}}
125
+ # @param [String] value string to apply the specified filter on
126
+ # @return [String] converted string with applied filter
127
+ def self.process_filter(filter, value)
128
+ @@registered_filters ||= {}
129
+ filter = filter.to_s
130
+ if @@registered_filters[filter]
131
+ @@registered_filters[filter].call(value)
132
+ elsif VALID_DEFAULT_FILTERS.include?(filter) && LuckyCase.valid_case_type?(filter)
133
+ LuckyCase.convert_case(value, filter)
134
+ else
135
+ message = "Invalid filter '#{filter}'. Valid filters are: #{self.valid_filters.join(' ')}"
136
+ raise InvalidFilterError, message
137
+ end
65
138
  end
66
139
 
67
140
  #----------------------------------------------------------------------------------------------------
68
141
 
69
- def self.register_filter(name, function)
70
- raise "NOT IMPLEMENTED YET!"
142
+ # Retrieve Array with valid filters
143
+ #
144
+ # @return [Array<String>] of valid filters
145
+ def self.valid_filters
146
+ all_filters = VALID_DEFAULT_FILTERS
147
+ @@registered_filters ||= {}
148
+ all_filters + @@registered_filters.keys.map(&:to_s)
71
149
  end
72
150
 
73
151
  #----------------------------------------------------------------------------------------------------
74
152
 
75
- def self.register_default_variable(name, function)
76
- raise "NOT IMPLEMENTED YET!"
153
+ # Check if a given filter is valid
154
+ #
155
+ # @param [String] name
156
+ # @return [Boolean] true if filter exists, otherwise false
157
+ def self.valid_filter?(name)
158
+ self.valid_filters.include? name
77
159
  end
78
160
 
79
161
  #----------------------------------------------------------------------------------------------------
80
162
 
81
- def self.process_filter(value, filter)
82
- return value unless filter
83
- if VALID_FILTERS.include? filter
84
- if LuckyCase.valid_case_type? filter
85
- return LuckyCase.convert_case(value, filter)
86
- else
87
- raise "FILTER '#{filter}' NOT IMPLEMENTED YET!"
88
- end
163
+ # Register a default variable to be replaced automatically by the given block value in future
164
+ # If the variable exists already, it will raise an VariableAlreadyRegisteredError
165
+ #
166
+ # @param [String] name of the default var
167
+ # @param [Proc] block
168
+ # @raise [VariableAlreadyRegisteredError] if variable is already registered
169
+ # @return [Proc] given block
170
+ def self.register_default_var(name, &block)
171
+ @@registered_default_vars ||= {}
172
+ name = name.to_s
173
+ if registered_default_var?(name)
174
+ raise VariableAlreadyRegisteredError, "The given variable name '#{name}' is already registered. If you want to override that variable explicitly, call #register_default_var! instead!"
175
+ else
176
+ @@registered_default_vars[name] = block
177
+ end
178
+ end
179
+
180
+ #----------------------------------------------------------------------------------------------------
181
+
182
+ # Return the given default variable by returning the result of its block/proc
183
+ #
184
+ # @param [String] name of the variable to return
185
+ # @return [String] value of the variable
186
+ def self.process_default_var(name)
187
+ @@registered_default_vars ||= {}
188
+ name = name.to_s
189
+ if @@registered_default_vars[name]
190
+ @@registered_default_vars[name].call()
191
+ else
192
+ message = "Invalid default variable '#{name}'. Valid registered default variables are: #{self.registered_default_vars.keys.join(' ')}"
193
+ raise InvalidVariableError, message
194
+ end
195
+ end
196
+
197
+ #----------------------------------------------------------------------------------------------------
198
+
199
+ # Register a default variable to be replaced automatically by the given block value in future
200
+ # If the variable exists already, it will be overwritten
201
+ #
202
+ # @param [String] name of the default var
203
+ # @param [Proc] block
204
+ # @raise [VariableAlreadyRegisteredError] if variable is already registered
205
+ # @return [Proc] given block
206
+ def self.register_default_var!(name, &block)
207
+ @@registered_default_vars ||= {}
208
+ name = name.to_s
209
+ @@registered_default_vars[name] = block
210
+ end
211
+
212
+ #----------------------------------------------------------------------------------------------------
213
+
214
+ # Unregister / remove an existing default variable
215
+ #
216
+ # @param [String] name of the variable
217
+ # @return [Boolean] true if variable existed and was unregistered, false if it didn't exist
218
+ def self.unregister_default_var(name)
219
+ @@registered_default_vars ||= {}
220
+ name = name.to_s
221
+ if @@registered_default_vars[name]
222
+ @@registered_default_vars.delete(name)
223
+ true
89
224
  else
90
- raise "Invalid filter '#{filter}'"
225
+ false
91
226
  end
92
227
  end
93
228
 
94
229
  #----------------------------------------------------------------------------------------------------
95
230
 
96
- def self.has_filter?(variable)
97
- decode_variable(variable)[:filter] != nil
231
+ # Return an array of registered default variables
232
+ #
233
+ # @return [Array<String>]
234
+ def self.registered_default_vars
235
+ @@registered_default_vars ||= {}
236
+ @@registered_default_vars.keys.map(&:to_s)
237
+ end
238
+
239
+ #----------------------------------------------------------------------------------------------------
240
+
241
+ # Check if the given variable is a registered default variable
242
+ #
243
+ # @param [String] name of the variable
244
+ # @return [Boolean] true if variable is registered, otherwise false
245
+ def self.registered_default_var?(name)
246
+ self.registered_default_vars.include? name
98
247
  end
99
248
 
100
249
  #----------------------------------------------------------------------------------------------------
@@ -105,26 +254,30 @@ module CurlyBracketParser
105
254
  # '{{var_name|filter_name}}' => { name: 'var_name', filter: 'filter_name' }
106
255
  #
107
256
  # @param [String] variable
108
- # @return [Array(String, String)] name, filter
257
+ # @return [Hash<String => String>] name, filter
109
258
  def self.decode_variable(variable)
110
- var = decoded_variables(variable).first
111
- [var.keys.first, var.values.first]
259
+ decoded_variables(variable).first
112
260
  end
113
261
 
114
262
  #----------------------------------------------------------------------------------------------------
115
263
 
116
- # scans the given url for variables with pattern '{{var}}'
264
+ # Scans the given url for variables with pattern '{{var|optional_filter}}'
265
+ #
266
+ # @example
267
+ # 'The variable {{my_var|my_filter}} is inside this string' => [{ name: "my_var", filter: "my_filter"}]
268
+ #
117
269
  # @param [String] string to scan
118
270
  # @return [Array<Hash<Symbol => String>>] array of variable names and its filters
119
271
  def self.decoded_variables(string)
120
- var_name = 0
121
- var_filter = 1
122
- string.scan(VARIABLE_DECODER_REGEX).map { |e| {"#{e[var_name].strip}": e[var_filter].strip != '' ? e[var_filter].strip : nil } }.flatten
272
+ var_name_index = 0
273
+ var_filter_index = 1
274
+ string.scan(VARIABLE_DECODER_REGEX).map { |e| { name: "#{e[var_name_index].strip}", filter: e[var_filter_index].strip != '' ? e[var_filter_index].strip : nil } }.flatten
123
275
  end
124
276
 
125
277
  #----------------------------------------------------------------------------------------------------
126
278
 
127
- # scans the given url for variables with pattern '{{var}}'
279
+ # Scans the given url for variables with pattern '{{var|optional_filter}}'
280
+ #
128
281
  # @param [String] string to scan
129
282
  # @return [Array<String>] array of variable names and its filters
130
283
  def self.variables(string)
@@ -133,12 +286,21 @@ module CurlyBracketParser
133
286
 
134
287
  #----------------------------------------------------------------------------------------------------
135
288
 
289
+ # Check if any variable is included in the given string
290
+ #
291
+ # @param [String] string name of variable to check for
292
+ # @return [Boolean] true if any variable is included in the given string, otherwise false
136
293
  def self.any_variable_included?(string)
137
294
  string.match(VARIABLE_REGEX) != nil
138
295
  end
139
296
 
140
297
  #----------------------------------------------------------------------------------------------------
141
298
 
299
+ # Check if one of the given variable names is included in the given string
300
+ #
301
+ # @param [Array<String>] variable_names
302
+ # @param [String] string name of variable to check for
303
+ # @return [Boolean] true if one given variable name is included in given the string, otherwise false
142
304
  def self.includes_one_variable_of(variable_names, string)
143
305
  decoded_variables(string).each do |dvar|
144
306
  return true if variable_names.include?(dvar[:name])
@@ -1,3 +1,3 @@
1
1
  module CurlyBracketParser
2
- VERSION = '0.0.1'.freeze
2
+ VERSION = '0.9.9'.freeze
3
3
  end
@@ -0,0 +1,2 @@
1
+ class FilterAlreadyRegisteredError < StandardError
2
+ end
@@ -0,0 +1,2 @@
1
+ class InvalidFilterError < StandardError
2
+ end
@@ -0,0 +1,2 @@
1
+ class InvalidVariableError < StandardError
2
+ end
@@ -0,0 +1,2 @@
1
+ class VariableAlreadyRegisteredError < StandardError
2
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: curly_bracket_parser
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.9.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matthäus Beyrle
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-08-17 00:00:00.000000000 Z
11
+ date: 2021-01-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: lucky_case
@@ -85,7 +85,11 @@ files:
85
85
  - curly_bracket_parser.gemspec
86
86
  - lib/curly_bracket_parser.rb
87
87
  - lib/curly_bracket_parser/version.rb
88
+ - lib/custom_errors/filter_already_registered_error.rb
89
+ - lib/custom_errors/invalid_filter_error.rb
90
+ - lib/custom_errors/invalid_variable_error.rb
88
91
  - lib/custom_errors/unresolved_variables_error.rb
92
+ - lib/custom_errors/variable_already_registered_error.rb
89
93
  homepage: https://github.com/magynhard/curly_bracket_parser
90
94
  licenses:
91
95
  - MIT