@@ -198,19 +198,24 @@ export default function createStreamingRenderer(
198198 } else {
199199 // New block boundary in tail: commit newly-finished blocks, replace active.
200200 const newActiveOffsetInTail = tailBlocks [ tailBlocks . length - 1 ] . startOffset ;
201- const committedTailEvents = tailEvents . filter ( ( [ , token ] ) => token . start . offset < newActiveOffsetInTail ) ;
202- const committedTailHTML = compile ( micromarkOptions ) ( committedTailEvents ) ;
203201
204202 activeBlockStartOffset += newActiveOffsetInTail ;
205203
204+ // Split at the micromark-event level so that blocks which compile to
205+ // multiple sibling DOM nodes (e.g. htmlFlow) are kept whole.
206+ const committedTailEvents = tailEvents . filter ( ( [ , token ] ) => token . start . offset < newActiveOffsetInTail ) ;
207+ const activeTailEvents = tailEvents . filter ( ( [ , token ] ) => token . start . offset >= newActiveOffsetInTail ) ;
208+
209+ const committedTailHTML = compile ( micromarkOptions ) ( committedTailEvents ) ;
210+ const activeTailHTML = compile ( micromarkOptions ) ( activeTailEvents ) ;
211+
206212 const committedDoc = domParser . parseFromString ( committedTailHTML , 'text/html' ) ;
207213 const committedFragment = committedDoc . createDocumentFragment ( ) ;
208214
209215 committedFragment . append ( ...Array . from ( committedDoc . body . childNodes ) ) ;
210216 betterLinkDocumentMod ( committedFragment , createDecorate ( emptyDefinitions , externalLinkAlt ) ) ;
211217
212- const remainingHTML = tailHTML . slice ( committedTailHTML . length ) ;
213- const activeDoc = domParser . parseFromString ( remainingHTML , 'text/html' ) ;
218+ const activeDoc = domParser . parseFromString ( activeTailHTML , 'text/html' ) ;
214219 const activeFragment = activeDoc . createDocumentFragment ( ) ;
215220
216221 activeFragment . append ( ...Array . from ( activeDoc . body . childNodes ) ) ;
@@ -243,27 +248,35 @@ export default function createStreamingRenderer(
243248
244249 // Full reparse path.
245250 const fullEvents = parseEvents ( processedMarkdown ) ;
246- const rawHTML = compile ( micromarkOptions ) ( fullEvents ) ;
247- const parsedDocument = domParser . parseFromString ( rawHTML , 'text/html' ) ;
248- const fragment = parsedDocument . createDocumentFragment ( ) ;
249-
250- fragment . append ( ...Array . from ( parsedDocument . body . childNodes ) ) ;
251-
252251 const blocks = findTopLevelBlocks ( fullEvents ) ;
253252
254253 if ( blocks . length >= 2 ) {
255- activeBlockStartOffset = blocks [ blocks . length - 1 ] . startOffset ;
254+ const lastBlock = blocks [ blocks . length - 1 ] ;
256255
257- const range = document . createRange ( ) ;
256+ activeBlockStartOffset = lastBlock . startOffset ;
258257
259- range . setStartBefore ( fragment . firstChild ! ) ;
260- range . setEndBefore ( fragment . lastElementChild ! ) ;
258+ // Split at the micromark-event level so that blocks which compile to
259+ // multiple sibling DOM nodes (e.g. htmlFlow) are kept whole.
260+ const committedEvents = fullEvents . filter ( ( [ , token ] ) => token . start . offset < lastBlock . startOffset ) ;
261+ const activeEvents = fullEvents . filter ( ( [ , token ] ) => token . start . offset >= lastBlock . startOffset ) ;
262+
263+ const committedHTML = compile ( micromarkOptions ) ( committedEvents ) ;
264+ const activeHTML = compile ( micromarkOptions ) ( activeEvents ) ;
265+
266+ const committedDoc = domParser . parseFromString ( committedHTML , 'text/html' ) ;
267+ const committedFragment = committedDoc . createDocumentFragment ( ) ;
268+
269+ committedFragment . append ( ...Array . from ( committedDoc . body . childNodes ) ) ;
270+
271+ const activeDoc = domParser . parseFromString ( activeHTML , 'text/html' ) ;
272+ const activeFragment = activeDoc . createDocumentFragment ( ) ;
273+
274+ activeFragment . append ( ...Array . from ( activeDoc . body . childNodes ) ) ;
261275
262- const committedFragment = range . extractContents ( ) ;
263276 const decorate = createDecorate ( emptyDefinitions , externalLinkAlt ) ;
264277
265278 betterLinkDocumentMod ( committedFragment , decorate ) ;
266- betterLinkDocumentMod ( fragment , decorate ) ;
279+ betterLinkDocumentMod ( activeFragment , decorate ) ;
267280
268281 const wrapper = ensureWrapper ( options . container , options . containerClassName ) ;
269282
@@ -272,7 +285,7 @@ export default function createStreamingRenderer(
272285 wrapper . replaceChildren (
273286 applyTransform ( committedFragment , options . transformFragment ) ,
274287 activeSentinel ,
275- applyTransform ( fragment , options . transformFragment )
288+ applyTransform ( activeFragment , options . transformFragment )
276289 ) ;
277290
278291 return ;
@@ -282,6 +295,12 @@ export default function createStreamingRenderer(
282295 activeBlockStartOffset = 0 ;
283296 activeSentinel = null ;
284297
298+ const rawHTML = compile ( micromarkOptions ) ( fullEvents ) ;
299+ const parsedDocument = domParser . parseFromString ( rawHTML , 'text/html' ) ;
300+ const fragment = parsedDocument . createDocumentFragment ( ) ;
301+
302+ fragment . append ( ...Array . from ( parsedDocument . body . childNodes ) ) ;
303+
285304 betterLinkDocumentMod ( fragment , createDecorate ( emptyDefinitions , externalLinkAlt ) ) ;
286305
287306 const wrapper = ensureWrapper ( options . container , options . containerClassName ) ;
0 commit comments