@@ -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 [ ] = [ ] ;
@@ -914,7 +928,7 @@ export function paragraphToFlowBlocks({
914928 } ) ;
915929
916930 if ( ! trackedChangesConfig ) {
917- return blocks ;
931+ return finalizeParagraphBlocks ( blocks ) ;
918932 }
919933
920934 const processedBlocks : FlowBlock [ ] = [ ] ;
@@ -944,7 +958,7 @@ export function paragraphToFlowBlocks({
944958 processedBlocks . push ( block ) ;
945959 } ) ;
946960
947- return processedBlocks ;
961+ return finalizeParagraphBlocks ( processedBlocks ) ;
948962}
949963
950964type InlineConverterSpec = {
@@ -1063,7 +1077,10 @@ export function getLastParagraphFont(blocks: FlowBlock[]): ParagraphFont | undef
10631077 const para = block as ParagraphBlock ;
10641078 const firstRun = para . runs ?. [ 0 ] ;
10651079 if ( ! firstRun ) continue ;
1066- const run = firstRun as { fontFamily ?: string ; fontSize ?: number } ;
1080+ const run = firstRun as { text ?: string ; fontFamily ?: string ; fontSize ?: number } ;
1081+ if ( typeof run . text === 'string' && run . text . length === 0 ) {
1082+ continue ;
1083+ }
10671084 const fontFamily = typeof run . fontFamily === 'string' ? run . fontFamily . trim ( ) : '' ;
10681085 const fontSize = typeof run . fontSize === 'number' && Number . isFinite ( run . fontSize ) ? run . fontSize : NaN ;
10691086 if ( fontFamily . length > 0 && fontSize > 0 ) {
@@ -1133,15 +1150,26 @@ export function handleParagraphNode(node: PMNode, context: NodeHandlerContext):
11331150 // get() returns both the entry (if hit) and pre-computed nodeJson to avoid double serialization
11341151 const { entry : cached , nodeJson, nodeRev } = flowBlockCache . get ( prefixedStableId , node ) ;
11351152 if ( cached ) {
1136- // Cache hit: reuse blocks with position adjustment
1137- // Cache hit reuses previously-converted blocks as-is. That means we don't
1138- // recompute previousParagraphFont (used for empty list items without
1139- // explicit run properties). If the user changes the font on the prior
1140- // paragraph (e.g. paragraph A), an empty list item (paragraph B) can keep
1141- // the old font until the cache entry is invalidated. Narrow case, but
1142- // avoids confusing incremental-edit behavior.
1153+ // Cache hit: reuse blocks with position adjustment, then re-sync marker font
1154+ // from live PM state. Empty list items have no textStyle marks, so pass
1155+ // previousParagraphFont instead of falling back to stale cached runs.
11431156 const delta = pmStart - cached . pmStart ;
11441157 const reusedBlocks = shiftCachedBlocks ( cached . blocks , delta ) ;
1158+ const paragraphProps = node . attrs ?. paragraphProperties as ParagraphProperties | undefined ;
1159+ const previousParagraphFont = ! hasExplicitParagraphRunProperties ( paragraphProps )
1160+ ? getLastParagraphFont ( blocks )
1161+ : undefined ;
1162+ reusedBlocks . forEach ( ( block ) => {
1163+ if ( block . kind === 'paragraph' ) {
1164+ syncListMarkerFontFromParagraphRuns ( {
1165+ block,
1166+ converterContext,
1167+ para : node ,
1168+ contentFontSource : 'paragraph' ,
1169+ previousParagraphFont,
1170+ } ) ;
1171+ }
1172+ } ) ;
11451173 applyTrackedGhostListAdjustments ( node , reusedBlocks , context ) ;
11461174
11471175 reusedBlocks . forEach ( ( block ) => {
0 commit comments