k_builder 0.0.28 → 0.0.37

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2dcd63316f0cc08692e83ef120cd5a9b940a4e3b73439cda7e6a298be420a05f
4
- data.tar.gz: '08e1adbd07386448c9c60bbdacbc069257660e216d8fd0aea6417bae94ee5342'
3
+ metadata.gz: '094bf462c5d39f6b39aa8df40e75d4623af9c5d1f6594109cb7afb4e9e82bfb2'
4
+ data.tar.gz: 4dd0400aa1a64e797c56aacc53d3af7ef4cda66c5aca9bbc32f13aeb1604e481
5
5
  SHA512:
6
- metadata.gz: fa441f9ed2e140c89cad9bf3e0246b82489572e3f3843e053e681310dfb86a7b92648bec69f2578b3cc37b4c74fd258e9b6f97829e727d12f80a49284c2a8e92
7
- data.tar.gz: 20d753e90550f3d28ab66f82c756e8f22fca1056c4b7af0bdc2ecc5105e89c28b33392baf083648d6dbffdacd800bad0ef9c07f95112fa67713e3a16d61c74e8
6
+ metadata.gz: a6196e9716b5e86f7cbdb5dba23252a5e7c477da329e2aa8a6a9989c59b790be10316130a9286fd6c5041c49d85a10282dc206a52ef5c73ce2ddf66601ad3c72
7
+ data.tar.gz: 301407050730841e77aad746a32bf046c636970346c4cda6f158699a571d125617eef1e15159a6495ba81fff19c125e25578a57f84407958a19c12f73f706dea
data/lib/k_builder.rb CHANGED
@@ -3,9 +3,10 @@
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/named_folders'
9
+ require 'k_builder/layered_folders'
9
10
 
10
11
  require 'handlebars/helpers/template'
11
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 :hash
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
- @hash = {}
38
+ configuration = KBuilder.configuration if configuration.nil?
48
39
 
49
- unless configuration.nil?
50
- raise KBuilder::StandardError, 'Unknown configuration object' unless configuration.is_a?(Hash)
40
+ @configuration = configuration
51
41
 
52
- hash.merge!(configuration)
53
- end
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
- raise NotImplementedError
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
- hash
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
@@ -16,18 +16,38 @@ module KBuilder
16
16
  end
17
17
  end
18
18
 
19
- def to_hash
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.to_hash if value.is_a?(KBuilder::BaseConfiguration)
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 :target_folder
25
- attr_accessor :template_folder
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
- kv 'target_folder' , target_folder
39
- kv 'template_folder' , template_folder
40
- kv 'global_template_folder', global_template_folder
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
@@ -38,6 +38,8 @@ module KBuilder
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
@@ -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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module KBuilder
4
- VERSION = '0.0.28'
4
+ VERSION = '0.0.37'
5
5
  end
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.28
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-15 00:00:00.000000000 Z
11
+ date: 2021-03-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: handlebars-helpers
@@ -55,9 +55,10 @@ 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/layered_folders.rb
61
+ - lib/k_builder/named_folders.rb
61
62
  - lib/k_builder/version.rb
62
63
  - usage/_out1.png
63
64
  - usage/_out2.png
@@ -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