@@ -8,64 +8,89 @@ module Elements
8
8
class Style
9
9
include Docx ::SimpleInspect
10
10
11
- @attributes = [ ]
11
+ class Attribute
12
+ attr_reader :name , :selectors , :required , :converter , :validator
13
+
14
+ def initialize ( name , selectors , required : false , converter :, validator :)
15
+ @name = name
16
+ @selectors = selectors
17
+ @required = required
18
+ @converter = converter || Converters ::DefaultValueConverter
19
+ @validator = validator || Validators ::DefaultValidator
20
+ end
12
21
13
- class << self
14
- attr_accessor :attributes
22
+ def required?
23
+ required
24
+ end
15
25
16
- def required_attributes
17
- attributes . select { |a | a [ :required ] }
26
+ def retrieve_from ( style )
27
+ selectors
28
+ . lazy
29
+ . filter_map { |node_xpath | style . node . at_xpath ( node_xpath ) &.value }
30
+ . map { |value | converter . decode ( value ) }
31
+ . first
18
32
end
19
33
20
- def attribute ( name , *selectors , required : false , converter : Converters ::DefaultValueConverter , validator : Validators ::DefaultValidator )
21
- attributes << { name : name , selectors : selectors , required : required , converter : converter , validator : validator }
34
+ def assign_to ( style , value )
35
+ ( required && value . nil? ) &&
36
+ raise ( Errors ::StyleRequiredPropertyValue , "Required value #{ name } " )
22
37
23
- define_method ( name ) do
24
- selectors
25
- . lazy
26
- . filter_map { |node_xpath | node . at_xpath ( node_xpath ) &.value }
27
- . map { |value | converter . decode ( value ) }
28
- . first
29
- end
38
+ validator . validate ( value ) ||
39
+ raise ( Errors ::StyleInvalidPropertyValue , "Invalid value for #{ name } : '#{ value . nil? ? "nil" : value } '" )
30
40
31
- define_method ( "#{ name } =" ) do |value |
32
- ( required && value . nil? ) &&
33
- raise ( Errors ::StyleRequiredPropertyValue , "Required value #{ name } " )
41
+ encoded_value = converter . encode ( value )
34
42
35
- validator . validate ( value ) ||
36
- raise ( Errors ::StyleInvalidPropertyValue , "Invalid value for #{ name } : '#{ value . nil? ? "nil" : value } '" )
43
+ selectors . map do |attribute_xpath |
44
+ if ( existing_attribute = style . node . at_xpath ( attribute_xpath ) )
45
+ if encoded_value . nil?
46
+ existing_attribute . remove
47
+ else
48
+ existing_attribute . value = encoded_value . to_s
49
+ end
37
50
38
- encoded_value = converter . encode ( value )
51
+ next encoded_value
52
+ end
39
53
40
- selectors . map do |attribute_xpath |
41
- if ( existing_attribute = node . at_xpath ( attribute_xpath ) )
42
- if encoded_value . nil?
43
- existing_attribute . remove
44
- else
45
- existing_attribute . value = encoded_value . to_s
54
+ next encoded_value if encoded_value . nil?
55
+
56
+ node_xpath , attribute = attribute_xpath . split ( "/@" )
57
+
58
+ created_node =
59
+ node_xpath
60
+ . split ( "/" )
61
+ . reduce ( style . node ) do |parent_node , child_xpath |
62
+ # find the child node
63
+ parent_node . at_xpath ( child_xpath ) ||
64
+ # or create the child node
65
+ Nokogiri ::XML ::Node . new ( child_xpath , parent_node )
66
+ . tap { |created_child_node | parent_node << created_child_node }
46
67
end
47
68
48
- next encoded_value
49
- end
69
+ created_node . set_attribute ( attribute , encoded_value )
70
+ end
71
+ . first
72
+ end
73
+ end
74
+
75
+ @attributes = [ ]
76
+
77
+ class << self
78
+ attr_accessor :attributes
50
79
51
- next encoded_value if encoded_value . nil?
80
+ def required_attributes
81
+ attributes . select ( &:required? )
82
+ end
52
83
53
- node_xpath , attribute = attribute_xpath . split ( "/@" )
84
+ def attribute ( name , *selectors , required : false , converter : nil , validator : nil )
85
+ new_attribute = Attribute . new ( name , selectors , required : required , converter : converter , validator : validator )
86
+ attributes << new_attribute
54
87
55
- created_node =
56
- node_xpath
57
- . split ( "/" )
58
- . reduce ( node ) do |parent_node , child_xpath |
59
- # find the child node
60
- parent_node . at_xpath ( child_xpath ) ||
61
- # or create the child node
62
- Nokogiri ::XML ::Node . new ( child_xpath , parent_node )
63
- . tap { |created_child_node | parent_node << created_child_node }
64
- end
88
+ define_method ( name ) do
89
+ new_attribute . retrieve_from ( self )
90
+ end
65
91
66
- created_node . set_attribute ( attribute , encoded_value )
67
- end
68
- . first
92
+ define_method ( "#{ name } =" ) do |value |
93
+ new_attribute . assign_to ( self , value )
69
94
end
70
95
end
71
96
@@ -135,11 +160,9 @@ def initialize(configuration, node, **attributes)
135
160
136
161
def valid?
137
162
self . class . required_attributes . all? do |a |
138
- validator = a [ :validator ]
139
- attribute_name = a [ :name ]
140
- attribute_value = self . send ( attribute_name )
163
+ attribute_value = a . retrieve_from ( self )
141
164
142
- validator &.validate ( attribute_value )
165
+ a . validator &.validate ( attribute_value )
143
166
end
144
167
end
145
168
0 commit comments