Skip to content

fix: custom style addressed review comments - #822

Open
hejsztynx wants to merge 15 commits into
@kacperzolkiewski/custom-stylefrom
@ksienkiewicz/fix-custom-style-review-fixes
Open

hejsztynx wants to merge 15 commits into
@kacperzolkiewski/custom-stylefrom
@ksienkiewicz/fix-custom-style-review-fixes

Conversation

@hejsztynx

@hejsztynx hejsztynx commented Oct 19, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Addressed the review comments on the base branch PR.

What was fixed:

  • on Android, the custom style's fontSize on allowFontScaling changes, during rebuildWithStyle a stale allowFontScaling value was used
  • on iOS a 4-length hexes were not handled and coverted into color objects like Android
  • on Web we had a custom function for deleting 'one character' backwards, but grapheme clusters (eg emojis) were not deleted as a whole
  • normalizer now flattens nested <span> tags, e.g:
<span style="color:red">123<span style="color:blue">456</span>789</span>
// becomes
<span style="color:red">123</span><span style="color:blue">456</span><span style="color:red">789</span>
  • there were various issues with font-family parsing/normalizing, as font-family can have whitespaces, commas or apostrophes in its name
  • font-family values were at some places not escaped, eg & -> &amp;

For more context, visit #817

Compatibility

OS Implemented
iOS ✅
Android ✅
Web ✅

Checklist

  • E2E tests are passing
  • Required E2E tests have been added (if applicable)

@hejsztynx
hejsztynx marked this pull request as draft October 19, 2026 09:21
@hejsztynx
hejsztynx requested a balanced review from Copilot October 19, 2026 09:21
@hejsztynx hejsztynx changed the title @ksienkiewicz/fix custom style review fixes fix: custom style addressed review comments Oct 19, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Unresolved deletion and HTML normalization issues can alter document content and formatting.

7 open issues
What changed in this PR

Addresses follow-up fixes for custom styling introduced in #817 across web, iOS, and Android.

Changes:

  • Flattens nested custom styles and expands normalization tests.
  • Adds grapheme-aware backward deletion on web.
  • Updates native style escaping, font parsing, color support, and font scaling.
File Description
src/​web/​utils/​deleteCharacterBackward.ts Adds grapheme-aware deletion.
src/​web/​normalization/​htmlNormalizer.ts Propagates nested custom styles.
src/​web/​formats/​EnrichedCustomStyle.ts Uses the deletion helper.
src/​web/​__tests__/​htmlNormalizer.test.ts Tests nested style normalization.
src/​web/​__tests__/​deleteCharacterBackward.test.ts Tests character and inline-node deletion.
ios/​htmlParser/​HtmlParser.mm Updates style escaping and parsing.
ios/​extensions/​ColorExtension.mm Supports four-digit hexadecimal colors.
cpp/​tests/​GumboParserTest.cpp Tests custom styles and escaping.
cpp/​parser/​GumboNormalizer.c Preserves fonts and flattens nested styles.
android/​src/​main/​java/​com/​swmansion/​enriched/​textinput/​styles/​HtmlStyle.kt Exposes font-scaling settings.
android/​src/​main/​java/​com/​swmansion/​enriched/​textinput/​spans/​EnrichedInputCustomStyleSpan.kt Rebuilds spans with current scaling.
android/​src/​main/​java/​com/​swmansion/​enriched/​textinput/​EnrichedTextInputView.kt Invalidates layout after styling.
android/​src/​main/​java/​com/​swmansion/​enriched/​text/​spans/​EnrichedTextCustomStyleSpan.kt Applies updated font scaling.
android/​src/​main/​java/​com/​swmansion/​enriched/​text/​EnrichedTextStyle.kt Stores font-scaling settings.
android/​src/​main/​java/​com/​swmansion/​enriched/​common/​spans/​EnrichedCustomStyleSpan.kt Removes the obsolete scaling accessor.
android/​src/​main/​java/​com/​swmansion/​enriched/​common/​parser/​EnrichedParser.java Escapes attributes and parses font stacks.

Review effort: Balanced

Comment thread android/src/main/java/com/swmansion/enriched/common/parser/EnrichedParser.java Outdated
Comment thread cpp/parser/GumboNormalizer.c Outdated
Comment thread cpp/parser/GumboNormalizer.c Outdated
Comment thread src/web/normalization/htmlNormalizer.ts Outdated
Comment thread src/web/normalization/htmlNormalizer.ts
Comment thread src/web/normalization/htmlNormalizer.ts
Comment thread src/web/utils/deleteCharacterBackward.ts

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Unresolved parsing and normalization defects can crash iOS or alter formatting and paragraph structure.

1 open issue
3 previously missed issues

In code that hasn't changed since last review

Medium severity Prevent crashes from malformed quoted font families

ios/​htmlParser/​HtmlParser.mm:1689

The updated attribute matcher accepts <span style="font-family: '">x</span>, leaving a one-character apostrophe here. It satisfies both quote checks below, so fontFamilyString.length - 2 underflows and substringWithRange: throws an exception. Malformed CSS can therefore crash iOS HTML parsing. Require at least two characters before removing surrounding quotes, and add a regression case.

Medium severity Preserve layout whitespace through transparent wrappers

src/​web/​normalization/​htmlNormalizer.ts:659

Inherited styling turns wrapped layout whitespace into an extra paragraph. For <span style="color:red"><p>A</p><span> </span><p><span style="color:blue">B</span></p></span>, the middle space gets a red wrapper because isLayoutWhitespace checks only its immediate parent. flushInlineP then sees markup rather than whitespace and emits three paragraphs instead of two. The same issue occurs in cpp/parser/GumboNormalizer.c:935–937. Preserve layout context through transparent wrappers without dropping meaningful inline spaces, and add this case to both test suites.

Medium severity Resolve inherit styles before flattening

src/​web/​normalization/​htmlNormalizer.ts:688

Flattening treats inherit as a concrete override. For <span style="color:red">A<span style="color:inherit">B</span></span>, it emits sibling red and inherit spans, so B no longer inherits red from its removed ancestor. The same merge in cpp/parser/GumboNormalizer.c:1002–1009 also loses that context. Resolve explicit inheritance against the parent style before flattening, and add this regression case to both normalizer test suites.

7 resolved since last review

Review effort: Balanced

Comment thread src/web/formats/EnrichedCustomStyle.ts
runAsATransaction {
customStyles?.setStyle(styleJSON)
}
layoutManager.invalidateLayout()

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.

The custom style can introduce a fontSize, which can changes the line heights, etc

@hejsztynx
hejsztynx marked this pull request as ready for review October 20, 2026 13:09
Comment on lines +1597 to +1598
regularExpressionWithPattern:
@"style\\s*=\\s*[\"']((?<=\")[^\"]*(?=\")|(?<=')[^']*(?='))[\"']"

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.

previously the regex did not properly detect quoted font-family values, e.g. font-family: 'Times New Roman';

This branch has not been deployed

No deployments
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.

2 participants