Skip to content

fix(android): unify line break strategy across measuring and drawing, add line break props#374

Open
eszlamczyk wants to merge 4 commits into
mainfrom
fix/android/incorrect-line-measure-on-long-links
Open

fix(android): unify line break strategy across measuring and drawing, add line break props#374
eszlamczyk wants to merge 4 commits into
mainfrom
fix/android/incorrect-line-measure-on-long-links

Conversation

@eszlamczyk

@eszlamczyk eszlamczyk commented Jun 3, 2026

Copy link
Copy Markdown
Collaborator

What/Why?

Adds textBreakStrategy (Android) and lineBreakStrategyIOS (iOS) props to both EnrichedMarkdownText, mirroring the same props available on React Native's core Text component.

On Android, the break strategy must match between the measurement pass (StaticLayout.Builder) and the render pass (TextView.breakStrategy) - a mismatch causes the measured line count to differ from the rendered one, which manifests as incorrect view height and clipped or scrolled content, most visibly with long links that wrap across lines. Previously the strategy was hardcoded to simple via a top-level function; this PR promotes it to a singleton (BreakStrategyUtils) that both paths read from, so changing the prop keeps them in sync.

On iOS, the lineBreakStrategy is applied to the NSParagraphStyle used when building attributed strings, allowing consumers to opt into standard, hangul-word, or push-out
breaking on iOS 14+.

Note: the defaults were kept in a way not to have any breaking changes

Testing

Go to playground in example app

paste (via set markdown option) string containing long text/links for example:

Check out this link: [A very long link label that should wrap onto the next line in a narrow container (https://example.com)

And a bare URL: https://this-is-a-very-long-url-that-will-force-line-wrapping.example.com/some/deep/path

To make this more visible adjust max width of the container (to for example 220)

Alternative Test

Create any view that has:

  • some <Text>
  • Markdown Text block with text before and link that is longer than one line
  • some <Text>
Example

Replace App.tsx in example app with

import { Text, View } from 'react-native';
import { EnrichedMarkdownText } from 'react-native-enriched-markdown';

export default function App() {
  return (
    <View style={{ padding: 16, marginTop: 50 }}>
      <Text>Some text before rendered Markdown</Text>
      <EnrichedMarkdownText
        markdown={
          'Find related: https://www.example.com/a-long-bit-of-text-that-keeps-going'
        }
      />
      <Text>Some text after rendered Markdown</Text>
    </View>
  );
}

Screenshots

Main test

Android
simple highQuality (default) balanced
image image image
iOS
none (default) standard hangul-word push-out
image image image image

Alternative test

Note: Before photo is partialy scrolled to display the issue

Before After
image image

PR Checklist

  • Code compiles and runs on iOS
  • Code compiles and runs on Android
  • Updated documentation/README if applicable
  • Ran example app to verify changes
  • E2E tests are passing
  • Required E2E tests have been added (if applicable)

closes #366

@eszlamczyk eszlamczyk marked this pull request as ready for review June 3, 2026 09:33
@eszlamczyk eszlamczyk requested a review from hryhoriiK97 June 3, 2026 09:33

@hryhoriiK97 hryhoriiK97 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this approach fixes the current problem, but changing from HIGH_QUALITY to SIMPLE could be a breaking change for existing library consumers. I'm thinking about introducing a lineBreakStrategy prop — the same as RN Text has: https://reactnative.dev/docs/text#textbreakstrategy-android

@eszlamczyk eszlamczyk marked this pull request as draft June 8, 2026 14:23
@eszlamczyk eszlamczyk marked this pull request as ready for review June 10, 2026 10:41
@eszlamczyk eszlamczyk requested a review from hryhoriiK97 June 10, 2026 10:42
@eszlamczyk eszlamczyk changed the title fix(android): unify line break strategy across measuring and drawing fix(android): unify line break strategy across measuring and drawing, add line break props Jun 10, 2026
@eszlamczyk eszlamczyk requested a review from Copilot June 10, 2026 12:46

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds cross-platform line-breaking configuration props to the library’s Markdown text components and updates native iOS/Android rendering/measurement to keep line breaking consistent (notably addressing Android height mis-measurement/clipping for long wrapped URLs/links).

Changes:

  • Add textBreakStrategy (Android) and lineBreakStrategyIOS (iOS) props to the public TS props and native codegen props for EnrichedMarkdownText / EnrichedMarkdown.
  • iOS: apply lineBreakStrategyIOS via NSParagraphStyle during attributed-string building.
  • Android: centralize break-strategy resolution and apply it in both StaticLayout.Builder (measurement) and TextView.breakStrategy (render).

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
src/types/MarkdownTextProps.ts Exposes new break-strategy props on EnrichedMarkdownTextProps.
src/native/EnrichedMarkdownText.tsx Wires new props from JS wrapper into native component props.
src/EnrichedMarkdownTextNativeComponent.ts Adds codegen native prop definitions for EnrichedMarkdownText.
src/EnrichedMarkdownNativeComponent.ts Adds codegen native prop definitions for EnrichedMarkdown (GFM/container renderer).
ios/utils/ParagraphStyleUtils.m Introduces global line-break strategy and applies it to paragraph styles.
ios/utils/ParagraphStyleUtils.h Declares the new line-break strategy setter.
ios/EnrichedMarkdownText.mm Plumbs lineBreakStrategyIOS prop changes into the iOS text renderer.
ios/EnrichedMarkdown.mm Plumbs lineBreakStrategyIOS prop changes into the iOS GFM/container renderer.
android/.../TextViewSetup.kt Applies resolved break strategy to the rendered TextView on API 23+.
android/.../utils/common/BreakStrategyUtils.kt Adds a shared resolver for Android break-strategy selection.
android/.../MeasurementStore.kt Applies the resolved break strategy during StaticLayout measurement on API 23+.
android/.../EnrichedMarkdownTextManager.kt Exposes textBreakStrategy as a React prop (and adds iOS-only prop no-ops).
android/.../EnrichedMarkdownText.kt Implements setTextBreakStrategy and invalidates measurement/re-render.
android/.../EnrichedMarkdownManager.kt Exposes textBreakStrategy as a React prop (and adds iOS-only prop no-ops).
android/.../EnrichedMarkdown.kt Propagates break-strategy changes to segment TextViews and forces height recalculation.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +19 to +20
void ENRMSetLineBreakStrategy(NSString *strategy);
void ENRMSetLineBreakStrategy(NSString *strategy);
Comment on lines 39 to 43
NSParagraphStyle *existing = [output attribute:NSParagraphStyleAttributeName atIndex:index effectiveRange:NULL];
NSMutableParagraphStyle *style = existing ? [existing mutableCopy] : [[NSMutableParagraphStyle alloc] init];
style.baseWritingDirection = currentWritingDirection();
style.lineBreakStrategy = gLineBreakStrategy;
return style;
Comment on lines +27 to +31
private var strategy: String = "simple"

fun setStrategy(newStrategy: String?) {
strategy = newStrategy ?: "simple"
}
Comment on lines +6 to +10
static NSLineBreakStrategy gLineBreakStrategy = NSLineBreakStrategyNone;

void ENRMSetLineBreakStrategy(NSString *strategy)
{
if ([strategy isEqualToString:@"standard"]) {
Comment on lines +26 to +28
object BreakStrategyUtils {
private var strategy: String = "simple"

Comment thread src/types/MarkdownTextProps.ts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug(android): Long URLs cause incorrect EnrichedMarkdownText height

3 participants