andreruffert/syntax-highlight-element

[Feature] Allow for `contenteditable`

Closed this issue · 4 comments

I love the execution of this Web Component. Great work! After trying it out for myself I noticed it's partially possible to use syntax-highlight with contenteditable="plaintext-only", by listening to the input event and running the update() method. The only issue is that it can't handle returns. With contenteditable adding a return causes almost like a new range within the element which confuses the internal component code. Maybe this could be mitigated with some kind of concatenation that doesn't reset the cursor position?

Check out the last example in this demo on CodePen https://codepen.io/daviddarnes/pen/bNVVVxQ. You'll see that the CSS does highlight when writing in a single line, but as soon as you press return the highlighting breaks and an error occurs.

@daviddarnes thank you for your kind words and feedback!

Actually using the custom element with the [contenteditable] attribute is already supported.
I implemented this myself for another OSS project.

https://github.com/andreruffert/range-slider-element/blob/main/docs/index.html#L260-L276

[contenteditable="plaintext-only"] uses HTML breaks from time to time and also creates new text nodes whenever hitting return. Since the custom element expects a single node, we need to flatten the text nodes before re-tokenizing the code.

Try executing the Node.normalize() method before calling the SyntaxHighlightElement.update() method.

I created a on-the-fly syntax highlighting CodePen demo.

It might make sense to flatten the text nodes by default before tokenizing the code 🤔

Wow that's awesome! I just tried it and you're right, works super well. I don't see why you can add this feature as part of the component. You could enable not only the node flattening but also the event listener as soon as they add contenteditable="plaintext-only" to the component instance.

PS. Might be worth adding a default role of code to the element for nice semantics, with the option to override it inline. I don't mind making a PR for this if you like

Wow that's awesome! I just tried it and you're right, works super well. I don't see why you can add this feature as part of the component. You could enable not only the node flattening but also the event listener as soon as they add contenteditable="plaintext-only" to the component instance.

I’m just a bit hesitant adding the functionality to the element itself. I like to keep things simple. 😄
Let’s see, might be something for the future just not entirely sure yet.

PS. Might be worth adding a default role of code to the element for nice semantics, with the option to override it inline. I don't mind making a PR for this if you like

Thanks, have you seen the current implementation is using ElementInternals to set the default ARIA role to code which can be overridden by using the [role] attribute directly.

https://github.com/andreruffert/syntax-highlight-element/blob/main/src/syntax-highlight-element.js#L49

As far as I know, this should take care of the semantics. However, I might be missing something...

I get it, might be asking for trouble by providing editing abilities.

Oh that's odd, I checked in the inspector and the element role was returning null 🤔