cecil 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 7aebd276ab6179fdf0fda6e2f2e5931ce8ca8a6ae1ba6921dc4aef92e408419c
4
+ data.tar.gz: bb381be1145ef880aa4348a156166c82eb51bc3e8cae94545683fbe928207d0a
5
+ SHA512:
6
+ metadata.gz: f311e7689597ca7d98bd9db7912d48e6bcc1105b73af29966ba4fc291ef77a0a0aedb6701a3700455b88ec9df8b8efc87e42467f7a4f2a612ab0d411fdc070c9
7
+ data.tar.gz: 9651d08d7bc741d6ee1548d89e0e87ab17bcd28aed7a91eb5715dad7741e5f97fc24bbc7da0c57a34691874bf6e010b45472bf3519dc4d85e9154655634c6a48
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/.rubocop.yml ADDED
@@ -0,0 +1,25 @@
1
+ AllCops:
2
+ TargetRubyVersion: 3.1
3
+ NewCops: enable
4
+
5
+ Style/StringLiterals:
6
+ Enabled: true
7
+ EnforcedStyle: double_quotes
8
+
9
+ Style/StringLiteralsInInterpolation:
10
+ Enabled: true
11
+ EnforcedStyle: double_quotes
12
+
13
+ Lint/AssignmentInCondition: { Enabled: false }
14
+ Metrics/AbcSize: { Enabled: false }
15
+ Metrics/BlockLength: { Enabled: false }
16
+ Metrics/ClassLength: { Enabled: false }
17
+ Metrics/CyclomaticComplexity: { Enabled: false }
18
+ Metrics/MethodLength: { Enabled: false }
19
+ Metrics/PerceivedComplexity: { Enabled: false }
20
+ Style/Documentation: { Enabled: false }
21
+ Style/FrozenStringLiteralComment: { Enabled: false }
22
+ Style/NumericPredicate: { Enabled: false }
23
+
24
+ Layout/LineLength:
25
+ Max: 120
data/.tool-versions ADDED
@@ -0,0 +1 @@
1
+ ruby 3.1.4
data/.yard/README.md ADDED
@@ -0,0 +1,492 @@
1
+ # Cecil
2
+
3
+ An experimental templating library for generating source code.
4
+
5
+ Cecil templates look like the source code you want to generate thanks to Ruby's flexible syntax.
6
+
7
+ ## Features
8
+
9
+ ### Write templates in plain Ruby
10
+
11
+ Call `Cecil::Code.generate_string` and pass it a block. Inside the block, add lines of code via backticks (or use `src` if you prefer). Cecil returns your generated source code as a string.
12
+
13
+ #### Example
14
+
15
+ ```ruby
16
+ model_code = Cecil::Code.generate_string do
17
+ # Use backticks to add lines of code
18
+ `import Model from '../model'`
19
+
20
+ # Multi-line strings work, too.
21
+ # Cecil preserves indentation.
22
+ `class User extends Model {
23
+ id: number
24
+ name: string
25
+ companyId: number | undefined
26
+ }`
27
+
28
+ # use #src if you prefer to avoid backticks
29
+ src "export type Username = User['name']"
30
+ end
31
+
32
+ puts model_code
33
+ ```
34
+
35
+ Returns:
36
+
37
+ ```typescript
38
+ import Model from '../model'
39
+ class User extends Model {
40
+ id: number
41
+ name: string
42
+ companyId: number | undefined
43
+ }
44
+ export type Username = User['name']
45
+ ```
46
+
47
+ ### Interpolate values with Cecil's low-noise syntax
48
+
49
+ Use `#[]` on the backticks to replace placeholders with actual values.
50
+
51
+ By default, placeholders start with `$` and are followed by an identifier.
52
+
53
+ Positional arguments match up with placeholders in order. Named arguments match placeholders by name.
54
+
55
+ #### Example
56
+
57
+ ```ruby
58
+ field = "user"
59
+ types = ["string", "string[]"]
60
+ default_value = ["SilentHaiku", "DriftingSnowfall"]
61
+ field_class = "Model"
62
+
63
+ Cecil::Code.generate_string do
64
+ # positional arguments match placeholders by position
65
+ `let $field: $FieldType = $default`[field, types.join('|'), default_value.sort.to_json]
66
+
67
+ # named arguments match placeholders by name
68
+ `let $field: $FieldClass<$Types> = new $FieldClass($default)`[
69
+ field: field,
70
+ FieldClass: field_class,
71
+ Types: types.join('|'),
72
+ default: default_value.sort.to_json
73
+ ]
74
+ end
75
+ ```
76
+
77
+ Returns:
78
+
79
+ ```typescript
80
+ let user: string|string[] = ["DriftingSnowfall","SilentHaiku"]
81
+ let user: Model<string|string[]> = new Model(["DriftingSnowfall","SilentHaiku"])
82
+ ```
83
+
84
+
85
+ #### "Doesn't Ruby already have string interpolation?"
86
+
87
+ Yes, but compare the readability of these two approaches:
88
+
89
+ ```ruby
90
+ `let $field: $FieldClass<$Types> = new $FieldClass($default)`[
91
+ field: field,
92
+ FieldClass: field_class,
93
+ Types: types.join('|'),
94
+ default: default_value.sort.to_json
95
+ ]
96
+
97
+ # vs
98
+
99
+ field_types = types.join('|'),
100
+ default_json = default_value.sort.to_json
101
+ "let #{field}: #{field_class}<#{field_types}> = new #{field_class}(#{default_json})"
102
+ ```
103
+
104
+ ### Indents code blocks & closes brackets automatically
105
+
106
+ Pass a block to `#[]` gets indented and open brackets get closed automatically.
107
+
108
+ #### Example
109
+
110
+ ```ruby
111
+ model = "User"
112
+ field_name = "name"
113
+ field_default = "Unnamed"
114
+
115
+ Cecil::Code.generate_string do
116
+ `class $Class extends Model {`[model] do
117
+ # indentation is preserved
118
+ `id: number`
119
+
120
+ `override get $field() {`[field_name] do
121
+ `return super.$field ?? $defaultValue`[field_name, field_default.to_json]
122
+ end
123
+ end # the open bracket from `... Model {` gets closed with "}"
124
+ end
125
+ ```
126
+
127
+ Returns:
128
+
129
+ ```typescript
130
+ class User extends Model {
131
+ id: number
132
+ override get name() {
133
+ return super.name ?? "Unnamed"
134
+ }
135
+ }
136
+ ```
137
+
138
+ ### Emit source code to other locations
139
+
140
+ When generating source code, things like functions, parameters, classes, etc, often need to be declared, imported, or otherwise setup or before being used.
141
+
142
+ `content_for` can be used to add content to a different location of your file.
143
+
144
+ Call `content_for(some_key) { ... }` with key and a block to store content under the key you provide. Call `content_for(some_key)` with the key and *no* block to insert your stored content at that location.
145
+
146
+ #### Example
147
+
148
+ ```ruby
149
+ models = [
150
+ { name: 'User', inherits: 'AuthModel' },
151
+ { name: 'Company', inherits: 'Model' },
152
+ ]
153
+
154
+ Cecil::Code.generate_string do
155
+ # insert content collected for :imports
156
+ content_for :imports
157
+
158
+ models.each do |model|
159
+ ``
160
+ `class $Class extends $SuperClass {`[model[:name], model[:inherits]] do
161
+ `id: number`
162
+ end
163
+
164
+ content_for :imports do
165
+ # this gets inserted above
166
+ `import $SuperClass from '../models/$SuperClass'`[SuperClass: model[:inherits]]
167
+ end
168
+
169
+ content_for :registrations do
170
+ # this gets inserted below
171
+ `$SuperClass.registerAncestor($Class)`[model[:inherits], model[:name]]
172
+ end
173
+ end
174
+
175
+ ``
176
+ # insert content collected for :registrations
177
+ content_for :registrations
178
+ end
179
+ ```
180
+
181
+ Returns:
182
+
183
+ ```typescript
184
+ import AuthModel from '../models/AuthModel'
185
+ import Model from '../models/Model'
186
+
187
+ class User extends AuthModel {
188
+ id: number
189
+ }
190
+
191
+ class Company extends Model {
192
+ id: number
193
+ }
194
+
195
+ AuthModel.registerAncestor(User)
196
+ Model.registerAncestor(Company)
197
+ ```
198
+
199
+ ### Collect data as you go then use it earlier in the document
200
+
201
+ The `#defer` method takes a block and waits to call it until the rest of the template is evaluated. The block's result is inserted at the location where `#defer` was called.
202
+
203
+ This gives a similar ability to `#content_for`, but is more flexible because you can collect any kind of data, not just source code.
204
+
205
+ #### Example
206
+
207
+ ```ruby
208
+ models = [
209
+ { name: 'User', inherits: 'AuthModel' },
210
+ { name: 'Company', inherits: 'Model' },
211
+ { name: 'Candidate', inherits: 'AuthModel' },
212
+ ]
213
+
214
+ Cecil::Code.generate_string do
215
+ superclasses = []
216
+
217
+ defer do
218
+ # This block gets called after the rest of the parent block is finished.
219
+ #
220
+ # By the time this block is called, the `superclasses` array is full of data
221
+ #
222
+ # Even though this block is called later, the output is added at the location where `defer` was called
223
+ `import { $SuperClasses } from '../models'`[superclasses.uniq.sort.join(', ')]
224
+ ``
225
+ end
226
+
227
+ models.each do |model|
228
+ superclasses << model[:inherits] # add more strings to `superclasses`, which is used in the block above
229
+
230
+ `class $Class extends $SuperClass {}`[model[:name], model[:inherits]]
231
+ end
232
+ end
233
+ ```
234
+
235
+ Returns:
236
+
237
+ ```typescript
238
+ import { AuthModel, Model } from '../models'
239
+
240
+ class User extends AuthModel {}
241
+ class Company extends Model {}
242
+ class Candidate extends AuthModel {}
243
+ ```
244
+
245
+ ### Customizable syntax and behaviors
246
+
247
+ Easily customize the following features to make Cecil suit your needs/preferences:
248
+
249
+ - placeholder syntax
250
+ - auto-closing brackets
251
+ - indentation
252
+
253
+ Customizations are performed by subclassing {Cecil::Code `Cecil::Code`} and overriding the relevant methods.
254
+
255
+ For example, Cecil comes with {Cecil::Lang::TypeScript `Cecil::Lang::TypeScript`} that you can use instead of of `Cecil::Code`. It has a few JavaScript/TypeScript-specific customizations. It's a subclass of `Cecil::Code` so it can be used the same way:
256
+
257
+ ```ruby
258
+ Cecil::Lang::TypeScript.generate_string do
259
+ # ...
260
+ end
261
+ ```
262
+
263
+ ## Use cases
264
+
265
+ Things I've personally used Cecil to generate:
266
+
267
+ - **serialization/deserialization code** generated from from specs (e.g. OpenAPI)
268
+ - **diagrams** (e.g. Mermaid, PlantUML, Dot/Graphviz)
269
+ - ERDs/schemas
270
+ - state machine diagrams
271
+ - graphs
272
+ - data visualizations
273
+ - **state machines** generated from a list of states and transitions
274
+ - **test cases** generated from data that describes inputs/setup and expected outputs; because parameterized tests can be very hard to debug
275
+ - **complex types** because meta-programming in TypeScript can get complex quickly
276
+
277
+ ## Quick Reference
278
+
279
+ Reference documentation is on RubyDoc.info:
280
+ [gem](https://www.rubydoc.info/gems/cecil)
281
+ |
282
+ [repo](https://www.rubydoc.info/github/nicholaides/cecil/main)
283
+
284
+ ### Calling Cecil
285
+
286
+ Call
287
+ {Cecil::Code.generate `Cecil::Code.generate`} /
288
+ {Cecil::Code.generate_string `generate_string`}
289
+ with a block and inside the block, use backticks or `#src` to emit lines of source code.
290
+ E.g.
291
+
292
+ ```ruby
293
+ # returns a string
294
+ Cecil::Code.generate_string do
295
+ `function greet() {}`
296
+ `function respond() {}`
297
+ end
298
+
299
+ # outputs to $stdout
300
+ Cecil::Code.generate do
301
+ `function greet() {}`
302
+ `function respond() {}`
303
+ end
304
+ ```
305
+
306
+ See: {Cecil::BlockContext Methods available inside a Cecil block}
307
+
308
+ ### Emitting source code
309
+
310
+ - {Cecil::BlockContext#src backticks/``` #`` ```/`#src`} emit source code.
311
+ E.g.:
312
+ ```ruby
313
+ Cecil::Code.generate_string do
314
+ `function greet() {}`
315
+ `function respond() {}`
316
+ src "function ask() {}"
317
+ end
318
+ # outputs:
319
+ # function greet() {}
320
+ # function respond() {}
321
+ # function ask() {}
322
+ ```
323
+
324
+ - {Cecil::Node#with `#[]`} interpolates data into placeholders. E.g.
325
+ ```ruby
326
+ Cecil::Code.generate_string do
327
+ `function $fn() {}`["greet"]
328
+ `function $fn() {}`[fn: "respond"]
329
+ end
330
+ # outputs:
331
+ # function greet() {}
332
+ # function respond() {}
333
+ ```
334
+ - {Cecil::Node#with `#[]`}`{ ... }` given a block, interpolates and indents the code emitted in its block.
335
+ E.g.
336
+ ```ruby
337
+ Cecil::Code.generate_string do
338
+ `function $fn() {`["greet"] do
339
+ `console.log("hello")`
340
+ end
341
+ end
342
+ # outputs:
343
+ # function greet() {
344
+ # console.log("hello")
345
+ # }
346
+ ```
347
+ - {Cecil::Node#<< `#<<`} adds code the last line of the block.
348
+ E.g.
349
+ ```ruby
350
+ Cecil::Code.generate_string do
351
+ `(function ${fn}Now() {`["greet"] do
352
+ `console.log("hello")`
353
+ end << ')()'
354
+ end
355
+ # outputs:
356
+ # (function greetNow() {
357
+ # console.log("hello")
358
+ # })()
359
+ ```
360
+ - {Cecil::BlockContext#content_for `#content_for`} emits source code to different locations
361
+ - {Cecil::BlockContext#defer `#defer`} for waits to emit the given source until after data has been gathered
362
+
363
+ ### Customizing behavior for the language of the source code you're generating
364
+
365
+ Many of Cecil's defaults can be customized by creating a subclass of {Cecil::Code `Cecil::Code`} and overriding methods to customize syntax and behavior of:
366
+ - placeholder syntax
367
+ - indentation
368
+ - auto-closing brackets
369
+
370
+ Currently, Cecil comes with:
371
+ - {Cecil::Code `Cecil::Code`} for generic code
372
+ - {Cecil::Lang::TypeScript `Cecil::Lang::TypeScript`} for JavaScript and TypeScript
373
+
374
+
375
+ ### Auto-closing brackets
376
+
377
+ > Customize which opening brackets are auto-closed by overriding {Cecil::Code#block_ending_pairs `Cecil::Code#block_ending_pairs`} in a subclass.
378
+
379
+ When nesting code blocks with `#[] { ... }`, open brackets at the end of the string get closed automatically.
380
+
381
+ For example, notice how we don't have to manually provide a closing `}` in the following:
382
+
383
+ ```ruby
384
+ `$var = {`[var: "user"] do
385
+ `id: 42`
386
+ end
387
+ ```
388
+ becomes
389
+ ```javascript
390
+ user = {
391
+ id: 42
392
+ }
393
+ ```
394
+
395
+ #### Multiple brackets
396
+
397
+ Every consecutive closing bracket at the end of the string gets closed. E.g.
398
+
399
+ ```ruby
400
+ `$var = [{(`[var: "user"] do
401
+ `id: 42`
402
+ end
403
+ ```
404
+
405
+ becomes
406
+
407
+ ```javascript
408
+ user = ([{
409
+ id: 42
410
+ )}]
411
+ ```
412
+
413
+ Currently, the algorithm is simplistic, so open brackets that aren't at the end of the string will *not* get closed.
414
+
415
+ In this example, the `(` in `test(` needs to be closed manually:
416
+
417
+ ```ruby
418
+ `test("getter $fn", () => {`[fn: 'getUsername'] do
419
+ `assert(false)`
420
+ end << `)'
421
+ ```
422
+
423
+ ```javascript
424
+ test("getter getUsername", () => {
425
+ assert(false)
426
+ })
427
+ ```
428
+
429
+ ### Placeholder syntax
430
+
431
+ Default placeholder rules:
432
+ - start with `$`-- e.g. `$foo`
433
+ - named with alpha-numeric and underscore -- e.g. `$foo_bar123`
434
+ - names can optionally be surrounded by optional brackets -- e.g `${my_placeholder}`
435
+
436
+ Surrounding with brackets can be useful to separate a placeholder from subsequent characters that would otherwise get parsed as a placeholder.
437
+
438
+ E.g. `function ${fn}Sync()`-- without curly brackets, the placeholder would be parsed as `fnSync`.
439
+
440
+ Customize placeholder syntax by subclassing {Cecil::Code `Cecil::Code`}
441
+ and overriding {Cecil::Code placeholder-related methods}.
442
+
443
+
444
+ ### Helper methods
445
+
446
+ If you use your generator frequently it can be helpful to define reusable helper methods on a subclass of {Cecil::Code `Cecil::Code`}.
447
+
448
+ For example, the {Cecil::Lang::TypeScript::Helpers `Cecil::Lang::TypeScript`][{Lang::TypeScript}] subclass defines several [helper methods} for generating TypeScript code.
449
+
450
+ [{BlockContext#content_for}]: https://www.rubydoc.info/github/nicholaides/cecil/main/Cecil/BlockContext#content_for-instance_method
451
+ [{BlockContext#defer}]: https://www.rubydoc.info/github/nicholaides/cecil/main/Cecil/BlockContext#defer-instance_method
452
+ [{BlockContext#src}]: https://www.rubydoc.info/github/nicholaides/cecil/main/Cecil/BlockContext#src-instance_method
453
+ [{BlockContext}]: https://www.rubydoc.info/github/nicholaides/cecil/main/Cecil/BlockContext
454
+ [{Code.generate_string}]: https://www.rubydoc.info/github/nicholaides/cecil/main/Cecil/Code#generate_string-class_method
455
+ [{Code.generate}]: https://www.rubydoc.info/github/nicholaides/cecil/main/Cecil/Code#generate-class_method
456
+ [{Code}]: https://www.rubydoc.info/github/nicholaides/cecil/main/Cecil/Code
457
+ [{Code#block_ending_pairs}]: https://www.rubydoc.info/github/nicholaides/cecil/main/Cecil/Code#block_ending_pairs-instance_method
458
+ [{Lang::TypeScript}]: https://www.rubydoc.info/github/nicholaides/cecil/main/Cecil/Lang/TypeScript
459
+ [{Lang::TypeScript::Helpers}]: https://www.rubydoc.info/github/nicholaides/cecil/main/Cecil/Lang/TypeScript/Helpers
460
+ [{Lang::TypeScript.generate_string}]: https://www.rubydoc.info/github/nicholaides/cecil/main/Cecil/Lang/TypeScript#generate_string-class_method
461
+ [{Lang::TypeScript.generate}]: https://www.rubydoc.info/github/nicholaides/cecil/main/Cecil/Code#generate-class_method
462
+ [{Node#<<}]: https://www.rubydoc.info/github/nicholaides/cecil/main/Cecil/Node#<<-instance_method
463
+ [{Node#with}]: https://www.rubydoc.info/github/nicholaides/cecil/main/Cecil/Node#with-instance_method
464
+
465
+ ## Installation
466
+
467
+ Gem can be installed from github. Once I'm ready to bother with version numbers and releases and such, then I'll publish to Rubygems.
468
+
469
+ From your shell:
470
+
471
+ ```sh
472
+ bundle add cecil --github=nicholaides/cecil
473
+ ```
474
+
475
+ Add it to your Gemfile like:
476
+
477
+ ```ruby
478
+ gem 'cecil', github: 'nicholaides/cecil'
479
+ ```
480
+ ## Development
481
+
482
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
483
+
484
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
485
+
486
+ ## Contributing
487
+
488
+ Bug reports and pull requests are welcome on GitHub at https://github.com/nicholaides/cecil.
489
+
490
+ ## License
491
+
492
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/.yardopts ADDED
@@ -0,0 +1,2 @@
1
+ --markup=markdown
2
+ --readme=.yard/README.md
data/Gemfile ADDED
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ # Specify your gem's dependencies in cecil.gemspec
6
+ gemspec
7
+
8
+ gem "rake", "~> 13.0"
9
+
10
+ gem "rspec", "~> 3.0"
11
+
12
+ gem "rubocop", "~> 1.21"
13
+
14
+ gem "retest", "~> 1.11"
15
+
16
+ gem "yard", "~> 0.9.34"
17
+
18
+ gem "webrick", "~> 1.8"
data/Gemfile.lock ADDED
@@ -0,0 +1,81 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ cecil (0.1.0)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ ast (2.4.2)
10
+ diff-lcs (1.5.0)
11
+ ffi (1.16.3)
12
+ json (2.7.1)
13
+ language_server-protocol (3.17.0.3)
14
+ listen (3.8.0)
15
+ rb-fsevent (~> 0.10, >= 0.10.3)
16
+ rb-inotify (~> 0.9, >= 0.9.10)
17
+ parallel (1.24.0)
18
+ parser (3.3.0.2)
19
+ ast (~> 2.4.1)
20
+ racc
21
+ racc (1.7.3)
22
+ rainbow (3.1.1)
23
+ rake (13.0.6)
24
+ rb-fsevent (0.11.2)
25
+ rb-inotify (0.10.1)
26
+ ffi (~> 1.0)
27
+ regexp_parser (2.9.0)
28
+ retest (1.11.0)
29
+ listen (~> 3.2)
30
+ string-similarity (~> 2.1)
31
+ tty-option (~> 0.1)
32
+ rexml (3.2.6)
33
+ rspec (3.12.0)
34
+ rspec-core (~> 3.12.0)
35
+ rspec-expectations (~> 3.12.0)
36
+ rspec-mocks (~> 3.12.0)
37
+ rspec-core (3.12.2)
38
+ rspec-support (~> 3.12.0)
39
+ rspec-expectations (3.12.3)
40
+ diff-lcs (>= 1.2.0, < 2.0)
41
+ rspec-support (~> 3.12.0)
42
+ rspec-mocks (3.12.6)
43
+ diff-lcs (>= 1.2.0, < 2.0)
44
+ rspec-support (~> 3.12.0)
45
+ rspec-support (3.12.1)
46
+ rubocop (1.59.0)
47
+ json (~> 2.3)
48
+ language_server-protocol (>= 3.17.0)
49
+ parallel (~> 1.10)
50
+ parser (>= 3.2.2.4)
51
+ rainbow (>= 2.2.2, < 4.0)
52
+ regexp_parser (>= 1.8, < 3.0)
53
+ rexml (>= 3.2.5, < 4.0)
54
+ rubocop-ast (>= 1.30.0, < 2.0)
55
+ ruby-progressbar (~> 1.7)
56
+ unicode-display_width (>= 2.4.0, < 3.0)
57
+ rubocop-ast (1.30.0)
58
+ parser (>= 3.2.1.0)
59
+ ruby-progressbar (1.13.0)
60
+ string-similarity (2.1.0)
61
+ tty-option (0.3.0)
62
+ unicode-display_width (2.5.0)
63
+ webrick (1.8.1)
64
+ yard (0.9.34)
65
+
66
+ PLATFORMS
67
+ arm64-darwin-22
68
+ arm64-darwin-23
69
+ x86_64-linux
70
+
71
+ DEPENDENCIES
72
+ cecil!
73
+ rake (~> 13.0)
74
+ retest (~> 1.11)
75
+ rspec (~> 3.0)
76
+ rubocop (~> 1.21)
77
+ webrick (~> 1.8)
78
+ yard (~> 0.9.34)
79
+
80
+ BUNDLED WITH
81
+ 2.4.10
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2023 Mike Nicholaides
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.