tsx-mode.el icon indicating copy to clipboard operation
tsx-mode.el copied to clipboard

Interpolating Javascript Breaks CSS Syntax Highlighting

Open stevemolitor opened this issue 2 years ago • 6 comments

A interpolated JS string in CSS causes all subsequent CSS to be syntax highlighted as if it were Javascript:

Running describe-face tells me that display, flex-direction and height, are tree-sitter-hl-face:variable, which is correct for CSS.

However background-color and width are tree-sitter-hl-face:tag, which is not correct.

stevemolitor avatar Mar 31 '22 15:03 stevemolitor

I get a similar experience. I think tsx-mode needs a strategy to detect template literals a bit like this issue:

https://github.com/polymode/polymode/issues/297

This is my experience:

Screenshot 2022-04-26 at 10 37 47

danieljamesross avatar Apr 26 '22 10:04 danieljamesross

FWIW I think this is best solved by using a tree-sitter grammar which understands CSS-in-JS. I've forked the existing tree-sitter CSS grammar repo and have something which mostly works, but (a) there are still a few rough edges and (b) I'm not sure if a CSS grammar is the correct place for such enhancements or if it would be better to create an entirely new grammar which inherits from CSS (like the Typescript grammar does from Javascript).

orzechowskid avatar Jul 18 '22 03:07 orzechowskid

I think you're probably right regarding writing a new grammar. Perhaps it ought to inherit CSS, javascript and typescript? It would be nice to have completion suggestions within template literals that are js or ts.

danieljamesross avatar Jul 20 '22 20:07 danieljamesross

thanks to the existing tree-sitter TS grammar we already know if point is inside a string template substitution, and if so then we enable TS autocompletion instead of CSS even if we're inside a CSS-in-JS region:

image

( https://github.com/orzechowskid/tsx-mode.el/blob/master/tsx-mode.el#L523 )

so that bit already exists, if I understand your comment correctly. for the rest of it, I think what needs to happen is one of the following:

  • extend the JS/TS grammar to detect CSS-in-JS, and tag the strings with a new node type so that we can use language injection to parse those nodes as CSS
  • extend the CSS grammar to detect JS template-string substitutions, and tag the substitutions with a new node type so that we can use language injection to parse those nodes as JS (or TS)

it seems like with the first option I'd have to play whack-a-mole with each new tagged-template string syntax that the community releases (I'd rather do that here in elisp :smile: ). but the second option should be enough to support all CSS-in-JS solutions which use tagged-template strings.

I've started deriving a CSS-in-JS grammar here if you're interested in following along (or helping out!).

orzechowskid avatar Jul 21 '22 01:07 orzechowskid

I'm happy with the current state of that CSS-in-JS grammar, and I've a new branch of tsx-mode (feature/css-in-js) which incorporates it and tells tree-sitter to use it. please add the straight.el recipe for that grammar repo to your init file:

(straight-use-package '(tree-sitter-css-in-js :type git :host github :repo "orzechowskid/tree-sitter-css-in-js"))

and update your recipe for tsx-mode to point to the above-mentioned branch, and let me know how it goes.

you can verify that everything is working by switching to the *tsx-mode css* hidden buffer and running (tree-sitter-debug-mode) in it. the resulting CST should contain some nice new js_interpolation nodes.

I've only tested the grammar on my Ubuntu machine so I'd be especially interested to hear from anyone who uses OSX or Windows, but all feedback is greatly appreciated.

this should also fix #11 .

orzechowskid avatar Aug 15 '22 02:08 orzechowskid

the next branch should contain the fix for this.

orzechowskid avatar Aug 28 '22 05:08 orzechowskid