sheng 0.3.4 → 0.4.0
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/.ruby-version +1 -1
- data/docs/creating_templates.docx +0 -0
- data/docs/creating_templates.md +14 -0
- data/lib/sheng/merge_field.rb +62 -11
- data/lib/sheng/merge_field_set.rb +2 -0
- data/lib/sheng/support.rb +1 -1
- data/lib/sheng/version.rb +1 -1
- data/sheng.gemspec +1 -0
- data/spec/fixtures/trees/merge_field_set.yml +4 -0
- data/spec/fixtures/xml_fragments/input/merge_field/math_merge_field.xml +14 -0
- data/spec/fixtures/xml_fragments/input/merge_field_set/merge_field_set.xml +26 -0
- data/spec/fixtures/xml_fragments/output/merge_field/math_merge_field.xml +12 -0
- data/spec/fixtures/xml_fragments/output/merge_field_set/merge_field_set.xml +44 -0
- data/spec/lib/sheng/merge_field_set_spec.rb +40 -6
- data/spec/lib/sheng/merge_field_spec.rb +97 -5
- metadata +21 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ea5e2737e44d4a27d5d268bdfcefe21e1a3ff51b
|
4
|
+
data.tar.gz: 3245c5ef173eb186beaf1fb78acd487bfd42e04e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bd6309f22f7c16ddb93dc94d79fe8dbe4cb34c7ec4eb835883fe8afb1127271f8380c70dc79c262ff8da3f7c8d3bb442bd3e6f9b22fcbc3496b17ae4366f532c
|
7
|
+
data.tar.gz: 513affc5751aa7de19dc060c13e99974605d9e30afc57ae1711b8666fcd23294493d1c7790e8df6968fba145bd574d520d11a437e9e185ec3c3d1bcce15bc780
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.1.
|
1
|
+
2.1.
|
Binary file
|
data/docs/creating_templates.md
CHANGED
@@ -223,6 +223,20 @@ Filters can also be chained, and will be applied in which they appear (from left
|
|
223
223
|
|
224
224
|
«a_basic_integer|downcase»
|
225
225
|
|
226
|
+
## Basic Arithmetic Operations
|
227
|
+
|
228
|
+
You can perform basic arithmetic operations within a mergefield, using either hardcoded numeric values or variable names. The operators allowed are + (addition), - (subtraction), * (multiplication), and / (division). The usual order of precedence applies with these operators, and you can use parenthesis to control that precedence.
|
229
|
+
|
230
|
+
### Examples:
|
231
|
+
|
232
|
+
«25 * 6»
|
233
|
+
|
234
|
+
«8.3 + 5.232»
|
235
|
+
|
236
|
+
«(2.1 + 5) * 18»
|
237
|
+
|
238
|
+
«(hair.length * 2) + head.height»
|
239
|
+
|
226
240
|
# Checkboxes
|
227
241
|
|
228
242
|
To create a checkbox:
|
data/lib/sheng/merge_field.rb
CHANGED
@@ -1,8 +1,14 @@
|
|
1
|
+
require "dentaku"
|
2
|
+
|
1
3
|
module Sheng
|
2
4
|
class MergeField
|
3
|
-
|
4
|
-
|
5
|
-
|
5
|
+
MATH_TOKENS = %w[+ - / * ( )]
|
6
|
+
REGEXES = {
|
7
|
+
instruction_text: /^\s*MERGEFIELD(.*)\\\* MERGEFORMAT\s*$/,
|
8
|
+
key_string: /^(?<prefix>start:|end:|if:|end_if:|unless:|end_unless:)?\s*(?<key>[^\|]+)\s*\|?(?<filters>.*)?/,
|
9
|
+
numeric_string: /^[-+]?[0-9]*\.?[0-9]+$/
|
10
|
+
}
|
11
|
+
ALLOWED_FILTERS = [:upcase, :downcase, :capitalize, :titleize, :reverse]
|
6
12
|
|
7
13
|
class NotAMergeFieldError < StandardError; end
|
8
14
|
|
@@ -31,16 +37,16 @@ module Sheng
|
|
31
37
|
end
|
32
38
|
|
33
39
|
def key
|
34
|
-
raw_key.
|
40
|
+
raw_key.match(REGEXES[:key_string])[:key].strip
|
35
41
|
end
|
36
42
|
|
37
43
|
def filters
|
38
|
-
match = raw_key.match(
|
39
|
-
match
|
44
|
+
match = raw_key.match(REGEXES[:key_string])
|
45
|
+
match[:filters].split("|").map(&:strip)
|
40
46
|
end
|
41
47
|
|
42
48
|
def raw_key
|
43
|
-
@raw_key ||= mergefield_instruction_text.gsub(
|
49
|
+
@raw_key ||= mergefield_instruction_text.gsub(REGEXES[:instruction_text], '\1').strip
|
44
50
|
end
|
45
51
|
|
46
52
|
def mergefield_instruction_text
|
@@ -84,7 +90,7 @@ module Sheng
|
|
84
90
|
|
85
91
|
def block_prefix
|
86
92
|
@potential_prefix ||= begin
|
87
|
-
potential_prefix = raw_key.match(
|
93
|
+
potential_prefix = raw_key.match(REGEXES[:key_string])[:prefix]
|
88
94
|
potential_prefix && potential_prefix.gsub(/\:$/, '')
|
89
95
|
end
|
90
96
|
end
|
@@ -185,10 +191,55 @@ module Sheng
|
|
185
191
|
xml.remove
|
186
192
|
end
|
187
193
|
|
194
|
+
def key_parts
|
195
|
+
@key_parts ||= key.gsub(".", "_DOTSEPARATOR_").
|
196
|
+
split(/\b|\s/).
|
197
|
+
map(&:strip).
|
198
|
+
reject(&:empty?).
|
199
|
+
map { |token|
|
200
|
+
token.gsub("_DOTSEPARATOR_", ".")
|
201
|
+
}
|
202
|
+
end
|
203
|
+
|
204
|
+
def required_variables
|
205
|
+
key_parts.reject { |token|
|
206
|
+
REGEXES[:numeric_string].match(token) || MATH_TOKENS.include?(token)
|
207
|
+
}
|
208
|
+
end
|
209
|
+
|
210
|
+
def required_hash(placeholder: nil)
|
211
|
+
required_variables.inject({}) { |assembled, variable|
|
212
|
+
parts = variable.split(/\./)
|
213
|
+
last_key = parts.pop
|
214
|
+
hash = parts.reverse.inject(last_key => placeholder) do |memo, key|
|
215
|
+
memo = { key => memo }; memo
|
216
|
+
end
|
217
|
+
Sheng::Support.merge_required_hashes(assembled, hash)
|
218
|
+
}
|
219
|
+
end
|
220
|
+
|
221
|
+
def key_has_math?
|
222
|
+
!(MATH_TOKENS & key_parts).empty?
|
223
|
+
end
|
224
|
+
|
225
|
+
def get_value(data_set)
|
226
|
+
interpolated_string = key_parts.map { |token|
|
227
|
+
if REGEXES[:numeric_string].match(token) || MATH_TOKENS.include?(token)
|
228
|
+
token
|
229
|
+
else
|
230
|
+
data_set.fetch(token)
|
231
|
+
end
|
232
|
+
}.join(" ")
|
233
|
+
|
234
|
+
return interpolated_string unless key_has_math?
|
235
|
+
|
236
|
+
Dentaku::Calculator.new.evaluate!(interpolated_string)
|
237
|
+
end
|
238
|
+
|
188
239
|
def interpolate(data_set)
|
189
|
-
value = data_set
|
240
|
+
value = get_value(data_set)
|
190
241
|
replace_mergefield(filter_value(value))
|
191
|
-
rescue DataSet::KeyNotFound
|
242
|
+
rescue DataSet::KeyNotFound, Dentaku::UnboundVariableError
|
192
243
|
# Ignore this error; we'll collect all uninterpolated fields later and
|
193
244
|
# raise a new exception, so we can list all the fields in an error
|
194
245
|
# message.
|
@@ -197,7 +248,7 @@ module Sheng
|
|
197
248
|
|
198
249
|
def filter_value(value)
|
199
250
|
filters.inject(value) { |val, filter|
|
200
|
-
if
|
251
|
+
if ALLOWED_FILTERS.include?(filter.to_sym) && val.respond_to?(filter.to_sym)
|
201
252
|
val.send(filter)
|
202
253
|
else
|
203
254
|
val
|
@@ -36,6 +36,8 @@ module Sheng
|
|
36
36
|
nodes.inject({}) do |node_list, node|
|
37
37
|
hsh = if node.is_a?(ConditionalBlock)
|
38
38
|
node.required_hash(placeholder)
|
39
|
+
elsif node.is_a?(MergeField)
|
40
|
+
node.required_hash(placeholder: placeholder)
|
39
41
|
else
|
40
42
|
value = node.is_a?(Block) ? [node.required_hash(placeholder)].compact : placeholder
|
41
43
|
key_parts = node.key.split(/\./)
|
data/lib/sheng/support.rb
CHANGED
data/lib/sheng/version.rb
CHANGED
data/sheng.gemspec
CHANGED
@@ -10,6 +10,10 @@
|
|
10
10
|
:key: color
|
11
11
|
- :type: merge_field
|
12
12
|
:key: size
|
13
|
+
- :type: merge_field
|
14
|
+
:key: dimensions.width * dimensions.height
|
15
|
+
- :type: merge_field
|
16
|
+
:key: (dimensions.width * 2) + (dimensions.height * 2)
|
13
17
|
- :type: check_box
|
14
18
|
:key: veggies.green.spinach
|
15
19
|
- :type: merge_field
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
|
2
|
+
<w:p>
|
3
|
+
<w:fldSimple w:instr=" MERGEFIELD baskets.count * (3 + origami) \* MERGEFORMAT ">
|
4
|
+
<w:r>
|
5
|
+
<w:rPr>
|
6
|
+
<w:b/>
|
7
|
+
<w:i/>
|
8
|
+
<w:noProof/>
|
9
|
+
</w:rPr>
|
10
|
+
<w:t>«baskets.count * (3 + origami)»</w:t>
|
11
|
+
</w:r>
|
12
|
+
</w:fldSimple>
|
13
|
+
</w:p>
|
14
|
+
</w:document>
|
@@ -54,6 +54,32 @@
|
|
54
54
|
</w:r>
|
55
55
|
</w:fldSimple>
|
56
56
|
</w:p>
|
57
|
+
<w:p>
|
58
|
+
<w:r>
|
59
|
+
<w:t xml:space="preserve">Sock Area: </w:t>
|
60
|
+
</w:r>
|
61
|
+
<w:fldSimple w:instr=" MERGEFIELD dimensions.width * dimensions.height \* MERGEFORMAT ">
|
62
|
+
<w:r>
|
63
|
+
<w:rPr>
|
64
|
+
<w:noProof/>
|
65
|
+
</w:rPr>
|
66
|
+
<w:t>«dimensions.width * dimensions.height»</w:t>
|
67
|
+
</w:r>
|
68
|
+
</w:fldSimple>
|
69
|
+
</w:p>
|
70
|
+
<w:p>
|
71
|
+
<w:r>
|
72
|
+
<w:t xml:space="preserve">Sock Circumference: </w:t>
|
73
|
+
</w:r>
|
74
|
+
<w:fldSimple w:instr=" MERGEFIELD (dimensions.width * 2) + (dimensions.height * 2) \* MERGEFORMAT ">
|
75
|
+
<w:r>
|
76
|
+
<w:rPr>
|
77
|
+
<w:noProof/>
|
78
|
+
</w:rPr>
|
79
|
+
<w:t>«(dimensions.width * 2) + (dimensions.height * 2)»</w:t>
|
80
|
+
</w:r>
|
81
|
+
</w:fldSimple>
|
82
|
+
</w:p>
|
57
83
|
<w:p>
|
58
84
|
<w:fldSimple w:instr=" MERGEFIELD end:person.socks \* MERGEFORMAT ">
|
59
85
|
<w:r w:rsidR="00455C8A">
|
@@ -36,6 +36,28 @@
|
|
36
36
|
<w:t>Stumungous</w:t>
|
37
37
|
</w:r>
|
38
38
|
</w:p>
|
39
|
+
<w:p>
|
40
|
+
<w:r>
|
41
|
+
<w:t xml:space="preserve">Sock Area: </w:t>
|
42
|
+
</w:r>
|
43
|
+
<w:r>
|
44
|
+
<w:rPr>
|
45
|
+
<w:noProof/>
|
46
|
+
</w:rPr>
|
47
|
+
<w:t>70</w:t>
|
48
|
+
</w:r>
|
49
|
+
</w:p>
|
50
|
+
<w:p>
|
51
|
+
<w:r>
|
52
|
+
<w:t xml:space="preserve">Sock Circumference: </w:t>
|
53
|
+
</w:r>
|
54
|
+
<w:r>
|
55
|
+
<w:rPr>
|
56
|
+
<w:noProof/>
|
57
|
+
</w:rPr>
|
58
|
+
<w:t>38</w:t>
|
59
|
+
</w:r>
|
60
|
+
</w:p>
|
39
61
|
<w:p>
|
40
62
|
<w:r>
|
41
63
|
<w:rPr>
|
@@ -52,6 +74,28 @@
|
|
52
74
|
<w:t>Teensy</w:t>
|
53
75
|
</w:r>
|
54
76
|
</w:p>
|
77
|
+
<w:p>
|
78
|
+
<w:r>
|
79
|
+
<w:t xml:space="preserve">Sock Area: </w:t>
|
80
|
+
</w:r>
|
81
|
+
<w:r>
|
82
|
+
<w:rPr>
|
83
|
+
<w:noProof/>
|
84
|
+
</w:rPr>
|
85
|
+
<w:t>364</w:t>
|
86
|
+
</w:r>
|
87
|
+
</w:p>
|
88
|
+
<w:p>
|
89
|
+
<w:r>
|
90
|
+
<w:t xml:space="preserve">Sock Circumference: </w:t>
|
91
|
+
</w:r>
|
92
|
+
<w:r>
|
93
|
+
<w:rPr>
|
94
|
+
<w:noProof/>
|
95
|
+
</w:rPr>
|
96
|
+
<w:t>82</w:t>
|
97
|
+
</w:r>
|
98
|
+
</w:p>
|
55
99
|
<w:ffData>
|
56
100
|
<w:name w:val="veggies.green.spinach"/>
|
57
101
|
<w:enabled/>
|
@@ -28,8 +28,8 @@ describe Sheng::MergeFieldSet do
|
|
28
28
|
:first_name => 'Brad',
|
29
29
|
:last_name => 'Tucklemoof',
|
30
30
|
:socks => [
|
31
|
-
{ :color => 'Green', :size => 'Stumungous' },
|
32
|
-
{ :color => 'Whitish', :size => 'Teensy' }
|
31
|
+
{ :color => 'Green', :size => 'Stumungous', :dimensions => { :width => 14, :height => 5 } },
|
32
|
+
{ :color => 'Whitish', :size => 'Teensy', :dimensions => { :width => 28, :height => 13 } }
|
33
33
|
]
|
34
34
|
},
|
35
35
|
:veggies => { :green => { :spinach => true } }
|
@@ -117,15 +117,49 @@ describe Sheng::MergeFieldSet do
|
|
117
117
|
describe '#required_hash' do
|
118
118
|
it 'returns skeleton hash demonstrating required data for interpolation' do
|
119
119
|
expect(subject.required_hash).to eq({
|
120
|
-
"person" => {
|
121
|
-
|
120
|
+
"person" => {
|
121
|
+
"first_name" => nil,
|
122
|
+
"last_name" => nil,
|
123
|
+
"socks" => [
|
124
|
+
{
|
125
|
+
"color" => nil,
|
126
|
+
"size" => nil,
|
127
|
+
"dimensions" => {
|
128
|
+
"width" => nil,
|
129
|
+
"height" => nil
|
130
|
+
}
|
131
|
+
}
|
132
|
+
]
|
133
|
+
},
|
134
|
+
"veggies"=> {
|
135
|
+
"green" => {
|
136
|
+
"spinach" => nil
|
137
|
+
}
|
138
|
+
}
|
122
139
|
})
|
123
140
|
end
|
124
141
|
|
125
142
|
it 'uses given value as placeholder for mergefields/checkboxes' do
|
126
143
|
expect(subject.required_hash(:foo)).to eq({
|
127
|
-
"person" => {
|
128
|
-
|
144
|
+
"person" => {
|
145
|
+
"first_name" => :foo,
|
146
|
+
"last_name" => :foo,
|
147
|
+
"socks" => [
|
148
|
+
{
|
149
|
+
"color" => :foo,
|
150
|
+
"size" => :foo,
|
151
|
+
"dimensions" => {
|
152
|
+
"width" => :foo,
|
153
|
+
"height" => :foo
|
154
|
+
}
|
155
|
+
}
|
156
|
+
]
|
157
|
+
},
|
158
|
+
"veggies"=> {
|
159
|
+
"green" => {
|
160
|
+
"spinach" => :foo
|
161
|
+
}
|
162
|
+
}
|
129
163
|
})
|
130
164
|
end
|
131
165
|
|
@@ -27,6 +27,25 @@ describe Sheng::MergeField do
|
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
|
+
describe "mergefield with math operations" do
|
31
|
+
let(:fragment) { xml_fragment('input/merge_field/math_merge_field') }
|
32
|
+
let(:element) { fragment.xpath("//w:fldSimple[contains(@w:instr, 'MERGEFIELD')]").first }
|
33
|
+
|
34
|
+
describe '#interpolate' do
|
35
|
+
it 'interpolates values from dataset into mergefield' do
|
36
|
+
dataset = Sheng::DataSet.new({
|
37
|
+
:baskets => {
|
38
|
+
:count => 2
|
39
|
+
},
|
40
|
+
:origami => 8
|
41
|
+
})
|
42
|
+
|
43
|
+
subject.interpolate(dataset)
|
44
|
+
expect(subject.xml_document).to be_equivalent_to xml_fragment('output/merge_field/math_merge_field')
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
30
49
|
describe "new style merge field" do
|
31
50
|
let(:fragment) { xml_fragment('input/merge_field/new_merge_field') }
|
32
51
|
let(:element) { fragment.xpath("//w:fldChar[contains(@w:fldCharType, 'begin')]").first }
|
@@ -124,16 +143,70 @@ describe Sheng::MergeField do
|
|
124
143
|
end
|
125
144
|
end
|
126
145
|
|
127
|
-
describe
|
128
|
-
|
129
|
-
|
130
|
-
:ocean => { :fishy => "scrumblefish" }
|
146
|
+
describe "#get_value" do
|
147
|
+
let(:dataset) {
|
148
|
+
Sheng::DataSet.new({
|
149
|
+
:ocean => { :fishy => "scrumblefish" },
|
150
|
+
:numbers => { :first => 23, :second => 8 }
|
131
151
|
})
|
152
|
+
}
|
153
|
+
|
154
|
+
it "returns value from dataset when given simple lookup" do
|
155
|
+
allow(subject).to receive(:key).and_return("ocean.fishy")
|
156
|
+
expect(subject.get_value(dataset)).to eq("scrumblefish")
|
157
|
+
end
|
158
|
+
|
159
|
+
it "performs math operations on values from dataset" do
|
160
|
+
allow(subject).to receive(:key).and_return("(numbers.first * numbers.second) + 5")
|
161
|
+
expect(subject.get_value(dataset)).to eq(189)
|
162
|
+
end
|
163
|
+
|
164
|
+
it "performs math operations with no dataset lookup" do
|
165
|
+
allow(subject).to receive(:key).and_return("2 + (3*5)")
|
166
|
+
expect(subject.get_value(dataset)).to eq(17)
|
167
|
+
end
|
168
|
+
|
169
|
+
it "raises exception if key not found in simple lookup" do
|
170
|
+
allow(subject).to receive(:key).and_return("oliver.twist")
|
171
|
+
expect {
|
172
|
+
subject.get_value(dataset)
|
173
|
+
}.to raise_error(Sheng::DataSet::KeyNotFound)
|
174
|
+
end
|
175
|
+
|
176
|
+
it "raises exception if key not found in math formula" do
|
177
|
+
allow(subject).to receive(:key).and_return("oliver.twist * 15")
|
178
|
+
expect {
|
179
|
+
subject.get_value(dataset)
|
180
|
+
}.to raise_error(Sheng::DataSet::KeyNotFound)
|
181
|
+
end
|
182
|
+
|
183
|
+
it "raises exception if interpolated math formula includes invalid symbols" do
|
184
|
+
allow(subject).to receive(:key).and_return("ocean.fishy * 15")
|
185
|
+
expect {
|
186
|
+
subject.get_value(dataset)
|
187
|
+
}.to raise_error(Dentaku::UnboundVariableError)
|
188
|
+
end
|
189
|
+
end
|
132
190
|
|
191
|
+
describe '#interpolate' do
|
192
|
+
it 'interpolates filtered values from dataset into mergefield' do
|
193
|
+
allow(subject).to receive(:get_value).with(:a_dataset).and_return("scrumblefish")
|
133
194
|
allow(subject).to receive(:filter_value).with("scrumblefish").and_return("l33tphish")
|
134
|
-
subject.interpolate(
|
195
|
+
subject.interpolate(:a_dataset)
|
135
196
|
expect(subject.xml_document).to be_equivalent_to xml_fragment('output/merge_field/merge_field')
|
136
197
|
end
|
198
|
+
|
199
|
+
it "does not replace and returns nil if any keys not found" do
|
200
|
+
allow(subject).to receive(:get_value).with(:a_dataset).and_raise(Sheng::DataSet::KeyNotFound)
|
201
|
+
expect(subject).to receive(:replace_mergefield).never
|
202
|
+
expect(subject.interpolate(:a_dataset)).to be_nil
|
203
|
+
end
|
204
|
+
|
205
|
+
it "does not replace and returns nil if calculation error encountered" do
|
206
|
+
allow(subject).to receive(:get_value).with(:a_dataset).and_raise(Dentaku::UnboundVariableError.new([]))
|
207
|
+
expect(subject).to receive(:replace_mergefield).never
|
208
|
+
expect(subject.interpolate(:a_dataset)).to be_nil
|
209
|
+
end
|
137
210
|
end
|
138
211
|
|
139
212
|
describe "#xml" do
|
@@ -148,6 +221,20 @@ describe Sheng::MergeField do
|
|
148
221
|
end
|
149
222
|
end
|
150
223
|
|
224
|
+
describe "#required_variables" do
|
225
|
+
it "returns key parts that are not operators or numeric" do
|
226
|
+
allow(subject).to receive(:key).and_return("cat.toes * 15 + (yawns / 2.0)")
|
227
|
+
expect(subject.required_variables).to eq(["cat.toes", "yawns"])
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
describe "#key_parts" do
|
232
|
+
it "returns key split on all word boundaries except dot separators" do
|
233
|
+
allow(subject).to receive(:key).and_return("cat.toes * 15 + (yawns / 2.0)")
|
234
|
+
expect(subject.key_parts).to eq(["cat.toes", "*", "15", "+", "(", "yawns", "/", "2.0", ")"])
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
151
238
|
describe '#key' do
|
152
239
|
it 'returns the raw key with start/end metadata stripped off' do
|
153
240
|
allow(subject).to receive(:raw_key).and_return('start:whipple.dooter')
|
@@ -160,6 +247,11 @@ describe Sheng::MergeField do
|
|
160
247
|
allow(subject).to receive(:raw_key).and_return("whumpies | cook | dress(frock)")
|
161
248
|
expect(subject.key).to eq 'whumpies'
|
162
249
|
end
|
250
|
+
|
251
|
+
it 'returns key even if it contains math operations' do
|
252
|
+
allow(subject).to receive(:raw_key).and_return("whumpies * 3 | cook | dress(frock)")
|
253
|
+
expect(subject.key).to eq 'whumpies * 3'
|
254
|
+
end
|
163
255
|
end
|
164
256
|
|
165
257
|
describe "#filters" do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sheng
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ravi Gadad
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2016-01-27 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -137,6 +137,20 @@ dependencies:
|
|
137
137
|
- - "~>"
|
138
138
|
- !ruby/object:Gem::Version
|
139
139
|
version: '4.0'
|
140
|
+
- !ruby/object:Gem::Dependency
|
141
|
+
name: dentaku
|
142
|
+
requirement: !ruby/object:Gem::Requirement
|
143
|
+
requirements:
|
144
|
+
- - "~>"
|
145
|
+
- !ruby/object:Gem::Version
|
146
|
+
version: '2.0'
|
147
|
+
type: :runtime
|
148
|
+
prerelease: false
|
149
|
+
version_requirements: !ruby/object:Gem::Requirement
|
150
|
+
requirements:
|
151
|
+
- - "~>"
|
152
|
+
- !ruby/object:Gem::Version
|
153
|
+
version: '2.0'
|
140
154
|
description: A Ruby gem for data merging Word documents.
|
141
155
|
email:
|
142
156
|
- ravi@renewfund.com
|
@@ -194,6 +208,7 @@ files:
|
|
194
208
|
- spec/fixtures/xml_fragments/input/merge_field/bad/not_a_real_mergefield_old.xml
|
195
209
|
- spec/fixtures/xml_fragments/input/merge_field/bad/unclosed_merge_field.xml
|
196
210
|
- spec/fixtures/xml_fragments/input/merge_field/inline_merge_field.xml
|
211
|
+
- spec/fixtures/xml_fragments/input/merge_field/math_merge_field.xml
|
197
212
|
- spec/fixtures/xml_fragments/input/merge_field/merge_field.xml
|
198
213
|
- spec/fixtures/xml_fragments/input/merge_field/new_merge_field.xml
|
199
214
|
- spec/fixtures/xml_fragments/input/merge_field/split_merge_field.xml
|
@@ -224,6 +239,7 @@ files:
|
|
224
239
|
- spec/fixtures/xml_fragments/output/conditional_block/unless_does_not_exist.xml
|
225
240
|
- spec/fixtures/xml_fragments/output/conditional_block/unless_exists.xml
|
226
241
|
- spec/fixtures/xml_fragments/output/merge_field/inline_merge_field.xml
|
242
|
+
- spec/fixtures/xml_fragments/output/merge_field/math_merge_field.xml
|
227
243
|
- spec/fixtures/xml_fragments/output/merge_field/merge_field.xml
|
228
244
|
- spec/fixtures/xml_fragments/output/merge_field/split_merge_field.xml
|
229
245
|
- spec/fixtures/xml_fragments/output/merge_field_set/complex_nesting_and_reuse.xml
|
@@ -270,7 +286,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
270
286
|
version: '0'
|
271
287
|
requirements: []
|
272
288
|
rubyforge_project:
|
273
|
-
rubygems_version: 2.2.
|
289
|
+
rubygems_version: 2.2.5
|
274
290
|
signing_key:
|
275
291
|
specification_version: 4
|
276
292
|
summary: A Ruby gem for data merging Word documents, using native MergeFields as placeholders
|
@@ -301,6 +317,7 @@ test_files:
|
|
301
317
|
- spec/fixtures/xml_fragments/input/merge_field/bad/not_a_real_mergefield_old.xml
|
302
318
|
- spec/fixtures/xml_fragments/input/merge_field/bad/unclosed_merge_field.xml
|
303
319
|
- spec/fixtures/xml_fragments/input/merge_field/inline_merge_field.xml
|
320
|
+
- spec/fixtures/xml_fragments/input/merge_field/math_merge_field.xml
|
304
321
|
- spec/fixtures/xml_fragments/input/merge_field/merge_field.xml
|
305
322
|
- spec/fixtures/xml_fragments/input/merge_field/new_merge_field.xml
|
306
323
|
- spec/fixtures/xml_fragments/input/merge_field/split_merge_field.xml
|
@@ -331,6 +348,7 @@ test_files:
|
|
331
348
|
- spec/fixtures/xml_fragments/output/conditional_block/unless_does_not_exist.xml
|
332
349
|
- spec/fixtures/xml_fragments/output/conditional_block/unless_exists.xml
|
333
350
|
- spec/fixtures/xml_fragments/output/merge_field/inline_merge_field.xml
|
351
|
+
- spec/fixtures/xml_fragments/output/merge_field/math_merge_field.xml
|
334
352
|
- spec/fixtures/xml_fragments/output/merge_field/merge_field.xml
|
335
353
|
- spec/fixtures/xml_fragments/output/merge_field/split_merge_field.xml
|
336
354
|
- spec/fixtures/xml_fragments/output/merge_field_set/complex_nesting_and_reuse.xml
|