k_builder 0.0.61 → 0.0.69
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/Sample-original.xml +103 -0
- data/Sample.drawio +103 -0
- data/Sample.xml +103 -0
- data/hooks/pre-commit +2 -0
- data/k_builder.gemspec +0 -1
- data/lib/k_builder/assets/a.html +235 -0
- data/lib/k_builder/assets/b.html +109 -0
- data/lib/k_builder/assets/highlight.min.js +1120 -0
- data/lib/k_builder/assets/highlight_css +1 -0
- data/lib/k_builder/assets/ruby.min.js +7 -0
- data/lib/k_builder/base_builder.rb +255 -28
- data/lib/k_builder/commands/base_command.rb +36 -0
- data/lib/k_builder/commands/code_syntax_highlighter_command.rb +71 -0
- data/lib/k_builder/commands/rubo_cop_command.rb +112 -0
- data/lib/k_builder/configuration.rb +22 -12
- data/lib/k_builder/version.rb +1 -1
- data/lib/k_builder.rb +5 -0
- metadata +14 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/Users/davidcruwys/dev/slides-addons/highlight_css
|
|
@@ -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,108 @@ 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_action(file, **opts)
|
|
125
|
+
{
|
|
126
|
+
action: :add_file,
|
|
127
|
+
played: false,
|
|
128
|
+
file: file,
|
|
129
|
+
opts: opts
|
|
130
|
+
}
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
|
|
98
134
|
def add_file(file, **opts)
|
|
99
135
|
# move to command
|
|
100
|
-
full_file = opts.key?(:folder_key) ? target_file(file, folder: opts[:folder_key]) : target_file(file)
|
|
136
|
+
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
137
|
|
|
102
138
|
# Need logging options that can log these internal details
|
|
103
|
-
|
|
139
|
+
mkdir_p(File.dirname(full_file))
|
|
104
140
|
|
|
105
141
|
content = process_any_content(**opts)
|
|
106
142
|
|
|
107
|
-
|
|
143
|
+
file_write(full_file, content, on_exist: opts[:on_exist])
|
|
108
144
|
|
|
109
145
|
# Prettier needs to work with the original file name
|
|
110
|
-
run_prettier file
|
|
146
|
+
run_prettier file if opts.key?(:pretty)
|
|
147
|
+
# TODO: Add test
|
|
148
|
+
run_cop(full_file, fix_safe: true) if opts.key?(:cop) || opts.key?(:ruby_cop)
|
|
149
|
+
|
|
111
150
|
# Need support for rubocop -a
|
|
151
|
+
open_file(last_output_file) if opts.key?(:open)
|
|
152
|
+
open_file(last_template_file) if opts.key?(:open_template)
|
|
153
|
+
browse_file(last_output_file) if opts.key?(:browse)
|
|
154
|
+
pause(opts[:pause]) if opts[:pause]
|
|
112
155
|
|
|
113
156
|
self
|
|
114
157
|
end
|
|
158
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity
|
|
159
|
+
|
|
160
|
+
def play_actions(actions)
|
|
161
|
+
actions.reject { |action| action[:played] }.each do |action|
|
|
162
|
+
play_action(action)
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def play_action(action)
|
|
167
|
+
case action[:action]
|
|
168
|
+
when :add_file
|
|
169
|
+
add_file(action[:file], action[:opts])
|
|
170
|
+
when :delete_file
|
|
171
|
+
delete_file(action[:file], action[:opts])
|
|
172
|
+
when :vscode
|
|
173
|
+
vscode(action[:file_parts], action[:opts])
|
|
174
|
+
when :browse
|
|
175
|
+
browse(action[:file_parts], action[:opts])
|
|
176
|
+
when :set_current_folder
|
|
177
|
+
set_current_folder(action[:folder_key])
|
|
178
|
+
when :run_command
|
|
179
|
+
run_command(action[:command])
|
|
180
|
+
else
|
|
181
|
+
log.error "Unknown action: #{action[:action]}"
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
action[:played] = true
|
|
185
|
+
end
|
|
186
|
+
|
|
115
187
|
alias touch add_file # it is expected that you would not supply any options, just a file name
|
|
116
188
|
|
|
189
|
+
def delete_file_action(file, **opts)
|
|
190
|
+
{
|
|
191
|
+
action: :delete_file,
|
|
192
|
+
played: false,
|
|
193
|
+
file: file,
|
|
194
|
+
opts: opts
|
|
195
|
+
}
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
def delete_file(file, **opts)
|
|
199
|
+
full_file = target_file(file, **opts) # = opts.key?(:folder_key) ? target_file(file, folder: opts[:folder_key]) : target_file(file)
|
|
200
|
+
|
|
201
|
+
File.delete(full_file) if File.exist?(full_file)
|
|
202
|
+
|
|
203
|
+
self
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
def file_exist?(file, **opts)
|
|
207
|
+
# full_file = opts.key?(:folder_key) ? target_file(file, folder_key: opts[:folder_key]) : target_file(file)
|
|
208
|
+
full_file = target_file(file, **opts)
|
|
209
|
+
|
|
210
|
+
File.exist?(full_file)
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
# ToDo
|
|
214
|
+
# def delete_folder(file)
|
|
215
|
+
# FileUtils.remove_dir(path_to_directory) if File.directory?(path_to_directory)
|
|
216
|
+
|
|
217
|
+
# self
|
|
218
|
+
# end
|
|
219
|
+
|
|
117
220
|
def make_folder(folder_key = nil, sub_path: nil)
|
|
118
221
|
folder_key = current_folder_key if folder_key.nil?
|
|
119
222
|
folder = target_folder(folder_key)
|
|
120
223
|
folder = File.join(folder, sub_path) unless sub_path.nil?
|
|
121
224
|
|
|
122
|
-
|
|
225
|
+
mkdir_p(folder)
|
|
123
226
|
|
|
124
227
|
self
|
|
125
228
|
end
|
|
@@ -140,6 +243,8 @@ module KBuilder
|
|
|
140
243
|
|
|
141
244
|
begin
|
|
142
245
|
IO.popen('pbcopy', 'w') { |f| f << content }
|
|
246
|
+
|
|
247
|
+
open_file(last_template_file) if opts.key?(:open_template)
|
|
143
248
|
rescue Errno::ENOENT => e
|
|
144
249
|
if e.message == 'No such file or directory - pbcopy'
|
|
145
250
|
# May want to use this GEM in the future
|
|
@@ -152,15 +257,84 @@ module KBuilder
|
|
|
152
257
|
end
|
|
153
258
|
alias clipboard_copy add_clipboard
|
|
154
259
|
|
|
155
|
-
def
|
|
260
|
+
def vscode_action(*file_parts, folder_key: current_folder_key, file: nil)
|
|
261
|
+
{
|
|
262
|
+
action: :vscode,
|
|
263
|
+
played: false,
|
|
264
|
+
file_parts: file_parts,
|
|
265
|
+
opts: { folder_key: folder_key, file: file }
|
|
266
|
+
}
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
def vscode(*file_parts, folder_key: current_folder_key, file: nil)
|
|
156
270
|
# move to command
|
|
157
|
-
file = target_file(*file_parts,
|
|
271
|
+
file = target_file(*file_parts, folder_key: folder_key) if file.nil?
|
|
158
272
|
|
|
159
273
|
rc "code #{file}"
|
|
160
274
|
|
|
161
275
|
self
|
|
162
276
|
end
|
|
163
277
|
|
|
278
|
+
def browse_action(*file_parts, folder_key: current_folder_key, file: nil)
|
|
279
|
+
{
|
|
280
|
+
action: :browse,
|
|
281
|
+
played: false,
|
|
282
|
+
file_parts: file_parts,
|
|
283
|
+
opts: { folder_key: folder_key, file: file }
|
|
284
|
+
}
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
def browse(*file_parts, folder_key: current_folder_key, file: nil)
|
|
288
|
+
# move to command
|
|
289
|
+
file = target_file(*file_parts, folder_key: folder_key) if file.nil?
|
|
290
|
+
|
|
291
|
+
rc "open -a \"Google Chrome\" #{file}"
|
|
292
|
+
|
|
293
|
+
self
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
def open
|
|
297
|
+
open_file(last_output_file)
|
|
298
|
+
|
|
299
|
+
self
|
|
300
|
+
end
|
|
301
|
+
alias o open
|
|
302
|
+
|
|
303
|
+
def open_template
|
|
304
|
+
open_file(last_template_file)
|
|
305
|
+
|
|
306
|
+
self
|
|
307
|
+
end
|
|
308
|
+
alias ot open_template
|
|
309
|
+
|
|
310
|
+
def open_file(file)
|
|
311
|
+
if file.nil?
|
|
312
|
+
log.warn('open_file will not open when file is nil')
|
|
313
|
+
return self
|
|
314
|
+
end
|
|
315
|
+
|
|
316
|
+
vscode(file: file)
|
|
317
|
+
|
|
318
|
+
self
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
def browse_file(file)
|
|
322
|
+
if file.nil?
|
|
323
|
+
log.warn('browse_file will not browse when file is nil')
|
|
324
|
+
return self
|
|
325
|
+
end
|
|
326
|
+
|
|
327
|
+
browse(file: file)
|
|
328
|
+
|
|
329
|
+
self
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
def pause(seconds = 1)
|
|
333
|
+
sleep(seconds)
|
|
334
|
+
|
|
335
|
+
self
|
|
336
|
+
end
|
|
337
|
+
|
|
164
338
|
# ----------------------------------------------------------------------
|
|
165
339
|
# Attributes: Think getter/setter
|
|
166
340
|
#
|
|
@@ -174,6 +348,14 @@ module KBuilder
|
|
|
174
348
|
# Target folders and files
|
|
175
349
|
# ----------------------------------------------------------------------
|
|
176
350
|
|
|
351
|
+
def set_current_folder_action(folder_key)
|
|
352
|
+
{
|
|
353
|
+
action: :set_current_folder,
|
|
354
|
+
played: false,
|
|
355
|
+
folder_key: folder_key
|
|
356
|
+
}
|
|
357
|
+
end
|
|
358
|
+
|
|
177
359
|
def set_current_folder(folder_key)
|
|
178
360
|
target_folders.current = folder_key
|
|
179
361
|
|
|
@@ -216,12 +398,18 @@ module KBuilder
|
|
|
216
398
|
# target_file('/abc.txt')
|
|
217
399
|
# target_file('/xyz/abc.txt')
|
|
218
400
|
# target_file('/xyz', 'abc.txt')
|
|
219
|
-
def target_file(*file_parts, folder:
|
|
401
|
+
def target_file(*file_parts, folder_key: current_folder_key, folder: nil, **)
|
|
402
|
+
# TODO: Mismatch (sometimes called folder, sometimes called folder_key:)
|
|
403
|
+
if folder
|
|
404
|
+
log.error("Change folder: to folder_key: for #{folder} - #{file_parts}")
|
|
405
|
+
return
|
|
406
|
+
end
|
|
407
|
+
|
|
220
408
|
# Absolute path
|
|
221
409
|
return File.join(*file_parts) if Pathname.new(file_parts.first).absolute?
|
|
222
410
|
|
|
223
|
-
# Relative to :
|
|
224
|
-
File.join(target_folder(
|
|
411
|
+
# Relative to :folder_key
|
|
412
|
+
File.join(target_folder(folder_key), *file_parts)
|
|
225
413
|
end
|
|
226
414
|
|
|
227
415
|
# Template folder & Files
|
|
@@ -242,7 +430,8 @@ module KBuilder
|
|
|
242
430
|
# Gets a template_file relative to the template folder, looks first in
|
|
243
431
|
# local template folder and if not found, looks in global template folder
|
|
244
432
|
def find_template_file(file_parts)
|
|
245
|
-
template_folders.find_file(file_parts)
|
|
433
|
+
self.last_template_file = template_folders.find_file(file_parts)
|
|
434
|
+
last_template_file
|
|
246
435
|
end
|
|
247
436
|
|
|
248
437
|
# Building content from templates
|
|
@@ -268,15 +457,6 @@ module KBuilder
|
|
|
268
457
|
|
|
269
458
|
return "content not found: #{opts[:content_file]}" if cf.nil?
|
|
270
459
|
|
|
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
460
|
File.read(cf)
|
|
281
461
|
end
|
|
282
462
|
|
|
@@ -320,13 +500,11 @@ module KBuilder
|
|
|
320
500
|
Handlebars::Helpers::Template.render(template_content, opts) unless template_content.nil?
|
|
321
501
|
end
|
|
322
502
|
|
|
323
|
-
def run_cop(file,
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
opts.prepend('-a') if auto_safe
|
|
327
|
-
opts.prepend('-A') if auto_all
|
|
503
|
+
def run_cop(file, **opts)
|
|
504
|
+
command = Commands::RuboCopCommand.new(file, builder: self, **opts)
|
|
505
|
+
command.execute
|
|
328
506
|
|
|
329
|
-
|
|
507
|
+
self
|
|
330
508
|
end
|
|
331
509
|
|
|
332
510
|
# Need to handle absolute files, see
|
|
@@ -342,7 +520,7 @@ module KBuilder
|
|
|
342
520
|
# Deep path create if needed
|
|
343
521
|
tf = target_folder
|
|
344
522
|
|
|
345
|
-
|
|
523
|
+
mkdir_p(tf)
|
|
346
524
|
|
|
347
525
|
build_command = "cd #{tf} && #{command}"
|
|
348
526
|
|
|
@@ -353,5 +531,54 @@ module KBuilder
|
|
|
353
531
|
system(build_command)
|
|
354
532
|
end
|
|
355
533
|
alias rc run_command
|
|
534
|
+
|
|
535
|
+
def run_command_action(command)
|
|
536
|
+
{
|
|
537
|
+
action: :run_command,
|
|
538
|
+
played: false,
|
|
539
|
+
command: command
|
|
540
|
+
}
|
|
541
|
+
end
|
|
542
|
+
|
|
543
|
+
def file_write(file, content, on_exist: :skip)
|
|
544
|
+
self.last_output_file = file # if file not found, we still want to record this as the last_output_file
|
|
545
|
+
|
|
546
|
+
not_found = !File.exist?(file)
|
|
547
|
+
|
|
548
|
+
if not_found
|
|
549
|
+
File.write(file, content)
|
|
550
|
+
return
|
|
551
|
+
end
|
|
552
|
+
|
|
553
|
+
return if %i[skip ignore].include?(on_exist)
|
|
554
|
+
|
|
555
|
+
if %i[overwrite write].include?(on_exist)
|
|
556
|
+
File.write(file, content)
|
|
557
|
+
return
|
|
558
|
+
end
|
|
559
|
+
|
|
560
|
+
return unless on_exist == :compare
|
|
561
|
+
|
|
562
|
+
vscompare(file, content)
|
|
563
|
+
end
|
|
564
|
+
|
|
565
|
+
def vscompare(file, content)
|
|
566
|
+
# need to use some sort of caching folder for this
|
|
567
|
+
ext = File.extname(file)
|
|
568
|
+
fn = File.basename(file, ext)
|
|
569
|
+
temp_file = Tempfile.new([fn, ext])
|
|
570
|
+
|
|
571
|
+
temp_file.write(content)
|
|
572
|
+
temp_file.close
|
|
573
|
+
|
|
574
|
+
return if File.read(file) == content
|
|
575
|
+
|
|
576
|
+
system("code -d #{file} #{temp_file.path}")
|
|
577
|
+
sleep 2
|
|
578
|
+
end
|
|
579
|
+
|
|
580
|
+
def mkdir_p(folder)
|
|
581
|
+
@last_output_folder = FileUtils.mkdir_p(folder).first
|
|
582
|
+
end
|
|
356
583
|
end
|
|
357
584
|
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module KBuilder
|
|
4
|
+
module Commands
|
|
5
|
+
# Base command for single responsibility actions that can be fired
|
|
6
|
+
# from methods in the builder.
|
|
7
|
+
#
|
|
8
|
+
# Uses the command pattern
|
|
9
|
+
class BaseCommand
|
|
10
|
+
include KLog::Logging
|
|
11
|
+
|
|
12
|
+
attr_accessor :builder
|
|
13
|
+
attr_accessor :valid
|
|
14
|
+
|
|
15
|
+
def initialize(**opts)
|
|
16
|
+
@builder = opts[:builder]
|
|
17
|
+
@valid = true
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def guard(message)
|
|
21
|
+
# THIS SHOULD ONLY LOG IF DEBUGGING IS TURNED ON
|
|
22
|
+
log.error(message)
|
|
23
|
+
@valid = false
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def valid?
|
|
27
|
+
@valid
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def debug(title: nil)
|
|
31
|
+
log.section_heading(title) if title
|
|
32
|
+
debug_values if respond_to?(:debug_values)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
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
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module KBuilder
|
|
4
|
+
module Commands
|
|
5
|
+
# Run RuboCop against a file
|
|
6
|
+
class RuboCopCommand < BaseCommand
|
|
7
|
+
attr_reader :file_pattern
|
|
8
|
+
attr_reader :fix_safe
|
|
9
|
+
attr_reader :fix_unsafe
|
|
10
|
+
attr_reader :rubo_config_file
|
|
11
|
+
attr_reader :show_console
|
|
12
|
+
|
|
13
|
+
attr_reader :cop_options
|
|
14
|
+
attr_reader :cop_opt_values
|
|
15
|
+
|
|
16
|
+
# Initialize RuboCop command
|
|
17
|
+
#
|
|
18
|
+
# @param [String] file_pattern File name or file pattern
|
|
19
|
+
# @param [Hash] **opts The options
|
|
20
|
+
# @option opts [Boolean] :fix_safe RuboCop -a option will fix simple and safe issues
|
|
21
|
+
# @option opts [Boolean] :fix_unsafe RuboCop -A option will fix simple but potentially unsafe issues
|
|
22
|
+
# @option opts [Boolean] :show_console This will show in console, or if false set --out ~/last_cop.txt so that console is redirected to file
|
|
23
|
+
# @option opts [String] :rubo_config_file YAML file with RuboCop configuration options
|
|
24
|
+
#
|
|
25
|
+
# @example Cop for single file with auto fix turned on for simple issues
|
|
26
|
+
#
|
|
27
|
+
# RubCopCommand.new('abc.rb', fix_safe: true)
|
|
28
|
+
#
|
|
29
|
+
# @example Cop for all spec files to auto simple and unsafe issues
|
|
30
|
+
#
|
|
31
|
+
# RubCopCommand.new('spec/**/*.rb', fix_unsafe: true)
|
|
32
|
+
def initialize(file_pattern, **opts)
|
|
33
|
+
super(**opts)
|
|
34
|
+
|
|
35
|
+
@valid = true
|
|
36
|
+
|
|
37
|
+
self.file_pattern = file_pattern
|
|
38
|
+
|
|
39
|
+
self.fix_safe = opts[:fix_safe]
|
|
40
|
+
self.fix_unsafe = opts[:fix_unsafe]
|
|
41
|
+
self.show_console = opts[:show_console]
|
|
42
|
+
self.rubo_config_file = opts[:rubo_config_file]
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def execute
|
|
46
|
+
return unless valid?
|
|
47
|
+
|
|
48
|
+
cop_run
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def cli_options
|
|
52
|
+
cli_options = []
|
|
53
|
+
# quite is the same as simple, except you will see nothing if no offenses
|
|
54
|
+
cli_options << '--format' << 'quiet' # 'simple'
|
|
55
|
+
cli_options << '-a' if fix_safe
|
|
56
|
+
cli_options << '-A' if fix_unsafe
|
|
57
|
+
cli_options << '--config' << rubo_config_file if rubo_config_file
|
|
58
|
+
cli_options << '--out' << File.expand_path('~/last_cop.txt') unless show_console
|
|
59
|
+
cli_options << file_pattern
|
|
60
|
+
cli_options
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def debug_values
|
|
64
|
+
log.kv 'rubocop target', file_pattern
|
|
65
|
+
log.kv '-a', 'automatic fix for safe issues' if fix_safe
|
|
66
|
+
log.kv '-A', 'automatic fix for potentially unsafe issues' if fix_unsafe
|
|
67
|
+
log.kv '-config', rubo_config_file if rubo_config_file
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
private
|
|
71
|
+
|
|
72
|
+
def file_pattern=(value)
|
|
73
|
+
@file_pattern = value
|
|
74
|
+
|
|
75
|
+
if value.nil? || value.empty?
|
|
76
|
+
guard 'file_pattern is required'
|
|
77
|
+
elsif Pathname.glob(value).length.zero?
|
|
78
|
+
guard 'file_pattern does not reference an existing file'
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def fix_safe=(value)
|
|
83
|
+
@fix_safe = value || false
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def fix_unsafe=(value)
|
|
87
|
+
@fix_unsafe = value || false
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def show_console=(value)
|
|
91
|
+
@show_console = value || false
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def rubo_config_file=(value)
|
|
95
|
+
@rubo_config_file = value
|
|
96
|
+
|
|
97
|
+
return if value.nil? || value.empty?
|
|
98
|
+
|
|
99
|
+
guard("Unknown RuboCop config file: #{value}") unless File.exist?(value)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def cop_run
|
|
103
|
+
cli = RuboCop::CLI.new
|
|
104
|
+
|
|
105
|
+
# log.section_heading('CLI OPTIONS')
|
|
106
|
+
# log.block cli_options
|
|
107
|
+
|
|
108
|
+
cli.run(cli_options)
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
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
|
-
|
|
11
|
-
|
|
12
|
-
|
|
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
|
-
|
|
15
|
-
|
|
16
|
-
|
|
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
|
-
|
|
19
|
-
|
|
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.
|
|
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
|
''
|