k_doc 0.0.1 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +3 -0
- data/Guardfile +30 -0
- data/README.md +10 -3
- data/STORIES.md +44 -0
- data/USAGE.md +19 -0
- data/k_doc.gemspec +2 -0
- data/lib/k_doc.rb +43 -1
- data/lib/k_doc/data.rb +258 -0
- data/lib/k_doc/document.rb +188 -0
- data/lib/k_doc/fake_opinion.rb +27 -0
- data/lib/k_doc/settings.rb +131 -0
- data/lib/k_doc/table.rb +115 -0
- data/lib/k_doc/util.rb +14 -0
- data/lib/k_doc/version.rb +1 -1
- metadata +40 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b3ade2c96c7dd68a9b948f680c63a3a3f28d79f48a3808df328435054e32048f
|
4
|
+
data.tar.gz: f932c466c175cd9258220b370ea040982e2fd57be560fd816c8a60818d4344c6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6f18c5daebd800c3e3e33ce5c8ec882833cc64b97c7d8b415c6078abed1c7fce76a6bb59f53afe51511035e77e198fdd1e106cf746dcff6fa7a96a3d0af88128
|
7
|
+
data.tar.gz: 36ab77e3f217d639bc02f911b23674322ad0dd2c2e1aed0042f57195fda0b6b8f95e0119758e0c85f0bddb485b0ea77d73d2543b6c515b315bb5c5d95171ab77
|
data/.rubocop.yml
CHANGED
data/Guardfile
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
guard :bundler, cmd: 'bundle install' do
|
4
|
+
watch('Gemfile')
|
5
|
+
watch('k_doc.gemspec')
|
6
|
+
end
|
7
|
+
|
8
|
+
group :green_pass_then_cop, halt_on_fail: true do
|
9
|
+
guard :rspec, cmd: 'bundle exec rspec -f doc' do
|
10
|
+
require 'guard/rspec/dsl'
|
11
|
+
dsl = Guard::RSpec::Dsl.new(self)
|
12
|
+
|
13
|
+
# RSpec files
|
14
|
+
rspec = dsl.rspec
|
15
|
+
watch(rspec.spec_helper) { rspec.spec_dir }
|
16
|
+
watch(rspec.spec_support) { rspec.spec_dir }
|
17
|
+
watch(rspec.spec_files)
|
18
|
+
|
19
|
+
# Ruby files
|
20
|
+
ruby = dsl.ruby
|
21
|
+
dsl.watch_spec_files_for(ruby.lib_files)
|
22
|
+
watch(%r{^lib/k_doc/(.+)\.rb$}) { |m| "spec/unit/#{m[1]}_spec.rb" }
|
23
|
+
watch(%r{^lib/k_doc/commands/(.+)\.rb$}) { |m| "spec/unit/commands/#{m[1]}_spec.rb" }
|
24
|
+
end
|
25
|
+
|
26
|
+
guard :rubocop, all_on_start: false, cli: ['--format', 'clang'] do
|
27
|
+
watch(/{.+\.rb$/)
|
28
|
+
watch(%r{(?:.+/)?\.rubocop(?:_todo)?\.yml$}) { |m| File.dirname(m[0]) }
|
29
|
+
end
|
30
|
+
end
|
data/README.md
CHANGED
@@ -26,16 +26,23 @@ gem install k_doc
|
|
26
26
|
|
27
27
|
### Main Story
|
28
28
|
|
29
|
-
|
29
|
+
As a Developer, I need flexible data structures defined in DSL, so can model rich documents
|
30
30
|
|
31
31
|
See all [stories](./STORIES.md)
|
32
32
|
|
33
|
-
|
34
33
|
## Usage
|
35
34
|
|
36
35
|
See all [usage examples](./USAGE.md)
|
37
36
|
|
37
|
+
### Basic Example
|
38
|
+
|
39
|
+
#### Basic example
|
38
40
|
|
41
|
+
Description for a basic example to be featured in the main README.MD file
|
42
|
+
|
43
|
+
```ruby
|
44
|
+
class SomeRuby; end
|
45
|
+
```
|
39
46
|
|
40
47
|
## Development
|
41
48
|
|
@@ -45,7 +52,7 @@ Checkout the repo
|
|
45
52
|
git clone klueless-io/k_doc
|
46
53
|
```
|
47
54
|
|
48
|
-
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests.
|
55
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests.
|
49
56
|
|
50
57
|
You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
51
58
|
|
data/STORIES.md
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
# K Doc
|
2
|
+
|
3
|
+
> KDoc provides a document in the form a DSL that contains flexible key/value and tabular data
|
4
|
+
|
5
|
+
As a Developer, I need flexible data structures defined in DSL, so can model rich documents
|
6
|
+
|
7
|
+
## Development radar
|
8
|
+
|
9
|
+
### Stories next on list
|
10
|
+
|
11
|
+
As a Developer, I need flexible data structures defined in DSL, so can model rich documents
|
12
|
+
|
13
|
+
### Tasks next on list
|
14
|
+
|
15
|
+
Setup RubyGems and RubyDoc
|
16
|
+
|
17
|
+
- Build and deploy gem to [rubygems.org](https://rubygems.org/gems/k_doc)
|
18
|
+
- Attach documentation to [rubydoc.info](https://rubydoc.info/github/to-do-/k_doc/master)
|
19
|
+
|
20
|
+
Setup GitHub Action (test and lint)
|
21
|
+
|
22
|
+
- Setup Rspec action
|
23
|
+
- Setup RuboCop action
|
24
|
+
|
25
|
+
## Stories and tasks
|
26
|
+
|
27
|
+
### Tasks - completed
|
28
|
+
|
29
|
+
Setup project management, requirement and SCRUM documents
|
30
|
+
|
31
|
+
- Setup readme file
|
32
|
+
- Setup user stories and tasks
|
33
|
+
- Setup a project backlog
|
34
|
+
- Setup an examples/usage document
|
35
|
+
|
36
|
+
Setup new Ruby GEM
|
37
|
+
|
38
|
+
- Build out a standard GEM structure
|
39
|
+
- Add automated semantic versioning
|
40
|
+
- Add Rspec unit testing framework
|
41
|
+
- Add RuboCop linting
|
42
|
+
- Add Guard for automatic watch and test
|
43
|
+
- Add GitFlow support
|
44
|
+
- Add GitHub Repository
|
data/USAGE.md
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# K Doc
|
2
|
+
|
3
|
+
> KDoc provides a document in the form a DSL that contains flexible key/value and tabular data
|
4
|
+
|
5
|
+
As a Developer, I need flexible data structures defined in DSL, so can model rich documents
|
6
|
+
|
7
|
+
## Usage
|
8
|
+
|
9
|
+
### Sample Classes
|
10
|
+
|
11
|
+
#### Simple example
|
12
|
+
|
13
|
+
Description for a simple example that shows up in the USAGE.MD
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
class SomeRuby
|
17
|
+
def initialize; end
|
18
|
+
end
|
19
|
+
```
|
data/k_doc.gemspec
CHANGED
data/lib/k_doc.rb
CHANGED
@@ -1,10 +1,52 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'securerandom'
|
4
|
+
|
5
|
+
require 'logger'
|
6
|
+
require 'table_print'
|
7
|
+
require 'k_log'
|
8
|
+
require 'k_util'
|
9
|
+
require 'k_log/log_formatter'
|
10
|
+
require 'k_log/log_helper'
|
11
|
+
require 'k_log/log_util'
|
12
|
+
|
3
13
|
require 'k_doc/version'
|
14
|
+
require 'k_doc/data'
|
15
|
+
require 'k_doc/document'
|
16
|
+
require 'k_doc/fake_opinion'
|
17
|
+
require 'k_doc/settings'
|
18
|
+
require 'k_doc/table'
|
19
|
+
require 'k_doc/util'
|
4
20
|
|
5
21
|
module KDoc
|
6
22
|
# raise KDoc::Error, 'Sample message'
|
7
23
|
class Error < StandardError; end
|
8
24
|
|
9
|
-
|
25
|
+
class << self
|
26
|
+
# Factory method to create a new document
|
27
|
+
def doc(key = nil, **options, &block)
|
28
|
+
doc = KDoc::Document.new(key, **options, &block)
|
29
|
+
doc.execute_block
|
30
|
+
doc
|
31
|
+
end
|
32
|
+
|
33
|
+
attr_accessor :opinion
|
34
|
+
attr_accessor :util
|
35
|
+
attr_accessor :log
|
36
|
+
end
|
37
|
+
|
38
|
+
KDoc.opinion = KDoc::FakeOpinion.new
|
39
|
+
KDoc.util = KDoc::Util.new
|
40
|
+
|
41
|
+
# Need to move this into a KLog factory
|
42
|
+
def self.configure_logger
|
43
|
+
logger = Logger.new($stdout)
|
44
|
+
logger.level = Logger::DEBUG
|
45
|
+
logger.formatter = KLog::LogFormatter.new
|
46
|
+
KLog::LogUtil.new(logger)
|
47
|
+
end
|
48
|
+
|
49
|
+
# KDoc.log = configure_logger
|
10
50
|
end
|
51
|
+
|
52
|
+
L = KDoc.configure_logger
|
data/lib/k_doc/data.rb
ADDED
@@ -0,0 +1,258 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# module KDoc
|
4
|
+
# # TODO
|
5
|
+
# # Missing tests around errors
|
6
|
+
# # Make sure that error writes to resource or document appropriately
|
7
|
+
# # Puts errors onto a project manager pipeline so that they can be be printed out after the documents
|
8
|
+
# #
|
9
|
+
# # General purpose document DSL
|
10
|
+
# #
|
11
|
+
# # Made up of 0 or more setting groups and table groups
|
12
|
+
# class Data
|
13
|
+
# extend Forwardable
|
14
|
+
|
15
|
+
# attr_reader :key
|
16
|
+
# attr_reader :type
|
17
|
+
# attr_reader :namespace
|
18
|
+
# attr_reader :options
|
19
|
+
# attr_reader :error
|
20
|
+
|
21
|
+
# # State of document
|
22
|
+
# # - :initializing
|
23
|
+
# # - :initialized
|
24
|
+
# # - :loading
|
25
|
+
# # - :loaded
|
26
|
+
# # - :executing
|
27
|
+
# # - :executed
|
28
|
+
# attr_reader :state
|
29
|
+
|
30
|
+
# # Shortcut to formatter
|
31
|
+
# attr_reader :f
|
32
|
+
|
33
|
+
# attr_accessor :resource
|
34
|
+
|
35
|
+
# def_delegator :resource, :project
|
36
|
+
|
37
|
+
# def state=(state)
|
38
|
+
# @state = state
|
39
|
+
# # if [:initialized, :loaded, :executed].include?(state) &&
|
40
|
+
# # (project.nil? || project.name == 'k_dsl')
|
41
|
+
# # # pname = project.nil? ? '' : "#{project&.name} "
|
42
|
+
# # L.kv "#{unique_key} - state", state
|
43
|
+
# # end
|
44
|
+
# @state
|
45
|
+
# end
|
46
|
+
|
47
|
+
# # Create document
|
48
|
+
# #
|
49
|
+
# # @param [String|Symbol] name Name of the document
|
50
|
+
# # @param args[0] Type of the document, defaults to KDsl.config.default_document_type if not set
|
51
|
+
# # @param default: Default value (using named params), as above
|
52
|
+
# def initialize(key = SecureRandom.alphanumeric(8), *args, **options, &block)
|
53
|
+
# @key = key
|
54
|
+
# @type = args.length.positive? ? args[0] || KDsl.config.default_document_type : KDsl.config.default_document_type
|
55
|
+
|
56
|
+
# @options = options || {}
|
57
|
+
# @namespace = options[:namespace] || ''
|
58
|
+
# default_data = options[:default_data] || {}
|
59
|
+
|
60
|
+
# @namespace = @namespace.to_s
|
61
|
+
# @error = nil
|
62
|
+
|
63
|
+
# self.state = :initializing
|
64
|
+
|
65
|
+
# # Most documents live within a hash, some tabular documents such as
|
66
|
+
# # CSV will use an []
|
67
|
+
# set_data(default_data)
|
68
|
+
|
69
|
+
# @f = KDsl::Util.format
|
70
|
+
|
71
|
+
# @block = block if block_given?
|
72
|
+
|
73
|
+
# self.state = :initialized
|
74
|
+
# end
|
75
|
+
|
76
|
+
# def execute_block(run_actions: nil)
|
77
|
+
# return if @block.nil?
|
78
|
+
|
79
|
+
# # The DSL actions method will only run on run_actions: true
|
80
|
+
# @run_actions = run_actions
|
81
|
+
|
82
|
+
# # if unique_key == 'template_options_entity'
|
83
|
+
# # L.kv '2:CLASS_ID', object_id
|
84
|
+
# # end
|
85
|
+
# if initialized?
|
86
|
+
# self.state = :loading
|
87
|
+
# instance_eval(&@block)
|
88
|
+
# self.state = :loaded
|
89
|
+
# end
|
90
|
+
# # if unique_key == 'template_options_entity'
|
91
|
+
# # L.kv '3:CLASS_ID', resource_document.object_id
|
92
|
+
# # end
|
93
|
+
|
94
|
+
# if loaded? && run_actions && respond_to?(:on_action)
|
95
|
+
# @state = :executed
|
96
|
+
# on_action
|
97
|
+
# end
|
98
|
+
# rescue KDsl::Error => e
|
99
|
+
# L.error('KDsl::Error in document')
|
100
|
+
# L.kv 'key', unique_key
|
101
|
+
# L.kv 'file', KDsl::Util.data.console_file_hyperlink(resource.file, resource.file)
|
102
|
+
# L.error(e.message)
|
103
|
+
# @error = e
|
104
|
+
# # L.heading "Invalid code block in document_dsl during registration: #{k_key}"
|
105
|
+
# # L.exception exception
|
106
|
+
# raise
|
107
|
+
# rescue StandardError => e
|
108
|
+
# L.error('Standard error in document')
|
109
|
+
# L.kv 'key', unique_key
|
110
|
+
# L.kv 'file', KDsl::Util.data.console_file_hyperlink(resource.file, resource.file)
|
111
|
+
# L.error(e.message)
|
112
|
+
# @error = e
|
113
|
+
# # L.exception exception2
|
114
|
+
# raise
|
115
|
+
# ensure
|
116
|
+
# @run_actions = nil
|
117
|
+
# return
|
118
|
+
# end
|
119
|
+
|
120
|
+
# def initialized?
|
121
|
+
# @state == :initialized
|
122
|
+
# end
|
123
|
+
|
124
|
+
# def loaded?
|
125
|
+
# @state == :loaded
|
126
|
+
# end
|
127
|
+
|
128
|
+
# def executed?
|
129
|
+
# @state == :executed
|
130
|
+
# end
|
131
|
+
|
132
|
+
# def unique_key
|
133
|
+
# @unique_key ||= KDsl::Util.dsl.build_unique_key(key, type, namespace)
|
134
|
+
# end
|
135
|
+
|
136
|
+
# def settings(key = nil, **options, &block)
|
137
|
+
# options ||= {}
|
138
|
+
|
139
|
+
# opts = {}.merge(@options) # Document Options
|
140
|
+
# .merge(options) # Settings Options
|
141
|
+
|
142
|
+
# settings = settings_instance(@data, key, parent: self, &block)
|
143
|
+
# settings.run_decorators(opts)
|
144
|
+
# settings
|
145
|
+
# end
|
146
|
+
|
147
|
+
# def table(key = :table, &block)
|
148
|
+
# # NEED to add support for run_decorators I think
|
149
|
+
# table_instance(@data, key, parent: self, &block)
|
150
|
+
# end
|
151
|
+
# alias rows table
|
152
|
+
|
153
|
+
# # Sweet add-on would be builders
|
154
|
+
# # def builder(key, &block)
|
155
|
+
# # # example
|
156
|
+
# # KDsl::Builder::Shotstack.new(@data, key, &block)
|
157
|
+
# # end
|
158
|
+
|
159
|
+
# def set_data(data)
|
160
|
+
# @data = data
|
161
|
+
# end
|
162
|
+
|
163
|
+
# def data
|
164
|
+
# @data.clone
|
165
|
+
# end
|
166
|
+
|
167
|
+
# def data_struct
|
168
|
+
# KDsl::Util.data.to_struct(data)
|
169
|
+
# end
|
170
|
+
# alias d data_struct
|
171
|
+
|
172
|
+
# def raw_data_struct
|
173
|
+
# KDsl::Util.data.to_struct(raw_data)
|
174
|
+
# end
|
175
|
+
|
176
|
+
# def get_node_type(node_name)
|
177
|
+
# node_name = KDsl::Util.data.clean_symbol(node_name)
|
178
|
+
# node_data = @data[node_name]
|
179
|
+
|
180
|
+
# raise KDsl::Error, "Node not found: #{node_name}" if node_data.nil?
|
181
|
+
|
182
|
+
# if node_data.keys.length == 2 && (node_data.key?('fields') && node_data.key?('rows'))
|
183
|
+
# :table
|
184
|
+
# else
|
185
|
+
# :settings
|
186
|
+
# end
|
187
|
+
# end
|
188
|
+
|
189
|
+
# # Removes any meta data eg. "fields" from a table and just returns the raw data
|
190
|
+
# def raw_data
|
191
|
+
# # REFACT, what if this is CSV, meaning it is just an array?
|
192
|
+
# # add specs
|
193
|
+
# result = data
|
194
|
+
|
195
|
+
# result.each_key do |key|
|
196
|
+
# # ANTI: get_node_type uses @data while we are using @data.clone here
|
197
|
+
# data[key] = if get_node_type(key) == :table
|
198
|
+
# result[key].delete('fields')
|
199
|
+
# else
|
200
|
+
# result[key]
|
201
|
+
# end
|
202
|
+
# end
|
203
|
+
|
204
|
+
# data
|
205
|
+
# end
|
206
|
+
|
207
|
+
# # Move this out to the logger function when it has been refactor
|
208
|
+
# def debug(include_header = false)
|
209
|
+
# debug_header if include_header
|
210
|
+
|
211
|
+
# # tp dsls.values, :k_key, :k_type, :state, :save_at, :last_at, :data, :last_data, :source, { :file => { :width => 150 } }
|
212
|
+
# # puts JSON.pretty_generate(data)
|
213
|
+
# L.o(raw_data_struct)
|
214
|
+
# end
|
215
|
+
|
216
|
+
# def debug_header
|
217
|
+
# L.heading self.class.name
|
218
|
+
# L.kv 'key', key
|
219
|
+
# L.kv 'type', type
|
220
|
+
# L.kv 'namespace', namespace
|
221
|
+
# L.kv 'error', error
|
222
|
+
# L.kv 'state', state
|
223
|
+
# L.kv 'respond_to?(:on_import)', respond_to?(:on_import)
|
224
|
+
# L.kv 'respond_to?(:david)', respond_to?(:david)
|
225
|
+
# david if respond_to?(:david)
|
226
|
+
# # L.kv 'INITALIZED', resource_document.initialized?
|
227
|
+
# # L.kv 'EXECUTED', resource_document.executed?
|
228
|
+
|
229
|
+
# options&.keys.reject { |k| k == :namespace }&.each do |key|
|
230
|
+
# L.kv key, options[key]
|
231
|
+
# end
|
232
|
+
|
233
|
+
# L.line
|
234
|
+
# end
|
235
|
+
|
236
|
+
# # Helpers that often get called by extensions
|
237
|
+
|
238
|
+
# def project
|
239
|
+
# project ||= resource&.project
|
240
|
+
# end
|
241
|
+
|
242
|
+
# # Warning message
|
243
|
+
# def warn(message)
|
244
|
+
# L.warn message
|
245
|
+
# nil
|
246
|
+
# end
|
247
|
+
|
248
|
+
# private
|
249
|
+
|
250
|
+
# def settings_instance(data, key, **options, &block)
|
251
|
+
# KDsl.config.settings_class.new(data, key, **options, &block)
|
252
|
+
# end
|
253
|
+
|
254
|
+
# def table_instance(data, key, **options, &block)
|
255
|
+
# KDsl.config.table_class.new(data, key, **options, &block)
|
256
|
+
# end
|
257
|
+
# end
|
258
|
+
# end
|
@@ -0,0 +1,188 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module KDoc
|
4
|
+
# General purpose document DSL
|
5
|
+
#
|
6
|
+
# Made up of 0 or more setting groups and table groups
|
7
|
+
class Document
|
8
|
+
attr_reader :key
|
9
|
+
attr_reader :type
|
10
|
+
attr_reader :namespace
|
11
|
+
attr_reader :options
|
12
|
+
attr_reader :error
|
13
|
+
|
14
|
+
# Create document
|
15
|
+
#
|
16
|
+
# @param [String|Symbol] name Name of the document
|
17
|
+
# @param args[0] Type of the document, defaults to KDoc:: FakeOpinion.new.default_document_type if not set
|
18
|
+
# @param default: Default value (using named params), as above
|
19
|
+
def initialize(key = SecureRandom.alphanumeric(8), **options, &block)
|
20
|
+
initialize_attributes(key, **options)
|
21
|
+
|
22
|
+
@block = block if block_given?
|
23
|
+
end
|
24
|
+
|
25
|
+
def execute_block(run_actions: nil)
|
26
|
+
return if @block.nil?
|
27
|
+
|
28
|
+
# The DSL actions method will only run on run_actions: true
|
29
|
+
@run_actions = run_actions
|
30
|
+
|
31
|
+
instance_eval(&@block)
|
32
|
+
|
33
|
+
on_action if run_actions && respond_to?(:on_action)
|
34
|
+
# rescue KDoc::Error => e
|
35
|
+
# puts('KDoc::Error in document')
|
36
|
+
# puts "key #{unique_key}"
|
37
|
+
# # puts "file #{KUtil.data.console_file_hyperlink(resource.file, resource.file)}"
|
38
|
+
# puts(e.message)
|
39
|
+
# @error = e
|
40
|
+
# raise
|
41
|
+
rescue StandardError => e
|
42
|
+
L.error('Standard error in document')
|
43
|
+
puts "key #{unique_key}"
|
44
|
+
# puts "file #{KUtil.data.console_file_hyperlink(resource.file, resource.file)}"
|
45
|
+
L.error(e.message)
|
46
|
+
@error = e
|
47
|
+
# L.exception exception2
|
48
|
+
raise
|
49
|
+
ensure
|
50
|
+
@run_actions = nil
|
51
|
+
end
|
52
|
+
|
53
|
+
def unique_key
|
54
|
+
@unique_key ||= KDoc.util.build_unique_key(key, type, namespace)
|
55
|
+
end
|
56
|
+
|
57
|
+
def settings(key = nil, **options, &block)
|
58
|
+
options ||= {}
|
59
|
+
|
60
|
+
opts = {}.merge(@options) # Document Options
|
61
|
+
.merge(options) # Settings Options
|
62
|
+
.merge(parent: self)
|
63
|
+
|
64
|
+
settings_instance(@data, key, **opts, &block)
|
65
|
+
# settings.run_decorators(opts)
|
66
|
+
end
|
67
|
+
|
68
|
+
def table(key = :table, **options, &block)
|
69
|
+
# NEED to add support for run_decorators I think
|
70
|
+
options.merge(parent: self)
|
71
|
+
table_instance(@data, key, **options, &block)
|
72
|
+
end
|
73
|
+
alias rows table
|
74
|
+
|
75
|
+
# Sweet add-on would be builders
|
76
|
+
# def builder(key, &block)
|
77
|
+
# # example
|
78
|
+
# KDoc::Builder::Shotstack.new(@data, key, &block)
|
79
|
+
# end
|
80
|
+
|
81
|
+
# def set_data(data)
|
82
|
+
# @data = data
|
83
|
+
# end
|
84
|
+
|
85
|
+
def data
|
86
|
+
@data.clone
|
87
|
+
end
|
88
|
+
|
89
|
+
def data_struct
|
90
|
+
KUtil.data.to_open_struct(data)
|
91
|
+
end
|
92
|
+
# alias d data_struct
|
93
|
+
|
94
|
+
def raw_data_struct
|
95
|
+
KUtil.data.to_open_struct(raw_data)
|
96
|
+
end
|
97
|
+
|
98
|
+
def get_node_type(node_name)
|
99
|
+
node_name = KUtil.data.clean_symbol(node_name)
|
100
|
+
node_data = @data[node_name]
|
101
|
+
|
102
|
+
raise KDoc::Error, "Node not found: #{node_name}" if node_data.nil?
|
103
|
+
|
104
|
+
if node_data.keys.length == 2 && (node_data.key?('fields') && node_data.key?('rows'))
|
105
|
+
:table
|
106
|
+
else
|
107
|
+
:settings
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
# Removes any meta data eg. "fields" from a table and just returns the raw data
|
112
|
+
def raw_data
|
113
|
+
# REFACT, what if this is CSV, meaning it is just an array?
|
114
|
+
# add specs
|
115
|
+
result = data
|
116
|
+
|
117
|
+
result.each_key do |key|
|
118
|
+
# ANTI: get_node_type uses @data while we are using @data.clone here
|
119
|
+
data[key] = if get_node_type(key) == :table
|
120
|
+
result[key].delete('fields')
|
121
|
+
else
|
122
|
+
result[key]
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
data
|
127
|
+
end
|
128
|
+
|
129
|
+
# Move this out to the logger function when it has been refactor
|
130
|
+
def debug(include_header: false)
|
131
|
+
debug_header if include_header
|
132
|
+
|
133
|
+
# tp dsls.values, :k_key, :k_type, :state, :save_at, :last_at, :data, :last_data, :source, { :file => { :width => 150 } }
|
134
|
+
# puts JSON.pretty_generate(data)
|
135
|
+
L.o(raw_data_struct)
|
136
|
+
end
|
137
|
+
|
138
|
+
def debug_header
|
139
|
+
L.heading self.class.name
|
140
|
+
L.kv 'key', key
|
141
|
+
L.kv 'type', type
|
142
|
+
L.kv 'namespace', namespace
|
143
|
+
L.kv 'error', error
|
144
|
+
|
145
|
+
debug_header_keys
|
146
|
+
|
147
|
+
L.line
|
148
|
+
end
|
149
|
+
|
150
|
+
def debug_header_keys
|
151
|
+
options&.keys&.reject { |k| k == :namespace }&.each do |key|
|
152
|
+
L.kv key, options[key]
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
private
|
157
|
+
|
158
|
+
def initialize_attributes(key = nil, **options)
|
159
|
+
@key = key
|
160
|
+
|
161
|
+
@options = options || {}
|
162
|
+
@type = slice_option(:type) || KDoc.opinion.default_document_type
|
163
|
+
@namespace = slice_option(:namespace) || ''
|
164
|
+
@parent = slice_option(:parent)
|
165
|
+
|
166
|
+
# Most documents live within a hash, some tabular documents such as CSV will use an []
|
167
|
+
@data = slice_option(:default_data) || {}
|
168
|
+
|
169
|
+
@error = nil
|
170
|
+
end
|
171
|
+
|
172
|
+
def settings_instance(data, key, **options, &block)
|
173
|
+
KDoc.opinion.settings_class.new(data, key, **options, &block)
|
174
|
+
end
|
175
|
+
|
176
|
+
def table_instance(data, key, **options, &block)
|
177
|
+
KDoc.opinion.table_class.new(data, key, **options, &block)
|
178
|
+
end
|
179
|
+
|
180
|
+
def slice_option(key)
|
181
|
+
return nil unless @options.key?(key)
|
182
|
+
|
183
|
+
result = @options[key]
|
184
|
+
@options.delete(key)
|
185
|
+
result
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
module KDoc
|
6
|
+
# This is called fake opinion because I have not figured out
|
7
|
+
# how I want to implement this
|
8
|
+
class FakeOpinion
|
9
|
+
attr_accessor :default_document_type
|
10
|
+
attr_accessor :default_settings_key
|
11
|
+
attr_accessor :default_table_key
|
12
|
+
|
13
|
+
attr_accessor :document_class
|
14
|
+
attr_accessor :settings_class
|
15
|
+
attr_accessor :table_class
|
16
|
+
|
17
|
+
def initialize
|
18
|
+
@default_document_type = :entity
|
19
|
+
@default_settings_key = :settings
|
20
|
+
@default_table_key = :table
|
21
|
+
|
22
|
+
@document_class = KDoc::Document
|
23
|
+
@table_class = KDoc::Table
|
24
|
+
@settings_class = KDoc::Settings
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,131 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
module KDoc
|
6
|
+
# Builds up key/value settings from the block
|
7
|
+
# and applies them to a key coded node on the hash
|
8
|
+
class Settings
|
9
|
+
attr_reader :parent
|
10
|
+
attr_reader :key
|
11
|
+
|
12
|
+
alias kp parent
|
13
|
+
|
14
|
+
def initialize(data, key = nil, **options, &block)
|
15
|
+
initialize_attributes(data, key, **options)
|
16
|
+
|
17
|
+
# Need a way to find out the line number for errors and report it correctly
|
18
|
+
begin
|
19
|
+
instance_eval(&block) if block_given?
|
20
|
+
# rubocop:disable Style/RescueStandardError
|
21
|
+
rescue => e
|
22
|
+
# rubocop:enable Style/RescueStandardError
|
23
|
+
puts "Invalid code block in settings_dsl: #{@key}"
|
24
|
+
puts e.message
|
25
|
+
raise
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def my_data
|
30
|
+
@data[@key]
|
31
|
+
end
|
32
|
+
|
33
|
+
# def run_decorators(opts)
|
34
|
+
# decorators = KDoc::Decorator.decorate.decorators(opts[:decorators])
|
35
|
+
|
36
|
+
# return if decorators.empty?
|
37
|
+
|
38
|
+
# decorators.each do |decorator|
|
39
|
+
# decorator.send(:update, my_data) if decorator.respond_to?(:update)
|
40
|
+
# decorator.send(:call, my_data) if decorator.respond_to?(:call)
|
41
|
+
# end
|
42
|
+
# end
|
43
|
+
|
44
|
+
def respond_to_missing?(name, *_args, &_block)
|
45
|
+
# puts 'respond_to_missing?'
|
46
|
+
# puts "respond_to_missing: #{name}"
|
47
|
+
n = name.to_s
|
48
|
+
n = n[0..-2] if n.end_with?('=')
|
49
|
+
my_data.key?(n.to_s) || (!@parent.nil? && @parent.respond_to?(name, true)) || super
|
50
|
+
end
|
51
|
+
|
52
|
+
# rubocop:disable Metrics/AbcSize
|
53
|
+
def method_missing(name, *args, &_block)
|
54
|
+
# puts "method_missing: #{name}"
|
55
|
+
# puts "args.length : #{args.length}"
|
56
|
+
|
57
|
+
if name != :type && !@parent.nil? && @parent.respond_to?(name)
|
58
|
+
puts "NAME: #{name}"
|
59
|
+
return @parent.public_send(name, *args, &block)
|
60
|
+
end
|
61
|
+
raise KDoc::Error, 'Multiple setting values is not supported' if args.length > 1
|
62
|
+
|
63
|
+
add_getter_or_param_method(name)
|
64
|
+
add_setter_method(name)
|
65
|
+
|
66
|
+
send(name, args[0]) if args.length == 1 # name.end_with?('=')
|
67
|
+
|
68
|
+
super unless self.class.method_defined?(name)
|
69
|
+
end
|
70
|
+
# rubocop:enable Metrics/AbcSize
|
71
|
+
|
72
|
+
# Handles Getter method and method with single parameter
|
73
|
+
# object.my_name
|
74
|
+
# object.my_name('david')
|
75
|
+
def add_getter_or_param_method(name)
|
76
|
+
# L.progress(1, 'add_getter_or_param_method')
|
77
|
+
self.class.class_eval do
|
78
|
+
# L.progress(2, 'add_getter_or_param_method')
|
79
|
+
name = name.to_s.gsub(/=$/, '')
|
80
|
+
# L.progress(3, 'add_getter_or_param_method')
|
81
|
+
define_method(name) do |*args|
|
82
|
+
# L.progress(4, 'add_getter_or_param_method')
|
83
|
+
# L.kv 'add_getter_or_param_method', name
|
84
|
+
raise KDoc::Error, 'Multiple setting values is not supported' if args.length > 1
|
85
|
+
|
86
|
+
if args.length.zero?
|
87
|
+
get_value(name)
|
88
|
+
else
|
89
|
+
send("#{name}=", args[0])
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
# Handles Setter method
|
96
|
+
# object.my_name = 'david'
|
97
|
+
def add_setter_method(name)
|
98
|
+
# L.progress(1, 'add_setter_method')
|
99
|
+
self.class.class_eval do
|
100
|
+
# L.progress(2, 'add_setter_method')
|
101
|
+
name = name.to_s.gsub(/=$/, '')
|
102
|
+
# L.progress(3, 'add_setter_method')
|
103
|
+
# L.kv 'add_setter_method', name
|
104
|
+
define_method("#{name}=") do |value|
|
105
|
+
# L.progress(4, 'add_setter_method')
|
106
|
+
# L.kv 'value', value
|
107
|
+
my_data[name.to_s] = value
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def get_value(name)
|
113
|
+
my_data[name.to_s]
|
114
|
+
end
|
115
|
+
|
116
|
+
def debug
|
117
|
+
puts JSON.pretty_generate(my_data)
|
118
|
+
end
|
119
|
+
|
120
|
+
private
|
121
|
+
|
122
|
+
def initialize_attributes(data, key = nil, **options)
|
123
|
+
@data = data
|
124
|
+
@key = (key || FakeOpinion.new.default_settings_key).to_s
|
125
|
+
|
126
|
+
@parent = options[:parent] if !options.nil? && options.key?(:parent)
|
127
|
+
|
128
|
+
@data[@key] = {}
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
data/lib/k_doc/table.rb
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module KDoc
|
4
|
+
# Build rows (aka DataTable) with field definitions and rows of data
|
5
|
+
class Table
|
6
|
+
attr_reader :parent
|
7
|
+
attr_reader :name
|
8
|
+
|
9
|
+
def initialize(data, name = nil, **options, &block)
|
10
|
+
initialize_attributes(data, name, **options)
|
11
|
+
|
12
|
+
instance_eval(&block) if block_given?
|
13
|
+
end
|
14
|
+
|
15
|
+
def fields(field_definitions)
|
16
|
+
fields = @data[@name]['fields']
|
17
|
+
|
18
|
+
field_definitions.each do |fd|
|
19
|
+
fields << if fd.is_a?(String) || fd.is_a?(Symbol)
|
20
|
+
field(fd, nil, :string)
|
21
|
+
else
|
22
|
+
fd
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# rubocop:disable Metrics/AbcSize
|
28
|
+
def row(*args, **named_args)
|
29
|
+
fields = @data[@name]['fields']
|
30
|
+
|
31
|
+
raise "To many values for row, argument #{i}" if args.length > fields.length
|
32
|
+
|
33
|
+
# Apply column names with defaults
|
34
|
+
row = fields.each_with_object({}) do |f, hash|
|
35
|
+
hash[f['name']] = f['default']
|
36
|
+
end
|
37
|
+
|
38
|
+
# Override with positional arguments
|
39
|
+
args.each_with_index do |arg, i|
|
40
|
+
row[fields[i]['name']] = KUtil.data.clean_symbol(arg)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Override with named args
|
44
|
+
named_args.each_key do |key|
|
45
|
+
row[key.to_s] = named_args[key]
|
46
|
+
end
|
47
|
+
|
48
|
+
@data[@name]['rows'] << row
|
49
|
+
row
|
50
|
+
end
|
51
|
+
# rubocop:enable Metrics/AbcSize
|
52
|
+
|
53
|
+
# rubocop:disable Naming/AccessorMethodName
|
54
|
+
def get_fields
|
55
|
+
@data[@name]['fields']
|
56
|
+
end
|
57
|
+
|
58
|
+
def get_rows
|
59
|
+
@data[@name]['rows']
|
60
|
+
end
|
61
|
+
# rubocop:enable Naming/AccessorMethodName
|
62
|
+
|
63
|
+
def find_row(key, value)
|
64
|
+
@data[@name]['rows'].find { |r| r[key] == value }
|
65
|
+
end
|
66
|
+
|
67
|
+
# Field definition
|
68
|
+
#
|
69
|
+
# @param [String|Symbol] name Name of the field
|
70
|
+
# @param args[0] Default value if not specified, nil if not set
|
71
|
+
# @param args[1] Type of data, string if not set
|
72
|
+
# @param default: Default value (using named params), as above
|
73
|
+
# @param type: Type of data (using named params), as above
|
74
|
+
# @return [Hash] Field definition
|
75
|
+
def field(name, *args, default: nil, type: nil)
|
76
|
+
# default value can be found at position 0 or default: tag (see unit test edge cases)
|
77
|
+
default_value = if args.length.positive?
|
78
|
+
args[0].nil? ? default : args[0]
|
79
|
+
else
|
80
|
+
default
|
81
|
+
end
|
82
|
+
|
83
|
+
# type can be found at position 1 or type: tag
|
84
|
+
type_value = (args.length > 1 ? args[1] : type) || :string
|
85
|
+
|
86
|
+
{
|
87
|
+
'name' => KUtil.data.clean_symbol(name),
|
88
|
+
'default' => KUtil.data.clean_symbol(default_value),
|
89
|
+
'type' => KUtil.data.clean_symbol(type_value)
|
90
|
+
}
|
91
|
+
end
|
92
|
+
alias f field
|
93
|
+
|
94
|
+
private
|
95
|
+
|
96
|
+
def initialize_attributes(data, name = nil, **options)
|
97
|
+
@data = data
|
98
|
+
@name = (name || FakeOpinion.new.default_table_key.to_s).to_s
|
99
|
+
|
100
|
+
@parent = options[:parent] if !options.nil? && options.key?(:parent)
|
101
|
+
|
102
|
+
@data[@name] = { 'fields' => [], 'rows' => [] }
|
103
|
+
end
|
104
|
+
|
105
|
+
def respond_to_missing?(name, *_args, &_block)
|
106
|
+
(!@parent.nil? && @parent.respond_to?(name, true)) || super
|
107
|
+
end
|
108
|
+
|
109
|
+
def method_missing(name, *args, &block)
|
110
|
+
return super unless @parent.respond_to?(name)
|
111
|
+
|
112
|
+
@parent.public_send(name, *args, &block)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
data/lib/k_doc/util.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module KDoc
|
4
|
+
# Utility helper methods for KDoc
|
5
|
+
class Util
|
6
|
+
def build_unique_key(key, type = nil, namespace = nil)
|
7
|
+
raise KDoc::Error, 'key is required when generating unique key' if key.nil? || key.empty?
|
8
|
+
|
9
|
+
type ||= KDoc.opinion.default_document_type
|
10
|
+
|
11
|
+
namespace.nil? || namespace.empty? ? "#{key}_#{type}" : "#{namespace}_#{key}_#{type}"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
data/lib/k_doc/version.rb
CHANGED
metadata
CHANGED
@@ -1,15 +1,43 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: k_doc
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Cruwys
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
12
|
-
dependencies:
|
11
|
+
date: 2021-04-01 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: k_log
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.0.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.0.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: k_util
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.0.0
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.0.0
|
13
41
|
description: " KDoc provides a document in the form a DSL that contains flexible
|
14
42
|
key/value and tabular data\n"
|
15
43
|
email:
|
@@ -24,9 +52,12 @@ files:
|
|
24
52
|
- ".rubocop.yml"
|
25
53
|
- CODE_OF_CONDUCT.md
|
26
54
|
- Gemfile
|
55
|
+
- Guardfile
|
27
56
|
- LICENSE.txt
|
28
57
|
- README.md
|
29
58
|
- Rakefile
|
59
|
+
- STORIES.md
|
60
|
+
- USAGE.md
|
30
61
|
- bin/console
|
31
62
|
- bin/k
|
32
63
|
- bin/kgitsync
|
@@ -36,6 +67,12 @@ files:
|
|
36
67
|
- hooks/update-version
|
37
68
|
- k_doc.gemspec
|
38
69
|
- lib/k_doc.rb
|
70
|
+
- lib/k_doc/data.rb
|
71
|
+
- lib/k_doc/document.rb
|
72
|
+
- lib/k_doc/fake_opinion.rb
|
73
|
+
- lib/k_doc/settings.rb
|
74
|
+
- lib/k_doc/table.rb
|
75
|
+
- lib/k_doc/util.rb
|
39
76
|
- lib/k_doc/version.rb
|
40
77
|
homepage: http://appydave.com/gems/k-doc
|
41
78
|
licenses:
|