cecil 0.1.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 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.