openxml-package 0.3.1 → 0.3.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/lib/openxml-package/version.rb +1 -1
- data/lib/openxml/contains_properties.rb +5 -0
- data/lib/openxml/has_attributes.rb +33 -7
- data/lib/openxml/has_properties.rb +66 -20
- data/lib/openxml/parts/content_types.rb +1 -1
- data/lib/openxml/parts/rels.rb +6 -1
- data/lib/openxml/render_when_empty.rb +9 -0
- data/lib/openxml/unmet_requirement.rb +3 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1a0436dc9e0622316c63a9a049ebe243ebe50bd0
|
4
|
+
data.tar.gz: f598315aff5dea761320ef51fe2f64709bba9073
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c19ae66a76c4abcd5a4c431e567a0cf55060e35827afba22c2ba27bc35d9f7d1773c009e55b9e3a48d61221aca7c3811ec2a9907f6517432d7df7eebdcbd21ed
|
7
|
+
data.tar.gz: 2c17f6398cd89b909e36e8d3dd6d42a5f761ae7df2da319cf5ca99b609eb17a6c9e82dab5496cc13a5521dfc0e745a0ea2365589494ece87820fa919a7eed6d3
|
@@ -13,11 +13,16 @@ module OpenXml
|
|
13
13
|
module InstanceMethods
|
14
14
|
|
15
15
|
def property_xml(xml)
|
16
|
+
ensure_required_choices
|
16
17
|
props = active_properties
|
17
18
|
return unless render_properties? props
|
18
19
|
props.each { |prop| prop.to_xml(xml) }
|
19
20
|
end
|
20
21
|
|
22
|
+
def properties_attributes
|
23
|
+
{}
|
24
|
+
end
|
25
|
+
|
21
26
|
end
|
22
27
|
|
23
28
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require "openxml/unmet_requirement"
|
2
|
+
|
1
3
|
module OpenXml
|
2
4
|
module HasAttributes
|
3
5
|
|
@@ -7,10 +9,12 @@ module OpenXml
|
|
7
9
|
|
8
10
|
module ClassMethods
|
9
11
|
|
10
|
-
def attribute(name, expects: nil, one_of: nil, in_range: nil, displays_as: nil, namespace: nil, matches: nil, validation: nil, deprecated: false)
|
12
|
+
def attribute(name, expects: nil, one_of: nil, in_range: nil, displays_as: nil, namespace: nil, matches: nil, validation: nil, required: false, deprecated: false)
|
11
13
|
bad_names = %w{ tag name namespace properties_tag }
|
12
14
|
raise ArgumentError if bad_names.member? name.to_s
|
13
15
|
|
16
|
+
required_attributes.push(name) if required
|
17
|
+
|
14
18
|
attr_reader name
|
15
19
|
|
16
20
|
define_method "#{name}=" do |value|
|
@@ -27,17 +31,21 @@ module OpenXml
|
|
27
31
|
end
|
28
32
|
|
29
33
|
def attributes
|
30
|
-
@attributes ||=
|
34
|
+
@attributes ||= {}.tap do |attrs|
|
31
35
|
if superclass.respond_to?(:attributes)
|
32
|
-
|
33
|
-
[
|
34
|
-
|
35
|
-
else
|
36
|
-
{}
|
36
|
+
superclass.attributes.each do |key, value|
|
37
|
+
attrs[key] = value.dup
|
38
|
+
end
|
37
39
|
end
|
38
40
|
end
|
39
41
|
end
|
40
42
|
|
43
|
+
def required_attributes
|
44
|
+
@required_attributes ||= [].tap do |attrs|
|
45
|
+
attrs.push(*superclass.required_attributes) if superclass.respond_to?(:required_attributes)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
41
49
|
def with_namespace(namespace, &block)
|
42
50
|
@attribute_namespace = namespace
|
43
51
|
instance_eval(&block)
|
@@ -57,9 +65,14 @@ module OpenXml
|
|
57
65
|
self.class.attributes
|
58
66
|
end
|
59
67
|
|
68
|
+
def required_attributes
|
69
|
+
self.class.required_attributes
|
70
|
+
end
|
71
|
+
|
60
72
|
private
|
61
73
|
|
62
74
|
def xml_attributes
|
75
|
+
ensure_required_attributes_set
|
63
76
|
attributes.each_with_object({}) do |(name, options), attrs|
|
64
77
|
display, namespace = options
|
65
78
|
value = send(name)
|
@@ -69,6 +82,14 @@ module OpenXml
|
|
69
82
|
end
|
70
83
|
end
|
71
84
|
|
85
|
+
def ensure_required_attributes_set
|
86
|
+
unset_attributes = required_attributes.reject do |attr|
|
87
|
+
instance_variable_defined?("@#{attr}")
|
88
|
+
end
|
89
|
+
message = "Required attribute(s) #{unset_attributes.join(", ")} have not been set"
|
90
|
+
raise OpenXml::UnmetRequirementError, message if unset_attributes.any?
|
91
|
+
end
|
92
|
+
|
72
93
|
def boolean(value)
|
73
94
|
message = "Invalid #{name}: frame must be true or false"
|
74
95
|
raise ArgumentError, message unless [true, false].member? value
|
@@ -114,6 +135,11 @@ module OpenXml
|
|
114
135
|
raise ArgumentError, message if !value.is_a?(String) || value.length.zero?
|
115
136
|
end
|
116
137
|
|
138
|
+
def string_or_blank(value)
|
139
|
+
message = "Invalid #{name}: must be a string, even if the string is empty"
|
140
|
+
raise ArgumentError, message unless value.is_a?(String)
|
141
|
+
end
|
142
|
+
|
117
143
|
def in_range?(value, range)
|
118
144
|
message = "Invalid #{name}: must be a number between #{range.begin} and #{range.end}"
|
119
145
|
raise ArgumentError, message unless range.include?(value.to_i)
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require "openxml/unmet_requirement"
|
2
|
+
|
1
3
|
module OpenXml
|
2
4
|
module HasProperties
|
3
5
|
|
@@ -14,12 +16,13 @@ module OpenXml
|
|
14
16
|
@properties_tag ||= nil
|
15
17
|
end
|
16
18
|
|
17
|
-
def value_property(name, as: nil, klass: nil)
|
19
|
+
def value_property(name, as: nil, klass: nil, required: false, default_value: nil)
|
18
20
|
attr_reader name
|
19
21
|
|
20
22
|
properties[name] = (as || name).to_s
|
23
|
+
required_properties[name] = default_value if required
|
21
24
|
classified_name = properties[name].split("_").map(&:capitalize).join
|
22
|
-
class_name = klass.
|
25
|
+
class_name = klass.to_s unless klass.nil?
|
23
26
|
class_name ||= (to_s.split("::")[0...-2] + ["Properties", classified_name]).join("::")
|
24
27
|
|
25
28
|
(choice_groups[current_group] ||= []).push(name) unless current_group.nil?
|
@@ -33,17 +36,18 @@ module OpenXml
|
|
33
36
|
CODE
|
34
37
|
end
|
35
38
|
|
36
|
-
def property(name, as: nil, klass: nil)
|
39
|
+
def property(name, as: nil, klass: nil, required: false)
|
37
40
|
properties[name] = (as || name).to_s
|
41
|
+
required_properties[name] = true if required
|
38
42
|
classified_name = properties[name].split("_").map(&:capitalize).join
|
39
|
-
class_name = klass.
|
43
|
+
class_name = klass.to_s unless klass.nil?
|
40
44
|
class_name ||= (to_s.split("::")[0...-2] + ["Properties", classified_name]).join("::")
|
41
45
|
|
42
46
|
(choice_groups[current_group] ||= []).push(name) unless current_group.nil?
|
43
47
|
|
44
48
|
class_eval <<-CODE, __FILE__, __LINE__ + 1
|
45
49
|
def #{name}(*args)
|
46
|
-
|
50
|
+
unless instance_variable_defined?("@#{name}")
|
47
51
|
group_index = #{@current_group.inspect}
|
48
52
|
ensure_unique_in_group(:#{name}, group_index) unless group_index.nil?
|
49
53
|
instance_variable_set "@#{name}", #{class_name}.new(*args)
|
@@ -54,8 +58,9 @@ module OpenXml
|
|
54
58
|
CODE
|
55
59
|
end
|
56
60
|
|
57
|
-
def property_choice
|
61
|
+
def property_choice(required: false)
|
58
62
|
@current_group = choice_groups.length
|
63
|
+
required_choices << @current_group if required
|
59
64
|
yield
|
60
65
|
@current_group = nil
|
61
66
|
end
|
@@ -65,22 +70,26 @@ module OpenXml
|
|
65
70
|
end
|
66
71
|
|
67
72
|
def properties
|
68
|
-
@properties ||=
|
69
|
-
if superclass.respond_to?(:properties)
|
70
|
-
Hash[superclass.properties.map { |key, klass_name| [ key, klass_name.dup ] }]
|
71
|
-
else
|
72
|
-
{}
|
73
|
-
end
|
73
|
+
@properties ||= {}.tap do |props|
|
74
|
+
props.merge!(superclass.properties) if superclass.respond_to?(:properties)
|
74
75
|
end
|
75
76
|
end
|
76
77
|
|
77
78
|
def choice_groups
|
78
|
-
@choice_groups ||=
|
79
|
-
if superclass.respond_to?(:choice_groups)
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
79
|
+
@choice_groups ||= [].tap do |choices|
|
80
|
+
choices.push(*superclass.choice_groups.map(&:dup)) if superclass.respond_to?(:choice_groups)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def required_properties
|
85
|
+
@required_properties ||= {}.tap do |props|
|
86
|
+
props.merge!(superclass.required_properties) if superclass.respond_to?(:required_properties)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def required_choices
|
91
|
+
@required_choices ||= [].tap do |choices|
|
92
|
+
choices.push(*superclass.required_choices) if superclass.respond_to?(:required_choices)
|
84
93
|
end
|
85
94
|
end
|
86
95
|
|
@@ -110,6 +119,11 @@ module OpenXml
|
|
110
119
|
|
111
120
|
end
|
112
121
|
|
122
|
+
def initialize(*_args)
|
123
|
+
super
|
124
|
+
build_required_properties
|
125
|
+
end
|
126
|
+
|
113
127
|
def properties_element
|
114
128
|
@properties_element ||= self.class.properties_element.new
|
115
129
|
end
|
@@ -131,6 +145,7 @@ module OpenXml
|
|
131
145
|
end
|
132
146
|
|
133
147
|
def property_xml(xml)
|
148
|
+
ensure_required_choices
|
134
149
|
props = active_properties
|
135
150
|
return unless render_properties? props
|
136
151
|
|
@@ -139,6 +154,13 @@ module OpenXml
|
|
139
154
|
end
|
140
155
|
end
|
141
156
|
|
157
|
+
def build_required_properties
|
158
|
+
required_properties.each do |prop, default_value|
|
159
|
+
public_send(:"#{prop}=", default_value) if respond_to? :"#{prop}="
|
160
|
+
public_send(:"#{prop}")
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
142
164
|
private
|
143
165
|
|
144
166
|
def properties
|
@@ -150,7 +172,9 @@ module OpenXml
|
|
150
172
|
end
|
151
173
|
|
152
174
|
def render_properties?(properties=active_properties)
|
153
|
-
properties.any?(&:render?) || properties_attributes.any?
|
175
|
+
properties.any?(&:render?) || properties_attributes.keys.any? do |key|
|
176
|
+
properties_element.instance_variable_defined?("@#{key}")
|
177
|
+
end
|
154
178
|
end
|
155
179
|
|
156
180
|
def properties_tag
|
@@ -165,12 +189,34 @@ module OpenXml
|
|
165
189
|
self.class.choice_groups
|
166
190
|
end
|
167
191
|
|
192
|
+
def required_properties
|
193
|
+
self.class.required_properties
|
194
|
+
end
|
195
|
+
|
196
|
+
def required_choices
|
197
|
+
self.class.required_choices
|
198
|
+
end
|
199
|
+
|
168
200
|
def ensure_unique_in_group(name, group_index)
|
169
201
|
other_names = (choice_groups[group_index] - [name])
|
170
|
-
unique = other_names.
|
202
|
+
unique = other_names.none? { |other_name| instance_variable_defined?("@#{other_name}") }
|
171
203
|
message = "Property #{name} cannot also be set with #{other_names.join(", ")}."
|
172
204
|
raise ChoiceGroupUniqueError, message unless unique
|
173
205
|
end
|
174
206
|
|
207
|
+
def unmet_choices
|
208
|
+
required_choices.reject do |choice_index|
|
209
|
+
choice_groups[choice_index].one? do |prop_name|
|
210
|
+
instance_variable_defined?("@#{prop_name}")
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
def ensure_required_choices
|
216
|
+
unmet_choice_groups = unmet_choices.map { |index| choice_groups[index].join(", ") }
|
217
|
+
message = "Required choice from among group(s) (#{unmet_choice_groups.join("), (")}) not made"
|
218
|
+
raise OpenXml::UnmetRequirementError, message if unmet_choice_groups.any?
|
219
|
+
end
|
220
|
+
|
175
221
|
end
|
176
222
|
end
|
@@ -40,7 +40,7 @@ module OpenXml
|
|
40
40
|
end
|
41
41
|
|
42
42
|
def to_xml
|
43
|
-
|
43
|
+
build_standalone_xml do |xml|
|
44
44
|
xml.Types(xmlns: "http://schemas.openxmlformats.org/package/2006/content-types") {
|
45
45
|
defaults.each { |extension, content_type| xml.Default("Extension" => extension, "ContentType" => content_type) }
|
46
46
|
overrides.each { |part_name, content_type| xml.Override("PartName" => part_name, "ContentType" => content_type) }
|
data/lib/openxml/parts/rels.rb
CHANGED
@@ -23,7 +23,7 @@ module OpenXml
|
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
|
-
def add_relationship(type, target, id=
|
26
|
+
def add_relationship(type, target, id=next_id, target_mode=nil)
|
27
27
|
OpenXml::Elements::Relationship.new(type, target, id, target_mode).tap do |relationship|
|
28
28
|
relationships.push relationship
|
29
29
|
end
|
@@ -56,6 +56,11 @@ module OpenXml
|
|
56
56
|
private
|
57
57
|
attr_reader :relationships
|
58
58
|
|
59
|
+
def next_id
|
60
|
+
@current_id = (@current_id || 0) + 1
|
61
|
+
"rId#{@current_id}"
|
62
|
+
end
|
63
|
+
|
59
64
|
end
|
60
65
|
end
|
61
66
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: openxml-package
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bob Lail
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-09-
|
11
|
+
date: 2017-09-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rubyzip
|
@@ -221,8 +221,10 @@ files:
|
|
221
221
|
- lib/openxml/properties/transparent_container_property.rb
|
222
222
|
- lib/openxml/properties/value_property.rb
|
223
223
|
- lib/openxml/relationship.rb
|
224
|
+
- lib/openxml/render_when_empty.rb
|
224
225
|
- lib/openxml/rubyzip_fix.rb
|
225
226
|
- lib/openxml/types.rb
|
227
|
+
- lib/openxml/unmet_requirement.rb
|
226
228
|
- openxml-package.gemspec
|
227
229
|
- tmp/.keep
|
228
230
|
homepage: https://github.com/openxml/openxml-package
|