sablon 0.0.22 → 0.1.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.
@@ -12,120 +12,167 @@ class HTMLConverterTest < Sablon::TestCase
12
12
  def test_convert_text_inside_div
13
13
  input = '<div>Lorem ipsum dolor sit amet</div>'
14
14
  expected_output = <<-DOCX.strip
15
- <w:p>
16
- <w:pPr><w:pStyle w:val="Normal" /></w:pPr>
17
- <w:r><w:t xml:space="preserve">Lorem ipsum dolor sit amet</w:t></w:r>
18
- </w:p>
19
- DOCX
15
+ <w:p>
16
+ <w:pPr><w:pStyle w:val="Normal" /></w:pPr>
17
+ <w:r><w:t xml:space="preserve">Lorem ipsum dolor sit amet</w:t></w:r>
18
+ </w:p>
19
+ DOCX
20
20
  assert_equal normalize_wordml(expected_output), process(input)
21
21
  end
22
22
 
23
23
  def test_convert_text_inside_p
24
24
  input = '<p>Lorem ipsum dolor sit amet</p>'
25
25
  expected_output = <<-DOCX.strip
26
+ <w:p>
27
+ <w:pPr><w:pStyle w:val="Paragraph" /></w:pPr>
28
+ <w:r><w:t xml:space="preserve">Lorem ipsum dolor sit amet</w:t></w:r>
29
+ </w:p>
30
+ DOCX
31
+ assert_equal normalize_wordml(expected_output), process(input)
32
+ end
33
+
34
+ def test_convert_hyperlink_inside_div
35
+ uid_generator = UIDTestGenerator.new
36
+ SecureRandom.stub(:uuid, uid_generator.method(:new_uid)) do |secure_random_instance|
37
+
38
+ input = '<div>Lorem ipsum dolor sit amet; search it at <a href="http://www.google.com">google</a></div>'
39
+ expected_output = <<-DOCX.strip
26
40
  <w:p>
27
- <w:pPr><w:pStyle w:val="Paragraph" /></w:pPr>
28
- <w:r><w:t xml:space="preserve">Lorem ipsum dolor sit amet</w:t></w:r>
41
+ <w:pPr><w:pStyle w:val="Normal" /></w:pPr>
42
+ <w:r><w:t xml:space="preserve">Lorem ipsum dolor sit amet; search it at </w:t></w:r>
43
+ <w:hyperlink r:id=\"rId#{secure_random_instance.uuid}\">
44
+ <w:r>
45
+ <w:rPr>
46
+ <w:rStyle w:val=\"Hyperlink\" />
47
+ </w:rPr>
48
+ <w:t xml:space=\"preserve\">google</w:t>
49
+ </w:r>
50
+ </w:hyperlink>
29
51
  </w:p>
30
- DOCX
31
- assert_equal normalize_wordml(expected_output), process(input)
52
+ DOCX
53
+ uid_generator.reset
54
+ assert_equal normalize_wordml(expected_output), process(input)
55
+ end
56
+ end
57
+
58
+ def test_convert_hyperlink_inside_p
59
+ uid_generator = UIDTestGenerator.new
60
+ SecureRandom.stub(:uuid, uid_generator.method(:new_uid)) do |secure_random_instance|
61
+ input = '<p>Lorem ipsum dolor sit amet; search it at <a href="http://www.google.com">google</a></p>'
62
+ expected_output = <<-DOCX.strip
63
+ <w:p>
64
+ <w:pPr><w:pStyle w:val="Paragraph" /></w:pPr>
65
+ <w:r><w:t xml:space="preserve">Lorem ipsum dolor sit amet; search it at </w:t></w:r>
66
+ <w:hyperlink r:id=\"rId#{secure_random_instance.uuid}\">
67
+ <w:r>
68
+ <w:rPr>
69
+ <w:rStyle w:val=\"Hyperlink\" />
70
+ </w:rPr>
71
+ <w:t xml:space=\"preserve\">google</w:t>
72
+ </w:r>
73
+ </w:hyperlink>
74
+ </w:p>
75
+ DOCX
76
+ uid_generator.reset
77
+ assert_equal normalize_wordml(expected_output), process(input)
78
+ end
32
79
  end
33
80
 
34
81
  def test_convert_text_inside_multiple_divs
35
82
  input = '<div>Lorem ipsum</div><div>dolor sit amet</div>'
36
83
  expected_output = <<-DOCX.strip
37
- <w:p>
38
- <w:pPr><w:pStyle w:val="Normal" /></w:pPr>
39
- <w:r><w:t xml:space="preserve">Lorem ipsum</w:t></w:r>
40
- </w:p>
41
- <w:p>
42
- <w:pPr><w:pStyle w:val="Normal" /></w:pPr>
43
- <w:r><w:t xml:space="preserve">dolor sit amet</w:t></w:r>
44
- </w:p>
45
- DOCX
84
+ <w:p>
85
+ <w:pPr><w:pStyle w:val="Normal" /></w:pPr>
86
+ <w:r><w:t xml:space="preserve">Lorem ipsum</w:t></w:r>
87
+ </w:p>
88
+ <w:p>
89
+ <w:pPr><w:pStyle w:val="Normal" /></w:pPr>
90
+ <w:r><w:t xml:space="preserve">dolor sit amet</w:t></w:r>
91
+ </w:p>
92
+ DOCX
46
93
  assert_equal normalize_wordml(expected_output), process(input)
47
94
  end
48
95
 
49
96
  def test_convert_newline_inside_div
50
97
  input = '<div>Lorem ipsum<br>dolor sit amet</div>'
51
98
  expected_output = <<-DOCX.strip
52
- <w:p>
53
- <w:pPr><w:pStyle w:val="Normal" /></w:pPr>
54
- <w:r><w:t xml:space="preserve">Lorem ipsum</w:t></w:r>
55
- <w:r><w:br/></w:r>
56
- <w:r><w:t xml:space="preserve">dolor sit amet</w:t></w:r>
57
- </w:p>
58
- DOCX
99
+ <w:p>
100
+ <w:pPr><w:pStyle w:val="Normal" /></w:pPr>
101
+ <w:r><w:t xml:space="preserve">Lorem ipsum</w:t></w:r>
102
+ <w:r><w:br/></w:r>
103
+ <w:r><w:t xml:space="preserve">dolor sit amet</w:t></w:r>
104
+ </w:p>
105
+ DOCX
59
106
  assert_equal normalize_wordml(expected_output), process(input)
60
107
  end
61
108
 
62
109
  def test_convert_strong_tags_inside_div
63
110
  input = '<div>Lorem&nbsp;<strong>ipsum dolor</strong>&nbsp;sit amet</div>'
64
111
  expected_output = <<-DOCX.strip
65
- <w:p>
66
- <w:pPr><w:pStyle w:val="Normal" /></w:pPr>
67
- <w:r><w:t xml:space="preserve">Lorem </w:t></w:r>
68
- <w:r><w:rPr><w:b /></w:rPr><w:t xml:space="preserve">ipsum dolor</w:t></w:r>
69
- <w:r><w:t xml:space="preserve"> sit amet</w:t></w:r>
70
- </w:p>
71
- DOCX
112
+ <w:p>
113
+ <w:pPr><w:pStyle w:val="Normal" /></w:pPr>
114
+ <w:r><w:t xml:space="preserve">Lorem </w:t></w:r>
115
+ <w:r><w:rPr><w:b /></w:rPr><w:t xml:space="preserve">ipsum dolor</w:t></w:r>
116
+ <w:r><w:t xml:space="preserve"> sit amet</w:t></w:r>
117
+ </w:p>
118
+ DOCX
72
119
  assert_equal normalize_wordml(expected_output), process(input)
73
120
  end
74
121
 
75
122
  def test_convert_span_tags_inside_p
76
123
  input = '<p>Lorem&nbsp;<span>ipsum dolor</span>&nbsp;sit amet</p>'
77
124
  expected_output = <<-DOCX.strip
78
- <w:p>
79
- <w:pPr><w:pStyle w:val="Paragraph" /></w:pPr>
80
- <w:r><w:t xml:space="preserve">Lorem </w:t></w:r>
81
- <w:r><w:t xml:space="preserve">ipsum dolor</w:t></w:r>
82
- <w:r><w:t xml:space="preserve"> sit amet</w:t></w:r></w:p>
83
- DOCX
84
-
125
+ <w:p>
126
+ <w:pPr><w:pStyle w:val="Paragraph" /></w:pPr>
127
+ <w:r><w:t xml:space="preserve">Lorem </w:t></w:r>
128
+ <w:r><w:t xml:space="preserve">ipsum dolor</w:t></w:r>
129
+ <w:r><w:t xml:space="preserve"> sit amet</w:t></w:r>
130
+ </w:p>
131
+ DOCX
85
132
  assert_equal normalize_wordml(expected_output), process(input)
86
133
  end
87
134
 
88
135
  def test_convert_u_tags_inside_p
89
136
  input = '<p>Lorem&nbsp;<u>ipsum dolor</u>&nbsp;sit amet</p>'
90
137
  expected_output = <<-DOCX.strip
91
- <w:p>
92
- <w:pPr><w:pStyle w:val="Paragraph" /></w:pPr>
93
- <w:r><w:t xml:space="preserve">Lorem </w:t></w:r>
94
- <w:r>
95
- <w:rPr><w:u w:val="single" /></w:rPr>
96
- <w:t xml:space="preserve">ipsum dolor</w:t>
97
- </w:r>
98
- <w:r><w:t xml:space="preserve"> sit amet</w:t></w:r>
99
- </w:p>
100
- DOCX
138
+ <w:p>
139
+ <w:pPr><w:pStyle w:val="Paragraph" /></w:pPr>
140
+ <w:r><w:t xml:space="preserve">Lorem </w:t></w:r>
141
+ <w:r>
142
+ <w:rPr><w:u w:val="single" /></w:rPr>
143
+ <w:t xml:space="preserve">ipsum dolor</w:t>
144
+ </w:r>
145
+ <w:r><w:t xml:space="preserve"> sit amet</w:t></w:r>
146
+ </w:p>
147
+ DOCX
101
148
  assert_equal normalize_wordml(expected_output), process(input)
102
149
  end
103
150
 
104
151
  def test_convert_em_tags_inside_div
105
152
  input = '<div>Lorem&nbsp;<em>ipsum dolor</em>&nbsp;sit amet</div>'
106
153
  expected_output = <<-DOCX.strip
107
- <w:p>
108
- <w:pPr><w:pStyle w:val="Normal" /></w:pPr>
109
- <w:r><w:t xml:space="preserve">Lorem </w:t></w:r>
110
- <w:r><w:rPr><w:i /></w:rPr><w:t xml:space="preserve">ipsum dolor</w:t></w:r>
111
- <w:r><w:t xml:space="preserve"> sit amet</w:t></w:r>
112
- </w:p>
113
- DOCX
154
+ <w:p>
155
+ <w:pPr><w:pStyle w:val="Normal" /></w:pPr>
156
+ <w:r><w:t xml:space="preserve">Lorem </w:t></w:r>
157
+ <w:r><w:rPr><w:i /></w:rPr><w:t xml:space="preserve">ipsum dolor</w:t></w:r>
158
+ <w:r><w:t xml:space="preserve"> sit amet</w:t></w:r>
159
+ </w:p>
160
+ DOCX
114
161
  assert_equal normalize_wordml(expected_output), process(input)
115
162
  end
116
163
 
117
164
  def test_convert_s_tags_inside_p
118
165
  input = '<p>Lorem&nbsp;<s>ipsum dolor</s>&nbsp;sit amet</p>'
119
166
  expected_output = <<-DOCX.strip
120
- <w:p>
121
- <w:pPr><w:pStyle w:val="Paragraph" /></w:pPr>
122
- <w:r><w:t xml:space="preserve">Lorem </w:t></w:r>
123
- <w:r>
124
- <w:rPr><w:strike w:val="true" /></w:rPr>
125
- <w:t xml:space="preserve">ipsum dolor</w:t>
126
- </w:r>
127
- <w:r><w:t xml:space="preserve"> sit amet</w:t></w:r>
128
- </w:p>
167
+ <w:p>
168
+ <w:pPr><w:pStyle w:val="Paragraph" /></w:pPr>
169
+ <w:r><w:t xml:space="preserve">Lorem </w:t></w:r>
170
+ <w:r>
171
+ <w:rPr><w:strike w:val="true" /></w:rPr>
172
+ <w:t xml:space="preserve">ipsum dolor</w:t>
173
+ </w:r>
174
+ <w:r><w:t xml:space="preserve"> sit amet</w:t></w:r>
175
+ </w:p>
129
176
  DOCX
130
177
  assert_equal normalize_wordml(expected_output), process(input)
131
178
  end
@@ -133,15 +180,15 @@ DOCX
133
180
  def test_convert_sub_tags_inside_p
134
181
  input = '<p>Lorem&nbsp;<sub>ipsum dolor</sub>&nbsp;sit amet</p>'
135
182
  expected_output = <<-DOCX.strip
136
- <w:p>
137
- <w:pPr><w:pStyle w:val="Paragraph" /></w:pPr>
138
- <w:r><w:t xml:space="preserve">Lorem </w:t></w:r>
139
- <w:r>
140
- <w:rPr><w:vertAlign w:val="subscript" /></w:rPr>
141
- <w:t xml:space="preserve">ipsum dolor</w:t>
142
- </w:r>
143
- <w:r><w:t xml:space="preserve"> sit amet</w:t></w:r>
144
- </w:p>
183
+ <w:p>
184
+ <w:pPr><w:pStyle w:val="Paragraph" /></w:pPr>
185
+ <w:r><w:t xml:space="preserve">Lorem </w:t></w:r>
186
+ <w:r>
187
+ <w:rPr><w:vertAlign w:val="subscript" /></w:rPr>
188
+ <w:t xml:space="preserve">ipsum dolor</w:t>
189
+ </w:r>
190
+ <w:r><w:t xml:space="preserve"> sit amet</w:t></w:r>
191
+ </w:p>
145
192
  DOCX
146
193
  assert_equal normalize_wordml(expected_output), process(input)
147
194
  end
@@ -149,15 +196,15 @@ DOCX
149
196
  def test_convert_sup_tags_inside_p
150
197
  input = '<p>Lorem&nbsp;<sup>ipsum dolor</sup>&nbsp;sit amet</p>'
151
198
  expected_output = <<-DOCX.strip
152
- <w:p>
153
- <w:pPr><w:pStyle w:val="Paragraph" /></w:pPr>
154
- <w:r><w:t xml:space="preserve">Lorem </w:t></w:r>
155
- <w:r>
156
- <w:rPr><w:vertAlign w:val="superscript" /></w:rPr>
157
- <w:t xml:space="preserve">ipsum dolor</w:t>
158
- </w:r>
159
- <w:r><w:t xml:space="preserve"> sit amet</w:t></w:r>
160
- </w:p>
199
+ <w:p>
200
+ <w:pPr><w:pStyle w:val="Paragraph" /></w:pPr>
201
+ <w:r><w:t xml:space="preserve">Lorem </w:t></w:r>
202
+ <w:r>
203
+ <w:rPr><w:vertAlign w:val="superscript" /></w:rPr>
204
+ <w:t xml:space="preserve">ipsum dolor</w:t>
205
+ </w:r>
206
+ <w:r><w:t xml:space="preserve"> sit amet</w:t></w:r>
207
+ </w:p>
161
208
  DOCX
162
209
  assert_equal normalize_wordml(expected_output), process(input)
163
210
  end
@@ -165,153 +212,150 @@ DOCX
165
212
  def test_convert_br_tags_inside_strong
166
213
  input = '<div><strong><br />Lorem ipsum<br />dolor sit amet</strong></div>'
167
214
  expected_output = <<-DOCX
168
- <w:p>
169
- <w:pPr><w:pStyle w:val="Normal" /></w:pPr>
170
- <w:r><w:br/></w:r>
171
- <w:r>
172
- <w:rPr><w:b /></w:rPr>
173
- <w:t xml:space="preserve">Lorem ipsum</w:t></w:r>
174
- <w:r><w:br/></w:r>
175
- <w:r>
176
- <w:rPr><w:b /></w:rPr>
177
- <w:t xml:space="preserve">dolor sit amet</w:t>
178
- </w:r>
179
- </w:p>
180
- DOCX
215
+ <w:p>
216
+ <w:pPr><w:pStyle w:val="Normal" /></w:pPr>
217
+ <w:r><w:br/></w:r>
218
+ <w:r>
219
+ <w:rPr><w:b /></w:rPr>
220
+ <w:t xml:space="preserve">Lorem ipsum</w:t></w:r>
221
+ <w:r><w:br/></w:r>
222
+ <w:r>
223
+ <w:rPr><w:b /></w:rPr>
224
+ <w:t xml:space="preserve">dolor sit amet</w:t>
225
+ </w:r>
226
+ </w:p>
227
+ DOCX
181
228
  assert_equal normalize_wordml(expected_output), process(input)
182
229
  end
183
230
 
184
231
  def test_convert_h1
185
232
  input = '<h1>Lorem ipsum dolor</h1>'
186
- expected_output = <<-DOCX.strip
187
- <w:p>
188
- <w:pPr><w:pStyle w:val="Heading1" /></w:pPr>
189
- <w:r><w:t xml:space="preserve">Lorem ipsum dolor</w:t></w:r>
190
- </w:p>
191
- DOCX
233
+ expected_output = <<-DOCX.strip
234
+ <w:p>
235
+ <w:pPr><w:pStyle w:val="Heading1" /></w:pPr>
236
+ <w:r><w:t xml:space="preserve">Lorem ipsum dolor</w:t></w:r>
237
+ </w:p>
238
+ DOCX
192
239
  assert_equal normalize_wordml(expected_output), process(input)
193
240
  end
194
241
 
195
242
  def test_unorderd_lists
196
243
  input = '<ul><li>Lorem</li><li>ipsum</li><li>dolor</li></ul>'
197
244
  expected_output = <<-DOCX.strip
198
- <w:p>
199
- <w:pPr>
200
- <w:pStyle w:val="ListBullet" />
201
- <w:numPr>
202
- <w:ilvl w:val="0" />
203
- <w:numId w:val="1001" />
204
- </w:numPr>
205
- </w:pPr>
206
- <w:r><w:t xml:space="preserve">Lorem</w:t></w:r>
207
- </w:p>
245
+ <w:p>
246
+ <w:pPr>
247
+ <w:pStyle w:val="ListBullet" />
248
+ <w:numPr>
249
+ <w:ilvl w:val="0" />
250
+ <w:numId w:val="1001" />
251
+ </w:numPr>
252
+ </w:pPr>
253
+ <w:r><w:t xml:space="preserve">Lorem</w:t></w:r>
254
+ </w:p>
208
255
 
209
- <w:p>
210
- <w:pPr>
211
- <w:pStyle w:val="ListBullet" />
212
- <w:numPr>
213
- <w:ilvl w:val="0" />
214
- <w:numId w:val="1001" />
215
- </w:numPr>
216
- </w:pPr>
217
- <w:r><w:t xml:space="preserve">ipsum</w:t></w:r>
218
- </w:p>
256
+ <w:p>
257
+ <w:pPr>
258
+ <w:pStyle w:val="ListBullet" />
259
+ <w:numPr>
260
+ <w:ilvl w:val="0" />
261
+ <w:numId w:val="1001" />
262
+ </w:numPr>
263
+ </w:pPr>
264
+ <w:r><w:t xml:space="preserve">ipsum</w:t></w:r>
265
+ </w:p>
219
266
 
220
- <w:p>
221
- <w:pPr>
222
- <w:pStyle w:val="ListBullet" />
223
- <w:numPr>
224
- <w:ilvl w:val="0" />
225
- <w:numId w:val="1001" />
226
- </w:numPr>
227
- </w:pPr>
228
- <w:r><w:t xml:space="preserve">dolor</w:t></w:r>
229
- </w:p>
230
- DOCX
267
+ <w:p>
268
+ <w:pPr>
269
+ <w:pStyle w:val="ListBullet" />
270
+ <w:numPr>
271
+ <w:ilvl w:val="0" />
272
+ <w:numId w:val="1001" />
273
+ </w:numPr>
274
+ </w:pPr>
275
+ <w:r><w:t xml:space="preserve">dolor</w:t></w:r>
276
+ </w:p>
277
+ DOCX
231
278
  assert_equal normalize_wordml(expected_output), process(input)
232
-
233
279
  assert_equal [Sablon::Numbering::Definition.new(1001, 'ListBullet')], @numbering.definitions
234
280
  end
235
281
 
236
282
  def test_ordered_lists
237
283
  input = '<ol><li>Lorem</li><li>ipsum</li><li>dolor</li></ol>'
238
284
  expected_output = <<-DOCX.strip
239
- <w:p>
240
- <w:pPr>
241
- <w:pStyle w:val="ListNumber" />
242
- <w:numPr>
243
- <w:ilvl w:val="0" />
244
- <w:numId w:val="1001" />
245
- </w:numPr>
246
- </w:pPr>
247
- <w:r><w:t xml:space="preserve">Lorem</w:t></w:r>
248
- </w:p>
285
+ <w:p>
286
+ <w:pPr>
287
+ <w:pStyle w:val="ListNumber" />
288
+ <w:numPr>
289
+ <w:ilvl w:val="0" />
290
+ <w:numId w:val="1001" />
291
+ </w:numPr>
292
+ </w:pPr>
293
+ <w:r><w:t xml:space="preserve">Lorem</w:t></w:r>
294
+ </w:p>
249
295
 
250
- <w:p>
251
- <w:pPr>
252
- <w:pStyle w:val="ListNumber" />
253
- <w:numPr>
254
- <w:ilvl w:val="0" />
255
- <w:numId w:val="1001" />
256
- </w:numPr>
257
- </w:pPr>
258
- <w:r><w:t xml:space="preserve">ipsum</w:t></w:r>
259
- </w:p>
296
+ <w:p>
297
+ <w:pPr>
298
+ <w:pStyle w:val="ListNumber" />
299
+ <w:numPr>
300
+ <w:ilvl w:val="0" />
301
+ <w:numId w:val="1001" />
302
+ </w:numPr>
303
+ </w:pPr>
304
+ <w:r><w:t xml:space="preserve">ipsum</w:t></w:r>
305
+ </w:p>
260
306
 
261
- <w:p>
262
- <w:pPr>
263
- <w:pStyle w:val="ListNumber" />
264
- <w:numPr>
265
- <w:ilvl w:val="0" />
266
- <w:numId w:val="1001" />
267
- </w:numPr>
268
- </w:pPr>
269
- <w:r><w:t xml:space="preserve">dolor</w:t></w:r>
270
- </w:p>
271
- DOCX
307
+ <w:p>
308
+ <w:pPr>
309
+ <w:pStyle w:val="ListNumber" />
310
+ <w:numPr>
311
+ <w:ilvl w:val="0" />
312
+ <w:numId w:val="1001" />
313
+ </w:numPr>
314
+ </w:pPr>
315
+ <w:r><w:t xml:space="preserve">dolor</w:t></w:r>
316
+ </w:p>
317
+ DOCX
272
318
  assert_equal normalize_wordml(expected_output), process(input)
273
-
274
319
  assert_equal [Sablon::Numbering::Definition.new(1001, 'ListNumber')], @numbering.definitions
275
320
  end
276
321
 
277
322
  def test_mixed_lists
278
323
  input = '<ol><li>Lorem</li></ol><ul><li>ipsum</li></ul><ol><li>dolor</li></ol>'
279
324
  expected_output = <<-DOCX.strip
280
- <w:p>
281
- <w:pPr>
282
- <w:pStyle w:val="ListNumber" />
283
- <w:numPr>
284
- <w:ilvl w:val="0" />
285
- <w:numId w:val="1001" />
286
- </w:numPr>
287
- </w:pPr>
288
- <w:r><w:t xml:space=\"preserve\">Lorem</w:t></w:r>
289
- </w:p>
325
+ <w:p>
326
+ <w:pPr>
327
+ <w:pStyle w:val="ListNumber" />
328
+ <w:numPr>
329
+ <w:ilvl w:val="0" />
330
+ <w:numId w:val="1001" />
331
+ </w:numPr>
332
+ </w:pPr>
333
+ <w:r><w:t xml:space=\"preserve\">Lorem</w:t></w:r>
334
+ </w:p>
290
335
 
291
- <w:p>
292
- <w:pPr>
293
- <w:pStyle w:val="ListBullet" />
294
- <w:numPr>
295
- <w:ilvl w:val="0" />
296
- <w:numId w:val="1002" />
297
- </w:numPr>
298
- </w:pPr>
299
- <w:r><w:t xml:space="preserve">ipsum</w:t></w:r>
300
- </w:p>
336
+ <w:p>
337
+ <w:pPr>
338
+ <w:pStyle w:val="ListBullet" />
339
+ <w:numPr>
340
+ <w:ilvl w:val="0" />
341
+ <w:numId w:val="1002" />
342
+ </w:numPr>
343
+ </w:pPr>
344
+ <w:r><w:t xml:space="preserve">ipsum</w:t></w:r>
345
+ </w:p>
301
346
 
302
- <w:p>
303
- <w:pPr>
304
- <w:pStyle w:val="ListNumber" />
305
- <w:numPr>
306
- <w:ilvl w:val="0" />
307
- <w:numId w:val="1003" />
308
- </w:numPr>
309
- </w:pPr>
310
- <w:r><w:t xml:space="preserve">dolor</w:t></w:r>
311
- </w:p>
312
- DOCX
347
+ <w:p>
348
+ <w:pPr>
349
+ <w:pStyle w:val="ListNumber" />
350
+ <w:numPr>
351
+ <w:ilvl w:val="0" />
352
+ <w:numId w:val="1003" />
353
+ </w:numPr>
354
+ </w:pPr>
355
+ <w:r><w:t xml:space="preserve">dolor</w:t></w:r>
356
+ </w:p>
357
+ DOCX
313
358
  assert_equal normalize_wordml(expected_output), process(input)
314
-
315
359
  assert_equal [Sablon::Numbering::Definition.new(1001, 'ListNumber'),
316
360
  Sablon::Numbering::Definition.new(1002, 'ListBullet'),
317
361
  Sablon::Numbering::Definition.new(1003, 'ListNumber')], @numbering.definitions
@@ -320,354 +364,216 @@ DOCX
320
364
  def test_nested_unordered_lists
321
365
  input = '<ul><li>Lorem<ul><li>ipsum<ul><li>dolor</li></ul></li></ul></li></ul>'
322
366
  expected_output = <<-DOCX.strip
323
- <w:p>
324
- <w:pPr>
325
- <w:pStyle w:val="ListBullet" />
326
- <w:numPr>
327
- <w:ilvl w:val="0" />
328
- <w:numId w:val="1001" />
329
- </w:numPr>
330
- </w:pPr>
331
- <w:r><w:t xml:space="preserve">Lorem</w:t></w:r>
332
- </w:p>
367
+ <w:p>
368
+ <w:pPr>
369
+ <w:pStyle w:val="ListBullet" />
370
+ <w:numPr>
371
+ <w:ilvl w:val="0" />
372
+ <w:numId w:val="1001" />
373
+ </w:numPr>
374
+ </w:pPr>
375
+ <w:r><w:t xml:space="preserve">Lorem</w:t></w:r>
376
+ </w:p>
333
377
 
334
- <w:p>
335
- <w:pPr>
336
- <w:pStyle w:val="ListBullet" />
337
- <w:numPr>
338
- <w:ilvl w:val="1" />
339
- <w:numId w:val="1001" />
340
- </w:numPr>
341
- </w:pPr>
342
- <w:r><w:t xml:space="preserve">ipsum</w:t></w:r>
343
- </w:p>
378
+ <w:p>
379
+ <w:pPr>
380
+ <w:pStyle w:val="ListBullet" />
381
+ <w:numPr>
382
+ <w:ilvl w:val="1" />
383
+ <w:numId w:val="1001" />
384
+ </w:numPr>
385
+ </w:pPr>
386
+ <w:r><w:t xml:space="preserve">ipsum</w:t></w:r>
387
+ </w:p>
344
388
 
345
- <w:p>
346
- <w:pPr>
347
- <w:pStyle w:val="ListBullet" />
348
- <w:numPr>
349
- <w:ilvl w:val="2" />
350
- <w:numId w:val="1001" />
351
- </w:numPr>
352
- </w:pPr>
353
- <w:r><w:t xml:space="preserve">dolor</w:t></w:r>
354
- </w:p>
355
- DOCX
389
+ <w:p>
390
+ <w:pPr>
391
+ <w:pStyle w:val="ListBullet" />
392
+ <w:numPr>
393
+ <w:ilvl w:val="2" />
394
+ <w:numId w:val="1001" />
395
+ </w:numPr>
396
+ </w:pPr>
397
+ <w:r><w:t xml:space="preserve">dolor</w:t></w:r>
398
+ </w:p>
399
+ DOCX
356
400
  assert_equal normalize_wordml(expected_output), process(input)
357
-
358
401
  assert_equal [Sablon::Numbering::Definition.new(1001, 'ListBullet')], @numbering.definitions
359
402
  end
360
403
 
361
- def test_unknown_tag
362
- e = assert_raises ArgumentError do
363
- process('<badtag/>')
404
+ def test_anchor_tag
405
+ uid_generator = UIDTestGenerator.new
406
+ input = '<p><a href="www.github.com">GitHub</a></p>'
407
+ SecureRandom.stub(:uuid, uid_generator.method(:new_uid)) do |secure_random_instance|
408
+ expected_output = <<-DOCX.strip
409
+ <w:p>
410
+ <w:pPr>
411
+ <w:pStyle w:val="Paragraph" />
412
+ </w:pPr>
413
+ <w:hyperlink r:id="rId#{secure_random_instance.uuid}">
414
+ <w:r>
415
+ <w:rPr>
416
+ <w:rStyle w:val="Hyperlink" />
417
+ </w:rPr>
418
+ <w:t xml:space="preserve">GitHub</w:t>
419
+ </w:r>
420
+ </w:hyperlink>
421
+ </w:p>
422
+ DOCX
423
+ uid_generator.reset
424
+ assert_equal normalize_wordml(expected_output), process(input)
364
425
  end
365
- assert_match(/Don't know how to handle HTML tag:/, e.message)
366
- end
367
-
368
- private
369
-
370
- def process(input)
371
- @converter.process(input, @env)
372
- end
373
-
374
- def normalize_wordml(wordml)
375
- wordml.gsub(/^\s+/, '').tr("\n", '')
376
426
  end
377
- end
378
-
379
- class HTMLConverterStyleTest < Sablon::TestCase
380
- def setup
381
- super
382
- @env = Sablon::Environment.new(nil)
383
- @converter = Sablon::HTMLConverter.new
384
- end
385
-
386
- # testing direct CSS style -> WordML conversion for paragraphs
387
-
388
- def test_paragraph_with_background_color
389
- input = '<p style="background-color: #123456"></p>'
390
- expected_output = para_with_ppr('<w:shd w:val="clear" w:fill="123456" />')
391
- assert_equal normalize_wordml(expected_output), process(input)
392
- end
393
-
394
- def test_paragraph_with_borders
395
- # Basic single line black border
396
- input = '<p style="border: 1px"></p>'
397
- ppr = <<-DOCX.strip
398
- <w:pBdr>
399
- <w:top w:sz="2" w:val="single" w:color="000000" />
400
- <w:bottom w:sz="2" w:val="single" w:color="000000" />
401
- <w:left w:sz="2" w:val="single" w:color="000000" />
402
- <w:right w:sz="2" w:val="single" w:color="000000" />
403
- </w:pBdr>
404
- DOCX
405
- expected_output = para_with_ppr(ppr)
406
- assert_equal normalize_wordml(expected_output), process(input)
407
- # border with a line style
408
- input = '<p style="border: 1px wavy"></p>'
409
- ppr = <<-DOCX.strip
410
- <w:pBdr>
411
- <w:top w:sz="2" w:val="wavy" w:color="000000" />
412
- <w:bottom w:sz="2" w:val="wavy" w:color="000000" />
413
- <w:left w:sz="2" w:val="wavy" w:color="000000" />
414
- <w:right w:sz="2" w:val="wavy" w:color="000000" />
415
- </w:pBdr>
416
- DOCX
417
- expected_output = para_with_ppr(ppr)
418
- assert_equal normalize_wordml(expected_output), process(input)
419
- # border with line style and color
420
- input = '<p style="border: 1px wavy #123456"></p>'
421
- ppr = <<-DOCX.strip
422
- <w:pBdr>
423
- <w:top w:sz="2" w:val="wavy" w:color="123456" />
424
- <w:bottom w:sz="2" w:val="wavy" w:color="123456" />
425
- <w:left w:sz="2" w:val="wavy" w:color="123456" />
426
- <w:right w:sz="2" w:val="wavy" w:color="123456" />
427
- </w:pBdr>
428
- DOCX
429
- expected_output = para_with_ppr(ppr)
430
- assert_equal normalize_wordml(expected_output), process(input)
431
- end
432
-
433
- def test_paragraph_with_text_align
434
- input = '<p style="text-align: both"></p>'
435
- expected_output = para_with_ppr('<w:jc w:val="both" />')
436
- assert_equal normalize_wordml(expected_output), process(input)
437
- end
438
-
439
- def test_paragraph_with_vertical_align
440
- input = '<p style="vertical-align: baseline"></p>'
441
- expected_output = para_with_ppr('<w:textAlignment w:val="baseline" />')
442
- assert_equal normalize_wordml(expected_output), process(input)
443
- end
444
-
445
- def test_paragraph_with_unsupported_property
446
- input = '<p style="unsupported: true"></p>'
447
- expected_output = para_with_ppr('')
448
- assert_equal normalize_wordml(expected_output), process(input)
449
- end
450
-
451
- def test_run_with_background_color
452
- input = '<p><span style="background-color: #123456">test</span></p>'
453
- expected_output = run_with_rpr('<w:shd w:val="clear" w:fill="123456" />')
454
- assert_equal normalize_wordml(expected_output), process(input)
455
- end
456
-
457
- def test_run_with_color
458
- input = '<p><span style="color: #123456">test</span></p>'
459
- expected_output = run_with_rpr('<w:color w:val="123456" />')
460
- assert_equal normalize_wordml(expected_output), process(input)
461
- end
462
-
463
- def test_run_with_font_size
464
- input = '<p><span style="font-size: 20">test</span></p>'
465
- expected_output = run_with_rpr('<w:sz w:val="40" />')
466
- assert_equal normalize_wordml(expected_output), process(input)
467
-
468
- # test that non-numeric are ignored
469
- input = '<p><span style="font-size: 20pts">test</span></p>'
470
- assert_equal normalize_wordml(expected_output), process(input)
471
-
472
- # test that floats round up
473
- input = '<p><span style="font-size: 19.1pts">test</span></p>'
474
- assert_equal normalize_wordml(expected_output), process(input)
475
- end
476
-
477
- def test_run_with_font_style
478
- input = '<p><span style="font-style: bold">test</span></p>'
479
- expected_output = run_with_rpr('<w:b />')
480
- assert_equal normalize_wordml(expected_output), process(input)
481
427
 
482
- # test that non-numeric are ignored
483
- input = '<p><span style="font-style: italic">test</span></p>'
484
- expected_output = run_with_rpr('<w:i />')
428
+ def test_table_tag
429
+ input = '<table></table>'
430
+ expected_output = '<w:tbl></w:tbl>'
485
431
  assert_equal normalize_wordml(expected_output), process(input)
486
432
  end
487
433
 
488
- def test_run_with_font_wieght
489
- input = '<p><span style="font-weight: bold">test</span></p>'
490
- expected_output = run_with_rpr('<w:b />')
434
+ def test_table_with_table_row
435
+ # This would generate an invalid docu
436
+ input = '<table><tr></tr><tr></tr></table>'
437
+ expected_output = '<w:tbl><w:tr></w:tr><w:tr></w:tr></w:tbl>'
491
438
  assert_equal normalize_wordml(expected_output), process(input)
492
439
  end
493
440
 
494
- def test_run_with_text_decoration
495
- # testing underline configurations
496
- input = '<p><span style="text-decoration: underline">test</span></p>'
497
- expected_output = run_with_rpr('<w:u w:val="single" />')
498
- assert_equal normalize_wordml(expected_output), process(input)
499
-
500
- input = '<p><span style="text-decoration: underline dash">test</span></p>'
501
- expected_output = run_with_rpr('<w:u w:val="dash" w:color="auto" />')
502
- assert_equal normalize_wordml(expected_output), process(input)
503
-
504
- input = '<p><span style="text-decoration: underline dash #123456">test</span></p>'
505
- expected_output = run_with_rpr('<w:u w:val="dash" w:color="123456" />')
506
- assert_equal normalize_wordml(expected_output), process(input)
507
-
508
- # testing line-through
509
- input = '<p><span style="text-decoration: line-through">test</span></p>'
510
- expected_output = run_with_rpr('<w:strike w:val="true" />')
511
- assert_equal normalize_wordml(expected_output), process(input)
512
-
513
- # testing that unsupported values are passed through as a toggle
514
- input = '<p><span style="text-decoration: strike">test</span></p>'
515
- expected_output = run_with_rpr('<w:strike w:val="true" />')
516
- assert_equal normalize_wordml(expected_output), process(input)
517
-
518
- input = '<p><span style="text-decoration: emboss">test</span></p>'
519
- expected_output = run_with_rpr('<w:emboss w:val="true" />')
520
- assert_equal normalize_wordml(expected_output), process(input)
521
- end
522
-
523
- def test_run_with_vertical_align
524
- input = '<p><span style="vertical-align: subscript">test</span></p>'
525
- expected_output = run_with_rpr('<w:vertAlign w:val="subscript" />')
526
- assert_equal normalize_wordml(expected_output), process(input)
527
-
528
- input = '<p><span style="vertical-align: superscript">test</span></p>'
529
- expected_output = run_with_rpr('<w:vertAlign w:val="superscript" />')
530
- assert_equal normalize_wordml(expected_output), process(input)
531
- end
532
-
533
- def test_run_with_unsupported_property
534
- input = '<p><span style="unsupported: true">test</span></p>'
535
- expected_output = '<w:p><w:pPr><w:pStyle w:val="Paragraph" /></w:pPr><w:r><w:t xml:space="preserve">test</w:t></w:r></w:p>'
441
+ def test_table_with_table_row_and_table_cell
442
+ # This would generate an invalid docu
443
+ input = '<table><tr><td>Content</td></tr></table>'
444
+ expected_output = <<-DOCX.strip
445
+ <w:tbl>
446
+ <w:tr>
447
+ <w:tc>
448
+ <w:p>
449
+ <w:pPr><w:pStyle w:val="Paragraph" /></w:pPr>
450
+ <w:r><w:t xml:space="preserve">Content</w:t></w:r>
451
+ </w:p>
452
+ </w:tc>
453
+ </w:tr>
454
+ </w:tbl>
455
+ DOCX
536
456
  assert_equal normalize_wordml(expected_output), process(input)
537
457
  end
538
458
 
539
- # tests with nested runs and styles
540
-
541
- def test_paragraph_props_passed_to_runs
542
- input = '<p style="color: #123456"><b>Lorem</b><span>ipsum</span></p>'
459
+ def test_table_with_table_row_and_table_header_cell
460
+ # This would generate an invalid docu
461
+ input = '<table><tr><th>Content</th></tr></table>'
543
462
  expected_output = <<-DOCX.strip
544
- <w:p>
545
- <w:pPr>
546
- <w:pStyle w:val="Paragraph" />
547
- </w:pPr>
548
- <w:r>
549
- <w:rPr>
550
- <w:color w:val="123456" />
551
- <w:b />
552
- </w:rPr>
553
- <w:t xml:space="preserve">Lorem</w:t>
554
- </w:r>
555
- <w:r>
556
- <w:rPr>
557
- <w:color w:val="123456" />
558
- </w:rPr>
559
- <w:t xml:space="preserve">ipsum</w:t>
560
- </w:r>
561
- </w:p>
463
+ <w:tbl>
464
+ <w:tr>
465
+ <w:tc>
466
+ <w:p>
467
+ <w:pPr>
468
+ <w:jc w:val="center" />
469
+ <w:pStyle w:val="Paragraph" />
470
+ </w:pPr>
471
+ <w:r>
472
+ <w:rPr><w:b /></w:rPr>
473
+ <w:t xml:space="preserve">Content</w:t>
474
+ </w:r>
475
+ </w:p>
476
+ </w:tc>
477
+ </w:tr>
478
+ </w:tbl>
562
479
  DOCX
563
480
  assert_equal normalize_wordml(expected_output), process(input)
564
481
  end
565
482
 
566
- def test_run_prop_override_paragraph_prop
567
- input = '<p style="text-align: center; color: #FF0000">Lorem<span style="color: blue;">ipsum</span></p>'
483
+ def test_table_with_table_row_table_header_cell_and_caption
484
+ # This would generate an invalid docu
485
+ input = '<table><caption>Table Title</caption><tr><th>Content</th></tr></table>'
568
486
  expected_output = <<-DOCX.strip
569
487
  <w:p>
570
488
  <w:pPr>
571
- <w:pStyle w:val="Paragraph" />
572
- <w:jc w:val="center" />
489
+ <w:pStyle w:val="Caption" />
573
490
  </w:pPr>
574
491
  <w:r>
575
- <w:rPr>
576
- <w:color w:val="FF0000" />
577
- </w:rPr>
578
- <w:t xml:space="preserve">Lorem</w:t>
579
- </w:r>
580
- <w:r>
581
- <w:rPr>
582
- <w:color w:val="blue" />
583
- </w:rPr>
584
- <w:t xml:space="preserve">ipsum</w:t>
492
+ <w:t xml:space="preserve">Table Title</w:t>
585
493
  </w:r>
586
494
  </w:p>
495
+ <w:tbl>
496
+ <w:tr>
497
+ <w:tc>
498
+ <w:p>
499
+ <w:pPr>
500
+ <w:jc w:val="center" />
501
+ <w:pStyle w:val="Paragraph" />
502
+ </w:pPr>
503
+ <w:r>
504
+ <w:rPr><w:b /></w:rPr>
505
+ <w:t xml:space="preserve">Content</w:t>
506
+ </w:r>
507
+ </w:p>
508
+ </w:tc>
509
+ </w:tr>
510
+ </w:tbl>
587
511
  DOCX
588
512
  assert_equal normalize_wordml(expected_output), process(input)
589
513
  end
590
514
 
591
- def test_inline_style_overrides_tag_style
592
- # Note: a toggle property can not be removed once it becomes a symbol
593
- # unless there is a specific CSS style that will set it to false. This
594
- # is because CSS styles can only override parent properties not remove them.
595
- input = '<p><u style="text-decoration: underline wavyDouble">test</u></p>'
596
- expected_output = run_with_rpr('<w:u w:val="wavyDouble" w:color="auto" />')
597
- assert_equal normalize_wordml(expected_output), process(input)
598
- end
599
-
600
- def test_conversion_of_a_registered_tag_without_ast_class
601
- # This registers a new tag with the configuration object and then trys
602
- # to convert it
603
- Sablon.configure do |config|
604
- config.register_html_tag(:bgcyan, :inline, properties: { 'highlight' => { val: 'cyan' } })
605
- end
606
- #
607
- input = '<p><bgcyan>test</bgcyan></p>'
608
- expected_output = run_with_rpr('<w:highlight w:val="cyan" />')
609
- assert_equal normalize_wordml(expected_output), process(input)
610
-
611
- # remove the tag to avoid any accidental side effects
612
- Sablon.configure do |config|
613
- config.remove_html_tag(:bgcyan)
614
- end
615
- end
616
-
617
- def test_conversion_of_a_registered_tag_with_ast_class
618
- Sablon.configure do |config|
619
- # create the AST class and then pass it onto the register tag method
620
- ast_class = Class.new(Sablon::HTMLConverter::Node) do
621
- def self.name
622
- 'TestInstr'
623
- end
624
-
625
- def initialize(_env, node, _properties)
626
- @content = node.text
627
- end
628
-
629
- def inspect
630
- @content
631
- end
632
-
633
- def to_docx
634
- "<w:instrText xml:space=\"preserve\"> #{@content} </w:instrText>"
635
- end
636
- end
637
- #
638
- config.register_html_tag(:test_instr, :inline, ast_class: ast_class)
639
- end
640
- #
641
- input = '<p><test_instr>test</test_instr></p>'
515
+ def test_table_with_table_row_table_header_cell_thead_tbody_and_tfoot
516
+ # This would generate an invalid docu
517
+ input = <<-HTML.strip
518
+ <table>
519
+ <thead><tr><th>Head</th></tr></thead>
520
+ <tbody><tr><td>Body</td></tr></tbody>
521
+ <tfoot><tr><td>Foot</td></tr></tfoot>
522
+ </table>
523
+ HTML
642
524
  expected_output = <<-DOCX.strip
643
- <w:p>
644
- <w:pPr>
645
- <w:pStyle w:val="Paragraph" />
646
- </w:pPr>
647
- <w:instrText xml:space="preserve"> test </w:instrText>
648
- </w:p>
525
+ <w:tbl>
526
+ <w:tr>
527
+ <w:trPr>
528
+ <w:tblHeader />
529
+ </w:trPr>
530
+ <w:tc>
531
+ <w:p>
532
+ <w:pPr>
533
+ <w:jc w:val="center" />
534
+ <w:pStyle w:val="Paragraph" />
535
+ </w:pPr>
536
+ <w:r>
537
+ <w:rPr><w:b /></w:rPr>
538
+ <w:t xml:space="preserve">Head</w:t>
539
+ </w:r>
540
+ </w:p>
541
+ </w:tc>
542
+ </w:tr>
543
+ <w:tr>
544
+ <w:tc>
545
+ <w:p>
546
+ <w:pPr>
547
+ <w:pStyle w:val="Paragraph" />
548
+ </w:pPr>
549
+ <w:r>
550
+ <w:t xml:space="preserve">Body</w:t>
551
+ </w:r>
552
+ </w:p>
553
+ </w:tc>
554
+ </w:tr>
555
+ <w:tr>
556
+ <w:tc>
557
+ <w:p>
558
+ <w:pPr>
559
+ <w:pStyle w:val="Paragraph" />
560
+ </w:pPr>
561
+ <w:r>
562
+ <w:t xml:space="preserve">Foot</w:t>
563
+ </w:r>
564
+ </w:p>
565
+ </w:tc>
566
+ </w:tr>
567
+ </w:tbl>
649
568
  DOCX
650
569
  assert_equal normalize_wordml(expected_output), process(input)
651
-
652
- # remove the tag to avoid any accidental side effects
653
- Sablon.configure do |config|
654
- config.remove_html_tag(:test_instr)
655
- end
656
570
  end
657
571
 
658
- def test_conversion_of_registered_style_attribute
659
- Sablon.configure do |config|
660
- converter = ->(v) { return :highlight, v }
661
- config.register_style_converter(:run, 'test-highlight', converter)
662
- end
663
- #
664
- input = '<p><span style="test-highlight: green">test</span></p>'
665
- expected_output = run_with_rpr('<w:highlight w:val="green" />')
666
- assert_equal normalize_wordml(expected_output), process(input)
667
- #
668
- Sablon.configure do |config|
669
- config.remove_style_converter(:run, 'test-highlight')
572
+ def test_unknown_tag
573
+ e = assert_raises ArgumentError do
574
+ process('<badtag/>')
670
575
  end
576
+ assert_match(/Don't know how to handle HTML tag:/, e.message)
671
577
  end
672
578
 
673
579
  private
@@ -676,28 +582,6 @@ class HTMLConverterStyleTest < Sablon::TestCase
676
582
  @converter.process(input, @env)
677
583
  end
678
584
 
679
- def para_with_ppr(ppr_str)
680
- para_str = '<w:p><w:pPr><w:pStyle w:val="Paragraph" />%s</w:pPr></w:p>'
681
- format(para_str, ppr_str)
682
- end
683
-
684
- def run_with_rpr(rpr_str)
685
- para_str = <<-DOCX.strip
686
- <w:p>
687
- <w:pPr>
688
- <w:pStyle w:val="Paragraph" />
689
- </w:pPr>
690
- <w:r>
691
- <w:rPr>
692
- %s
693
- </w:rPr>
694
- <w:t xml:space="preserve">test</w:t>
695
- </w:r>
696
- </w:p>
697
- DOCX
698
- format(para_str, rpr_str)
699
- end
700
-
701
585
  def normalize_wordml(wordml)
702
586
  wordml.gsub(/^\s+/, '').tr("\n", '')
703
587
  end