@@ -37,6 +37,7 @@ import { applyTrackedChangesModeToRuns } from '../tracked-changes.js';
3737import { textNodeToRun } from './inline-converters/text-run.js' ;
3838import { DEFAULT_HYPERLINK_CONFIG , TOKEN_INLINE_TYPES } from '../constants.js' ;
3939import { computeRunAttrs , hasExplicitParagraphRunProperties } from '../attributes/paragraph.js' ;
40+ import { syncListMarkerFontFromParagraphRuns } from '../list-marker-font.js' ;
4041import { resolveRunProperties } from '@superdoc/style-engine/ooxml' ;
4142import { footnoteReferenceToBlock } from './inline-converters/footnote-reference.js' ;
4243import { endnoteReferenceToBlock } from './inline-converters/endnote-reference.js' ;
@@ -604,6 +605,19 @@ export function paragraphToFlowBlocks({
604605 const defaultSize =
605606 usePreviousFont && previousParagraphFont . fontSize ? previousParagraphFont . fontSize : extracted . defaultSize ;
606607
608+ const finalizeParagraphBlocks = ( outputBlocks : FlowBlock [ ] ) : FlowBlock [ ] => {
609+ outputBlocks . forEach ( ( block ) => {
610+ if ( block . kind === 'paragraph' ) {
611+ syncListMarkerFontFromParagraphRuns ( {
612+ block,
613+ converterContext,
614+ para,
615+ } ) ;
616+ }
617+ } ) ;
618+ return outputBlocks ;
619+ } ;
620+
607621 if ( paragraphAttrs . pageBreakBefore ) {
608622 blocks . push ( {
609623 kind : 'pageBreak' ,
@@ -615,7 +629,7 @@ export function paragraphToFlowBlocks({
615629
616630 if ( ! para . content || para . content . length === 0 ) {
617631 if ( paragraphProps . runProperties ?. vanish ) {
618- return blocks ;
632+ return finalizeParagraphBlocks ( blocks ) ;
619633 }
620634 const paragraphMarkTrackedChange = getParagraphMarkTrackedChange ( paragraphProps , storyKey ) ;
621635 // Get the PM position of the empty paragraph for caret rendering
@@ -650,12 +664,12 @@ export function paragraphToFlowBlocks({
650664 sourceAnchor,
651665 } ) ;
652666 if ( ! trackedChangesConfig ) {
653- return blocks ;
667+ return finalizeParagraphBlocks ( blocks ) ;
654668 }
655669
656670 const paragraphBlock = blocks [ blocks . length - 1 ] ;
657671 if ( paragraphBlock ?. kind !== 'paragraph' ) {
658- return blocks ;
672+ return finalizeParagraphBlocks ( blocks ) ;
659673 }
660674
661675 const filteredRuns = applyTrackedChangesModeToRuns (
@@ -682,7 +696,7 @@ export function paragraphToFlowBlocks({
682696
683697 if ( trackedChangesConfig . enabled && ( filteredRuns . length === 0 || isGhostTrackedListArtifact ) ) {
684698 blocks . pop ( ) ;
685- return blocks ;
699+ return finalizeParagraphBlocks ( blocks ) ;
686700 }
687701
688702 paragraphBlock . runs = filteredRuns ;
@@ -691,7 +705,7 @@ export function paragraphToFlowBlocks({
691705 trackedChangesMode : trackedChangesConfig . mode ,
692706 trackedChangesEnabled : trackedChangesConfig . enabled ,
693707 } ;
694- return blocks ;
708+ return finalizeParagraphBlocks ( blocks ) ;
695709 }
696710
697711 let currentRuns : Run [ ] = [ ] ;
@@ -923,7 +937,7 @@ export function paragraphToFlowBlocks({
923937 } ) ;
924938
925939 if ( ! trackedChangesConfig ) {
926- return blocks ;
940+ return finalizeParagraphBlocks ( blocks ) ;
927941 }
928942
929943 const processedBlocks : FlowBlock [ ] = [ ] ;
@@ -953,7 +967,7 @@ export function paragraphToFlowBlocks({
953967 processedBlocks . push ( block ) ;
954968 } ) ;
955969
956- return processedBlocks ;
970+ return finalizeParagraphBlocks ( processedBlocks ) ;
957971}
958972
959973type InlineConverterSpec = {
@@ -1072,7 +1086,10 @@ export function getLastParagraphFont(blocks: FlowBlock[]): ParagraphFont | undef
10721086 const para = block as ParagraphBlock ;
10731087 const firstRun = para . runs ?. [ 0 ] ;
10741088 if ( ! firstRun ) continue ;
1075- const run = firstRun as { fontFamily ?: string ; fontSize ?: number } ;
1089+ const run = firstRun as { text ?: string ; fontFamily ?: string ; fontSize ?: number } ;
1090+ if ( typeof run . text === 'string' && run . text . length === 0 ) {
1091+ continue ;
1092+ }
10761093 const fontFamily = typeof run . fontFamily === 'string' ? run . fontFamily . trim ( ) : '' ;
10771094 const fontSize = typeof run . fontSize === 'number' && Number . isFinite ( run . fontSize ) ? run . fontSize : NaN ;
10781095 if ( fontFamily . length > 0 && fontSize > 0 ) {
@@ -1142,15 +1159,26 @@ export function handleParagraphNode(node: PMNode, context: NodeHandlerContext):
11421159 // get() returns both the entry (if hit) and pre-computed nodeJson to avoid double serialization
11431160 const { entry : cached , nodeJson, nodeRev } = flowBlockCache . get ( prefixedStableId , node ) ;
11441161 if ( cached ) {
1145- // Cache hit: reuse blocks with position adjustment
1146- // Cache hit reuses previously-converted blocks as-is. That means we don't
1147- // recompute previousParagraphFont (used for empty list items without
1148- // explicit run properties). If the user changes the font on the prior
1149- // paragraph (e.g. paragraph A), an empty list item (paragraph B) can keep
1150- // the old font until the cache entry is invalidated. Narrow case, but
1151- // avoids confusing incremental-edit behavior.
1162+ // Cache hit: reuse blocks with position adjustment, then re-sync marker font
1163+ // from live PM state. Empty list items have no textStyle marks, so pass
1164+ // previousParagraphFont instead of falling back to stale cached runs.
11521165 const delta = pmStart - cached . pmStart ;
11531166 const reusedBlocks = shiftCachedBlocks ( cached . blocks , delta ) ;
1167+ const paragraphProps = node . attrs ?. paragraphProperties as ParagraphProperties | undefined ;
1168+ const previousParagraphFont = ! hasExplicitParagraphRunProperties ( paragraphProps )
1169+ ? getLastParagraphFont ( blocks )
1170+ : undefined ;
1171+ reusedBlocks . forEach ( ( block ) => {
1172+ if ( block . kind === 'paragraph' ) {
1173+ syncListMarkerFontFromParagraphRuns ( {
1174+ block,
1175+ converterContext,
1176+ para : node ,
1177+ contentFontSource : 'paragraph' ,
1178+ previousParagraphFont,
1179+ } ) ;
1180+ }
1181+ } ) ;
11541182 applyTrackedGhostListAdjustments ( node , reusedBlocks , context ) ;
11551183
11561184 reusedBlocks . forEach ( ( block ) => {
0 commit comments