Skip to content

Spellcheck: Live check - #776

Open
robinbisping wants to merge 9 commits into
masterfrom
spellcheck-live-check
Open

robinbisping wants to merge 9 commits into
masterfrom
spellcheck-live-check

Conversation

@robinbisping

@robinbisping robinbisping commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Relations:

Description

Spellchecking needs to underline mistakes in a text, but a mistake is not part of the document. The existing highlighting wraps text in marker elements, which would put the underlines into the content. This adds a second way to highlight, built on the CSS Custom Highlight API. The browser paints the ranges and the DOM stays untouched.

  • setCssHighlight({name, ranges}) highlights character ranges under a name. One call can cover ranges in many editables, and it replaces everything held under that name. The look is up to the consumer through the ::highlight() selector.
  • deleteCssHighlight({name}) removes the highlights of a name and forgets where they were.
  • getCssHighlightText({editableHost}) returns the text of an editable without its markup. This is the text the character offsets count against.
  • getCssHighlightCursorOffset({editableHost}) returns the cursor position as a character offset in that text, which tells a caller which highlight the cursor sits in.
  • getCssHighlightRects({editableHost, start, end}) returns where a character range sits on screen, so a caller can place a popover next to it.
  • replaceCssHighlight({editableHost, start, end, text}) replaces a character range with new text, dispatched like any other edit.

Changelog

  • 🎁 New API to highlight character ranges in an editable without changing its content, based on the CSS Custom Highlight API. Highlights survive markup changes such as comments and formatting.

@robinbisping robinbisping changed the title Spellcheck Spellcheck: Live check Aug 21, 2026
@robinbisping
robinbisping force-pushed the spellcheck-live-check branch from fc34d11 to 7bbb8c6 Compare August 21, 2026 12:01
@robinbisping
robinbisping marked this pull request as ready for review August 21, 2026 12:15
@robinbisping
robinbisping requested a review from eileenoo August 21, 2026 12:15
@eileenoo
eileenoo requested review from ajwild and arddor August 26, 2026 11:36
@ajwild

ajwild commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

My main question would be whether something introduced in Firefox in March 2026 is ready for roll-out, I've been thinking about this for comments, but I wasn't sure we could move forward with it until March 2027. I'll try to dig into how things work on older versions of Firefox.

@robinbisping

robinbisping commented Aug 28, 2026

Copy link
Copy Markdown
Contributor Author

My main question would be whether something introduced in Firefox in March 2026 is ready for roll-out, I've been thinking about this for comments, but I wasn't sure we could move forward with it until March 2027. I'll try to dig into how things work on older versions of Firefox.

Ah, I have a misunderstood it then. I thought we discussed this briefly in a team meeting and the conclusion was that we should move forward with CSS highlights even though Firefox just introduced support for it.

Realisticly this feature will only be rolled out beginning of next year anyway. No customer has signed a contract yet. So that makes the Firefox issue a bit less severe. But of course we'd still break our own promise.

What we need for sure is error handling if the feature is not supported. That's still lacking.

Let's discuss in the meeting how to proceed here. :)

@ajwild

ajwild commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Sorry, you're right, I'd forgotten about that discussion. It's also a great point about the expected roll-out date - we'll be around 1 year of browser support by then anyway. We should just bump the supported browser versions listed on the technical release notes whenever a customer starts to use it.

Comment thread src/smartQuotes.js
}
const newText = `${nodeValue.substring(0, index)}${quoteType}${nodeValue.substring(index + 1)}`
const newTextNode = document.createTextNode(newText)
startContainer.replaceWith(newTextNode)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I had to rewrite this implementation to not replace entire nodes. It cleared the css highlights.

ajwild and others added 3 commits September 8, 2026 17:59
Blurring runs cleanInternals, which rewrites the whole markup, so the ranges
the browser was painting no longer point at anything.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
An empty editable is given a zero width space and a newline puts one after the
break, and typing on both sides leaves one inside a word. It counted towards the
offsets until the clean on blur took it out, which moved every mark behind it
and dropped the ones that then reached past the end of the text.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The clean on blur drops leading breaks and trims the whitespace at both ends, so
counting those moved every mark behind them and dropped the ones that then
reached past the end of the text. Leaving them out can only hide a position the
clean would have kept, never keep one it takes away.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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