Proposal for better ergonomics when rendering marks
See original GitHub issueI’m facing a pain point with mark rendering in slate-react, and I know how I wish things worked, but I’m not sure what would actually be needed implementation-wise to pull it off.
Here’s a contrived example of what I’m going for.
Imagine wanting to linkify all text that matches a URL pattern, but you also want to (again, contrived) make the domain bold:
Using an inline isn’t great because it’s cumbersome to validate and restructure on every match and mismatch, and you still want the text to behave like normal text with cursor, focus, and selection.
Marks are a good fit, and especially decorations. You can just decorate with a link mark and a bold mark for each match with a single regex.
Imagine that the link mark has some styling to make the link red on hover. You’d want it to look like this:
Unforunately, because of the way marks are rendered, if you happen to hover over the domain portion, it would look like this:
And if you hovered the scheme, it would look like this:
This is because mark rendering actually breaks up overlapping marks into a series of smaller contiguous marks.
Ie. instead of rendering mark components like this:
<Link>https://<Bold>www.google.com</Bold>/webhp</Link>
They’re rendered like this:
<Link>https://</Link><Link><Bold>www.google.com</Bold></Link><Link>/webhp</Link>
I worked around this previously with a hack in my mark components themselves, making the assumption that children
of mark components would always be a string. I’d just create a single Link
component for the whole match and manipulate its children
into several strings wrapped in <span>
s, making the appropriate section bold.
However, after recent changes, leaves render text wrapped in a <span>
, meaning my brittle hack to manipulate strings can’t operate (slate-react expects the leaf span, with its attributes, to wrap the final text).
I think the changes helped a lot with focus behavior, but I can’t find a good way to pull off the desired behavior. I think what I really want is just more expected component rendering for marks, so marks that overlap would render components like this:
<Link>https://<Bold>www.google.com</Bold>/webhp</Link>
Is this feasible somehow? Any other approaches that would work well?
Issue Analytics
- State:
- Created 5 years ago
- Reactions:4
- Comments:13 (12 by maintainers)
Top GitHub Comments
Sounds good! I do think
isAtomic
is the right approach. In the short term, however, I decided it would be good for the health of my app to break as many decorations as possible down into smaller marks, then refactor everything to use pure CSS and just renderchildren
as-is. In the end, the only one that really didn’t fit well (and whereisAtomic
would help) is theStars
example above. For now, I have a glorious CSS hack to style the last star darker, which will someday be my shame when another developer uncovers it…Will see if I can get a chance to poke at atomic marks sometime soon! I’m sure it will bite me again.
@timothyarmes correctly pointed out that this is not solved. The leaves themselves are still broken up so there’s no guarantee the link remains intact. My bad!