@@ -15,6 +15,8 @@ export default class XmlElements {
1515 document : XmlDocument ;
1616 params : XmlElementParams ;
1717 defaultValues : Record < string , string > ;
18+ paragraphTemplate : XmlElement ;
19+ runTemplate : XmlElement ;
1820
1921 constructor ( element : XmlDocument | XmlElement , params ?: XmlElementParams ) {
2022 this . element = element ;
@@ -47,9 +49,44 @@ export default class XmlElements {
4749 if ( ! txBody ) {
4850 txBody = this . document . createElement ( 'p:txBody' ) ;
4951 this . element . appendChild ( txBody ) ;
52+
53+ const bodyPr = this . document . createElement ( 'a:bodyPr' ) ;
54+ txBody . appendChild ( bodyPr ) ;
55+
56+ const lstStyle = this . document . createElement ( 'a:lstStyle' ) ;
57+ txBody . appendChild ( lstStyle ) ;
58+
59+ this . paragraphTemplate = this . document . createElement ( 'a:p' ) ;
60+ txBody . appendChild ( this . paragraphTemplate ) ;
61+
62+ this . runTemplate = this . document . createElement ( 'a:r' ) ;
63+ const rPr = this . document . createElement ( 'a:rPr' ) ;
64+ this . runTemplate . appendChild ( rPr ) ;
5065 } else {
51- while ( txBody . firstChild ) {
52- txBody . removeChild ( txBody . firstChild ) ;
66+ let bodyPr = txBody . getElementsByTagName ( 'a:bodyPr' ) [ 0 ] ;
67+ if ( ! bodyPr ) {
68+ bodyPr = this . document . createElement ( 'a:bodyPr' ) ;
69+ txBody . insertBefore ( bodyPr , txBody . firstChild ) ;
70+ }
71+
72+ let lstStyle = txBody . getElementsByTagName ( 'a:lstStyle' ) [ 0 ] ;
73+ if ( ! lstStyle ) {
74+ lstStyle = this . document . createElement ( 'a:lstStyle' ) ;
75+ txBody . insertBefore ( lstStyle , bodyPr . nextSibling ) ;
76+ }
77+
78+ const paragraphs = txBody . getElementsByTagName ( 'a:p' ) ;
79+ this . paragraphTemplate = paragraphs [ 0 ] ;
80+ XmlHelper . sliceCollection ( paragraphs , 0 ) ;
81+
82+
83+ const runs = this . paragraphTemplate . getElementsByTagName ( 'a:r' ) ;
84+ if ( runs . length > 0 ) {
85+ this . runTemplate = runs [ 0 ] ;
86+ } else {
87+ this . runTemplate = this . document . createElement ( 'a:r' ) ;
88+ const rPr = this . document . createElement ( 'a:rPr' ) ;
89+ this . runTemplate . appendChild ( rPr ) ;
5390 }
5491 }
5592 return txBody ;
@@ -81,24 +118,39 @@ export default class XmlElements {
81118 }
82119
83120 createParagraph ( level : number ) : XmlElement {
84- const p = this . document . createElement ( 'a:p' ) ;
85- const pPr = this . document . createElement ( 'a:pPr' ) ;
86- if ( level > 0 ) {
87- pPr . setAttribute ( 'lvl' , String ( level ) ) ;
121+ const p = this . paragraphTemplate . cloneNode ( true ) as XmlElement ;
122+ const pPr = p . getElementsByTagName ( 'a:pPr' ) [ 0 ] ;
123+ if ( pPr ) {
124+ if ( level > 0 ) {
125+ pPr . setAttribute ( 'lvl' , String ( level ) ) ;
126+ pPr . removeAttribute ( 'indent' ) ;
127+ pPr . removeAttribute ( 'marL' ) ;
128+ } else {
129+ pPr . removeAttribute ( 'lvl' ) ;
130+ }
131+ } else {
132+ const newPPr = this . document . createElement ( 'a:pPr' ) ;
133+ if ( level > 0 ) {
134+ newPPr . setAttribute ( 'lvl' , String ( level ) ) ;
135+ }
136+ p . insertBefore ( newPPr , p . firstChild ) ;
88137 }
89- p . appendChild ( pPr ) ;
138+ const runs = p . getElementsByTagName ( 'a:r' ) ;
139+ XmlHelper . sliceCollection ( runs , 0 ) ;
90140 return p ;
91141 }
92142
93143 createTextRun ( text : string ) : XmlElement {
94- const r = this . document . createElement ( 'a:r' ) ;
95- const rPr = this . document . createElement ( 'a:rPr' ) ;
96- r . appendChild ( rPr ) ;
97-
98- const t = this . document . createElement ( 'a:t' ) ;
99- t . textContent = String ( text ) ;
144+ const r = this . runTemplate . cloneNode ( true ) as XmlElement ;
145+ const t = r . getElementsByTagName ( 'a:t' ) [ 0 ] ;
146+ if ( t ) {
147+ t . textContent = text ;
148+ } else {
149+ const newT = this . document . createElement ( 'a:t' ) ;
150+ newT . textContent = text ;
151+ r . appendChild ( newT ) ;
152+ }
100153
101- r . appendChild ( t ) ;
102154 return r ;
103155 }
104156
0 commit comments