@@ -274,20 +274,139 @@ def get_heading_tag(self, paragraph):
274
274
return HtmlTag (tag , id = paragraph .bookmark_name )
275
275
return HtmlTag (tag )
276
276
277
+ def export_run (self , run ):
278
+ results = super (PyDocXHTMLExporter , self ).export_run (run )
279
+
280
+ for result in self .export_borders (run , results , tag_name = 'span' ):
281
+ yield result
282
+
277
283
def export_paragraph (self , paragraph ):
278
284
results = super (PyDocXHTMLExporter , self ).export_paragraph (paragraph )
279
285
280
286
results = is_not_empty_and_not_only_whitespace (results )
281
- if results is None :
287
+
288
+ # TODO@botzill In PR#234 we render empty paragraphs properly so
289
+ # we don't need this check anymore. Adding for now and to be removed when merging
290
+ if results is None and not paragraph .has_border_properties :
282
291
return
283
292
284
293
tag = self .get_paragraph_tag (paragraph )
285
294
if tag :
286
295
results = tag .apply (results )
287
296
297
+ for tag in self .export_borders (paragraph , results , tag_name = 'div' ):
298
+ yield tag
299
+
300
+ def export_close_paragraph_border (self ):
301
+ if self .current_border_item .get ('Paragraph' ):
302
+ yield HtmlTag ('div' , closed = True )
303
+ self .current_border_item ['Paragraph' ] = None
304
+
305
+ def export_borders (self , item , results , tag_name = 'div' ):
306
+ if self .first_pass :
307
+ for result in results :
308
+ yield result
309
+ return
310
+
311
+ # For now we have here Paragraph and Run
312
+ item_name = item .__class__ .__name__
313
+ item_is_run = isinstance (item , wordprocessing .Run )
314
+ item_is_paragraph = isinstance (item , wordprocessing .Paragraph )
315
+
316
+ prev_borders_properties = None
317
+ border_properties = None
318
+ current_border_item = self .current_border_item .get (item_name )
319
+ if current_border_item :
320
+ prev_borders_properties = current_border_item .\
321
+ effective_properties .border_properties
322
+
323
+ last_item = False
324
+ close_border = True
325
+
326
+ def current_item_is_last_child (children , child_type ):
327
+ for p_child in reversed (children ):
328
+ if isinstance (p_child , child_type ):
329
+ return p_child == item
330
+ return False
331
+
332
+ def is_last_item ():
333
+ if item_is_paragraph :
334
+ if isinstance (item .parent , wordprocessing .TableCell ):
335
+ return current_item_is_last_child (
336
+ item .parent .children , wordprocessing .Paragraph )
337
+ elif item == self .last_paragraph :
338
+ return True
339
+ elif item_is_run :
340
+ # Check if current item is the last Run item from paragraph children
341
+ return current_item_is_last_child (item .parent .children , wordprocessing .Run )
342
+
343
+ return False
344
+
345
+ if item .effective_properties :
346
+ border_properties = item .effective_properties .border_properties
347
+ if border_properties :
348
+ last_item = is_last_item ()
349
+ close_border = False
350
+ run_has_different_parent = False
351
+
352
+ # If run is from different paragraph then we may need to draw separate border
353
+ # even if border properties are the same
354
+ if item_is_run and current_border_item :
355
+ if current_border_item .parent != item .parent :
356
+ run_has_different_parent = True
357
+
358
+ if border_properties != prev_borders_properties or run_has_different_parent :
359
+ if prev_borders_properties is not None :
360
+ # We have a previous border tag opened, so need to close it
361
+ yield HtmlTag (tag_name , closed = True )
362
+
363
+ # Open a new tag for the new border and include all the properties
364
+ border_attrs = self .get_borders_property (border_properties )
365
+ yield HtmlTag (tag_name , closed = False , ** border_attrs )
366
+
367
+ self .current_border_item [item_name ] = item
368
+ else :
369
+ if prev_borders_properties is not None and \
370
+ getattr (border_properties , 'between' , None ):
371
+ # Render border between items
372
+ border_attrs = self .get_borders_property (
373
+ border_properties , only_between = True )
374
+
375
+ yield HtmlTag (tag_name , ** border_attrs )
376
+ yield HtmlTag (tag_name , closed = True )
377
+
378
+ if close_border and prev_borders_properties is not None :
379
+ # At this stage we need to make sure that if there is an previously open tag
380
+ # about border we need to close it
381
+ yield HtmlTag (tag_name , closed = True )
382
+ self .current_border_item [item_name ] = None
383
+
384
+ # All the inner items inside border tag are issued here
288
385
for result in results :
289
386
yield result
290
387
388
+ if border_properties and last_item :
389
+ # If the item with border is the last one we need to make sure that we close the
390
+ # tag
391
+ yield HtmlTag (tag_name , closed = True )
392
+ self .current_border_item [item_name ] = None
393
+
394
+ def get_borders_property (self , border_properties , only_between = False ):
395
+ attrs = {}
396
+ style = {}
397
+
398
+ if only_between :
399
+ style .update (border_properties .get_between_border_style ())
400
+ else :
401
+ style .update (border_properties .get_padding_style ())
402
+ style .update (border_properties .get_border_style ())
403
+ style .update (border_properties .get_shadow_style ())
404
+
405
+ if style :
406
+ attrs ['style' ] = convert_dictionary_to_style_fragment (style )
407
+
408
+ return attrs
409
+
291
410
def export_paragraph_property_justification (self , paragraph , results ):
292
411
# TODO these classes could be applied on the paragraph, and not as
293
412
# inline spans
@@ -633,8 +752,17 @@ def export_table(self, table):
633
752
table_cell_spans = table .calculate_table_cell_spans ()
634
753
self .table_cell_rowspan_tracking [table ] = table_cell_spans
635
754
results = super (PyDocXHTMLExporter , self ).export_table (table )
755
+
756
+ # Before starting new table new need to make sure that if there is any paragraph
757
+ # with border opened before, we need to close it here.
758
+ for result in self .export_close_paragraph_border ():
759
+ yield result
760
+
636
761
tag = self .get_table_tag (table )
637
- return tag .apply (results )
762
+ results = tag .apply (results )
763
+
764
+ for result in results :
765
+ yield result
638
766
639
767
def export_table_row (self , table_row ):
640
768
results = super (PyDocXHTMLExporter , self ).export_table_row (table_row )
0 commit comments