1515
1616from docxcompose .image import ImageWrapper
1717from docxcompose .properties import CustomProperties
18+ from docxcompose .utils import increment_name
1819from docxcompose .utils import NS
1920from docxcompose .utils import xpath
2021
@@ -41,6 +42,7 @@ def __init__(self, doc):
4142 self .pkg = doc .part .package
4243
4344 self .restart_numbering = True
45+ self .preserve_styles = True
4446
4547 self .reset_reference_mapping ()
4648
@@ -59,6 +61,7 @@ def append(self, doc, remove_property_fields=True):
5961 def insert (self , index , doc , remove_property_fields = True ):
6062 """Insert the given document at the given index."""
6163 self .reset_reference_mapping ()
64+ self ._preserved_styles = {}
6265
6366 # Remove custom property fields but keep the values
6467 if remove_property_fields :
@@ -299,24 +302,30 @@ def add_styles(self, doc, element):
299302
300303 for style_id in used_style_ids :
301304 our_style_id = self .mapped_style_id (style_id )
302- if our_style_id not in our_style_ids :
305+ if self .preserve_styles and our_style_id in our_style_ids :
306+ if our_style_id not in self ._preserved_styles :
307+ style_element = deepcopy (doc .styles .element .get_by_id (style_id ))
308+ our_style_element = self .doc .styles .element .get_by_id (our_style_id )
309+ if style_element .xml != our_style_element .xml :
310+ new_id = increment_name (our_style_id )
311+ new_name = increment_name (style_element .name .val )
312+ while new_id in our_style_ids :
313+ new_id = increment_name (new_id )
314+ new_name = increment_name (new_name )
315+ style_element .styleId = new_id
316+ style_element .name .val = new_name
317+ self .doc .styles .element .append (style_element )
318+ self .add_numberings (doc , style_element )
319+ self .add_linked_styles (doc , style_element )
320+ self ._preserved_styles [our_style_id ] = style_element .styleId
321+ for el in xpath (element , ".//w:tblStyle|.//w:pStyle|.//w:rStyle" ):
322+ el .val = self ._preserved_styles [our_style_id ]
323+ elif our_style_id not in our_style_ids :
303324 style_element = deepcopy (doc .styles .element .get_by_id (style_id ))
304325 if style_element is not None :
305326 self .doc .styles .element .append (style_element )
306327 self .add_numberings (doc , style_element )
307- # Also add linked styles
308- linked_style_ids = xpath (style_element , ".//w:link/@w:val" )
309- if linked_style_ids :
310- linked_style_id = linked_style_ids [0 ]
311- our_linked_style_id = self .mapped_style_id (linked_style_id )
312- if our_linked_style_id not in our_style_ids :
313- our_linked_style = doc .styles .element .get_by_id (
314- linked_style_id
315- )
316- if our_linked_style is not None :
317- self .doc .styles .element .append (
318- deepcopy (our_linked_style )
319- )
328+ self .add_linked_styles (doc , style_element )
320329 else :
321330 # Create a mapping for abstractNumIds used in existing styles
322331 # This is used when adding numberings to avoid having multiple
@@ -360,6 +369,21 @@ def add_styles(self, doc, element):
360369 # Update our style ids
361370 our_style_ids = [s .style_id for s in self .doc .styles ]
362371
372+ def add_linked_styles (self , doc , element ):
373+ linked_style_ids = xpath (element , ".//w:link/@w:val" )
374+ if linked_style_ids :
375+ linked_style_id = linked_style_ids [0 ]
376+ our_linked_style_id = self .mapped_style_id (linked_style_id )
377+ our_style_ids = [s .style_id for s in self .doc .styles ]
378+ if our_linked_style_id not in our_style_ids :
379+ our_linked_style = doc .styles .element .get_by_id (
380+ linked_style_id
381+ )
382+ if our_linked_style is not None :
383+ self .doc .styles .element .append (
384+ deepcopy (our_linked_style )
385+ )
386+
363387 def add_numberings (self , doc , element ):
364388 """Add numberings from the given document used in the given element."""
365389 # Search for numbering references
0 commit comments