k_builder 0.0.63 → 0.0.68

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ /Users/davidcruwys/dev/slides-addons/highlight_css
@@ -0,0 +1,7 @@
1
+ <html>
2
+ <head><title>404 Not Found</title></head>
3
+ <body bgcolor="white">
4
+ <center><h1>404 Not Found</h1></center>
5
+ <hr><center>nginx</center>
6
+ </body>
7
+ </html>
@@ -1,21 +1,38 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module KBuilder
4
+ # TODO: Why is this called BaseBuilder, why not just builder
5
+ # TODO: Is this really the builder pattern, it could be the class used by a director
6
+ # but it is not really storing information for builder purposes.
7
+ #
4
8
  # Base builder defines builder methods, build method and configuration
5
9
  #
6
10
  # Convention: Setter methods (are Fluent) and use the prefix set_
7
11
  # Getter methods (are NOT fluent) and return the stored value
8
12
  # Setter methods (are NOT fluent) can be created as needed
9
13
  # these methods would not be prefixed with the set_
14
+
15
+ # process_any_content(content: 'abc')
16
+ # process_any_content(content_file: 'abc.txt')
17
+ # process_any_content(template: 'abc {{name}}', name: 'sean')
18
+ # process_any_content(template_file: 'abc.txt', name: 'sean')
19
+
20
+ # process_any_content(content_gist: 'https://gist.github.com/klueless-io/8d4b6d199dbe4a5d40807a47fff8ed1c')
21
+ # process_any_content(template_gist: 'https://gist.github.com/klueless-io/8d4b6d199dbe4a5d40807a47fff8ed1c', name: 'sean')
22
+
10
23
  class BaseBuilder
11
24
  include KLog::Logging
12
25
 
13
26
  attr_reader :configuration
14
27
 
15
28
  attr_accessor :target_folders
16
-
17
29
  attr_accessor :template_folders
18
30
 
31
+ attr_accessor :last_output_file
32
+ attr_accessor :last_output_folder
33
+ # attr_accessor :last_template
34
+ attr_accessor :last_template_file
35
+
19
36
  # Factory method that provides a builder for a specified structure
20
37
  # runs through a configuration block and then builds the final structure
21
38
  #
@@ -59,6 +76,7 @@ module KBuilder
59
76
  }
60
77
  end
61
78
 
79
+ # rubocop:disable Metrics/AbcSize
62
80
  def debug
63
81
  log.subheading 'kbuilder'
64
82
 
@@ -69,8 +87,16 @@ module KBuilder
69
87
  log.info ''
70
88
 
71
89
  template_folders.debug(title: 'template folders (search order)')
90
+
91
+ log.info ''
92
+ log.kv 'last output file' , last_output_file
93
+ log.kv 'last output folder' , last_output_folder
94
+ # log.kv 'last template' , last_template
95
+ log.kv 'last template file' , last_template_file
96
+
72
97
  ''
73
98
  end
99
+ # rubocop:enable Metrics/AbcSize
74
100
 
75
101
  # ----------------------------------------------------------------------
76
102
  # Fluent interface
@@ -95,31 +121,92 @@ module KBuilder
95
121
  # Extra options will be used as data for templates, e.g
96
122
  # @option opts [String] :to Recipient email
97
123
  # @option opts [String] :body The email's body
124
+ def add_file_command(file, **opts)
125
+ {
126
+ action: :add_file,
127
+ file: file,
128
+ opts: opts
129
+ }
130
+ end
131
+
132
+ # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
98
133
  def add_file(file, **opts)
99
134
  # move to command
100
- full_file = opts.key?(:folder_key) ? target_file(file, folder: opts[:folder_key]) : target_file(file)
135
+ full_file = target_file(file, **opts) # opts.key?(:folder_key) || opts.key?(:folder) ? target_file(file, folder: opts[:folder], folder_key: opts[:folder_key]) : target_file(file)
101
136
 
102
137
  # Need logging options that can log these internal details
103
- FileUtils.mkdir_p(File.dirname(full_file))
138
+ mkdir_p(File.dirname(full_file))
104
139
 
105
140
  content = process_any_content(**opts)
106
141
 
107
- File.write(full_file, content)
142
+ file_write(full_file, content, on_exist: opts[:on_exist])
108
143
 
109
144
  # Prettier needs to work with the original file name
110
- run_prettier file if opts.key?(:pretty)
145
+ run_prettier file if opts.key?(:pretty)
146
+ # TODO: Add test
147
+ run_cop(full_file, fix_safe: true) if opts.key?(:cop) || opts.key?(:ruby_cop)
148
+
111
149
  # Need support for rubocop -a
150
+ open_file(last_output_file) if opts.key?(:open)
151
+ open_file(last_template_file) if opts.key?(:open_template)
152
+ browse_file(last_output_file) if opts.key?(:browse)
153
+ pause(opts[:pause]) if opts[:pause]
112
154
 
113
155
  self
114
156
  end
157
+ # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity
158
+
159
+ def replay_commands(commands)
160
+ commands.each do |command|
161
+ case command[:action]
162
+ when :add_file
163
+ add_file(command[:file], command[:opts])
164
+ when :delete_file
165
+ delete_file(command[:file], command[:opts])
166
+ else
167
+ log.error "Unknown command: #{command[:action]}"
168
+ end
169
+ end
170
+ end
171
+
115
172
  alias touch add_file # it is expected that you would not supply any options, just a file name
116
173
 
174
+ def delete_file_command(file, **opts)
175
+ {
176
+ action: :delete_file,
177
+ file: file,
178
+ opts: opts
179
+ }
180
+ end
181
+
182
+ def delete_file(file, **opts)
183
+ full_file = target_file(file, **opts) # = opts.key?(:folder_key) ? target_file(file, folder: opts[:folder_key]) : target_file(file)
184
+
185
+ File.delete(full_file) if File.exist?(full_file)
186
+
187
+ self
188
+ end
189
+
190
+ def file_exist?(file, **opts)
191
+ # full_file = opts.key?(:folder_key) ? target_file(file, folder_key: opts[:folder_key]) : target_file(file)
192
+ full_file = target_file(file, **opts)
193
+
194
+ File.exist?(full_file)
195
+ end
196
+
197
+ # ToDo
198
+ # def delete_folder(file)
199
+ # FileUtils.remove_dir(path_to_directory) if File.directory?(path_to_directory)
200
+
201
+ # self
202
+ # end
203
+
117
204
  def make_folder(folder_key = nil, sub_path: nil)
118
205
  folder_key = current_folder_key if folder_key.nil?
119
206
  folder = target_folder(folder_key)
120
207
  folder = File.join(folder, sub_path) unless sub_path.nil?
121
208
 
122
- FileUtils.mkdir_p(folder)
209
+ mkdir_p(folder)
123
210
 
124
211
  self
125
212
  end
@@ -140,6 +227,8 @@ module KBuilder
140
227
 
141
228
  begin
142
229
  IO.popen('pbcopy', 'w') { |f| f << content }
230
+
231
+ open_file(last_template_file) if opts.key?(:open_template)
143
232
  rescue Errno::ENOENT => e
144
233
  if e.message == 'No such file or directory - pbcopy'
145
234
  # May want to use this GEM in the future
@@ -152,15 +241,82 @@ module KBuilder
152
241
  end
153
242
  alias clipboard_copy add_clipboard
154
243
 
155
- def vscode(*file_parts, folder: current_folder_key)
244
+ def vscode_command(*file_parts, folder_key: current_folder_key, file: nil)
245
+ {
246
+ action: :vscode,
247
+ file_parts: file_parts,
248
+ opts: { folder_key: folder_key, file: file }
249
+ }
250
+ end
251
+
252
+ def vscode(*file_parts, folder_key: current_folder_key, file: nil)
156
253
  # move to command
157
- file = target_file(*file_parts, folder: folder)
254
+ file = target_file(*file_parts, folder_key: folder_key) if file.nil?
158
255
 
159
256
  rc "code #{file}"
160
257
 
161
258
  self
162
259
  end
163
260
 
261
+ def browse_command(*file_parts, folder_key: current_folder_key, file: nil)
262
+ {
263
+ action: :browse,
264
+ file_parts: file_parts,
265
+ opts: { folder_key: folder_key, file: file }
266
+ }
267
+ end
268
+
269
+ def browse(*file_parts, folder_key: current_folder_key, file: nil)
270
+ # move to command
271
+ file = target_file(*file_parts, folder_key: folder_key) if file.nil?
272
+
273
+ rc "open -a \"Google Chrome\" #{file}"
274
+
275
+ self
276
+ end
277
+
278
+ def open
279
+ open_file(last_output_file)
280
+
281
+ self
282
+ end
283
+ alias o open
284
+
285
+ def open_template
286
+ open_file(last_template_file)
287
+
288
+ self
289
+ end
290
+ alias ot open_template
291
+
292
+ def open_file(file)
293
+ if file.nil?
294
+ log.warn('open_file will not open when file is nil')
295
+ return self
296
+ end
297
+
298
+ vscode(file: file)
299
+
300
+ self
301
+ end
302
+
303
+ def browse_file(file)
304
+ if file.nil?
305
+ log.warn('browse_file will not browse when file is nil')
306
+ return self
307
+ end
308
+
309
+ browse(file: file)
310
+
311
+ self
312
+ end
313
+
314
+ def pause(seconds = 1)
315
+ sleep(seconds)
316
+
317
+ self
318
+ end
319
+
164
320
  # ----------------------------------------------------------------------
165
321
  # Attributes: Think getter/setter
166
322
  #
@@ -216,12 +372,18 @@ module KBuilder
216
372
  # target_file('/abc.txt')
217
373
  # target_file('/xyz/abc.txt')
218
374
  # target_file('/xyz', 'abc.txt')
219
- def target_file(*file_parts, folder: current_folder_key)
375
+ def target_file(*file_parts, folder_key: current_folder_key, folder: nil, **)
376
+ # TODO: Mismatch (sometimes called folder, sometimes called folder_key:)
377
+ if folder
378
+ log.error("Change folder: to folder_key: for #{folder} - #{file_parts}")
379
+ return
380
+ end
381
+
220
382
  # Absolute path
221
383
  return File.join(*file_parts) if Pathname.new(file_parts.first).absolute?
222
384
 
223
- # Relative to :folder
224
- File.join(target_folder(folder), *file_parts)
385
+ # Relative to :folder_key
386
+ File.join(target_folder(folder_key), *file_parts)
225
387
  end
226
388
 
227
389
  # Template folder & Files
@@ -242,7 +404,8 @@ module KBuilder
242
404
  # Gets a template_file relative to the template folder, looks first in
243
405
  # local template folder and if not found, looks in global template folder
244
406
  def find_template_file(file_parts)
245
- template_folders.find_file(file_parts)
407
+ self.last_template_file = template_folders.find_file(file_parts)
408
+ last_template_file
246
409
  end
247
410
 
248
411
  # Building content from templates
@@ -268,15 +431,6 @@ module KBuilder
268
431
 
269
432
  return "content not found: #{opts[:content_file]}" if cf.nil?
270
433
 
271
- # cf = opts[:content_file]
272
-
273
- # unless File.exist?(cf)
274
- # cf_from_template_folders = find_template_file(cf)
275
- # return "Content not found: #{File.expand_path(cf)}" unless File.exist?(cf_from_template_folders)
276
-
277
- # cf = cf_from_template_folders
278
- # end
279
-
280
434
  File.read(cf)
281
435
  end
282
436
 
@@ -340,7 +494,7 @@ module KBuilder
340
494
  # Deep path create if needed
341
495
  tf = target_folder
342
496
 
343
- FileUtils.mkdir_p(tf)
497
+ mkdir_p(tf)
344
498
 
345
499
  build_command = "cd #{tf} && #{command}"
346
500
 
@@ -351,5 +505,46 @@ module KBuilder
351
505
  system(build_command)
352
506
  end
353
507
  alias rc run_command
508
+
509
+ def file_write(file, content, on_exist: :skip)
510
+ self.last_output_file = file # if file not found, we still want to record this as the last_output_file
511
+
512
+ not_found = !File.exist?(file)
513
+
514
+ if not_found
515
+ File.write(file, content)
516
+ return
517
+ end
518
+
519
+ return if %i[skip ignore].include?(on_exist)
520
+
521
+ if %i[overwrite write].include?(on_exist)
522
+ File.write(file, content)
523
+ return
524
+ end
525
+
526
+ return unless on_exist == :compare
527
+
528
+ vscompare(file, content)
529
+ end
530
+
531
+ def vscompare(file, content)
532
+ # need to use some sort of caching folder for this
533
+ ext = File.extname(file)
534
+ fn = File.basename(file, ext)
535
+ temp_file = Tempfile.new([fn, ext])
536
+
537
+ temp_file.write(content)
538
+ temp_file.close
539
+
540
+ return if File.read(file) == content
541
+
542
+ system("code -d #{file} #{temp_file.path}")
543
+ sleep 2
544
+ end
545
+
546
+ def mkdir_p(folder)
547
+ @last_output_folder = FileUtils.mkdir_p(folder).first
548
+ end
354
549
  end
355
550
  end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ module KBuilder
4
+ module Commands
5
+ # Run CodeSyntaxHighlighter against source code and produce a styled HTML representation
6
+ #
7
+ # Alternatives to Highlighter-js could be carbon-now and ray.so
8
+ class CodeSyntaxHighlighterCommand < BaseCommand
9
+ attr_reader :source_code
10
+ attr_reader :formatted_code
11
+
12
+ def initialize(source_code, **opts)
13
+ super(**opts)
14
+
15
+ self.source_code = source_code
16
+ end
17
+
18
+ def execute
19
+ return unless valid?
20
+
21
+ run
22
+ end
23
+
24
+ private
25
+
26
+ def source_code=(value)
27
+ @source_code = value
28
+
29
+ guard('Source code is required for formatting') if value.nil? || value.empty?
30
+ end
31
+
32
+ def run
33
+ # @formatted_code = ExecJS.eval("'red yellow blue'.split(' ')")
34
+
35
+ # # highlight_source = 'lib/k_builder/assets/a.js'
36
+ # highlight_source = 'lib/k_builder/assets/highlight.min.js'
37
+
38
+ # log.error ExecJS.runtime.name
39
+
40
+ # a = File.read(highlight_source)
41
+ # # context = ExecJS.compile(a)
42
+ # context = ExecJS.compile(highlight_source)
43
+ # context.call("html = hljs.highlightAuto('<h1>Hello World!</h1>').value")
44
+
45
+ # get_js_asset('highlight')
46
+ # get_js_asset('ruby')
47
+ end
48
+
49
+ # https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.0.1/highlight.min.js
50
+ # https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.0.1/languages/ruby.min.js
51
+
52
+ def get_js_asset(name)
53
+ url = "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.0.1/#{name}.min.js"
54
+ target_folder = 'lib/k_builder/assets'
55
+ file = "#{name}.min.js"
56
+
57
+ get_asset(url, target_folder, file)
58
+ end
59
+
60
+ def get_asset(url, target_folder, file)
61
+ local_asset_file = File.join(target_folder, file)
62
+
63
+ return if File.exist?(local_asset_file)
64
+
65
+ content = Net::HTTP.get(URI.parse(url))
66
+
67
+ File.write(local_asset_file, content)
68
+ end
69
+ end
70
+ end
71
+ end
@@ -5,18 +5,24 @@ module KBuilder
5
5
  # Configuration for webpack5/builder
6
6
  class << self
7
7
  attr_writer :configuration
8
- end
9
8
 
10
- def self.configuration
11
- @configuration ||= Configuration.new
12
- end
9
+ def configuration(name = :default)
10
+ @configuration ||= Hash.new do |h, key|
11
+ h[key] = KBuilder::Configuration.new
12
+ end
13
+ @configuration[name]
14
+ end
13
15
 
14
- def self.reset
15
- @configuration = Configuration.new
16
- end
16
+ def reset(name = :default)
17
+ @configuration ||= Hash.new do |h, key|
18
+ h[key] = KBuilder::Configuration.new
19
+ end
20
+ @configuration[name] = KBuilder::Configuration.new
21
+ end
17
22
 
18
- def self.configure
19
- yield(configuration)
23
+ def configure(name = :default)
24
+ yield(configuration(name))
25
+ end
20
26
  end
21
27
 
22
28
  # Does this class need to move out into k_types?
@@ -48,12 +54,16 @@ module KBuilder
48
54
  @template_folders = orig.template_folders.clone
49
55
  end
50
56
 
51
- def debug
52
- log.subheading 'kbuilder base configuration'
57
+ def debug(heading: 'kbuilder base configuration')
58
+ log.section_heading 'kbuilder base configuration' if heading
59
+
60
+ # TODO: Add name to configuration object
61
+ # Don't have support for name on the configuration object yet
62
+ # log.kv 'config name', name
53
63
 
54
64
  target_folders.debug(title: 'target_folders')
55
65
 
56
- log.info ''
66
+ # log.info ''
57
67
 
58
68
  template_folders.debug(title: 'template folders (search order)')
59
69
  ''
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module KBuilder
4
- VERSION = '0.0.63'
4
+ VERSION = '0.0.68'
5
5
  end
data/lib/k_builder.rb CHANGED
@@ -10,8 +10,11 @@ require 'k_builder/base_builder'
10
10
  require 'k_builder/base_configuration'
11
11
  require 'k_builder/configuration'
12
12
  require 'k_builder/file_segments'
13
+
14
+ # should commands be in their own gem?
13
15
  require 'k_builder/commands/base_command'
14
16
  require 'k_builder/commands/rubo_cop_command'
17
+ require 'k_builder/commands/code_syntax_highlighter_command'
15
18
 
16
19
  require 'handlebars/helpers/template'
17
20
 
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.63
4
+ version: 0.0.68
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-07-01 00:00:00.000000000 Z
11
+ date: 2022-01-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: handlebars-helpers
@@ -99,6 +99,9 @@ files:
99
99
  - README.md
100
100
  - Rakefile
101
101
  - STORIES.md
102
+ - Sample-original.xml
103
+ - Sample.drawio
104
+ - Sample.xml
102
105
  - USAGE.md
103
106
  - bin/console
104
107
  - bin/k
@@ -109,9 +112,15 @@ files:
109
112
  - hooks/update-version
110
113
  - k_builder.gemspec
111
114
  - lib/k_builder.rb
115
+ - lib/k_builder/assets/a.html
116
+ - lib/k_builder/assets/b.html
117
+ - lib/k_builder/assets/highlight.min.js
118
+ - lib/k_builder/assets/highlight_css
119
+ - lib/k_builder/assets/ruby.min.js
112
120
  - lib/k_builder/base_builder.rb
113
121
  - lib/k_builder/base_configuration.rb
114
122
  - lib/k_builder/commands/base_command.rb
123
+ - lib/k_builder/commands/code_syntax_highlighter_command.rb
115
124
  - lib/k_builder/commands/rubo_cop_command.rb
116
125
  - lib/k_builder/configuration.rb
117
126
  - lib/k_builder/file_segments.rb
@@ -145,7 +154,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
145
154
  - !ruby/object:Gem::Version
146
155
  version: '0'
147
156
  requirements: []
148
- rubygems_version: 3.2.7
157
+ rubygems_version: 3.2.33
149
158
  signing_key:
150
159
  specification_version: 4
151
160
  summary: K Builder provides various fluent builders for initializing applications