openapi-sourcetools 0.7.1 → 0.8.1

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,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright © 2024-2025 Ismo Kärkkäinen
4
+ # Licensed under Universal Permissive License. See LICENSE.txt.
5
+
6
+ require_relative 'sourcetools/task'
7
+ require_relative 'sourcetools/config'
8
+ require_relative 'sourcetools/version'
9
+ require_relative 'sourcetools/apiobjects'
10
+ # Other modules or classes are exposed via Gen attributes as class instances as needed.
11
+ # Docs is only needed for run-time storage of whatever loaders can handle.
12
+ # Loaders array is exposed and can be added to at run-time.
13
+ # Helper instance is accessible via Gen.h.
14
+ # Output is exposed via Gen.o and Gen.output. Note that if you assign to one,
15
+ # the other will not change.
16
+ # The rest are for internal implementation.
metadata CHANGED
@@ -1,26 +1,47 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: openapi-sourcetools
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.1
4
+ version: 0.8.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ismo Kärkkäinen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-08-28 00:00:00.000000000 Z
12
- dependencies: []
13
- description: |2
11
+ date: 2025-01-31 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: deep_merge
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.2'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 1.2.2
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '1.2'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 1.2.2
33
+ description: |-
34
+ Tools for handling API specification in OpenAPI format.
35
+ Programs to replace of duplicate definitions with references. Other checks.
14
36
 
15
- Tools for handling API specification in OpenAPI format. Replacement of
16
- duplicate definitions with references. Other checks. Does not validate
17
- the document against OpenAPI format specification.
37
+ Does not validate the document against OpenAPI format specification.
18
38
  email: ismokarkkainen@icloud.com
19
39
  executables:
20
40
  - openapi-addheaders
21
41
  - openapi-addparameters
22
42
  - openapi-addresponses
23
43
  - openapi-addschemas
44
+ - openapi-addsecurityschemes
24
45
  - openapi-checkschemas
25
46
  - openapi-frequencies
26
47
  - openapi-generate
@@ -35,21 +56,25 @@ files:
35
56
  - bin/openapi-addparameters
36
57
  - bin/openapi-addresponses
37
58
  - bin/openapi-addschemas
59
+ - bin/openapi-addsecurityschemes
38
60
  - bin/openapi-checkschemas
39
61
  - bin/openapi-frequencies
40
62
  - bin/openapi-generate
41
63
  - bin/openapi-merge
42
64
  - bin/openapi-modifypaths
43
65
  - bin/openapi-processpaths
44
- - lib/apiobjects.rb
45
- - lib/common.rb
46
- - lib/docs.rb
47
- - lib/gen.rb
48
- - lib/generate.rb
49
- - lib/helper.rb
50
- - lib/loaders.rb
51
- - lib/output.rb
52
- - lib/task.rb
66
+ - lib/openapi/sourcetools.rb
67
+ - lib/openapi/sourcetools/apiobjects.rb
68
+ - lib/openapi/sourcetools/common.rb
69
+ - lib/openapi/sourcetools/config.rb
70
+ - lib/openapi/sourcetools/docs.rb
71
+ - lib/openapi/sourcetools/gen.rb
72
+ - lib/openapi/sourcetools/generate.rb
73
+ - lib/openapi/sourcetools/helper.rb
74
+ - lib/openapi/sourcetools/loaders.rb
75
+ - lib/openapi/sourcetools/output.rb
76
+ - lib/openapi/sourcetools/task.rb
77
+ - lib/openapi/sourcetools/version.rb
53
78
  homepage: https://xn--ismo-krkkinen-gfbd.fi/openapi-sourcetools/index.html
54
79
  licenses:
55
80
  - UPL-1.0
@@ -63,14 +88,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
63
88
  requirements:
64
89
  - - ">="
65
90
  - !ruby/object:Gem::Version
66
- version: 3.0.0
91
+ version: 3.2.5
67
92
  required_rubygems_version: !ruby/object:Gem::Requirement
68
93
  requirements:
69
94
  - - ">="
70
95
  - !ruby/object:Gem::Version
71
96
  version: '0'
72
97
  requirements: []
73
- rubygems_version: 3.2.33
98
+ rubygems_version: 3.4.19
74
99
  signing_key:
75
100
  specification_version: 4
76
101
  summary: Tools for creating source code from API specification.
data/lib/apiobjects.rb DELETED
@@ -1,306 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative './common'
4
- require 'set'
5
-
6
- def same(a, b, ignored_keys = Set.new(%w[summary description]))
7
- return a == b unless a.is_a?(Hash) && b.is_a?(Hash)
8
- keys = Set.new(a.keys + b.keys) - ignored_keys
9
- keys.to_a.each do |k|
10
- return false unless a.key?(k) && b.key?(k)
11
- return false unless same(a[k], b[k], ignored_keys)
12
- end
13
- true
14
- end
15
-
16
- def ref_string(name, schema_path)
17
- "#{schema_path}/#{name}"
18
- end
19
-
20
- def reference(obj, schemas, schema_path, ignored_keys = Set.new(%w[summary description]), prefix = 'Schema')
21
- # Check if identical schema has been added and if so, return the $ref string.
22
- schemas.keys.sort.each do |k|
23
- return ref_string(k, schema_path) if same(obj, schemas[k], ignored_keys)
24
- end
25
- # One of the numbers will not match existing keys. More number than keys.
26
- (schemas.size + 1).times do |n|
27
- # 'x' is to simplify find and replace (Schema1x vs Schema1 and Schema10)
28
- k = "#{prefix}#{n}x"
29
- next if schemas.key?(k)
30
- schemas[k] = obj.merge
31
- return ref_string(k, schema_path)
32
- end
33
- end
34
-
35
- class Components
36
- attr_reader :path, :prefix, :anchor2ref, :schema_names
37
- attr_accessor :items, :ignored_keys
38
-
39
- def initialize(path, prefix, ignored_keys = %w[summary description examples example $anchor])
40
- path = "#/#{path.join('/')}/" if path.is_a?(Array)
41
- path = "#{path}/" unless path.end_with?('/')
42
- @path = path
43
- @prefix = prefix
44
- @anchor2ref = {}
45
- @schema_names = Set.new
46
- @items = {}
47
- @ignored_keys = Set.new(ignored_keys)
48
- end
49
-
50
- def add_options(opts)
51
- opts.on('--use FIELD', 'Use FIELD in comparisons.') do |f|
52
- @ignored_keys.delete(f)
53
- end
54
- opts.on('--ignore FIELD', 'Ignore FIELD in comparisons.') do |f|
55
- @ignored_keys.add(f)
56
- end
57
- end
58
-
59
- def help
60
- %(All fields are used in object equality comparisons except:\n#{@ignored_keys.to_a.sort!.join("\n")})
61
- end
62
-
63
- def add_schema_name(name)
64
- @schema_names.add(name)
65
- end
66
-
67
- def ref_string(name)
68
- return nil if name.nil?
69
- "#{@path}#{name}"
70
- end
71
-
72
- def reference(obj)
73
- # Check if identical schema has been added. If so, return the $ref string.
74
- @items.each do |k, v|
75
- return ref_string(k) if same(obj, v, @ignored_keys)
76
- end
77
- # One of the numbers will not match existing keys. More number than keys.
78
- (@items.size + 1).times do |n|
79
- # 'x' is to simplify find and replace (Schema1x vs Schema1 and Schema10)
80
- cand = "#{@prefix}#{n}x"
81
- next if @items.key?(cand)
82
- @items[cand] = obj.merge
83
- @schema_names.add(cand)
84
- return ref_string(cand)
85
- end
86
- end
87
-
88
- def store_anchor(obj, ref = nil)
89
- anchor_name = obj['$anchor']
90
- return if anchor_name.nil?
91
- ref = obj['$ref'] if ref.nil?
92
- raise Exception, 'ref is nil and no $ref or it is nil' if ref.nil?
93
- @anchor2ref[anchor_name] = ref
94
- end
95
-
96
- def alter_anchors
97
- replacements = {}
98
- @anchor2ref.each do |a, r|
99
- next if @schema_names.member?(a)
100
- replacements[a] = ref_string(a)
101
- @schema_names.add(a)
102
- end
103
- replacements.each do |a, r|
104
- @anchor2ref[a] = r
105
- end
106
- end
107
-
108
- def anchor_ref_replacement(ref)
109
- @anchor2ref[ref[1...ref.size]] || ref
110
- end
111
- end
112
-
113
- class ServerPath
114
- # Probably moves to a separate file once processpaths and frequencies receive
115
- # some attention.
116
- include Comparable
117
-
118
- attr_accessor :parts
119
-
120
- def initialize(parts)
121
- @parts = parts
122
- end
123
-
124
- def <=>(other) # Variables are after fixed strings.
125
- pp = other.is_a?(Array) ? other : p.parts
126
- parts.each_index do |k|
127
- return 1 if pp.size <= k # Longer comes after shorter.
128
- pk = parts[k]
129
- ppk = pp[k]
130
- if pk.is_a? String
131
- if ppk.is_a? String
132
- c = pk <=> ppk
133
- else
134
- return -1
135
- end
136
- else
137
- if ppk.is_a? String
138
- return 1
139
- else
140
- c = pk.fetch('var', '') <=> ppk.fetch('var', '')
141
- end
142
- end
143
- return c unless c.zero?
144
- end
145
- (parts.size < pp.size) ? -1 : 0
146
- end
147
-
148
- def compare(p, range = nil) # Not fit for sorting. Variable equals anything.
149
- pp = p.is_a?(Array) ? p : p.parts
150
- if range.nil?
151
- range = 0...parts.size
152
- elsif range.is_a? Number
153
- range = range...(range + 1)
154
- end
155
- range.each do |k|
156
- return 1 if pp.size <= k # Longer comes after shorter.
157
- ppk = pp[k]
158
- next unless ppk.is_a? String
159
- pk = parts[k]
160
- next unless pk.is_a? String
161
- c = pk <=> ppk
162
- return c unless c.zero?
163
- end
164
- (parts.size < pp.size) ? -1 : 0
165
- end
166
- end
167
-
168
- # The rest probably ends up in a gem that orders schemas and does nothing else.
169
-
170
- # Adds all refs found in the array to refs with given required state.
171
- def gather_array_refs(refs, items, required)
172
- items.each do |s|
173
- r = s['$ref']
174
- next if r.nil?
175
- refs[r] = required || refs.fetch(r, false)
176
- end
177
- end
178
-
179
- # For any key '$ref' adds to refs whether referred type is required.
180
- # Requires that there are no in-lined schemas, openapi-addschemas has been run.
181
- def gather_refs(refs, schema)
182
- # This implies types mixed together according to examples. Needs mixed type.
183
- # AND. Also, mixing may fail. Adds a new schema, do here.
184
- items = schema['allOf']
185
- return gather_array_refs(refs, items, true) unless items.nil?
186
- # As long as one schema is fulfilled, it is ok. OR, first that fits.
187
- items = schema['anyOf'] if items.nil?
188
- # oneOf implies selection between different types. No multiple matches. XOR.
189
- # Needs to ensure that later types do not match.
190
- # Should check if there is enough difference to ensure single match.
191
- # Use separate program run after addschemas to create allOf mixed schema
192
- # and verify the others can be dealt with.
193
- items = schema['oneOf'] if items.nil?
194
- return gather_array_refs(refs, items, false) unless items.nil?
195
- # Defaults below handle it if "type" is not "object".
196
- reqs = schema.fetch('required', [])
197
- schema.fetch('properties', {}).each do |name, spec|
198
- r = spec['$ref']
199
- next if r.nil?
200
- refs[r] = reqs.include?(name) || refs.fetch(r, false)
201
- end
202
- end
203
-
204
- class SchemaInfo
205
- attr_accessor :ref, :schema, :direct_refs, :name, :post_refs
206
-
207
- def initialize(ref, name, schema)
208
- @ref = ref
209
- @name = name
210
- @schema = schema
211
- @direct_refs = {}
212
- gather_refs(@direct_refs, schema)
213
- end
214
-
215
- def set_post_refs(seen)
216
- @post_refs = Set.new(@direct_refs.keys) - seen
217
- end
218
-
219
- def to_s
220
- v = @direct_refs.keys.sort.map { |k| "#{k}:#{@direct_refs[k] ? 'req' : 'opt'}" }
221
- "#{@ref}: #{v.join(' ')}"
222
- end
223
- end
224
-
225
- def var_or_method_value(x, name)
226
- if name.start_with?('@')
227
- n = name
228
- else
229
- n = "@#{name}"
230
- end
231
- return x.instance_variable_get(n) if x.instance_variable_defined?(n)
232
- return x.public_send(name) if x.respond_to?(name)
233
- raise ArgumentError, "#{name} is not #{x.class} instance variable nor public method"
234
- end
235
-
236
- class SchemaOrderer
237
- attr_accessor :schemas, :order, :orderer
238
-
239
- def initialize(path, schema_specs)
240
- @schemas = {}
241
- schema_specs.each do |name, schema|
242
- r = "#{path}#{name}"
243
- @schemas[r] = SchemaInfo.new(r, name, schema)
244
- end
245
- end
246
-
247
- def sort!(orderer = 'required_first')
248
- case orderer
249
- when 'required_first' then @order = required_first
250
- when '<=>' then @order = @schemas.values.sort { |a, b| a <=> b }
251
- else
252
- @order = @schemas.values.sort do |a, b|
253
- va = var_or_method_value(a, orderer)
254
- vb = var_or_method_value(b, orderer)
255
- va <=> vb
256
- end
257
- end
258
- @orderer = orderer
259
- seen = Set.new
260
- @order.each do |si|
261
- si.set_post_refs(seen)
262
- seen.add(si.ref)
263
- end
264
- @order
265
- end
266
-
267
- def required_first
268
- chosen = []
269
- until chosen.size == @schemas.size
270
- used = Set.new(chosen.map { |si| si.ref })
271
- avail = @schemas.values.select { |si| !used.member?(si.ref) }
272
- best = nil
273
- avail.each do |si|
274
- prereq = chosen.count { |x| x.direct_refs.fetch(si.ref, false) }
275
- fulfilled = chosen.count { |x| si.direct_refs.fetch(x.ref, false) }
276
- postreq = si.direct_refs.size - (prereq + fulfilled)
277
- better = false
278
- if best.nil?
279
- better = true
280
- else
281
- # Minimize preceding types requiring this.
282
- if prereq < best.first
283
- better = true
284
- elsif prereq == best.first
285
- # Minimize remaining unfulfilled requires.
286
- if postreq < best[1]
287
- better = true
288
- elsif postreq == best[1]
289
- # Check mutual direct requirements.
290
- best_req_si = best.last.direct_refs.fetch(si.ref, false)
291
- si_req_best = si.direct_refs.fetch(best.last.ref, false)
292
- if best_req_si
293
- better = true unless si_req_best
294
- end
295
- # Order by name if no other difference.
296
- better = si.ref < best.last.ref unless better
297
- end
298
- end
299
- end
300
- best = [ prereq, postreq, si ] if better
301
- end
302
- chosen.push(best.last)
303
- end
304
- chosen
305
- end
306
- end
data/lib/common.rb DELETED
@@ -1,114 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Copyright © 2021-2024 Ismo Kärkkäinen
4
- # Licensed under Universal Permissive License. See LICENSE.txt.
5
-
6
- require 'pathname'
7
-
8
-
9
- def aargh(message, return_value = nil)
10
- message = message.map(&:to_s).join("\n") if message.is_a? Array
11
- $stderr.puts message
12
- return_value
13
- end
14
-
15
- def yesno(boolean)
16
- boolean ? 'yes' : 'no'
17
- end
18
-
19
- def bury(doc, path, value)
20
- (path.size - 1).times do |k|
21
- p = path[k]
22
- doc[p] = {} unless doc.key?(p)
23
- doc = doc[p]
24
- end
25
- doc[path.last] = value
26
- end
27
-
28
- module Out
29
- attr_reader :count
30
-
31
- def put(message)
32
- aargh(message)
33
- count += 1
34
- end
35
- end
36
-
37
- def split_path(p, spec = false)
38
- parts = []
39
- p = p.strip
40
- unless spec
41
- q = p.index('?')
42
- p.slice!(0...q) unless q.nil?
43
- end
44
- p.split('/').each do |s|
45
- next if s.empty?
46
- s = { var: s } if spec && s.include?('{')
47
- parts.push(s)
48
- end
49
- parts
50
- end
51
-
52
- def load_source(input)
53
- YAML.safe_load(input.nil? ? $stdin : File.read(input))
54
- rescue Errno::ENOENT
55
- aargh "Could not load #{input || 'stdin'}"
56
- rescue StandardError => e
57
- aargh "#{e}\nFailed to read #{input || 'stdin'}"
58
- end
59
-
60
- def dump_result(output, doc, error_return)
61
- doc = YAML.dump(doc, line_width: 1_000_000) unless doc.is_a?(String)
62
- if output.nil?
63
- $stdout.puts doc
64
- else
65
- fp = Pathname.new output
66
- fp.open('w') do |f|
67
- f.puts doc
68
- end
69
- end
70
- 0
71
- rescue StandardError => e
72
- aargh([ e, "Failed to write output: #{output || 'stdout'}" ], error_return)
73
- end
74
-
75
- ServerPath = Struct.new(:parts) do
76
- # Variables are after fixed strings.
77
- def <=>(other)
78
- pp = other.is_a?(Array) ? other : other.parts
79
- parts.each_index do |k|
80
- return 1 if pp.size <= k # Longer comes after shorter.
81
- pk = parts[k]
82
- ppk = pp[k]
83
- if pk.is_a? String
84
- return -1 unless ppk.is_a? String
85
- c = pk <=> ppk
86
- else
87
- return 1 if ppk.is_a? String
88
- c = pk.fetch('var', '') <=> ppk.fetch('var', '')
89
- end
90
- return c unless c.zero?
91
- end
92
- (parts.size < pp.size) ? -1 : 0
93
- end
94
-
95
- # Not fit for sorting. Variable equals anything.
96
- def compare(p, range = nil)
97
- pp = p.is_a?(Array) ? p : p.parts
98
- if range.nil?
99
- range = 0...parts.size
100
- elsif range.is_a? Number
101
- range = range...(range + 1)
102
- end
103
- range.each do |k|
104
- return 1 if pp.size <= k # Longer comes after shorter.
105
- ppk = pp[k]
106
- next unless ppk.is_a? String
107
- pk = parts[k]
108
- next unless pk.is_a? String
109
- c = pk <=> ppk
110
- return c unless c.zero?
111
- end
112
- (parts.size < pp.size) ? -1 : 0
113
- end
114
- end
data/lib/docs.rb DELETED
@@ -1,33 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Copyright © 2024 Ismo Kärkkäinen
4
- # Licensed under Universal Permissive License. See LICENSE.txt.
5
-
6
- require_relative 'common'
7
-
8
-
9
- class Docs
10
- attr_reader :docs
11
-
12
- def initialize
13
- @docs = {}
14
- end
15
-
16
- def method_missing(method_name, *args)
17
- name = method_name.to_s
18
- if name.end_with?('=')
19
- name = name[0...(name.size - 1)]
20
- super unless @docs.key?(name)
21
- @docs[name] = args.first
22
- return args.first
23
- end
24
- super unless @docs.key?(name)
25
- @docs[name]
26
- end
27
-
28
- def add(name, content)
29
- return false if docs.key?(name)
30
- @docs[name] = content
31
- true
32
- end
33
- end
data/lib/gen.rb DELETED
@@ -1,104 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Copyright © 2024 Ismo Kärkkäinen
4
- # Licensed under Universal Permissive License. See LICENSE.txt.
5
-
6
- require_relative 'task'
7
- require_relative 'helper'
8
- require_relative 'docs'
9
- require_relative 'output'
10
-
11
-
12
- module Gen
13
- def self.add_doc(symbol, docstr)
14
- return if docstr.nil?
15
- @docsrc = [] unless instance_variable_defined?('@docsrc')
16
- @docsrc.push("- #{symbol.to_s} : #{docstr}")
17
- end
18
-
19
- def self.read_attr(symbol, default)
20
- return if symbol.nil?
21
- attr_reader(symbol)
22
- module_function(symbol)
23
- instance_variable_set("@#{symbol.to_s}", default)
24
- end
25
-
26
- def self.mod_attr2_reader(symbol, symbol2, docstr = nil, default = nil)
27
- read_attr(symbol, default)
28
- read_attr(symbol2, default)
29
- add_doc(symbol, docstr)
30
- end
31
-
32
- def self.mod_attr_reader(symbol, docstr = nil, default = nil)
33
- mod_attr2_reader(symbol, nil, docstr, default)
34
- end
35
-
36
- def self.rw_attr(symbol, default)
37
- attr_accessor(symbol)
38
- module_function(symbol)
39
- s = symbol.to_s
40
- module_function((s + '=').to_sym)
41
- instance_variable_set("@#{s}", default)
42
- end
43
-
44
- def self.mod_attr2_accessor(symbol, symbol2, docstr = nil, default = nil)
45
- rw_attr(symbol, default)
46
- rw_attr(symbol2, default) unless symbol2.nil?
47
- add_doc(symbol, docstr)
48
- end
49
-
50
- def self.mod_attr_accessor(symbol, docstr = nil, default = nil)
51
- mod_attr2_accessor(symbol, nil, docstr, default)
52
- end
53
-
54
- mod_attr_reader :doc, 'OpenAPI document.'
55
- mod_attr_reader :outdir, 'Output directory name.'
56
- mod_attr_reader :d, 'Other documents object.', Docs.new
57
- mod_attr_accessor :in_name, 'OpenAPI document name, nil if stdin.'
58
- mod_attr_accessor :in_basename, 'OpenAPI document basename, nil if stdin.'
59
- mod_attr_accessor :tasks, 'Tasks array.', []
60
- mod_attr_accessor :g, 'Hash for storing values visible to all tasks.', {}
61
- mod_attr_accessor :a, 'Intended for instance with defined attributes.'
62
- mod_attr_accessor :h, 'Instance of class with helper methods.'
63
- mod_attr2_accessor :task, :t, 'Current task instance.'
64
- mod_attr_accessor :task_index, 'Current task index.'
65
- mod_attr_accessor :loaders, 'Array of generator loader methods.', []
66
- mod_attr2_accessor :output, :o, 'Output-related methods.', Output.new
67
-
68
- def self.setup(document_content, input_name, output_directory)
69
- @doc = document_content
70
- @outdir = output_directory
71
- unless input_name.nil?
72
- @in_name = File.basename(input_name)
73
- @in_basename = File.basename(input_name, '.*')
74
- end
75
- add_task(task: HelperTask.new)
76
- end
77
-
78
- def self.add_task(task:, name: nil, executable: false, x: nil)
79
- @tasks.push(task)
80
- # Since this method allows the user to pass their own task type instance,
81
- # assign optional values with defaults only when clearly given.
82
- @tasks.last.name = name unless name.nil?
83
- @tasks.last.executable = executable unless executable == false
84
- @tasks.last.x = x unless x.nil?
85
- end
86
-
87
- def self.add_write_content(name:, content:, executable: false)
88
- add_task(task: WriteTask.new(name, content, executable))
89
- end
90
-
91
- def self.add(source:, template: nil, template_name: nil, name: nil, executable: false, x: nil)
92
- add_task(task: Task.new(source, template, template_name), name: name, executable: executable, x: x)
93
- end
94
-
95
- def self.document
96
- @docsrc.join("\n") + %(
97
- - add_task(task:, name: nil, executable: false, x: nil) : Adds task object.
98
- - add_write_content(name:, content:, executable: false) : Add file write task.
99
- - add(source:, template: nil, template_name: nil, name: nil,
100
- executable: false, x: nil) :
101
- Adds template task with source as object to process.
102
- )
103
- end
104
- end