babel-plugin-text-break-resolver
v0.3.0
Published
Babel plugin that automatically fixes Android text rendering issues in React Native. Injects textBreakStrategy="simple" into every <Text> component at build time — zero runtime cost. Optionally adds numberOfLines and adjustsFontSizeToFit via config — full
Maintainers
Readme
babel-plugin-text-break-resolver
babel-plugin-text-break-resolver is a Babel plugin for React Native that automatically fixes Android text rendering anomalies (truncation, clipping, and word-splitting) at compile time with zero runtime overhead.
The Problem
React Native's <Text> component on Android defaults to textBreakStrategy="highQuality". This native line-breaking algorithm frequently causes rendering bugs on Android devices, including:
- Text cut off at the end of a word or sentence.
- Truncated or clipped text despite sufficient container space.
- Incorrect word splitting across lines.
- Text overflow anomalies that do not occur on iOS.
Architecture & Solution
To bypass the Android highQuality layout constraints, developers typically must manually apply textBreakStrategy="simple" and append trailing whitespace to every <Text> component in the application.
This plugin automates that process via an Abstract Syntax Tree (AST) visitor during the Metro bundling phase. It locates every JSX <Text> element and injects the necessary properties at compile time:
- Automatically injects
textBreakStrategy="simple". - Automatically appends a 2-space ASCII buffer aligned with the text's directionality (trailing spaces for left-aligned, leading spaces for right-aligned, and both for centered text).
- Avoids modifying files within
node_modules. - Bypasses
<Text>components that already have these properties defined. - Executes entirely at build time, resulting in zero runtime performance penalty.
Installation
Install the package as a development dependency using your preferred package manager.
Using npm:
npm install --save-dev babel-plugin-text-break-resolverUsing yarn:
yarn add -D babel-plugin-text-break-resolverConfiguration
Register the plugin in your babel.config.js file.
module.exports = {
presets: ['module:@react-native/babel-preset'],
plugins: [
['babel-plugin-text-break-resolver', {
numberOfLines: false,
adjustsFontSizeToFit: false,
trailingSpaces: true
}],
// react-native-reanimated/plugin must remain last if used
]
};Options Table
| Option | Default | Description |
|--------|---------|-------------|
| numberOfLines | false | Injects numberOfLines={1} into all <Text> elements. |
| adjustsFontSizeToFit | false | Injects adjustsFontSizeToFit={true} into all <Text> elements. |
| trailingSpaces | true | Appends 2 ASCII spaces using an alignment-aware strategy based on standard layout behaviors. |
(Note: textBreakStrategy="simple" is strictly enforced and always applied by the plugin.)
Per-element Opt-out & Overrides
For isolated cases where the automatic buffer disrupts specific layouts, use the noTrailingSpaces or textBreakBuffer props directly on the element.
// Disable the space buffer for this specific component
<Text noTrailingSpaces style={styles.badgeText}>{count}</Text>
// Force the buffer strategy explicitly
<Text textBreakBuffer="both">{label}</Text>At compile time, the plugin:
- Strips these custom props (they are never rendered in the final bundle).
- Applies the requested buffer strategy (or skips it).
- Continues to apply
textBreakStrategy="simple".
TypeScript Support
Because noTrailingSpaces and textBreakBuffer are compile-time attributes, TypeScript will initially flag them as invalid React Native props.
To resolve this, you do not need to configure anything complex. The next time you run your Metro bundler (e.g. yarn start), the plugin will automatically generate a text-break-env.d.ts file in your project root!
Simply add that generated file to your tsconfig.json's include array:
{
"include": [
"src",
"text-break-env.d.ts"
]
}Build Reporting
When Metro processes files during a full build (such as an APK or AAB generation), the plugin generates a detailed modification report at:
android/app/build/generated/logs/textBreakReport.txt
The report documents the exact line numbers and applied properties for every <Text> element modified by the AST visitor.
Advanced Usage
CI/CD and Build Scripts
Metro's JavaScript cache may prevent the plugin from evaluating unmodified files. In automated build pipelines (e.g., Fastlane or build.sh), force the plugin to execute on all files by clearing the cache during the bundle phase.
npx react-native bundle \
--platform android \
--dev false \
--entry-file index.js \
--bundle-output android/app/src/main/assets/index.android.bundle \
--assets-dest android/app/src/main/res \
--reset-cacheTroubleshooting
The text is still cut off after installing the plugin. Babel plugins only run on files compiled by Metro. If Metro caches the files, your changes will not reflect. You must restart Metro and explicitly clear the cache:
npx react-native start --reset-cacheFAQ
Why is text cut off or truncated on Android in React Native?
React Native defaults to a highQuality text breaking strategy on Android. This native engine algorithm has known issues evaluating line bounds, resulting in clipped text. Overriding this value to simple and appending padding typically resolves the rendering anomaly.
How does this plugin prevent text from being truncated?
It systematically applies textBreakStrategy="simple" to all <Text> nodes and injects a 2-character ASCII space buffer to extend the layout boundary constraint, ensuring the Android UI renderer draws the entire text string.
Will this plugin affect iOS rendering?
No. The textBreakStrategy attribute is Android-specific. iOS uses a separate native text renderer (CoreText) and simply ignores the property.
Does this plugin degrade app performance? No. The plugin is a build-time dependency. AST modifications are compiled directly into the JavaScript bundle before runtime, meaning the application incurs zero processing overhead on the user's device.
Compatibility
| React Native | Android | Babel | Status | |---|---|---|---| | 0.72+ | API 24+ | 7.x | Supported |
