@@ -211,29 +211,31 @@ class _MarkdownToDocument implements md.NodeVisitor {
211211 _addHeader (element, level: 6 );
212212 break ;
213213 case 'p' :
214- final blockImage = _maybeParseBlockImage (element.textContent);
215- if (blockImage != null ) {
216- _addImage (blockImage);
217- } else {
218- final captionAndImage = _maybeParseImageWithCaption (element.textContent);
219- if (captionAndImage != null ) {
220- final captionText = parseInlineMarkdown (
221- captionAndImage.caption,
222- inlineMarkdownSyntaxes: inlineMarkdownSyntaxes,
223- inlineHtmlSyntaxes: inlineHtmlSyntaxes,
224- encodeHtml: encodeHtml,
225- );
226- _addParagraph (captionText, element.attributes);
227- _addImage (captionAndImage.image);
228- } else {
229- final attributedText = parseInlineMarkdown (
230- element.textContent,
231- inlineMarkdownSyntaxes: inlineMarkdownSyntaxes,
232- inlineHtmlSyntaxes: inlineHtmlSyntaxes,
233- encodeHtml: encodeHtml,
234- );
235- _addParagraph (attributedText, element.attributes);
214+ final mixedContent = syntax == MarkdownSyntax .superEditor
215+ ? _parseMixedParagraphContent (element.textContent)
216+ : null ;
217+ if (mixedContent != null ) {
218+ for (final segment in mixedContent) {
219+ if (segment.image != null ) {
220+ _addImage (segment.image! );
221+ } else {
222+ final attributedText = parseInlineMarkdown (
223+ segment.text! ,
224+ inlineMarkdownSyntaxes: inlineMarkdownSyntaxes,
225+ inlineHtmlSyntaxes: inlineHtmlSyntaxes,
226+ encodeHtml: encodeHtml,
227+ );
228+ _addParagraph (attributedText, element.attributes);
229+ }
236230 }
231+ } else {
232+ final attributedText = parseInlineMarkdown (
233+ element.textContent,
234+ inlineMarkdownSyntaxes: inlineMarkdownSyntaxes,
235+ inlineHtmlSyntaxes: inlineHtmlSyntaxes,
236+ encodeHtml: encodeHtml,
237+ );
238+ _addParagraph (attributedText, element.attributes);
237239 }
238240
239241 break ;
@@ -494,23 +496,49 @@ class _MarkdownToDocument implements md.NodeVisitor {
494496 );
495497 }
496498
497- /// If the last line of [markdown] is a block image and there is at least one
498- /// preceding line (the caption), returns a [_CaptionAndImage] containing the
499- /// caption text and the parsed image. Otherwise returns `null` .
500- _CaptionAndImage ? _maybeParseImageWithCaption (String markdown) {
501- final newlineIndex = markdown.lastIndexOf ('\n ' );
502- if (newlineIndex < 0 ) {
503- return null ;
499+ /// Splits [markdown] (a multi-line paragraph) into an ordered list of
500+ /// paragraph-text segments and block images.
501+ ///
502+ /// Returns `null` if the content contains no block images, in which case the
503+ /// caller should treat the whole text as a single paragraph.
504+ ///
505+ /// When images are present, consecutive non-image lines are grouped into a
506+ /// single paragraph segment. For example:
507+ ///
508+ /// ```
509+ /// A caption:
510+ /// 
511+ /// B caption:
512+ /// 
513+ /// ```
514+ ///
515+ /// produces: paragraph("A caption:"), image(url1), paragraph("B caption:"), image(url2).
516+ List <_ParagraphOrImage >? _parseMixedParagraphContent (String markdown) {
517+ final lines = markdown.split ('\n ' );
518+ final segments = < _ParagraphOrImage > [];
519+ final textBuffer = StringBuffer ();
520+ bool foundImage = false ;
521+
522+ for (final line in lines) {
523+ final image = _maybeParseBlockImage (line);
524+ if (image != null ) {
525+ foundImage = true ;
526+ if (textBuffer.isNotEmpty) {
527+ segments.add (_ParagraphOrImage .paragraph (textBuffer.toString ()));
528+ textBuffer.clear ();
529+ }
530+ segments.add (_ParagraphOrImage .image (image));
531+ } else {
532+ if (textBuffer.isNotEmpty) textBuffer.write ('\n ' );
533+ textBuffer.write (line);
534+ }
504535 }
505536
506- final lastLine = markdown.substring (newlineIndex + 1 );
507- final image = _maybeParseBlockImage (lastLine);
508- if (image == null ) {
509- return null ;
537+ if (textBuffer.isNotEmpty) {
538+ segments.add (_ParagraphOrImage .paragraph (textBuffer.toString ()));
510539 }
511540
512- final caption = markdown.substring (0 , newlineIndex);
513- return _CaptionAndImage (caption: caption, image: image);
541+ return foundImage ? segments : null ;
514542 }
515543}
516544
@@ -874,11 +902,13 @@ class _HeaderWithAlignmentSyntax extends md.BlockSyntax {
874902 }
875903}
876904
877- class _CaptionAndImage {
878- const _CaptionAndImage ({required this .caption, required this .image});
905+ /// A segment of a mixed paragraph: either a run of plain text or a block image.
906+ class _ParagraphOrImage {
907+ _ParagraphOrImage .paragraph (String this .text) : image = null ;
908+ _ParagraphOrImage .image (_MarkdownImage this .image) : text = null ;
879909
880- final String caption ;
881- final _MarkdownImage image;
910+ final String ? text ;
911+ final _MarkdownImage ? image;
882912}
883913
884914class _MarkdownImage {
0 commit comments