k_builder 0.0.27 → 0.0.51
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 +4 -4
- data/STORIES.md +22 -2
- data/USAGE.md +24 -24
- data/lib/k_builder.rb +3 -1
- data/lib/k_builder/base_builder.rb +255 -81
- data/lib/k_builder/base_configuration.rb +22 -2
- data/lib/k_builder/configuration.rb +27 -9
- data/lib/k_builder/data_helper.rb +4 -2
- data/lib/k_builder/file_segments.rb +32 -0
- data/lib/k_builder/layered_folders.rb +104 -0
- data/lib/k_builder/named_folders.rb +116 -0
- data/lib/k_builder/version.rb +1 -1
- metadata +5 -3
- data/lib/k_builder/builder.rb +0 -258
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 528f2587aacba6aa1d13d32737aa081b3ebb5364d3bc7e4628a2935a3746ff15
|
4
|
+
data.tar.gz: bb780d8e64e7c814e0b51c8561537a2cbdc31a1ab81f5ee4c78e8d3bb3fa1e89
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2d1dfa3e5875b691576390c970d8005036244566277fee71bbaebe5fc8e63e43588b87780c7616d8e5e07df838dcc3f2ccbf2d4edad8689d2308b8ce41e780e0
|
7
|
+
data.tar.gz: 2eda2bb2b6caa396b0a7ffa0052d22e1bd98fc2931fbb3eb1352ff0b2e0c4fe86880c70e947f456d862d7279bf862f948ffb1c8eea9f9581b29257eb75ded468
|
data/STORIES.md
CHANGED
@@ -10,14 +10,34 @@ As a Polyglot Developer, I want to be up and running in any development language
|
|
10
10
|
|
11
11
|
As a Polyglot Developer, I want to be up and running in any development language with consistency, so I am productive and using best practices [EPIC]
|
12
12
|
|
13
|
-
|
13
|
+
As a Developer, I need builders to be easier to use, so I am more efficient
|
14
14
|
|
15
|
-
|
15
|
+
- Logging needs to be more informative
|
16
|
+
- Template errors need to log the template and the filename
|
17
|
+
- add_file with template_file: needs to support optional filename that is the same as the template_file (or use a token, eg. $TF_PATH$, $TF_NAME$, $TF_FILE$
|
18
|
+
- add_file, the files being generated are not being logged
|
16
19
|
|
17
20
|
## Stories and tasks
|
18
21
|
|
22
|
+
### Stories - completed
|
23
|
+
|
24
|
+
As a Developer, I want have multiple template, so I can group my templates by area of specialty
|
25
|
+
|
26
|
+
- Refactor global and app templates to a layered folder array using (First In, Last Out) priority
|
27
|
+
- Support subfolders of any template folder (maybe)
|
28
|
+
|
29
|
+
As a Developer, I want have multiple output folders, so I can write to multiple locations
|
30
|
+
|
31
|
+
- Refactor output folder so that there are multiple named output folders, with :default working the same way as the existing system
|
32
|
+
- Support subfolders of any output folder
|
33
|
+
- Support output folder change of focus
|
34
|
+
|
19
35
|
### Tasks - completed
|
20
36
|
|
37
|
+
WatchBuilder - Build Watcher (as a builder) - [k_builder-watch](https://github.com/klueless-io/k_builder-watch)
|
38
|
+
|
39
|
+
Refactor BaseBuilder
|
40
|
+
|
21
41
|
Setup RubyGems and RubyDoc
|
22
42
|
|
23
43
|
- Build and deploy gem to [rubygems.org](https://rubygems.org/gems/k_builder)
|
data/USAGE.md
CHANGED
@@ -55,26 +55,26 @@ TEXT
|
|
55
55
|
|
56
56
|
builder = KBuilder::Builder.init
|
57
57
|
|
58
|
-
builder
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
58
|
+
builder.add_file('main.rb', template_file: 'class.rb', name: 'main').add_file(
|
59
|
+
'person.rb',
|
60
|
+
template_file: 'model.rb', name: 'person', fields: %i[first_name last_name]
|
61
|
+
).add_file(
|
62
|
+
'address.rb',
|
63
|
+
template_file: 'model.rb',
|
64
|
+
name: 'address',
|
65
|
+
fields: %i[street1 street2 post_code state]
|
66
|
+
).add_file(
|
67
|
+
'configuration.log.txt',
|
68
|
+
template: template,
|
69
|
+
a: builder.template_folder,
|
70
|
+
b: builder.global_template_folder,
|
71
|
+
c: builder.target_folder
|
72
|
+
).add_file(
|
73
|
+
'css/index.css',
|
74
|
+
template: '{{#each colors}} .{{.}} { color: {{.}} } {{/each}}',
|
75
|
+
colors: %w[red blue green],
|
76
|
+
pretty: true
|
77
|
+
)
|
78
78
|
```
|
79
79
|
|
80
80
|
#### Folder Structure (after)
|
@@ -85,7 +85,7 @@ Folder structure after running the builder
|
|
85
85
|
|
86
86
|
#### main.rb
|
87
87
|
|
88
|
-

|
89
89
|
|
90
90
|
#### person.rb
|
91
91
|
|
@@ -93,12 +93,12 @@ Folder structure after running the builder
|
|
93
93
|
|
94
94
|
#### address.rb
|
95
95
|
|
96
|
-

|
97
97
|
|
98
98
|
#### configuration.log.txt
|
99
99
|
|
100
|
-

|
101
101
|
|
102
102
|
#### css/index.css
|
103
103
|
|
104
|
-

|
data/lib/k_builder.rb
CHANGED
@@ -3,9 +3,11 @@
|
|
3
3
|
require 'k_builder/version'
|
4
4
|
require 'k_builder/base_builder'
|
5
5
|
require 'k_builder/base_configuration'
|
6
|
-
require 'k_builder/builder'
|
7
6
|
require 'k_builder/configuration'
|
8
7
|
require 'k_builder/data_helper'
|
8
|
+
require 'k_builder/file_segments'
|
9
|
+
require 'k_builder/named_folders'
|
10
|
+
require 'k_builder/layered_folders'
|
9
11
|
|
10
12
|
require 'handlebars/helpers/template'
|
11
13
|
|
@@ -8,7 +8,11 @@ module KBuilder
|
|
8
8
|
# Setter methods (are NOT fluent) can be created as needed
|
9
9
|
# these methods would not be prefixed with the set_
|
10
10
|
class BaseBuilder
|
11
|
-
attr_reader :
|
11
|
+
attr_reader :configuration
|
12
|
+
|
13
|
+
attr_accessor :target_folders
|
14
|
+
|
15
|
+
attr_accessor :template_folders
|
12
16
|
|
13
17
|
# Factory method that provides a builder for a specified structure
|
14
18
|
# runs through a configuration block and then builds the final structure
|
@@ -20,112 +24,282 @@ module KBuilder
|
|
20
24
|
|
21
25
|
# Create and initialize the builder.
|
22
26
|
#
|
23
|
-
# Initialization can be done via any of these three sequential steps.
|
24
|
-
# - Configuration hash
|
25
|
-
# - After new event
|
26
|
-
# - Configuration block (lambda)
|
27
|
-
#
|
28
27
|
# @return [Builder] Returns the builder via fluent interface
|
29
28
|
def self.init(configuration = nil)
|
30
29
|
builder = new(configuration)
|
31
30
|
|
32
|
-
builder.after_new
|
33
|
-
|
34
31
|
yield(builder) if block_given?
|
35
32
|
|
36
33
|
builder
|
37
34
|
end
|
38
35
|
|
39
|
-
# Use after_new to massage hash values that come in via
|
40
|
-
# configuration into more complex values
|
41
|
-
#
|
42
|
-
# Abstract method
|
43
|
-
def after_new; end
|
44
|
-
|
45
36
|
# assigns a builder hash and defines builder methods
|
46
37
|
def initialize(configuration = nil)
|
47
|
-
|
48
|
-
|
49
|
-
unless configuration.nil?
|
50
|
-
raise KBuilder::StandardError, 'Unknown configuration object' unless configuration.is_a?(Hash)
|
38
|
+
configuration = KBuilder.configuration if configuration.nil?
|
51
39
|
|
52
|
-
|
53
|
-
end
|
40
|
+
@configuration = configuration
|
54
41
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
# Return an array of symbols to represent the fluent
|
59
|
-
# setter methods that you want on your builder.
|
60
|
-
#
|
61
|
-
# Abstract method
|
62
|
-
def builder_setter_methods
|
63
|
-
raise NotImplementedError
|
42
|
+
@target_folders = configuration.target_folders.clone
|
43
|
+
@template_folders = configuration.template_folders.clone
|
64
44
|
end
|
65
45
|
|
66
46
|
# @return [Hash/StrongType] Returns data object, can be a hash
|
67
47
|
# or strong typed object that you
|
68
48
|
# have wrapped around the hash
|
69
49
|
def build
|
70
|
-
|
71
|
-
end
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
#
|
81
|
-
#
|
82
|
-
#
|
83
|
-
|
84
|
-
#
|
85
|
-
#
|
86
|
-
# # @return [type=Hash]
|
87
|
-
# def build_nested(data_structure, builder, attributes = {}, &block)
|
88
|
-
# if block_given?
|
89
|
-
# builder.build(&block).to_h
|
90
|
-
# else
|
91
|
-
# build_hash(data_structure, attributes)
|
92
|
-
# end
|
93
|
-
# end
|
94
|
-
|
95
|
-
private
|
96
|
-
|
97
|
-
# #
|
98
|
-
# # @param data_structure [type=DataStructure]
|
99
|
-
# # @param attributes [type=Hash, DataStructure]
|
100
|
-
# #
|
101
|
-
# # @return [type=Hash]
|
102
|
-
# def build_hash(data_structure, attributes)
|
103
|
-
# if attributes.is_a?(data_structure)
|
104
|
-
# attributes.to_h
|
105
|
-
# else
|
106
|
-
# data_structure.new(attributes).to_h
|
107
|
-
# end
|
108
|
-
# end
|
109
|
-
|
110
|
-
# Defines all of the necessary builder setter methods
|
50
|
+
raise NotImplementedError
|
51
|
+
end
|
52
|
+
|
53
|
+
def to_h
|
54
|
+
{
|
55
|
+
target_folders: target_folders.to_h,
|
56
|
+
template_folders: template_folders.to_h
|
57
|
+
}
|
58
|
+
end
|
59
|
+
|
60
|
+
# ----------------------------------------------------------------------
|
61
|
+
# Fluent interface
|
62
|
+
# ----------------------------------------------------------------------
|
63
|
+
|
64
|
+
# Internal Actions are considered helpers for the builder, they do
|
65
|
+
# something useful, but they do not tend to implement fluent interfaces.
|
111
66
|
#
|
112
|
-
#
|
113
|
-
|
114
|
-
|
67
|
+
# They some times do actions, they sometimes return information.
|
68
|
+
#
|
69
|
+
# NOTE: [SRP] - These methods should probably be converted into objects
|
70
|
+
# ----------------------------------------------------------------------
|
71
|
+
|
72
|
+
# Add a file to the target location
|
73
|
+
#
|
74
|
+
# @param [String] file The file name with or without relative path, eg. my_file.json or src/my_file.json
|
75
|
+
# @option opts [String] :content Supply the content that you want to write to the file
|
76
|
+
# @option opts [String] :template Supply the template that you want to write to the file, template will be processed ('nobody') From address
|
77
|
+
# @option opts [String] :content_file File with content, file location is based on where the program is running
|
78
|
+
# @option opts [String] :template_file File with handlebars templated content that will be transformed, file location is based on the configured template_path
|
79
|
+
#
|
80
|
+
# Extra options will be used as data for templates, e.g
|
81
|
+
# @option opts [String] :to Recipient email
|
82
|
+
# @option opts [String] :body The email's body
|
83
|
+
def add_file(file, **opts)
|
84
|
+
full_file = opts.key?(:folder_key) ? target_file(file, folder: opts[:folder_key]) : target_file(file)
|
85
|
+
|
86
|
+
# Need logging options that can log these internal details
|
87
|
+
FileUtils.mkdir_p(File.dirname(full_file))
|
88
|
+
|
89
|
+
content = process_any_content(**opts)
|
90
|
+
|
91
|
+
File.write(full_file, content)
|
92
|
+
|
93
|
+
# Prettier needs to work with the original file name
|
94
|
+
run_prettier file if opts.key?(:pretty)
|
95
|
+
|
115
96
|
self
|
116
97
|
end
|
98
|
+
alias touch add_file # it is expected that you would not supply any options, just a file name
|
117
99
|
|
118
|
-
#
|
100
|
+
# Add content to the clipboard
|
119
101
|
#
|
120
|
-
#
|
121
|
-
#
|
102
|
+
# @option opts [String] :content Supply the content that you want to write to the file
|
103
|
+
# @option opts [String] :template Supply the template that you want to write to the file, template will be processed ('nobody') From address
|
104
|
+
# @option opts [String] :content_file File with content, file location is based on where the program is running
|
105
|
+
# @option opts [String] :template_file File with handlebars templated content that will be transformed, file location is based on the configured template_path
|
122
106
|
#
|
123
|
-
#
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
107
|
+
# Extra options will be used as data for templates, e.g
|
108
|
+
# @option opts [String] :to Recipient email
|
109
|
+
# @option opts [String] :body The email's body
|
110
|
+
def add_clipboard(**opts)
|
111
|
+
content = process_any_content(**opts)
|
112
|
+
|
113
|
+
begin
|
114
|
+
IO.popen('pbcopy', 'w') { |f| f << content }
|
115
|
+
rescue Errno::ENOENT => e
|
116
|
+
if e.message == 'No such file or directory - pbcopy'
|
117
|
+
# May want to use this GEM in the future
|
118
|
+
# https://github.com/janlelis/clipboard
|
119
|
+
puts 'Clipboard paste is currently only supported on MAC'
|
120
|
+
end
|
128
121
|
end
|
122
|
+
|
123
|
+
self
|
124
|
+
end
|
125
|
+
alias clipboard_copy add_clipboard
|
126
|
+
|
127
|
+
def vscode(*file_parts, folder: current_folder_key)
|
128
|
+
file = target_file(*file_parts, folder: folder)
|
129
|
+
|
130
|
+
rc "code #{file}"
|
131
|
+
|
132
|
+
self
|
133
|
+
end
|
134
|
+
|
135
|
+
# ----------------------------------------------------------------------
|
136
|
+
# Attributes: Think getter/setter
|
137
|
+
#
|
138
|
+
# The following getter/setters can be referenced both inside and outside
|
139
|
+
# of the fluent builder fluent API. They do not implement the fluent
|
140
|
+
# interface unless prefixed by set_.
|
141
|
+
#
|
142
|
+
# set_: Only setters with the prefix _set are considered fluent.
|
143
|
+
# ----------------------------------------------------------------------
|
144
|
+
|
145
|
+
# Target folders and files
|
146
|
+
# ----------------------------------------------------------------------
|
147
|
+
|
148
|
+
def set_current_folder(folder_key)
|
149
|
+
target_folders.current = folder_key
|
150
|
+
|
151
|
+
self
|
152
|
+
end
|
153
|
+
alias cd set_current_folder
|
154
|
+
|
155
|
+
# Fluent adder for target folder (KBuilder::NamedFolders)
|
156
|
+
def add_target_folder(folder_key, value)
|
157
|
+
target_folders.add(folder_key, value)
|
158
|
+
|
159
|
+
self
|
160
|
+
end
|
161
|
+
|
162
|
+
def current_folder_key
|
163
|
+
target_folders.current
|
164
|
+
end
|
165
|
+
|
166
|
+
# Get target folder by folder_key
|
167
|
+
#
|
168
|
+
# If folder_key not supplied then get the current target folder
|
169
|
+
def target_folder(folder_key = current_folder_key)
|
170
|
+
target_folders.get(folder_key)
|
171
|
+
end
|
172
|
+
|
173
|
+
# Get target file
|
174
|
+
#
|
175
|
+
# If you provide a relative folder, then it will be relative to the :folder parameter
|
176
|
+
#
|
177
|
+
# If the :folder is not set, then it will be relative to the current folder
|
178
|
+
#
|
179
|
+
# @examples
|
180
|
+
# target_file('abc.txt')
|
181
|
+
# target_file('xyz/abc.txt')
|
182
|
+
# target_file('xyz', 'abc.txt')
|
183
|
+
#
|
184
|
+
# If you provide an absolute folder, then it will ignore the :folder parameter
|
185
|
+
#
|
186
|
+
# @examples
|
187
|
+
# target_file('/abc.txt')
|
188
|
+
# target_file('/xyz/abc.txt')
|
189
|
+
# target_file('/xyz', 'abc.txt')
|
190
|
+
def target_file(*file_parts, folder: current_folder_key)
|
191
|
+
# Absolute path
|
192
|
+
return File.join(*file_parts) if Pathname.new(file_parts.first).absolute?
|
193
|
+
|
194
|
+
# Relative to :folder
|
195
|
+
File.join(target_folder(folder), *file_parts)
|
196
|
+
end
|
197
|
+
|
198
|
+
# Template folder & Files
|
199
|
+
# ----------------------------------------------------------------------
|
200
|
+
|
201
|
+
# Fluent adder for template folder (KBuilder::LayeredFolders)
|
202
|
+
def add_template_folder(folder_key, value)
|
203
|
+
template_folders.add(folder_key, value)
|
204
|
+
|
205
|
+
self
|
206
|
+
end
|
207
|
+
|
208
|
+
# Get for template folder
|
209
|
+
def get_template_folder(folder_key)
|
210
|
+
template_folders.get(folder_key)
|
211
|
+
end
|
212
|
+
|
213
|
+
# Gets a template_file relative to the template folder, looks first in
|
214
|
+
# local template folder and if not found, looks in global template folder
|
215
|
+
def find_template_file(file_parts)
|
216
|
+
template_folders.find_file(file_parts)
|
217
|
+
end
|
218
|
+
|
219
|
+
# Building content from templates
|
220
|
+
# ----------------------------------------------------------------------
|
221
|
+
|
222
|
+
# Use content from a a selection of content sources
|
223
|
+
#
|
224
|
+
# @option opts [String] :content Just pass through the :content as is.
|
225
|
+
# @option opts [String] :content_file Read content from the :content_file
|
226
|
+
#
|
227
|
+
# Future options
|
228
|
+
# @option opts [String] :content_loren [TODO]Create Loren Ipsum text as a :content_loren count of words
|
229
|
+
# @option opts [String] :content_url Read content from the :content_url
|
230
|
+
#
|
231
|
+
# @return Returns some content
|
232
|
+
def use_content(**opts)
|
233
|
+
return opts[:content] unless opts[:content].nil?
|
234
|
+
|
235
|
+
return unless opts[:content_file]
|
236
|
+
|
237
|
+
cf = opts[:content_file]
|
238
|
+
|
239
|
+
return "Content not found: #{File.expand_path(cf)}" unless File.exist?(cf)
|
240
|
+
|
241
|
+
File.read(cf)
|
242
|
+
end
|
243
|
+
|
244
|
+
# Use template from a a selection of template sources
|
245
|
+
#
|
246
|
+
# @option opts [String] :template Just pass through the :template as is.
|
247
|
+
# @option opts [String] :template_file Read template from the :template_file
|
248
|
+
#
|
249
|
+
# @return Returns some template
|
250
|
+
def use_template(**opts)
|
251
|
+
return opts[:template] unless opts[:template].nil?
|
252
|
+
|
253
|
+
return unless opts[:template_file]
|
254
|
+
|
255
|
+
tf = find_template_file(opts[:template_file])
|
256
|
+
|
257
|
+
return "template not found: #{opts[:template_file]}" if tf.nil?
|
258
|
+
|
259
|
+
File.read(tf)
|
260
|
+
end
|
261
|
+
|
262
|
+
# Process content will take any one of the following
|
263
|
+
# - Raw content
|
264
|
+
# - File based content
|
265
|
+
# - Raw template (translated via handlebars)
|
266
|
+
# - File base template (translated via handlebars)
|
267
|
+
#
|
268
|
+
# Process any of the above inputs to create final content output
|
269
|
+
#
|
270
|
+
# @option opts [String] :content Supply the content that you want to write to the file
|
271
|
+
# @option opts [String] :template Supply the template that you want to write to the file, template will be transformed using handlebars
|
272
|
+
# @option opts [String] :content_file File with content, file location is based on where the program is running
|
273
|
+
# @option opts [String] :template_file File with handlebars templated content that will be transformed, file location is based on the configured template_path
|
274
|
+
def process_any_content(**opts)
|
275
|
+
raw_content = use_content(**opts)
|
276
|
+
|
277
|
+
return raw_content if raw_content
|
278
|
+
|
279
|
+
template_content = use_template(**opts)
|
280
|
+
|
281
|
+
Handlebars::Helpers::Template.render(template_content, opts) unless template_content.nil?
|
282
|
+
end
|
283
|
+
|
284
|
+
def run_prettier(file, log_level: :log)
|
285
|
+
# command = "prettier --check #{file} --write #{file}"
|
286
|
+
command = "npx prettier --loglevel #{log_level} --write #{file}"
|
287
|
+
|
288
|
+
run_command command
|
289
|
+
end
|
290
|
+
|
291
|
+
def run_command(command)
|
292
|
+
# Deep path create if needed
|
293
|
+
tf = target_folder
|
294
|
+
|
295
|
+
FileUtils.mkdir_p(tf)
|
296
|
+
|
297
|
+
build_command = "cd #{tf} && #{command}"
|
298
|
+
|
299
|
+
puts build_command
|
300
|
+
|
301
|
+
system(build_command)
|
129
302
|
end
|
303
|
+
alias rc run_command
|
130
304
|
end
|
131
305
|
end
|
@@ -16,18 +16,38 @@ module KBuilder
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
-
|
19
|
+
# move out into module
|
20
|
+
def to_h
|
20
21
|
hash = {}
|
21
22
|
instance_variables.each do |var|
|
22
23
|
value = instance_variable_get(var)
|
23
24
|
|
24
|
-
value = value
|
25
|
+
value = KBuilder.data.struct_to_hash(value) if complex_type?(value)
|
25
26
|
|
26
27
|
hash[var.to_s.delete('@')] = value
|
27
28
|
end
|
28
29
|
hash
|
29
30
|
end
|
30
31
|
|
32
|
+
# Any basic (aka primitive) type
|
33
|
+
def basic_type?(value)
|
34
|
+
value.is_a?(String) ||
|
35
|
+
value.is_a?(Symbol) ||
|
36
|
+
value.is_a?(FalseClass) ||
|
37
|
+
value.is_a?(TrueClass) ||
|
38
|
+
value.is_a?(Integer) ||
|
39
|
+
value.is_a?(Float)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Anything container that is not a regular class
|
43
|
+
def complex_type?(value)
|
44
|
+
value.is_a?(Array) ||
|
45
|
+
value.is_a?(Hash) ||
|
46
|
+
value.is_a?(Struct) ||
|
47
|
+
value.is_a?(OpenStruct) ||
|
48
|
+
value.respond_to?(:to_h)
|
49
|
+
end
|
50
|
+
|
31
51
|
def kv(name, value)
|
32
52
|
puts "#{name.rjust(30)} : #{value}"
|
33
53
|
end
|
@@ -21,23 +21,41 @@ module KBuilder
|
|
21
21
|
|
22
22
|
# Configuration class
|
23
23
|
class Configuration < BaseConfiguration
|
24
|
-
attr_accessor :
|
25
|
-
attr_accessor :
|
26
|
-
attr_accessor :global_template_folder
|
24
|
+
attr_accessor :target_folders
|
25
|
+
attr_accessor :template_folders
|
27
26
|
|
28
27
|
def initialize
|
29
28
|
super
|
30
|
-
@target_folder = Dir.getwd
|
31
|
-
@template_folder = File.join(Dir.getwd, '.templates')
|
32
|
-
@global_template_folder = nil
|
29
|
+
# @target_folder = Dir.getwd
|
30
|
+
# @template_folder = File.join(Dir.getwd, '.templates')
|
31
|
+
# @global_template_folder = nil
|
32
|
+
@target_folders = NamedFolders.new
|
33
|
+
@template_folders = LayeredFolders.new
|
33
34
|
end
|
34
35
|
|
36
|
+
def initialize_copy(orig)
|
37
|
+
super(orig)
|
38
|
+
|
39
|
+
@target_folders = orig.target_folders.clone
|
40
|
+
@template_folders = orig.template_folders.clone
|
41
|
+
end
|
42
|
+
|
43
|
+
# rubocop:disable Metrics/AbcSize
|
35
44
|
def debug
|
36
45
|
puts '-' * 120
|
37
46
|
puts 'kbuilder base configuration'
|
38
|
-
|
39
|
-
|
40
|
-
|
47
|
+
|
48
|
+
puts 'target_folders'
|
49
|
+
target_folders.folders.each_key do |key|
|
50
|
+
folder = target_folders.folders[key]
|
51
|
+
kv key.to_s, folder
|
52
|
+
end
|
53
|
+
|
54
|
+
puts 'template folders (search order)'
|
55
|
+
template_folders.ordered_folders.each do |folder|
|
56
|
+
puts folder.to_s
|
57
|
+
end
|
41
58
|
end
|
59
|
+
# rubocop:enable Metrics/AbcSize
|
42
60
|
end
|
43
61
|
end
|
@@ -31,13 +31,15 @@ module KBuilder
|
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
|
-
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
|
34
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
35
35
|
def struct_to_hash(data)
|
36
36
|
# No test yet
|
37
37
|
if data.is_a?(Array)
|
38
38
|
return data.map { |v| v.is_a?(OpenStruct) ? struct_to_hash(v) : v }
|
39
39
|
end
|
40
40
|
|
41
|
+
return struct_to_hash(data.to_h) if !data.is_a?(Hash) && data.respond_to?(:to_h)
|
42
|
+
|
41
43
|
data.each_pair.with_object({}) do |(key, value), hash|
|
42
44
|
case value
|
43
45
|
when OpenStruct, Struct, Hash
|
@@ -53,7 +55,7 @@ module KBuilder
|
|
53
55
|
end
|
54
56
|
end
|
55
57
|
end
|
56
|
-
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity
|
58
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
57
59
|
|
58
60
|
def clean_symbol(value)
|
59
61
|
return value if value.nil?
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module KBuilder
|
4
|
+
# Splits a file into its base parts (file, path, file_name, extension and file_name_only)
|
5
|
+
#
|
6
|
+
# Provides the interpolate helper to rebuild a different filename using those segments
|
7
|
+
class FileSegments
|
8
|
+
attr_reader :file
|
9
|
+
attr_reader :path
|
10
|
+
attr_reader :file_name
|
11
|
+
attr_reader :ext
|
12
|
+
attr_reader :file_name_only
|
13
|
+
|
14
|
+
def initialize(file)
|
15
|
+
@file = file
|
16
|
+
@path = File.dirname(file)
|
17
|
+
@file_name = File.basename(file)
|
18
|
+
@ext = File.extname(file)
|
19
|
+
@file_name_only = File.basename(file, @ext)
|
20
|
+
end
|
21
|
+
|
22
|
+
def interpolate(target_file)
|
23
|
+
# p str.gsub( /#{var}/, 'foo' ) # => "a test foo"
|
24
|
+
target_file
|
25
|
+
.gsub(/\$T_FILE\$/i, file)
|
26
|
+
.gsub(/\$T_PATH\$/i, path)
|
27
|
+
.gsub(/\$T_FILE_NAME\$/i, file_name)
|
28
|
+
.gsub(/\$T_EXT\$/i, ext)
|
29
|
+
.gsub(/\$T_FILE_NAME_ONLY\$/i, file_name_only)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module KBuilder
|
4
|
+
#
|
5
|
+
# Named folders makes sense for generated/output folders because you may want
|
6
|
+
# more than one type of location to generate output.
|
7
|
+
#
|
8
|
+
# Don't confuse multiple named output folders with sub-paths, when you want to
|
9
|
+
# build up a file name in a child folder, you can do that as part of building
|
10
|
+
# the filename.
|
11
|
+
#
|
12
|
+
# The idea behind named folders is for when you have two or more totally different
|
13
|
+
# outputs that (may live in the a similar location) or live in different locations.
|
14
|
+
|
15
|
+
# Layered folders allow files to be found in any of the searchable folders
|
16
|
+
#
|
17
|
+
# They derive from and thus work just like named folders in that they allow folders
|
18
|
+
# to be stored with easy to remember names/alias's.
|
19
|
+
#
|
20
|
+
# Where they differ is that they are retrieved in preferential search order that is
|
21
|
+
# by default (First In, Last Out) priority aka a Stack (Last In, First Out) or
|
22
|
+
# optionally over ridden via the search_order method
|
23
|
+
#
|
24
|
+
# Layered folders makes sense for use with template files and source data/model
|
25
|
+
# where you can have specific usage files available and if they are not found then
|
26
|
+
# you can use fall-back files in other folders.
|
27
|
+
#
|
28
|
+
# example:
|
29
|
+
# folders = LayeredFolders.new
|
30
|
+
# folders.add(:global , '~/global_templates')
|
31
|
+
# folders.add(:domain , '/my-project/domain_templates')
|
32
|
+
# folders.add(:app , '/my-project/my-app/.templates')
|
33
|
+
#
|
34
|
+
# # Find a file and folder will in folders in this order
|
35
|
+
# # app_templates, then domain_templates and then finally global templates
|
36
|
+
# # ['/my-project/my-app/.templates', '/my-project/domain_templates', '~/global_templates']
|
37
|
+
# #
|
38
|
+
# # Find a file called template1.txt and return its fully-qualified path
|
39
|
+
# folders.find_file('template1.txt')
|
40
|
+
#
|
41
|
+
# # As above, but returns the folder only, file name and sub-paths are ignored
|
42
|
+
# folders.find_file_folder('template1.txt')
|
43
|
+
# folders.find_file_folder('abc/xyz/deep-template.txt')
|
44
|
+
#
|
45
|
+
# # If an additional folder is added, say in child configuration that is designed
|
46
|
+
# # to override some of the global templates, then you can run a search_order
|
47
|
+
# # method to re-order the templates
|
48
|
+
#
|
49
|
+
# folders.add(:global_shim , '~/global_templates_shim')
|
50
|
+
# folders.search_order(:app, :domain, :global_shim, :global)
|
51
|
+
#
|
52
|
+
# class Builder < KBuilder::BaseBuilder
|
53
|
+
class LayeredFolders < KBuilder::NamedFolders
|
54
|
+
attr_reader :ordered_keys
|
55
|
+
attr_reader :ordered_folders
|
56
|
+
|
57
|
+
def initialize
|
58
|
+
super()
|
59
|
+
|
60
|
+
@ordered_keys = []
|
61
|
+
@ordered_folders = []
|
62
|
+
end
|
63
|
+
|
64
|
+
def initialize_copy(orig)
|
65
|
+
super(orig)
|
66
|
+
|
67
|
+
@ordered_keys = orig.ordered_keys.clone
|
68
|
+
@ordered_folders = orig.ordered_folders.clone
|
69
|
+
end
|
70
|
+
|
71
|
+
def add(folder_key, *folder_parts)
|
72
|
+
folder = super(folder_key, *folder_parts)
|
73
|
+
|
74
|
+
ordered_keys.prepend(folder_key)
|
75
|
+
ordered_folders.prepend(folder)
|
76
|
+
|
77
|
+
folder
|
78
|
+
end
|
79
|
+
|
80
|
+
# File name or array of sub-paths plus file
|
81
|
+
#
|
82
|
+
# Return the folder that a file is found in
|
83
|
+
def find_file(file_parts)
|
84
|
+
folder = find_file_folder(file_parts)
|
85
|
+
folder.nil? ? nil : File.join(folder, file_parts)
|
86
|
+
end
|
87
|
+
|
88
|
+
# File name or array of sub-paths plus file
|
89
|
+
#
|
90
|
+
# Return the folder that a file is found in
|
91
|
+
def find_file_folder(file_parts)
|
92
|
+
ordered_folders.find { |folder| File.exist?(File.join(folder, file_parts)) }
|
93
|
+
end
|
94
|
+
|
95
|
+
def to_h
|
96
|
+
{
|
97
|
+
ordered: {
|
98
|
+
keys: ordered_keys,
|
99
|
+
folders: ordered_folders
|
100
|
+
}
|
101
|
+
}.merge(@folders)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module KBuilder
|
4
|
+
# Named folders allow folders to be stored with easy to remember names/alias's
|
5
|
+
# Secondarily, you can also build up file names based on these named folders.
|
6
|
+
#
|
7
|
+
# Named folders makes sense for generated/output folders because you may want
|
8
|
+
# more than one type of location to generate output.
|
9
|
+
#
|
10
|
+
# Don't confuse multiple named output folders with sub-paths, when you want to
|
11
|
+
# build up a file name in a child folder, you can do that as part of building
|
12
|
+
# the filename.
|
13
|
+
#
|
14
|
+
# The idea behind named folders is for when you have two or more totally different
|
15
|
+
# outputs that (may live in the a similar location) or live in different locations.
|
16
|
+
# Samples:
|
17
|
+
# name: :code - generating source code into a project
|
18
|
+
# name: :slide - generating slide deck into a documentation folder
|
19
|
+
# name: :webpack - folder where you might generate webpack files, e.g. webpack.config.*.json
|
20
|
+
#
|
21
|
+
# example:
|
22
|
+
# folders = NamedFolders.new
|
23
|
+
# folders.add(:csharp , '~/dev/csharp/cool-project')
|
24
|
+
# folders.add(:package_json , :csharp)
|
25
|
+
# folders.add(:webpack , folders.join(:csharp, 'config'))
|
26
|
+
# folders.add(:builder , folders.join(:csharp, 'builder'))
|
27
|
+
# folders.add(:slides , '~/doc/csharp/cool-project')
|
28
|
+
#
|
29
|
+
# puts folders.get(:builder)
|
30
|
+
#
|
31
|
+
# puts folders.get_filename(:csharp, 'Program.cs')
|
32
|
+
# puts folders.get_filename(:csharp, 'Models/Order.cs')
|
33
|
+
# puts folders.get_filename(:csharp, 'Models', 'Order.cs')
|
34
|
+
#
|
35
|
+
# Do I need to support :default?
|
36
|
+
class NamedFolders
|
37
|
+
attr_reader :folders
|
38
|
+
|
39
|
+
attr_reader :current
|
40
|
+
|
41
|
+
def initialize
|
42
|
+
@folders = {}
|
43
|
+
@current = nil
|
44
|
+
end
|
45
|
+
|
46
|
+
def initialize_copy(orig)
|
47
|
+
super(orig)
|
48
|
+
|
49
|
+
@folders = orig.folders.clone
|
50
|
+
end
|
51
|
+
|
52
|
+
def current=(folder_key)
|
53
|
+
guard_folder_key(folder_key)
|
54
|
+
@current = folder_key
|
55
|
+
end
|
56
|
+
|
57
|
+
# Add support for file_parts
|
58
|
+
def add(folder_key, *folder_parts)
|
59
|
+
# get a predefined folder by symbol
|
60
|
+
folder = join_folder_parts(folder_parts)
|
61
|
+
if folder.is_a?(Symbol)
|
62
|
+
folder = get(folder)
|
63
|
+
elsif folder.start_with?('~')
|
64
|
+
folder = File.expand_path(folder)
|
65
|
+
end
|
66
|
+
|
67
|
+
@current = folder_key if @current.nil?
|
68
|
+
folders[folder_key] = folder
|
69
|
+
end
|
70
|
+
|
71
|
+
# Get a folder
|
72
|
+
def get(folder_key)
|
73
|
+
guard_folder_key(folder_key)
|
74
|
+
folders[folder_key]
|
75
|
+
end
|
76
|
+
|
77
|
+
# Join the lookup folder key with the subpath folder parts (optionally + filename) and return the folder or filename
|
78
|
+
#
|
79
|
+
# Return fully qualified filename
|
80
|
+
def join(folder_key, *file_folder_parts)
|
81
|
+
folder = get(folder_key)
|
82
|
+
|
83
|
+
File.join(folder, file_folder_parts)
|
84
|
+
end
|
85
|
+
# Get a file name using the lookup folder key and the file name or array of sub-paths plus filename
|
86
|
+
alias get_filename join
|
87
|
+
|
88
|
+
def folder_keys
|
89
|
+
@folders.keys
|
90
|
+
end
|
91
|
+
|
92
|
+
def to_h
|
93
|
+
@folders
|
94
|
+
end
|
95
|
+
|
96
|
+
private
|
97
|
+
|
98
|
+
def join_folder_parts(folder_parts)
|
99
|
+
raise KBuilder::Error, 'No folder part provided' if folder_parts.nil? || folder_parts.length.zero?
|
100
|
+
|
101
|
+
# If only one part, and that can be a folder or :folder_key, then just return it
|
102
|
+
return folder_parts.first if folder_parts.length == 1
|
103
|
+
|
104
|
+
folder_parts = folder_parts.map.with_index do |folder_part, index|
|
105
|
+
folder_part = get(folder_part) if index.zero? && folder_part.is_a?(Symbol)
|
106
|
+
folder_part
|
107
|
+
end
|
108
|
+
|
109
|
+
File.join(folder_parts)
|
110
|
+
end
|
111
|
+
|
112
|
+
def guard_folder_key(folder_key)
|
113
|
+
raise KBuilder::Error, "Folder not found, this folder key not found: #{folder_key}" unless folders.key?(folder_key)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
data/lib/k_builder/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: k_builder
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.51
|
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-03-
|
11
|
+
date: 2021-03-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: handlebars-helpers
|
@@ -55,9 +55,11 @@ files:
|
|
55
55
|
- lib/k_builder.rb
|
56
56
|
- lib/k_builder/base_builder.rb
|
57
57
|
- lib/k_builder/base_configuration.rb
|
58
|
-
- lib/k_builder/builder.rb
|
59
58
|
- lib/k_builder/configuration.rb
|
60
59
|
- lib/k_builder/data_helper.rb
|
60
|
+
- lib/k_builder/file_segments.rb
|
61
|
+
- lib/k_builder/layered_folders.rb
|
62
|
+
- lib/k_builder/named_folders.rb
|
61
63
|
- lib/k_builder/version.rb
|
62
64
|
- usage/_out1.png
|
63
65
|
- usage/_out2.png
|
data/lib/k_builder/builder.rb
DELETED
@@ -1,258 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module KBuilder
|
4
|
-
# Base builder defines builder methods, build method and configuration
|
5
|
-
class Builder < KBuilder::BaseBuilder
|
6
|
-
# builder_setter_methods = %w[].freeze
|
7
|
-
# target_folder
|
8
|
-
# template_folder
|
9
|
-
# global_template_folder
|
10
|
-
|
11
|
-
def initialize(configuration = nil)
|
12
|
-
configuration = KBuilder.configuration.to_hash if configuration.nil?
|
13
|
-
|
14
|
-
super(configuration)
|
15
|
-
end
|
16
|
-
|
17
|
-
# rubocop:disable Metrics/AbcSize
|
18
|
-
def after_new
|
19
|
-
# ensure that any configured folders are expanded
|
20
|
-
self.target_folder = hash['target_folder'] unless hash['target_folder'].nil?
|
21
|
-
self.template_folder = hash['template_folder'] unless hash['template_folder'].nil?
|
22
|
-
self.global_template_folder = hash['global_template_folder'] unless hash['global_template_folder'].nil?
|
23
|
-
end
|
24
|
-
# rubocop:enable Metrics/AbcSize
|
25
|
-
|
26
|
-
# Return an array of symbols to represent the fluent setter methods in this builder.
|
27
|
-
def builder_setter_methods
|
28
|
-
# Currently I have manually created my settings because I needed custom
|
29
|
-
# logic in the settings to handle path expansion
|
30
|
-
[]
|
31
|
-
end
|
32
|
-
|
33
|
-
# def build
|
34
|
-
# # SomeDryStruct.new(hash)
|
35
|
-
# end
|
36
|
-
|
37
|
-
# ----------------------------------------------------------------------
|
38
|
-
# Fluent interface
|
39
|
-
# ----------------------------------------------------------------------
|
40
|
-
|
41
|
-
# Add a file to the target location
|
42
|
-
#
|
43
|
-
# @param [String] file The file name with or without relative path, eg. my_file.json or src/my_file.json
|
44
|
-
# @option opts [String] :content Supply the content that you want to write to the file
|
45
|
-
# @option opts [String] :template Supply the template that you want to write to the file, template will be processed ('nobody') From address
|
46
|
-
# @option opts [String] :content_file File with content, file location is based on where the program is running
|
47
|
-
# @option opts [String] :template_file File with handlebars templated content that will be transformed, file location is based on the configured template_path
|
48
|
-
#
|
49
|
-
# Extra options will be used as data for templates, e.g
|
50
|
-
# @option opts [String] :to Recipient email
|
51
|
-
# @option opts [String] :body The email's body
|
52
|
-
def add_file(file, **opts)
|
53
|
-
full_file = target_file(file)
|
54
|
-
|
55
|
-
FileUtils.mkdir_p(File.dirname(full_file))
|
56
|
-
|
57
|
-
content = process_any_content(**opts)
|
58
|
-
|
59
|
-
File.write(full_file, content)
|
60
|
-
|
61
|
-
# Prettier needs to work with the original file name
|
62
|
-
run_prettier file if opts.key?(:pretty)
|
63
|
-
|
64
|
-
self
|
65
|
-
end
|
66
|
-
|
67
|
-
# ----------------------------------------------------------------------
|
68
|
-
# Attributes: Think getter/setter
|
69
|
-
#
|
70
|
-
# The following getter/setters can be referenced both inside and outside
|
71
|
-
# of the fluent builder fluent API. They do not implement the fluent
|
72
|
-
# interface unless prefixed by set_.
|
73
|
-
#
|
74
|
-
# set_: Only setters with the prefix _set are considered fluent.
|
75
|
-
# ----------------------------------------------------------------------
|
76
|
-
|
77
|
-
# Target folder
|
78
|
-
# ----------------------------------------------------------------------
|
79
|
-
|
80
|
-
# Fluent setter for target folder
|
81
|
-
def set_target_folder(value)
|
82
|
-
self.target_folder = value
|
83
|
-
|
84
|
-
self
|
85
|
-
end
|
86
|
-
|
87
|
-
# Setter for target folder
|
88
|
-
def target_folder=(value)
|
89
|
-
hash['target_folder'] = File.expand_path(value)
|
90
|
-
end
|
91
|
-
|
92
|
-
# Getter for target folder
|
93
|
-
def target_folder
|
94
|
-
hash['target_folder']
|
95
|
-
end
|
96
|
-
|
97
|
-
# Template folder
|
98
|
-
# ----------------------------------------------------------------------
|
99
|
-
|
100
|
-
# Fluent setter for template folder
|
101
|
-
def set_template_folder(value)
|
102
|
-
self.template_folder = value
|
103
|
-
|
104
|
-
self
|
105
|
-
end
|
106
|
-
|
107
|
-
# Setter for template folder
|
108
|
-
# Refactor: Make Private
|
109
|
-
def template_folder=(value)
|
110
|
-
hash['template_folder'] = File.expand_path(value)
|
111
|
-
end
|
112
|
-
|
113
|
-
# Getter for template folder
|
114
|
-
# Refactor: generate
|
115
|
-
def template_folder
|
116
|
-
hash['template_folder']
|
117
|
-
end
|
118
|
-
|
119
|
-
# Global Target folder
|
120
|
-
# ----------------------------------------------------------------------
|
121
|
-
|
122
|
-
# Fluent setter for global template folder
|
123
|
-
def set_global_template_folder(value)
|
124
|
-
self.global_template_folder = value
|
125
|
-
|
126
|
-
self
|
127
|
-
end
|
128
|
-
|
129
|
-
# Setter for global template folder
|
130
|
-
# Refactor: Make Private
|
131
|
-
def global_template_folder=(value)
|
132
|
-
hash['global_template_folder'] = File.expand_path(value)
|
133
|
-
end
|
134
|
-
|
135
|
-
# Setter for global template folder
|
136
|
-
# Refactor: generate
|
137
|
-
def global_template_folder
|
138
|
-
hash['global_template_folder']
|
139
|
-
end
|
140
|
-
|
141
|
-
# Internal Actions are considered helpers for the builder, they do
|
142
|
-
# something useful, but they do not tend to implement fluent interfaces.
|
143
|
-
#
|
144
|
-
# They some times do actions, they sometimes return information.
|
145
|
-
#
|
146
|
-
# NOTE: [SRP] - These methods should probably be converted into objects
|
147
|
-
# ----------------------------------------------------------------------
|
148
|
-
|
149
|
-
# Gets a target_file relative to target folder
|
150
|
-
def target_file(file)
|
151
|
-
File.join(target_folder, file)
|
152
|
-
end
|
153
|
-
|
154
|
-
# Gets a template_file relative to the template folder
|
155
|
-
def template_file(file)
|
156
|
-
File.join(template_folder, file)
|
157
|
-
end
|
158
|
-
|
159
|
-
# Gets a global_template_file relative to the global template folder
|
160
|
-
def global_template_file(file)
|
161
|
-
File.join(global_template_folder, file)
|
162
|
-
end
|
163
|
-
|
164
|
-
# Gets a template_file relative to the template folder, looks first in
|
165
|
-
# local template folder and if not found, looks in global template folder
|
166
|
-
def find_template_file(file)
|
167
|
-
full_file = template_file(file)
|
168
|
-
return full_file if File.exist?(full_file)
|
169
|
-
|
170
|
-
full_file = global_template_file(file)
|
171
|
-
return full_file if File.exist?(full_file)
|
172
|
-
|
173
|
-
# File not found
|
174
|
-
nil
|
175
|
-
end
|
176
|
-
|
177
|
-
# Use content from a a selection of content sources
|
178
|
-
#
|
179
|
-
# @option opts [String] :content Just pass through the :content as is.
|
180
|
-
# @option opts [String] :content_file Read content from the :content_file
|
181
|
-
#
|
182
|
-
# Future options
|
183
|
-
# @option opts [String] :content_loren [TODO]Create Loren Ipsum text as a :content_loren count of words
|
184
|
-
# @option opts [String] :content_url Read content from the :content_url
|
185
|
-
#
|
186
|
-
# @return Returns some content
|
187
|
-
def use_content(**opts)
|
188
|
-
return opts[:content] unless opts[:content].nil?
|
189
|
-
|
190
|
-
return unless opts[:content_file]
|
191
|
-
|
192
|
-
cf = opts[:content_file]
|
193
|
-
|
194
|
-
return "Content not found: #{File.expand_path(cf)}" unless File.exist?(cf)
|
195
|
-
|
196
|
-
File.read(cf)
|
197
|
-
end
|
198
|
-
|
199
|
-
# Use template from a a selection of template sources
|
200
|
-
#
|
201
|
-
# @option opts [String] :template Just pass through the :template as is.
|
202
|
-
# @option opts [String] :template_file Read template from the :template_file
|
203
|
-
#
|
204
|
-
# @return Returns some template
|
205
|
-
def use_template(**opts)
|
206
|
-
return opts[:template] unless opts[:template].nil?
|
207
|
-
|
208
|
-
return unless opts[:template_file]
|
209
|
-
|
210
|
-
tf = find_template_file(opts[:template_file])
|
211
|
-
|
212
|
-
return "template not found: #{opts[:template_file]}" if tf.nil?
|
213
|
-
|
214
|
-
File.read(tf)
|
215
|
-
end
|
216
|
-
|
217
|
-
# Process content will take any one of the following
|
218
|
-
# - Raw content
|
219
|
-
# - File based content
|
220
|
-
# - Raw template (translated via handlebars)
|
221
|
-
# - File base template (translated via handlebars)
|
222
|
-
#
|
223
|
-
# Process any of the above inputs to create final content output
|
224
|
-
#
|
225
|
-
# @option opts [String] :content Supply the content that you want to write to the file
|
226
|
-
# @option opts [String] :template Supply the template that you want to write to the file, template will be transformed using handlebars
|
227
|
-
# @option opts [String] :content_file File with content, file location is based on where the program is running
|
228
|
-
# @option opts [String] :template_file File with handlebars templated content that will be transformed, file location is based on the configured template_path
|
229
|
-
def process_any_content(**opts)
|
230
|
-
raw_content = use_content(**opts)
|
231
|
-
|
232
|
-
return raw_content if raw_content
|
233
|
-
|
234
|
-
template_content = use_template(**opts)
|
235
|
-
|
236
|
-
Handlebars::Helpers::Template.render(template_content, opts) unless template_content.nil?
|
237
|
-
end
|
238
|
-
|
239
|
-
def run_prettier(file, log_level: :log)
|
240
|
-
# command = "prettier --check #{file} --write #{file}"
|
241
|
-
command = "npx prettier --loglevel #{log_level} --write #{file}"
|
242
|
-
|
243
|
-
run_command command
|
244
|
-
end
|
245
|
-
|
246
|
-
def run_command(command)
|
247
|
-
# Deep path create if needed
|
248
|
-
FileUtils.mkdir_p(target_folder)
|
249
|
-
|
250
|
-
build_command = "cd #{target_folder} && #{command}"
|
251
|
-
|
252
|
-
puts build_command
|
253
|
-
|
254
|
-
system(build_command)
|
255
|
-
end
|
256
|
-
alias rc run_command
|
257
|
-
end
|
258
|
-
end
|