7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
|
# File 'lib/express_templates/components/capabilities/configurable.rb', line 7
def self.included(base)
base.class_eval do
class_attribute :supported_options
self.supported_options = {}
class_attribute :supported_arguments
self.supported_arguments = {}
def self.emits(*args, &block)
warn ".emits is deprecrated"
self.contains(*args, &block)
end
def build(*args, &block)
_process_builder_args!(args)
super(*args, &block)
end
def config
@config ||= {}
end
def self.has_option(name, description, type: :string, required: nil, default: nil, attribute: nil, values: nil)
raise "name must be a symbol" unless name.kind_of?(Symbol)
option_definition = {description: description}
option_definition.merge!(type: type, required: required, default: default, attribute: attribute, values: values)
self.supported_options =
self.supported_options.merge(name => option_definition)
end
def required_options
supported_options.select {|k,v| v[:required] unless v[:default] }
end
def self.has_argument(name, description, as: nil, type: :string, default: nil, optional: false)
raise "name must be a symbol" unless name.kind_of?(Symbol)
argument_definition = {description: description, as: as, type: type, default: default, optional: optional}
self.supported_arguments =
self.supported_arguments.merge(name => argument_definition)
end
has_argument :id, "The id of the component.", type: :symbol, optional: true
protected
def _default_options
supported_options.select {|k,v| v[:default] }
end
def _check_required_options(supplied)
missing = required_options.keys - supplied.keys
if missing.any?
raise "#{self.class} missing required option(s): #{missing}"
end
end
def _set_defaults
_default_options.each do |key, value|
default_value = value[:default].respond_to?(:call) ? value[:default].call : value[:default]
if !!value[:attribute]
set_attribute key, default_value
else
if config[key].nil?
config[key] = default_value
end
end
end
end
def _valid_types(definition)
valid_type_names = if definition[:type].kind_of?(Symbol)
[definition[:type]]
elsif definition[:type].respond_to?(:keys)
definition[:type].keys
else
definition[:type] || []
end
valid_type_names.map do |type_name|
if type_name.eql?(:boolean)
type_name
else
type_name.to_s.classify.constantize
end
end
end
def _is_valid?(value, definition)
valid_types = _valid_types(definition)
if valid_types.empty? && value.kind_of?(String)
true
elsif valid_types.include?(value.class)
true
elsif valid_types.include?(:boolean) &&
[1, 0, true, false].include?(value)
true
else
false
end
end
def _optional_argument?(definition)
definition[:default] || definition[:optional]
end
def _required_argument?(definition)
!_optional_argument?(definition)
end
def (args)
supported_arguments.each do |key, definition|
value = args.shift
if value.nil? && _required_argument?(definition)
raise "argument for #{key} not supplied"
end
unless _is_valid?(value, definition)
if _required_argument?(definition)
raise "argument for #{key} invalid (#{value.class}) '#{value.to_s}'; Allowable: #{_valid_types(definition).inspect}"
else
args.unshift value
next
end
end
config_key = definition[:as] || key
config[config_key] = value || definition[:default]
end
end
def _set_id_attribute
attributes[:id] = config[:id]
end
def (builder_options)
builder_options.each do |key, value|
if supported_options.keys.include?(key)
unless supported_options[key][:attribute]
config[key] = builder_options.delete(key)
end
end
end
end
def _process_builder_args!(args)
(args)
builder_options = args.last.try(:kind_of?, Hash) ? args.last : {}
_check_required_options(builder_options)
(builder_options)
_set_defaults
_set_id_attribute
end
end
end
|