diff --git a/android/src/main/java/com/swmansion/enriched/common/parser/EnrichedParser.java b/android/src/main/java/com/swmansion/enriched/common/parser/EnrichedParser.java index 11d55a487..53d761c38 100644 --- a/android/src/main/java/com/swmansion/enriched/common/parser/EnrichedParser.java +++ b/android/src/main/java/com/swmansion/enriched/common/parser/EnrichedParser.java @@ -94,8 +94,9 @@ public static String toHtml(Spanned text) { String normalizedBlockQuote = normalizedCodeBlock.replaceAll("\\n
", ""); - // Replace empty

tags (with or without style attributes) with
- String normalizedHtml = normalizedBlockQuote.replaceAll("]*>

", "
"); + // Replace empty

tags with
, except when they carry text-align + String normalizedHtml = + normalizedBlockQuote.replaceAll("]*text-align\\s*:)[^>]*>

", "
"); return "\n" + normalizedHtml + ""; } @@ -593,7 +594,14 @@ private void handleEndTag(String tag) { if (tag.equalsIgnoreCase("br")) { handleBr(mSpannableStringBuilder); } else if (tag.equalsIgnoreCase("p")) { + boolean empty = isEmptyTag; + Alignment pendingAlignment = empty ? getLast(mSpannableStringBuilder, Alignment.class) : null; endBlockElement(mSpannableStringBuilder, mSpanFactory); + // Plain empty paragraphs never reach setParagraphSpanFromMark (no ZWS). + // Represent them as a blank line so they round-trip as
. + if (empty && pendingAlignment == null) { + handleBr(mSpannableStringBuilder); + } } else if (tag.equalsIgnoreCase("ul")) { currentListAlignmentCssValue = null; endBlockElement(mSpannableStringBuilder, mSpanFactory); diff --git a/ios/htmlParser/HtmlParser.mm b/ios/htmlParser/HtmlParser.mm index 1b8d3fd32..0ed3d879a 100644 --- a/ios/htmlParser/HtmlParser.mm +++ b/ios/htmlParser/HtmlParser.mm @@ -957,7 +957,16 @@ + (NSString *)parseToHtmlFromRange:(NSRange)range inCheckboxList = NO; } } else { - [result appendString:@"\n
"]; + NSString *cssStyleString = + [self prepareCssStyleString:currentRange.location + isOpeningTag:YES + host:host]; + if (cssStyleString.length > 0) { + [result appendString:[NSString stringWithFormat:@"\n

", + cssStyleString]]; + } else { + [result appendString:@"\n
"]; + } } } else { // newline finishes a paragraph and all style tags need to be closed @@ -1456,7 +1465,7 @@ + (NSString *)prepareCssStyleString:(NSInteger)location } + (void)checkForAlignments:(NSArray *)tagData - plainText:(NSString *)plainText + plainText:(NSMutableString *)plainText foundAlignments:(NSMutableArray *)foundAlignments precedingImageCount:(NSInteger)precedingImageCount { if (tagData == nil) { @@ -1474,6 +1483,12 @@ + (void)checkForAlignments:(NSArray *)tagData NSInteger actualStart = startLoc + precedingImageCount; NSInteger length = plainText.length - startLoc; + // Empty aligned paragraphs have no characters to attach alignment to. + if (length == 0) { + [plainText appendString:@"\u200B"]; + length = 1; + } + if (length > 0) { AlignmentEntry *entry = [[AlignmentEntry alloc] init]; entry.alignment = align;