From bd6dadaa0b2e950c80ab3c9610dc1678078b67a9 Mon Sep 17 00:00:00 2001 From: finico Date: Thu, 2 Apr 2026 19:26:08 +0300 Subject: [PATCH] languages: Change syntax highlighting for JSX elements (#49881) Syntax highlighting and its customization are very important to many developers, including me. I've looked through a number of issues and discussions on this topic and haven't found any active PRs. Currently, there's no way to customize highlighting for custom JSX tags, as they use `@type`. Since TSX has a particularly complex syntax and can often contain types/aliases/generics/tags in a dense sequence, they all blends into a single color and makes it difficult to "parse" by eyes. To avoid proposing something arbitrary, I looked into how this is done elsewhere. - VS Code `support.class.component.tsx` [TypeScriptReact.tmLanguage.json](https://github.com/microsoft/vscode/blob/724656efa2c26ab6e7eb2023426dcf2658dc3203/extensions/typescript-basics/syntaxes/TypeScriptReact.tmLanguage.json#L5802) But it relies on both legacy [tmLanguage naming conventions](https://macromates.com/manual/en/language_grammars#:~:text=rarely%20be%20used\).-,support,-%E2%80%94%20things%20provided%20by) and the outdated assumption that React components are always classes. - ReScript `@tag` [rescript-zed](https://github.com/rescript-lang/rescript-zed/blob/b3930c1754ab2762938244546ea2c7fb97d01cb3/languages/rescript/highlights.scm#L277) It's not entirely correct to just use a `@tag` - it's better to distinguish JSX Intrinsic Elements from custom ones. - Vue `@tag @tag.component.type.constructor` [zed-extensions/vue](https://github.com/zed-extensions/vue/blob/2697588c5cde11375d47f53f9449af8e32600d81/languages/vue/highlights.scm#L9C21-L9C52) - Svelte `@tag @tag.component.type.constructor` [zed-extensions/svelte](https://github.com/zed-extensions/svelte/blob/ae381a1217d14c26cbedfaf84b0a2f5ae508f40c/languages/svelte/highlights.scm#L46C21-L46C52) The similarity between Vue and Svelte implementations (perhaps one borrowed from the other) didn't seem coincidental and the approach felt appropriate. **I decided to adopt the same one to maintain consistency for theme creators.** So, how it looks: **Release (0.224.9) version** zed-one-release **Local version with changes** - no breaking changes for builtin themes - uses `type` color as before and can be changed in themes separately if needed zed-one-local **Local version with changes and theme overrides** zed-one-with-overrides With these changes in the config: ```jsonc "theme_overrides": { "One Light": { "syntax": { // "tag.component" also matches "type.component": { "color": "#d3604fff", }, }, }, }, ``` I'm pretty sure this will help many developers enjoy Zed even more. Release Notes: - Improved syntax highlighting for custom jsx elements in TSX and JavaScript languages. Theme authors and users can now highlight these in their theme/theme overrides using `tag.component.jsx` --- crates/grammars/src/javascript/highlights.scm | 18 +++++++++--------- crates/grammars/src/tsx/highlights.scm | 18 +++++++++--------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/crates/grammars/src/javascript/highlights.scm b/crates/grammars/src/javascript/highlights.scm index 4af87cc578e3060e72d1e1374f4904d8c7629ddf..f6354dd3a016f544e5be1616c3dfb12144855775 100644 --- a/crates/grammars/src/javascript/highlights.scm +++ b/crates/grammars/src/javascript/highlights.scm @@ -328,26 +328,26 @@ ; JSX elements (jsx_opening_element [ - (identifier) @type + (identifier) @type @tag.component.jsx (member_expression - object: (identifier) @type - property: (property_identifier) @type) + object: (identifier) @type @tag.component.jsx + property: (property_identifier) @type @tag.component.jsx) ]) (jsx_closing_element [ - (identifier) @type + (identifier) @type @tag.component.jsx (member_expression - object: (identifier) @type - property: (property_identifier) @type) + object: (identifier) @type @tag.component.jsx + property: (property_identifier) @type @tag.component.jsx) ]) (jsx_self_closing_element [ - (identifier) @type + (identifier) @type @tag.component.jsx (member_expression - object: (identifier) @type - property: (property_identifier) @type) + object: (identifier) @type @tag.component.jsx + property: (property_identifier) @type @tag.component.jsx) ]) (jsx_opening_element diff --git a/crates/grammars/src/tsx/highlights.scm b/crates/grammars/src/tsx/highlights.scm index 482bba7f081a44b78a2f2d72c3435d8a6419b874..0f203e7112cf14268d0edfed39b5624375d1a859 100644 --- a/crates/grammars/src/tsx/highlights.scm +++ b/crates/grammars/src/tsx/highlights.scm @@ -389,26 +389,26 @@ (jsx_opening_element [ - (identifier) @type + (identifier) @type @tag.component.jsx (member_expression - object: (identifier) @type - property: (property_identifier) @type) + object: (identifier) @type @tag.component.jsx + property: (property_identifier) @type @tag.component.jsx) ]) (jsx_closing_element [ - (identifier) @type + (identifier) @type @tag.component.jsx (member_expression - object: (identifier) @type - property: (property_identifier) @type) + object: (identifier) @type @tag.component.jsx + property: (property_identifier) @type @tag.component.jsx) ]) (jsx_self_closing_element [ - (identifier) @type + (identifier) @type @tag.component.jsx (member_expression - object: (identifier) @type - property: (property_identifier) @type) + object: (identifier) @type @tag.component.jsx + property: (property_identifier) @type @tag.component.jsx) ]) (jsx_opening_element