bblib 0.4.1 → 1.0.2
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/.gitignore +12 -11
- data/.rspec +2 -2
- data/.travis.yml +4 -4
- data/CODE_OF_CONDUCT.md +13 -13
- data/Gemfile +4 -4
- data/LICENSE.txt +21 -21
- data/Rakefile +6 -6
- data/bblib.gemspec +34 -34
- data/bin/console +14 -14
- data/bin/setup +7 -7
- data/lib/array/bbarray.rb +2 -2
- data/lib/bblib.rb +1 -0
- data/lib/bblib/version.rb +1 -1
- data/lib/class/effortless.rb +2 -2
- data/lib/file/bbfile.rb +10 -8
- data/lib/hash/bbhash.rb +23 -15
- data/lib/hash/hash_struct.rb +1 -1
- data/lib/hash/tree_hash.rb +1 -1
- data/lib/hash_path/hash_path.rb +3 -3
- data/lib/hash_path/part.rb +2 -2
- data/lib/html/bbhtml.rb +1 -0
- data/lib/html/builder.rb +15 -6
- data/lib/html/tag.rb +74 -5
- data/lib/html/tag_set.rb +20 -0
- data/lib/logging/bblogging.rb +2 -1
- data/lib/mixins/attrs.rb +40 -25
- data/lib/mixins/bbmixins.rb +2 -0
- data/lib/mixins/family_tree.rb +12 -0
- data/lib/mixins/hooks.rb +8 -1
- data/lib/mixins/logger.rb +10 -10
- data/lib/mixins/prototype.rb +26 -0
- data/lib/mixins/simple_init.rb +47 -17
- data/lib/mixins/type_init.rb +21 -0
- data/lib/number/bbnumber.rb +90 -0
- data/lib/object/bbobject.rb +1 -5
- data/lib/opal/bbopal.rb +5 -0
- data/lib/os/bbos.rb +0 -63
- data/lib/string/bbstring.rb +22 -1
- data/lib/string/cases.rb +4 -4
- data/lib/time/bbtime.rb +27 -0
- data/lib/time/task_timer.rb +3 -1
- metadata +4 -2
- data/lib/os/bbsys.rb +0 -255
data/lib/hash_path/part.rb
CHANGED
data/lib/html/bbhtml.rb
CHANGED
data/lib/html/builder.rb
CHANGED
@@ -8,14 +8,19 @@ module BBLib
|
|
8
8
|
SELF_CLOSING_TAGS.include?(tag.to_s.downcase)
|
9
9
|
end
|
10
10
|
|
11
|
+
def self.build(*args, &block)
|
12
|
+
Builder.build(*args, &block)
|
13
|
+
end
|
14
|
+
|
11
15
|
module Builder
|
12
16
|
|
13
17
|
BBLib::HTML::TAGS.each do |tag|
|
14
18
|
define_method(tag) do |content = nil, **attributes, &block|
|
15
19
|
context = attributes.delete(:context) || self.context
|
16
|
-
|
17
|
-
|
18
|
-
|
20
|
+
Tag.new(type: tag, attributes: attributes, content: content, context: context).tap do |t|
|
21
|
+
children << t
|
22
|
+
t.instance_eval(&block) if block
|
23
|
+
end
|
19
24
|
end
|
20
25
|
end
|
21
26
|
|
@@ -24,10 +29,14 @@ module BBLib
|
|
24
29
|
self
|
25
30
|
end
|
26
31
|
|
27
|
-
def self.build(type, content = nil, **attributes, &block)
|
28
|
-
raise ArgumentError, "Unknown element type '#{type}'." unless TAGS.include?(type.to_s.downcase)
|
32
|
+
def self.build(type = nil, content = nil, **attributes, &block)
|
33
|
+
raise ArgumentError, "Unknown element type '#{type}'." unless TAGS.include?(type.to_s.downcase) || type == nil
|
29
34
|
context = attributes.delete(:context)
|
30
|
-
|
35
|
+
if type
|
36
|
+
Tag.new(type: type, attributes: attributes, content: content, context: context, &block)
|
37
|
+
else
|
38
|
+
TagSet.new(attributes: attributes, context: context, &block)
|
39
|
+
end
|
31
40
|
end
|
32
41
|
end
|
33
42
|
end
|
data/lib/html/tag.rb
CHANGED
@@ -4,12 +4,16 @@ module BBLib
|
|
4
4
|
include BBLib::Effortless
|
5
5
|
include Builder
|
6
6
|
|
7
|
+
APPEND_ATTRIBUTES = [:class, :style].freeze
|
8
|
+
|
7
9
|
attr_str :type, required: true, arg_at: 0, arg_at_accept: [String, Symbol]
|
8
|
-
attr_str :content, arg_at: 1, arg_at_accept: [String, Symbol]
|
10
|
+
attr_str :content, default: nil, allow_nil: true, arg_at: 1, arg_at_accept: [String, Symbol]
|
9
11
|
attr_hash :attributes, default: {}
|
10
12
|
attr_ary_of Tag, :children, default: []
|
11
13
|
attr_of Object, :context, default: nil, allow_nil: true
|
12
14
|
|
15
|
+
init_type :loose
|
16
|
+
|
13
17
|
def render(pretty: false, tabs: 0)
|
14
18
|
cont = render_content(pretty: pretty, tabs: tabs)
|
15
19
|
tabbing = pretty ? ("\n" + ("\t" * tabs)) : ''
|
@@ -21,29 +25,94 @@ module BBLib
|
|
21
25
|
end
|
22
26
|
end
|
23
27
|
|
24
|
-
|
25
|
-
|
28
|
+
alias to_html render
|
29
|
+
|
30
|
+
def add(*childs)
|
31
|
+
[childs].flatten.each { |child| children.push(child) }
|
32
|
+
nil
|
33
|
+
end
|
34
|
+
|
35
|
+
def to_s(*args)
|
36
|
+
render(*args)
|
26
37
|
end
|
27
38
|
|
28
39
|
def to_str
|
29
40
|
to_s
|
30
41
|
end
|
31
42
|
|
43
|
+
def set_attribute(attribute, value)
|
44
|
+
attributes[attribute] = value
|
45
|
+
end
|
46
|
+
|
47
|
+
def append_attribute(attribute, value)
|
48
|
+
attributes[attribute] = [attributes[attribute], value.to_s].compact.join(' ')
|
49
|
+
end
|
50
|
+
|
32
51
|
def render_attributes
|
33
52
|
return nil if attributes.empty?
|
34
53
|
attributes[:style] = attributes[:style].map { |k, v| "#{k}: #{v}" }.join('; ') if attributes[:style] && attributes[:style].is_a?(Hash)
|
35
|
-
' ' + attributes.map
|
54
|
+
' ' + attributes.map do | k, v|
|
55
|
+
v = v.join(' ') if v.is_a?(Array)
|
56
|
+
"#{k}=\"#{v.to_s.gsub('"', '"')}\""
|
57
|
+
end.join(' ')
|
36
58
|
end
|
37
59
|
|
38
60
|
def render_content(pretty: false, tabs: 0)
|
39
61
|
return nil if (content.nil? || content.empty?) && children.empty?
|
40
62
|
tabbing = pretty ? ("\n" + ("\t" * (tabs + 1))) : ''
|
41
63
|
text = if content && !content.empty?
|
42
|
-
"#{tabbing}#{content.gsub("\n", tabbing)}"
|
64
|
+
"#{tabbing}#{content.gsub("\n", pretty ? tabbing : "\n")}"
|
43
65
|
end
|
44
66
|
html = children.map { |tag| tag.render(pretty: pretty, tabs: tabs + 1) }.join
|
45
67
|
[text, html].compact.join
|
46
68
|
end
|
69
|
+
|
70
|
+
def merge(attributes)
|
71
|
+
raise ArgumentError, "Expected a Hash, got a #{attributes.class}" unless attributes.is_a?(Hash)
|
72
|
+
attributes.each do |k, v|
|
73
|
+
if APPEND_ATTRIBUTES.include?(k.to_sym)
|
74
|
+
append_attribute(k, v)
|
75
|
+
else
|
76
|
+
set_attribute(k, v)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
self
|
80
|
+
end
|
81
|
+
|
82
|
+
protected
|
83
|
+
|
84
|
+
def simple_init(*args)
|
85
|
+
BBLib.named_args(*args).each do |k, v|
|
86
|
+
next if _attrs.include?(k)
|
87
|
+
self.attributes[k] = v
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def method_missing(method, *args, &block)
|
92
|
+
if context && context.respond_to?(method)
|
93
|
+
context.send(method, *args, &block)
|
94
|
+
elsif method != :to_ary
|
95
|
+
if method.to_s.encap_by?('_')
|
96
|
+
self.set_attribute(:id, method.to_s.uncapsulate('_'))
|
97
|
+
else
|
98
|
+
klass = method.to_s.gsub(/(?<=[^\_])\_(?=[^\_])/, '-').gsub('__', '_')
|
99
|
+
self.append_attribute(:class, klass)
|
100
|
+
end
|
101
|
+
self._initialize(type, *args, &block)
|
102
|
+
self
|
103
|
+
else
|
104
|
+
super
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def respond_to_missing?(method, include_private = false)
|
109
|
+
super || context && context.respond_to?(method)
|
110
|
+
end
|
111
|
+
|
112
|
+
def simple_init_block_result(value)
|
113
|
+
return false unless value && content.nil? && !value.is_a?(Tag)
|
114
|
+
self.content = value.to_s
|
115
|
+
end
|
47
116
|
end
|
48
117
|
end
|
49
118
|
end
|
data/lib/html/tag_set.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
module BBLib
|
2
|
+
module HTML
|
3
|
+
# Similar to the default tag but isn't representative of a an HTML element.
|
4
|
+
# Instead, this is a collection of nested HTML Elements, so only children of
|
5
|
+
# TagSets are rendered to html.
|
6
|
+
class TagSet < Tag
|
7
|
+
attr_str :type, required: false, default: nil, allow_nil: true
|
8
|
+
|
9
|
+
def render(pretty: false, tabs: 0)
|
10
|
+
render_content(pretty: pretty, tabs: tabs)
|
11
|
+
end
|
12
|
+
|
13
|
+
def render_content(pretty: false, tabs: 0)
|
14
|
+
return '' if children.empty?
|
15
|
+
children.map { |tag| tag.render(pretty: pretty, tabs: tabs + 1) }.join
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/logging/bblogging.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require :logger.to_s unless BBLib::in_opal?
|
1
2
|
|
2
3
|
module BBLib
|
3
4
|
|
@@ -12,7 +13,7 @@ module BBLib
|
|
12
13
|
if msg.is_a?(Exception)
|
13
14
|
msg = msg.inspect + "\n\t" + msg.backtrace.join("\n\t")
|
14
15
|
end
|
15
|
-
"[#{datetime}] #{severity} - #{msg}\n"
|
16
|
+
"[#{datetime}] #{severity} - #{msg.to_s.chomp}\n"
|
16
17
|
end
|
17
18
|
log.datetime_format = '%Y-%m-%d %H:%M:%S'
|
18
19
|
log
|
data/lib/mixins/attrs.rb
CHANGED
@@ -68,9 +68,15 @@ module BBLib
|
|
68
68
|
ivar = "@#{method}".to_sym
|
69
69
|
mthd_type = opts[:singleton] ? :define_singleton_method : :define_method
|
70
70
|
|
71
|
-
self.send(mthd_type, "#{method}=") do
|
72
|
-
|
73
|
-
|
71
|
+
self.send(mthd_type, "#{method}=") do |args|
|
72
|
+
if opts[:pre_proc]
|
73
|
+
if opts[:pre_proc].is_a?(Proc)
|
74
|
+
args = opts[:pre_proc].call(args)
|
75
|
+
else
|
76
|
+
args = send(opts[:pre_proc], args)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
instance_variable_set(ivar, yield(args))
|
74
80
|
end
|
75
81
|
|
76
82
|
self.send(mthd_type, method) do
|
@@ -80,7 +86,7 @@ module BBLib
|
|
80
86
|
var
|
81
87
|
elsif opts.include?(:default) || opts.include?(:default_proc)
|
82
88
|
default_value =
|
83
|
-
if opts[:default].respond_to?(:dup) && BBLib.
|
89
|
+
if opts[:default].respond_to?(:dup) && BBLib.is_any?(opts[:default], Array, Hash)
|
84
90
|
opts[:default].dup rescue opts[:default]
|
85
91
|
elsif opts[:default_proc].is_a?(Proc)
|
86
92
|
prc = opts[:default_proc]
|
@@ -115,12 +121,12 @@ module BBLib
|
|
115
121
|
allowed = [klasses].flatten
|
116
122
|
methods.each do |method|
|
117
123
|
attr_custom(method, opts.merge(_attr_type: :of, classes: klasses)) do |arg|
|
118
|
-
if BBLib.
|
124
|
+
if BBLib.is_any?(arg, *allowed) || (arg.nil? && opts[:allow_nil])
|
119
125
|
arg
|
120
126
|
elsif arg && (!opts.include?(:pack) || opts[:pack]) && arg = _attr_pack(arg, klasses, opts)
|
121
127
|
arg
|
122
128
|
else
|
123
|
-
raise
|
129
|
+
raise TypeError, "#{method} must be set to a class of #{allowed.join_terms(:or)}, not #{arg.class}" unless opts[:suppress]
|
124
130
|
end
|
125
131
|
end
|
126
132
|
end
|
@@ -178,12 +184,17 @@ module BBLib
|
|
178
184
|
|
179
185
|
def attr_integer_between(min, max, *methods, **opts)
|
180
186
|
methods.each do |method|
|
181
|
-
attr_custom(method, opts) { |arg| arg.nil? && opts[:allow_nil] ? arg : BBLib.keep_between(arg, min, max) }
|
187
|
+
attr_custom(method, opts.merge(min: min, max: max)) { |arg| arg.nil? && opts[:allow_nil] ? arg : BBLib.keep_between(arg, min, max).to_i }
|
182
188
|
end
|
183
189
|
end
|
184
190
|
|
185
191
|
alias attr_int_between attr_integer_between
|
186
|
-
|
192
|
+
|
193
|
+
def attr_float_between(min, max, *methods, **opts)
|
194
|
+
methods.each do |method|
|
195
|
+
attr_custom(method, opts.merge(min: min, max: max)) { |arg| arg.nil? && opts[:allow_nil] ? arg : BBLib.keep_between(arg, min, max).to_f }
|
196
|
+
end
|
197
|
+
end
|
187
198
|
|
188
199
|
def attr_integer_loop(min, max, *methods, **opts)
|
189
200
|
methods.each do |method|
|
@@ -208,6 +219,7 @@ module BBLib
|
|
208
219
|
end
|
209
220
|
|
210
221
|
def attr_elements_of(list, *methods, **opts)
|
222
|
+
opts[:default] = [] unless opts.include?(:default) || opts.include?(:default_proc)
|
211
223
|
methods.each do |method|
|
212
224
|
attr_custom(method, opts.merge(list: list)) do |args|
|
213
225
|
ls = list.is_a?(Proc) ? list.call : list
|
@@ -225,6 +237,7 @@ module BBLib
|
|
225
237
|
end
|
226
238
|
|
227
239
|
def attr_array(*methods, **opts)
|
240
|
+
opts[:default] = [] unless opts.include?(:default) || opts.include?(:default_proc)
|
228
241
|
methods.each do |method|
|
229
242
|
attr_custom(method, opts) do |arg|
|
230
243
|
args = arg.is_a?(Array) ? arg : [arg]
|
@@ -239,6 +252,7 @@ module BBLib
|
|
239
252
|
alias attr_ary attr_array
|
240
253
|
|
241
254
|
def attr_array_of(klasses, *methods, **opts)
|
255
|
+
opts[:default] = [] unless opts.include?(:default) || opts.include?(:default_proc)
|
242
256
|
klasses = [klasses].flatten
|
243
257
|
methods.each do |method|
|
244
258
|
attr_custom(method, opts.merge(classes: klasses)) do |args|
|
@@ -252,17 +266,17 @@ module BBLib
|
|
252
266
|
else
|
253
267
|
args = [args] unless args.is_a?(Array)
|
254
268
|
args.each do |arg|
|
255
|
-
match = BBLib.
|
269
|
+
match = BBLib.is_any?(arg, *klasses)
|
256
270
|
if match
|
257
|
-
array.push(arg)
|
271
|
+
array.push(arg)
|
258
272
|
elsif arg && (!opts.include?(:pack) || opts[:pack]) && arg = _attr_pack(arg, klasses, opts)
|
259
273
|
array.push(arg)
|
260
274
|
else
|
261
|
-
raise
|
275
|
+
raise TypeError, "Invalid class passed to #{method} on #{self}: #{arg.class}. Must be a #{klasses.join_terms(:or)}." unless opts[:raise] == false
|
262
276
|
end
|
263
277
|
end
|
264
278
|
end
|
265
|
-
array
|
279
|
+
opts[:uniq] ? array.uniq : array
|
266
280
|
end
|
267
281
|
attr_array_adder(method, opts[:adder_name], singleton: opts[:singleton]) if opts[:add_rem] || opts[:adder]
|
268
282
|
attr_array_remover(method, opts[:remover_name], singleton: opts[:singleton]) if opts[:add_rem] || opts[:remover]
|
@@ -276,7 +290,7 @@ module BBLib
|
|
276
290
|
mthd_type = singleton ? :define_singleton_method : :define_method
|
277
291
|
send(mthd_type, name) do |*args|
|
278
292
|
array = send(method)
|
279
|
-
args.each do |arg|
|
293
|
+
[args].flatten(1).each do |arg|
|
280
294
|
arg = yield(arg) if block_given?
|
281
295
|
array.push(arg)
|
282
296
|
end
|
@@ -288,7 +302,7 @@ module BBLib
|
|
288
302
|
name = "remove_#{method}" unless name
|
289
303
|
define_method(name) do |*args|
|
290
304
|
array = instance_variable_get("@#{method}")
|
291
|
-
args.map do |arg|
|
305
|
+
[args].flatten(1).map do |arg|
|
292
306
|
next unless array && !array.empty?
|
293
307
|
array.delete(arg)
|
294
308
|
end
|
@@ -328,8 +342,8 @@ module BBLib
|
|
328
342
|
attr_custom(method, **opts) do |arg|
|
329
343
|
if opts[:formats]
|
330
344
|
arg = arg.to_s
|
331
|
-
opts[:
|
332
|
-
arg = Time.
|
345
|
+
[opts[:formats]].flatten.each do |format|
|
346
|
+
arg = Time.strptime(arg, format) rescue arg
|
333
347
|
end
|
334
348
|
end
|
335
349
|
if arg.is_a?(Time) || arg.nil? && opts[:allow_nil]
|
@@ -339,7 +353,7 @@ module BBLib
|
|
339
353
|
else
|
340
354
|
begin
|
341
355
|
Time.parse(arg.to_s)
|
342
|
-
rescue =>
|
356
|
+
rescue => _e
|
343
357
|
nil
|
344
358
|
end
|
345
359
|
end
|
@@ -352,8 +366,8 @@ module BBLib
|
|
352
366
|
attr_custom(method, **opts) do |arg|
|
353
367
|
if opts[:formats]
|
354
368
|
arg = arg.to_s
|
355
|
-
opts[:
|
356
|
-
arg = Date.
|
369
|
+
[opts[:formats]].flatten.each do |format|
|
370
|
+
arg = Date.strptime(arg, format) rescue arg
|
357
371
|
end
|
358
372
|
end
|
359
373
|
if arg.is_a?(Date) || arg.nil? && opts[:allow_nil]
|
@@ -363,7 +377,7 @@ module BBLib
|
|
363
377
|
else
|
364
378
|
begin
|
365
379
|
Date.parse(arg.to_s)
|
366
|
-
rescue =>
|
380
|
+
rescue => _e
|
367
381
|
nil
|
368
382
|
end
|
369
383
|
end
|
@@ -372,12 +386,13 @@ module BBLib
|
|
372
386
|
end
|
373
387
|
|
374
388
|
def attr_hash(*methods, **opts)
|
389
|
+
opts[:default] = {} unless opts.include?(:default) || opts.include?(:default_proc)
|
375
390
|
methods.each do |method|
|
376
391
|
attr_custom(method, **opts) do |arg|
|
377
392
|
raise ArgumentError, "#{method} must be set to a hash, not a #{arg.class} (for #{self})." unless arg.is_a?(Hash) || arg.nil? && opts[:allow_nil]
|
378
393
|
if opts[:keys] && arg
|
379
394
|
arg.keys.each do |key|
|
380
|
-
if BBLib.
|
395
|
+
if BBLib.is_any?(key, *opts[:keys])
|
381
396
|
next
|
382
397
|
elsif (opts.include?(:pack_key) && opts[:pack_key]) && new_key = _attr_pack(key, klasses, opts)
|
383
398
|
arg[new_key] = arg.delete(key)
|
@@ -388,12 +403,12 @@ module BBLib
|
|
388
403
|
end
|
389
404
|
if opts[:values] && arg
|
390
405
|
arg.each do |key, value|
|
391
|
-
if BBLib.
|
406
|
+
if BBLib.is_any?(value, *opts[:values])
|
392
407
|
next
|
393
408
|
elsif (!opts.include?(:pack_value) || opts[:pack_value]) && value = _attr_pack(value, klasses, opts)
|
394
409
|
arg[key] = arg.delete(value)
|
395
410
|
else
|
396
|
-
raise
|
411
|
+
raise TypeError, "Invalid value type for #{method}: #{value.class}. Must be #{opts[:values].join_terms(:or)}."
|
397
412
|
end
|
398
413
|
end
|
399
414
|
end
|
@@ -405,8 +420,8 @@ module BBLib
|
|
405
420
|
|
406
421
|
def _attr_pack(arg, klasses, opts = {})
|
407
422
|
klasses = [klasses].flatten
|
408
|
-
unless BBLib.
|
409
|
-
return klasses.first.new(*[arg].flatten(1))
|
423
|
+
unless BBLib.is_any?(arg, *klasses)
|
424
|
+
return klasses.first.new(*[arg].flatten(1)) if klasses.first.respond_to?(:new)
|
410
425
|
end
|
411
426
|
nil
|
412
427
|
end
|
data/lib/mixins/bbmixins.rb
CHANGED
data/lib/mixins/family_tree.rb
CHANGED
@@ -6,6 +6,7 @@ module BBLib
|
|
6
6
|
module FamilyTree
|
7
7
|
# Return all classes that inherit from this class
|
8
8
|
def descendants(include_singletons = false)
|
9
|
+
return _inherited_by.map { |c| [c, c.descendants] }.flatten.uniq if BBLib.in_opal?
|
9
10
|
ObjectSpace.each_object(Class).select do |c|
|
10
11
|
(include_singletons || !c.singleton_class?) && c < self
|
11
12
|
end
|
@@ -15,6 +16,7 @@ module BBLib
|
|
15
16
|
|
16
17
|
# Return all classes that directly inherit from this class
|
17
18
|
def direct_descendants(include_singletons = false)
|
19
|
+
return _inherited_by if BBLib.in_opal?
|
18
20
|
ObjectSpace.each_object(Class).select do |c|
|
19
21
|
(include_singletons || !c.singleton_class?) && c.ancestors[1] == self
|
20
22
|
end
|
@@ -37,5 +39,15 @@ module BBLib
|
|
37
39
|
|
38
40
|
alias direct_subclasses direct_descendants
|
39
41
|
|
42
|
+
# If we are in Opal we need to track descendants a bit differently
|
43
|
+
if BBLib.in_opal?
|
44
|
+
def _inherited_by
|
45
|
+
@_inherited_by ||= []
|
46
|
+
end
|
47
|
+
|
48
|
+
def inherited(klass)
|
49
|
+
_inherited_by.push(klass)
|
50
|
+
end
|
51
|
+
end
|
40
52
|
end
|
41
53
|
end
|