k_builder 0.0.23 → 0.0.37
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/USAGE.md +7 -7
- data/lib/k_builder.rb +4 -2
- data/lib/k_builder/base_builder.rb +206 -21
- data/lib/k_builder/base_configuration.rb +36 -87
- data/lib/k_builder/configuration.rb +27 -9
- data/lib/k_builder/data_helper.rb +66 -0
- data/lib/k_builder/layered_folders.rb +104 -0
- data/lib/k_builder/named_folders.rb +100 -0
- data/lib/k_builder/version.rb +1 -1
- data/{_out1.png → usage/_out1.png} +0 -0
- data/{_out2.png → usage/_out2.png} +0 -0
- data/{_out3.png → usage/_out3.png} +0 -0
- data/{_out4.png → usage/_out4.png} +0 -0
- data/{_out5.png → usage/_out5.png} +0 -0
- data/{_usage_folder_after.png → usage/_usage_folder_after.png} +0 -0
- data/{_usage_folder_before.png → usage/_usage_folder_before.png} +0 -0
- metadata +12 -10
- 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: '094bf462c5d39f6b39aa8df40e75d4623af9c5d1f6594109cb7afb4e9e82bfb2'
|
|
4
|
+
data.tar.gz: 4dd0400aa1a64e797c56aacc53d3af7ef4cda66c5aca9bbc32f13aeb1604e481
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a6196e9716b5e86f7cbdb5dba23252a5e7c477da329e2aa8a6a9989c59b790be10316130a9286fd6c5041c49d85a10282dc206a52ef5c73ce2ddf66601ad3c72
|
|
7
|
+
data.tar.gz: 301407050730841e77aad746a32bf046c636970346c4cda6f158699a571d125617eef1e15159a6495ba81fff19c125e25578a57f84407958a19c12f73f706dea
|
data/USAGE.md
CHANGED
|
@@ -36,7 +36,7 @@ Example folder structure for this usecase before running the builder
|
|
|
36
36
|
|
|
37
37
|
> Note: app-templates will take preference over global templates
|
|
38
38
|
|
|
39
|
-

|
|
39
|
+

|
|
40
40
|
|
|
41
41
|
#### Run builder
|
|
42
42
|
|
|
@@ -81,24 +81,24 @@ builder
|
|
|
81
81
|
|
|
82
82
|
Folder structure after running the builder
|
|
83
83
|
|
|
84
|
-

|
|
84
|
+

|
|
85
85
|
|
|
86
86
|
#### main.rb
|
|
87
87
|
|
|
88
|
-

|
|
88
|
+

|
|
89
89
|
|
|
90
90
|
#### person.rb
|
|
91
91
|
|
|
92
|
-

|
|
92
|
+

|
|
93
93
|
|
|
94
94
|
#### address.rb
|
|
95
95
|
|
|
96
|
-

|
|
96
|
+

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

|
|
100
|
+

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

|
|
104
|
+

|
data/lib/k_builder.rb
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'k_builder/version'
|
|
4
|
+
require 'k_builder/base_builder'
|
|
4
5
|
require 'k_builder/base_configuration'
|
|
5
6
|
require 'k_builder/configuration'
|
|
6
|
-
require 'k_builder/
|
|
7
|
-
require 'k_builder/
|
|
7
|
+
require 'k_builder/data_helper'
|
|
8
|
+
require 'k_builder/named_folders'
|
|
9
|
+
require 'k_builder/layered_folders'
|
|
8
10
|
|
|
9
11
|
require 'handlebars/helpers/template'
|
|
10
12
|
|
|
@@ -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,37 +24,23 @@ 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
|
-
|
|
38
|
+
configuration = KBuilder.configuration if configuration.nil?
|
|
48
39
|
|
|
49
|
-
|
|
50
|
-
raise KBuilder::StandardError, 'Unknown configuration object' unless configuration.is_a?(Hash)
|
|
40
|
+
@configuration = configuration
|
|
51
41
|
|
|
52
|
-
|
|
53
|
-
|
|
42
|
+
@target_folders = configuration.target_folders.clone
|
|
43
|
+
@template_folders = configuration.template_folders.clone
|
|
54
44
|
|
|
55
45
|
define_builder_setter_methods
|
|
56
46
|
end
|
|
@@ -60,15 +50,210 @@ module KBuilder
|
|
|
60
50
|
#
|
|
61
51
|
# Abstract method
|
|
62
52
|
def builder_setter_methods
|
|
63
|
-
|
|
53
|
+
[]
|
|
64
54
|
end
|
|
65
55
|
|
|
66
56
|
# @return [Hash/StrongType] Returns data object, can be a hash
|
|
67
57
|
# or strong typed object that you
|
|
68
58
|
# have wrapped around the hash
|
|
69
59
|
def build
|
|
70
|
-
|
|
60
|
+
raise NotImplementedError
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def to_h
|
|
64
|
+
{
|
|
65
|
+
target_folders: target_folders.to_h,
|
|
66
|
+
template_folders: template_folders.to_h
|
|
67
|
+
}
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# ----------------------------------------------------------------------
|
|
71
|
+
# Fluent interface
|
|
72
|
+
# ----------------------------------------------------------------------
|
|
73
|
+
|
|
74
|
+
# Internal Actions are considered helpers for the builder, they do
|
|
75
|
+
# something useful, but they do not tend to implement fluent interfaces.
|
|
76
|
+
#
|
|
77
|
+
# They some times do actions, they sometimes return information.
|
|
78
|
+
#
|
|
79
|
+
# NOTE: [SRP] - These methods should probably be converted into objects
|
|
80
|
+
# ----------------------------------------------------------------------
|
|
81
|
+
|
|
82
|
+
# Add a file to the target location
|
|
83
|
+
#
|
|
84
|
+
# @param [String] file The file name with or without relative path, eg. my_file.json or src/my_file.json
|
|
85
|
+
# @option opts [String] :content Supply the content that you want to write to the file
|
|
86
|
+
# @option opts [String] :template Supply the template that you want to write to the file, template will be processed ('nobody') From address
|
|
87
|
+
# @option opts [String] :content_file File with content, file location is based on where the program is running
|
|
88
|
+
# @option opts [String] :template_file File with handlebars templated content that will be transformed, file location is based on the configured template_path
|
|
89
|
+
#
|
|
90
|
+
# Extra options will be used as data for templates, e.g
|
|
91
|
+
# @option opts [String] :to Recipient email
|
|
92
|
+
# @option opts [String] :body The email's body
|
|
93
|
+
def add_file(file, **opts)
|
|
94
|
+
full_file = target_file(file)
|
|
95
|
+
|
|
96
|
+
FileUtils.mkdir_p(File.dirname(full_file))
|
|
97
|
+
|
|
98
|
+
content = process_any_content(**opts)
|
|
99
|
+
|
|
100
|
+
File.write(full_file, content)
|
|
101
|
+
|
|
102
|
+
# Prettier needs to work with the original file name
|
|
103
|
+
run_prettier file if opts.key?(:pretty)
|
|
104
|
+
|
|
105
|
+
self
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# ----------------------------------------------------------------------
|
|
109
|
+
# Attributes: Think getter/setter
|
|
110
|
+
#
|
|
111
|
+
# The following getter/setters can be referenced both inside and outside
|
|
112
|
+
# of the fluent builder fluent API. They do not implement the fluent
|
|
113
|
+
# interface unless prefixed by set_.
|
|
114
|
+
#
|
|
115
|
+
# set_: Only setters with the prefix _set are considered fluent.
|
|
116
|
+
# ----------------------------------------------------------------------
|
|
117
|
+
|
|
118
|
+
# Target folders and files
|
|
119
|
+
# ----------------------------------------------------------------------
|
|
120
|
+
|
|
121
|
+
def set_current_folder(folder_key)
|
|
122
|
+
target_folders.current = folder_key
|
|
123
|
+
|
|
124
|
+
self
|
|
125
|
+
end
|
|
126
|
+
alias cd set_current_folder
|
|
127
|
+
|
|
128
|
+
def current_folder_key
|
|
129
|
+
target_folders.current
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# Fluent adder for target folder (KBuilder::NamedFolders)
|
|
133
|
+
def add_target_folder(folder_key, value)
|
|
134
|
+
target_folders.add(folder_key, value)
|
|
135
|
+
|
|
136
|
+
self
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
# Get target folder
|
|
140
|
+
#
|
|
141
|
+
# Defaults to current_target_folder
|
|
142
|
+
def get_target_folder(folder_key = current_folder_key)
|
|
143
|
+
target_folders.get(folder_key)
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
# Get target file
|
|
147
|
+
def target_file(file_parts, folder: current_folder_key)
|
|
148
|
+
File.join(get_target_folder(folder), file_parts)
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
# Template folder & Files
|
|
152
|
+
# ----------------------------------------------------------------------
|
|
153
|
+
|
|
154
|
+
# Fluent adder for template folder (KBuilder::LayeredFolders)
|
|
155
|
+
def add_template_folder(folder_key, value)
|
|
156
|
+
template_folders.add(folder_key, value)
|
|
157
|
+
|
|
158
|
+
self
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
# Get for template folder
|
|
162
|
+
def get_template_folder(folder_key)
|
|
163
|
+
template_folders.get(folder_key)
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
# Gets a template_file relative to the template folder, looks first in
|
|
167
|
+
# local template folder and if not found, looks in global template folder
|
|
168
|
+
def find_template_file(file_parts)
|
|
169
|
+
template_folders.find_file(file_parts)
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
# Building content from templates
|
|
173
|
+
# ----------------------------------------------------------------------
|
|
174
|
+
|
|
175
|
+
# Use content from a a selection of content sources
|
|
176
|
+
#
|
|
177
|
+
# @option opts [String] :content Just pass through the :content as is.
|
|
178
|
+
# @option opts [String] :content_file Read content from the :content_file
|
|
179
|
+
#
|
|
180
|
+
# Future options
|
|
181
|
+
# @option opts [String] :content_loren [TODO]Create Loren Ipsum text as a :content_loren count of words
|
|
182
|
+
# @option opts [String] :content_url Read content from the :content_url
|
|
183
|
+
#
|
|
184
|
+
# @return Returns some content
|
|
185
|
+
def use_content(**opts)
|
|
186
|
+
return opts[:content] unless opts[:content].nil?
|
|
187
|
+
|
|
188
|
+
return unless opts[:content_file]
|
|
189
|
+
|
|
190
|
+
cf = opts[:content_file]
|
|
191
|
+
|
|
192
|
+
return "Content not found: #{File.expand_path(cf)}" unless File.exist?(cf)
|
|
193
|
+
|
|
194
|
+
File.read(cf)
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
# Use template from a a selection of template sources
|
|
198
|
+
#
|
|
199
|
+
# @option opts [String] :template Just pass through the :template as is.
|
|
200
|
+
# @option opts [String] :template_file Read template from the :template_file
|
|
201
|
+
#
|
|
202
|
+
# @return Returns some template
|
|
203
|
+
def use_template(**opts)
|
|
204
|
+
return opts[:template] unless opts[:template].nil?
|
|
205
|
+
|
|
206
|
+
return unless opts[:template_file]
|
|
207
|
+
|
|
208
|
+
tf = find_template_file(opts[:template_file])
|
|
209
|
+
|
|
210
|
+
return "template not found: #{opts[:template_file]}" if tf.nil?
|
|
211
|
+
|
|
212
|
+
File.read(tf)
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
# Process content will take any one of the following
|
|
216
|
+
# - Raw content
|
|
217
|
+
# - File based content
|
|
218
|
+
# - Raw template (translated via handlebars)
|
|
219
|
+
# - File base template (translated via handlebars)
|
|
220
|
+
#
|
|
221
|
+
# Process any of the above inputs to create final content output
|
|
222
|
+
#
|
|
223
|
+
# @option opts [String] :content Supply the content that you want to write to the file
|
|
224
|
+
# @option opts [String] :template Supply the template that you want to write to the file, template will be transformed using handlebars
|
|
225
|
+
# @option opts [String] :content_file File with content, file location is based on where the program is running
|
|
226
|
+
# @option opts [String] :template_file File with handlebars templated content that will be transformed, file location is based on the configured template_path
|
|
227
|
+
def process_any_content(**opts)
|
|
228
|
+
raw_content = use_content(**opts)
|
|
229
|
+
|
|
230
|
+
return raw_content if raw_content
|
|
231
|
+
|
|
232
|
+
template_content = use_template(**opts)
|
|
233
|
+
|
|
234
|
+
Handlebars::Helpers::Template.render(template_content, opts) unless template_content.nil?
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
def run_prettier(file, log_level: :log)
|
|
238
|
+
# command = "prettier --check #{file} --write #{file}"
|
|
239
|
+
command = "npx prettier --loglevel #{log_level} --write #{file}"
|
|
240
|
+
|
|
241
|
+
run_command command
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
def run_command(command)
|
|
245
|
+
# Deep path create if needed
|
|
246
|
+
target_folder = get_target_folder
|
|
247
|
+
|
|
248
|
+
FileUtils.mkdir_p(target_folder)
|
|
249
|
+
|
|
250
|
+
build_command = "cd #{target_folder} && #{command}"
|
|
251
|
+
|
|
252
|
+
puts build_command
|
|
253
|
+
|
|
254
|
+
system(build_command)
|
|
71
255
|
end
|
|
256
|
+
alias rc run_command
|
|
72
257
|
|
|
73
258
|
# TODO
|
|
74
259
|
# Support Nesting
|
|
@@ -3,104 +3,53 @@
|
|
|
3
3
|
module KBuilder
|
|
4
4
|
# Base configuration object for all k_builder* GEM
|
|
5
5
|
class BaseConfiguration
|
|
6
|
-
def
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
# All of this code should be extracted into a module
|
|
17
|
-
#
|
|
18
|
-
# The module should then be extracted out into a GEM so that
|
|
19
|
-
# I can include it as needed. The GEM might be called
|
|
20
|
-
# (dynamic attributes) and would allow a regular class to act like an OpenStruct
|
|
21
|
-
# K-DSL uses data hash, while base configuration uses instance variables
|
|
22
|
-
|
|
23
|
-
def respond_to_missing?(name, *_args, &_block)
|
|
24
|
-
# puts 'respond_to_missing?'
|
|
25
|
-
# puts "respond_to_missing: #{name}"
|
|
26
|
-
n = name.to_s
|
|
27
|
-
n = n[0..-2] if n.end_with?('=')
|
|
28
|
-
|
|
29
|
-
if n.end_with?('?')
|
|
30
|
-
super
|
|
31
|
-
else
|
|
32
|
-
# This has not been fully tested
|
|
33
|
-
instance_variable_defined?("@#{n}") || super
|
|
6
|
+
def self.attach_to(klass_me, klass_target, accessor_name)
|
|
7
|
+
# Create a memoized getter to an instance of the attaching class (:klass_me)
|
|
8
|
+
#
|
|
9
|
+
# def third_party
|
|
10
|
+
# @third_party ||= KBuilder::ThirdPartyGem::Configuration.new
|
|
11
|
+
# end
|
|
12
|
+
klass_target.send(:define_method, accessor_name) do
|
|
13
|
+
return instance_variable_get("@#{accessor_name}") if instance_variable_defined?("@#{accessor_name}")
|
|
14
|
+
|
|
15
|
+
instance_variable_set("@#{accessor_name}", klass_me.new)
|
|
34
16
|
end
|
|
35
17
|
end
|
|
36
18
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
add_setter_method(name)
|
|
19
|
+
# move out into module
|
|
20
|
+
def to_h
|
|
21
|
+
hash = {}
|
|
22
|
+
instance_variables.each do |var|
|
|
23
|
+
value = instance_variable_get(var)
|
|
43
24
|
|
|
44
|
-
|
|
25
|
+
value = KBuilder.data.struct_to_hash(value) if complex_type?(value)
|
|
45
26
|
|
|
46
|
-
|
|
27
|
+
hash[var.to_s.delete('@')] = value
|
|
28
|
+
end
|
|
29
|
+
hash
|
|
47
30
|
end
|
|
48
31
|
|
|
49
|
-
#
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
# L.progress(3, 'add_getter_or_param_method')
|
|
58
|
-
# L.kv 'name', name
|
|
59
|
-
define_method(name) do |*args|
|
|
60
|
-
# L.progress(4, 'add_getter_or_param_method')
|
|
61
|
-
# L.kv 'add_getter_or_param_method', name
|
|
62
|
-
raise KBuilder::Error, 'Multiple setting values is not supported' if args.length > 1
|
|
63
|
-
|
|
64
|
-
if args.length.zero?
|
|
65
|
-
get_value(name)
|
|
66
|
-
else
|
|
67
|
-
send("#{name}=", args[0])
|
|
68
|
-
end
|
|
69
|
-
end
|
|
70
|
-
end
|
|
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)
|
|
71
40
|
end
|
|
72
41
|
|
|
73
|
-
#
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
# L.progress(3, 'add_setter_method')
|
|
81
|
-
# L.kv 'add_setter_method', name
|
|
82
|
-
define_method("#{name}=") do |value|
|
|
83
|
-
# L.progress(4, 'add_setter_method')
|
|
84
|
-
# L.kv 'name', name
|
|
85
|
-
# L.kv 'value', value
|
|
86
|
-
instance_variable_set("@#{name}", value)
|
|
87
|
-
# my_data[name.to_s] = value
|
|
88
|
-
end
|
|
89
|
-
end
|
|
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)
|
|
90
49
|
end
|
|
91
50
|
|
|
92
|
-
def
|
|
93
|
-
|
|
51
|
+
def kv(name, value)
|
|
52
|
+
puts "#{name.rjust(30)} : #{value}"
|
|
94
53
|
end
|
|
95
54
|
end
|
|
96
|
-
|
|
97
|
-
# class L
|
|
98
|
-
# def self.progress(index, label)
|
|
99
|
-
# puts "#{index} - #{label}"
|
|
100
|
-
# end
|
|
101
|
-
|
|
102
|
-
# def self.kv(name, value)
|
|
103
|
-
# puts "#{name.rjust(30)} : #{value}"
|
|
104
|
-
# end
|
|
105
|
-
# end
|
|
106
55
|
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
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Attach data helper to the KBuilder module
|
|
4
|
+
module KBuilder
|
|
5
|
+
# Data helpers/utils for Kbuilder
|
|
6
|
+
class << self
|
|
7
|
+
attr_writer :data
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def self.data
|
|
11
|
+
@data ||= DataHelper.new
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# Helper methods attached to the namespace for working with Data
|
|
15
|
+
#
|
|
16
|
+
# Usage: KBuilder.data.to_struct(data)
|
|
17
|
+
class DataHelper
|
|
18
|
+
# Convert a hash into a deep OpenStruct or array an array
|
|
19
|
+
# of objects into an array of OpenStruct
|
|
20
|
+
def to_struct(data)
|
|
21
|
+
case data
|
|
22
|
+
when Hash
|
|
23
|
+
OpenStruct.new(data.transform_values { |v| to_struct(v) })
|
|
24
|
+
|
|
25
|
+
when Array
|
|
26
|
+
data.map { |o| to_struct(o) }
|
|
27
|
+
|
|
28
|
+
else
|
|
29
|
+
# Some primitave type: String, True/False, Symbol or an ObjectStruct
|
|
30
|
+
data
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
35
|
+
def struct_to_hash(data)
|
|
36
|
+
# No test yet
|
|
37
|
+
if data.is_a?(Array)
|
|
38
|
+
return data.map { |v| v.is_a?(OpenStruct) ? struct_to_hash(v) : v }
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
return struct_to_hash(data.to_h) if !data.is_a?(Hash) && data.respond_to?(:to_h)
|
|
42
|
+
|
|
43
|
+
data.each_pair.with_object({}) do |(key, value), hash|
|
|
44
|
+
case value
|
|
45
|
+
when OpenStruct, Struct, Hash
|
|
46
|
+
hash[key] = struct_to_hash(value)
|
|
47
|
+
when Array
|
|
48
|
+
# No test yet
|
|
49
|
+
values = value.map do |v|
|
|
50
|
+
v.is_a?(OpenStruct) || v.is_a?(Struct) || v.is_a?(Hash) ? struct_to_hash(v) : v
|
|
51
|
+
end
|
|
52
|
+
hash[key] = values
|
|
53
|
+
else
|
|
54
|
+
hash[key] = value
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
59
|
+
|
|
60
|
+
def clean_symbol(value)
|
|
61
|
+
return value if value.nil?
|
|
62
|
+
|
|
63
|
+
value.is_a?(Symbol) ? value.to_s : value
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
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)
|
|
72
|
+
folder = super(folder_key, folder)
|
|
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,100 @@
|
|
|
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
|
+
def add(folder_key, folder)
|
|
58
|
+
# get a predefined folder by symbol
|
|
59
|
+
if folder.is_a?(Symbol)
|
|
60
|
+
folder = get(folder)
|
|
61
|
+
elsif folder.start_with?('~')
|
|
62
|
+
folder = File.expand_path(folder)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
@current = folder_key if @current.nil?
|
|
66
|
+
folders[folder_key] = folder
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Get a folder
|
|
70
|
+
def get(folder_key)
|
|
71
|
+
guard_folder_key(folder_key)
|
|
72
|
+
folders[folder_key]
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Join the lookup folder key with the subpath folder parts (optionally + filename) and return the folder or filename
|
|
76
|
+
#
|
|
77
|
+
# Return fully qualified filename
|
|
78
|
+
def join(folder_key, *file_folder_parts)
|
|
79
|
+
folder = get(folder_key)
|
|
80
|
+
|
|
81
|
+
File.join(folder, file_folder_parts)
|
|
82
|
+
end
|
|
83
|
+
# Get a file name using the lookup folder key and the file name or array of sub-paths plus filename
|
|
84
|
+
alias get_filename join
|
|
85
|
+
|
|
86
|
+
def folder_keys
|
|
87
|
+
@folders.keys
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def to_h
|
|
91
|
+
@folders
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
private
|
|
95
|
+
|
|
96
|
+
def guard_folder_key(folder_key)
|
|
97
|
+
raise KBuilder::Error, "Folder not found, this folder key not found: #{folder_key}" unless folders.key?(folder_key)
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
data/lib/k_builder/version.rb
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
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.37
|
|
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-20 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: handlebars-helpers
|
|
@@ -44,13 +44,6 @@ files:
|
|
|
44
44
|
- Rakefile
|
|
45
45
|
- STORIES.md
|
|
46
46
|
- USAGE.md
|
|
47
|
-
- _out1.png
|
|
48
|
-
- _out2.png
|
|
49
|
-
- _out3.png
|
|
50
|
-
- _out4.png
|
|
51
|
-
- _out5.png
|
|
52
|
-
- _usage_folder_after.png
|
|
53
|
-
- _usage_folder_before.png
|
|
54
47
|
- bin/console
|
|
55
48
|
- bin/k
|
|
56
49
|
- bin/kgitsync
|
|
@@ -62,9 +55,18 @@ files:
|
|
|
62
55
|
- lib/k_builder.rb
|
|
63
56
|
- lib/k_builder/base_builder.rb
|
|
64
57
|
- lib/k_builder/base_configuration.rb
|
|
65
|
-
- lib/k_builder/builder.rb
|
|
66
58
|
- lib/k_builder/configuration.rb
|
|
59
|
+
- lib/k_builder/data_helper.rb
|
|
60
|
+
- lib/k_builder/layered_folders.rb
|
|
61
|
+
- lib/k_builder/named_folders.rb
|
|
67
62
|
- lib/k_builder/version.rb
|
|
63
|
+
- usage/_out1.png
|
|
64
|
+
- usage/_out2.png
|
|
65
|
+
- usage/_out3.png
|
|
66
|
+
- usage/_out4.png
|
|
67
|
+
- usage/_out5.png
|
|
68
|
+
- usage/_usage_folder_after.png
|
|
69
|
+
- usage/_usage_folder_before.png
|
|
68
70
|
homepage: http://appydave.com
|
|
69
71
|
licenses:
|
|
70
72
|
- MIT
|
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
|