Skip to content

fix(ios): code block background border radius#411

Open
eszlamczyk wants to merge 6 commits into
mainfrom
fix/354/code-block-background-border-clipping
Open

fix(ios): code block background border radius#411
eszlamczyk wants to merge 6 commits into
mainfrom
fix/354/code-block-background-border-clipping

Conversation

@eszlamczyk

@eszlamczyk eszlamczyk commented Jun 19, 2026

Copy link
Copy Markdown
Collaborator

What/Why?

On iOS, the bottom rounded corner of a codeBlock background would intermittently render as a square, depending on the exact number of lines and the padding value - and the visible bottom padding inside the block would sometimes collapse to ~0pt. Both symptoms had the same root cause.

The renderer emits a "bottom padding spacer" \n (paragraph style with minLineHeight = padding) at the end of every code block. Before this fix, removeTrailingSpacing would treat any trailing \n after the last visible character as deletable, so the bottom padding spacer got removed along with the codeBlockMarginBottom spacer when the code block was the last element in the document. CodeBlockBackground then compensated by extending the painted rect by codeBlockPadding, but iOS dispatches drawBackgroundForGlyphRange: in ~128pt tiles clipped to the laid-out content area. When the compensated rect crossed the next tile boundary, the bottom rounded corner fell outside every tile's clip and got sliced off - toggling visibly with each line added or removed.

The fix preserves the bottom padding spacer and keeps a single 1pt-tall tail \n immediately after it. With a non-padding \n as the trailing paragraph terminator, iOS lays the bottom padding spacer out as a normal interior line fragment (included in usedRect / boundingRectForGlyphRange: / the drawing tiles), so no rect extension is needed and the corner is always inside the clip. The tail's CodeBlockAttribute is stripped and its paragraphSpacing zeroed so it neither extends the background nor introduces a visible margin.

Testing

It is decently hard to test on playground, so the easiest way to verify the fix is to reproduce this:

Replace App.tsx with this
import { EnrichedMarkdownText } from "react-native-enriched-markdown";
import { SafeAreaProvider, SafeAreaView } from "react-native-safe-area-context";

const md = `
\`\`\`
// server.mjs
import { createServer } from 'node:http';

const server = createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.end('Hello World!\\n');
});

// starts a simple http server locally on port 3000
server.listen(3000, '127.0.0.1', () => {
  console.log('Listening on 127.0.0.1:3000');
});

// run with "node server.mjs"

// one more line
// one more line
// one more line
// one more line
// one more line
// one more line
// one more line
// one more line
// one more line
// one more line
// one more line
// one more line
// one more line
\`\`\`
`;

export default function App() {
  return (
    <SafeAreaProvider>
      <SafeAreaView>
        <EnrichedMarkdownText
          markdown={md}
          markdownStyle={{ codeBlock: { borderRadius: 12 } }}
        />
      </SafeAreaView>
    </SafeAreaProvider>
  );
}

keep adding // one more line or change markdownStyle

Tested on IOS 26.3 (Iphone 17 pro) and IOS 18.6 (Iphone 16 Plus) simulators

Screenshots

All screenshots were made with borderRadius: 12

Before After
very small padding (2) image image
default padding image image
big padding (40) 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 #354

@eszlamczyk eszlamczyk changed the title fix: code block background border radius fix(ios): code block background border radius Jun 22, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Nice, looks like some test also got fixed up

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 fixes an iOS rendering edge case where the bottom rounded corners (and sometimes bottom padding) of a codeBlock background could be clipped depending on line count and padding, by ensuring the code block’s bottom padding spacer is laid out inside iOS’s normal text tiles rather than relying on background-rect compensation.

Changes:

  • Added isLastBlockACodeBlock to detect a trailing code block while ignoring trailing newline spacers.
  • Updated removeTrailingSpacing to preserve the code block bottom padding spacer and keep a single trailing “tail” newline outside the code block range so iOS includes the padding spacer in usedRect/tiling.

Reviewed changes

Copilot reviewed 2 out of 7 changed files in this pull request and generated 3 comments.

File Description
packages/react-native-enriched-markdown/ios/utils/LastElementUtils.h Adds a new helper for identifying when the last semantic block is a code block despite trailing spacer newlines.
packages/react-native-enriched-markdown/ios/renderer/AttributedRenderer.m Adjusts trailing-trim logic to keep a non-code-block tail newline after code blocks to avoid iOS background clipping/tiling issues.

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

Comment on lines +132 to +137
NSParagraphStyle *style = [output attribute:NSParagraphStyleAttributeName atIndex:tailIdx effectiveRange:NULL];
NSMutableParagraphStyle *mutableStyle = style ? [style mutableCopy] : [[NSMutableParagraphStyle alloc] init];
mutableStyle.paragraphSpacing = 0;
mutableStyle.paragraphSpacingBefore = 0;
[output addAttribute:NSParagraphStyleAttributeName value:mutableStyle range:NSMakeRange(tailIdx, 1)];
}
Comment thread packages/react-native-enriched-markdown/ios/utils/LastElementUtils.h Outdated
Comment thread packages/react-native-enriched-markdown/ios/renderer/AttributedRenderer.m Outdated
@eszlamczyk eszlamczyk requested a review from hryhoriiK97 June 22, 2026 13:27
@eszlamczyk eszlamczyk marked this pull request as ready for review June 22, 2026 13:28
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.

iOS: CodeBlock background border-radius randomly clips at the bottom

2 participants