Skip to content

[SuperEditor][SuperReader] - Custom underline style configuration (Resolves #2675) #2677

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 11, 2025

Conversation

matthew-carroll
Copy link
Contributor

@matthew-carroll matthew-carroll commented May 19, 2025

[SuperEditor][SuperReader] - Custom underline style configuration (Resolves #2675)

Text can now be attributed for a custom underline, and that custom underline is painted by SuperEditor and SuperReader.

The first step is to attribute some text with a CustomUnderlineAttribution. This attribution includes a type which is a String that can be anything. The type is interpreted by the style system, so as long as the type maps to an underline style, it will be honored. An unknown type will paint a straight black underline.

Each TextComponentViewModel has the stylesheet applied to it in applyStyles(). Each text view model now looks for a collection of underline styles: customUnderlineStyles = styles[Styles.customUnderlineStyles];. Each TextComponentViewModel holds on to those styles.

A new style phase called CustomUnderlineStyler inspects each TextComponentViewModel and looks for CustomUnderlineAttributions in the text. If it finds any, then the CustomUnderlineStyler adds underlines to the TextComponentViewModel for each attribution.

After each view model runs applyStyles() and after the CustomUnderlineStyler parses the underlines out of the text, each TextComponentViewModel has enough information to create a list of underline styles for the text in the node. The method for this already existed before this PR - it's called createUnderlines(). That method now also creates these new custom underlines in addition to the existing composing region, spelling, and grammar underlines. The createUnderlines() method is called when the component is configured with the view model, e.g., when ParagraphComponent is created from the view model.

This PR also adds an offset property to the existing underline styles so that the underlines can be pushed up/down from their natural position.

Unrelated Changes

As I tried to add a new property to all text component view models, it became clear that it's tedious and error prone to maintain our approach to mixing in TextComponentViewModel and implementing copy(), ==, and hashCode. This requires replicating many lines per implementation and it's easy to miss one.

I refactored these relationships to significantly reduce tedious boilerplate.

Previously a call to copy() would create a new view model by passing every relevant property into its constructor. This required every text component to repeat all of these properties in the call to their constructors. The new approach in this PR is to leverage mutability, and let the mixin mutate all the properties that it wants. In other words, classes like ParagraphComponentViewModel and ListItemComponentViewModel now delegate to TextComponentViewModel to copy all the properties from TextComponentViewModel. As a result, we can implement new properties on TextComponentViewModel without altering any class that mixes in TextComponentViewModel.

A similar change was made to help with implementing == and hashCode via delegation to TextComponentViewModel.

Demo

Screenshot 2025-05-18 at 10 52 29 PM

Copy link
Collaborator

@angelosilvestre angelosilvestre left a comment

Choose a reason for hiding this comment

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

LGTM

@matthew-carroll matthew-carroll merged commit 8ed2d20 into main Jun 11, 2025
23 of 24 checks passed
@matthew-carroll matthew-carroll deleted the 2675_generalize-underline-styles branch June 11, 2025 23:49
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.

[SuperEditor] - Generalize underlines
2 participants