@@ -220,6 +220,18 @@ export function generateNewListDefinition(numbering: NumberingModel, options: Ge
220220 // Preserve the style's suffix (e.g. ".", ")") so paren styles stay paren.
221221 lvlText . attributes [ 'w:val' ] = `%${ targetLevel + 1 } ${ styleConfig . text . replace ( / ^ % \d + / , '' ) } ` ;
222222 }
223+
224+ // Default ordered list markers to right-justification so siblings
225+ // with varying widths (e.g. "I." vs "III.", "1." vs "10.") share a
226+ // single content-start X. The base ordered template ships with
227+ // lvlJc="left", which would otherwise leave wider markers pushing
228+ // their own line right.
229+ const lvlJc = lvl . elements . find ( ( el : any ) => el . name === 'w:lvlJc' ) ;
230+ if ( lvlJc ) {
231+ lvlJc . attributes [ 'w:val' ] = 'right' ;
232+ } else {
233+ lvl . elements . push ( { type : 'element' , name : 'w:lvlJc' , attributes : { 'w:val' : 'right' } } ) ;
234+ }
223235 }
224236 }
225237 }
@@ -511,26 +523,37 @@ export function setLvlStyleOnAbstract(
511523
512524 let numFmtValue : string | null = null ;
513525 let lvlTextValue : string | null = null ;
526+ let lvlJcValue : string | null = null ;
514527
515528 if ( options . bulletStyle ) {
516529 const char = BULLET_STYLE_CHARS [ options . bulletStyle ] ;
517530 if ( ! char ) return false ;
518531 numFmtValue = 'bullet' ;
519532 lvlTextValue = char ;
533+ // Bullet markers are single-character; the source's lvlJc carries no
534+ // meaningful drift. Leave it untouched to avoid clobbering imported docs.
520535 } else if ( options . orderedStyle ) {
521536 const config = ORDERED_LIST_STYLES [ options . orderedStyle ] ;
522537 if ( ! config ) return false ;
523538 // OOXML `%N` references counter level N-1 (1-indexed from the top), so at ilvl=N we
524539 // need `%(N+1)`. Preserve the style's suffix (e.g. ".", ")") so paren styles stay paren.
525540 numFmtValue = config . fmt ;
526541 lvlTextValue = `%${ ilvl + 1 } ${ config . text . replace ( / ^ % \d + / , '' ) } ` ;
542+ // Default ordered styles to right-justified markers: when widths vary
543+ // across siblings (e.g. "I." vs "III." in a roman list, or "1." vs
544+ // "10." in a long decimal list), right-justification keeps content
545+ // aligned at one X. The source's lvlJc was tied to the previous numFmt
546+ // (which may have been single-width like a bullet) and would otherwise
547+ // cause drift on the new style.
548+ lvlJcValue = 'right' ;
527549 } else {
528550 return false ;
529551 }
530552
531553 let changed = false ;
532554 if ( setOrAddChild ( 'w:numFmt' , numFmtValue ) ) changed = true ;
533555 if ( setOrAddChild ( 'w:lvlText' , lvlTextValue ) ) changed = true ;
556+ if ( lvlJcValue != null && setOrAddChild ( 'w:lvlJc' , lvlJcValue ) ) changed = true ;
534557 if ( stripMarkerFont ( ) ) changed = true ;
535558 return changed ;
536559}
0 commit comments