Add JSX and TSX syntax highlighting (#7686)

Robin PfΓ€ffle created

This PR fixes / adds support for syntax highlighting in JSX and TSX.

Previously to this PR the syntax highlighting was not really working.
HTML tags have not been displayed as such.

<img width="1127" alt="SCR-20240212-ihne"
src="https://github.com/zed-industries/zed/assets/67913738/793c778f-aa11-4574-883f-6d336247bd9e">

After:

<img width="1225" alt="SCR-20240212-jqvv"
src="https://github.com/zed-industries/zed/assets/67913738/f4d96b1d-6063-41ac-bd46-76ce1fc0a131">

Release Notes:

- Added support for JSX and TSX syntax highlighting

Change summary

crates/zed/src/languages/javascript/highlights.scm |  12 
crates/zed/src/languages/tsx/highlights.scm        |   1 
crates/zed/src/languages/tsx/highlights.scm        | 231 ++++++++++++++++
3 files changed, 242 insertions(+), 2 deletions(-)

Detailed changes

crates/zed/src/languages/javascript/highlights.scm πŸ”—

@@ -214,4 +214,14 @@
   "type"
   "readonly"
   "override"
-] @keyword
+] @keyword
+
+; JSX elements
+(jsx_opening_element (identifier) @tag (#match? @tag "^[a-z][^.]*$"))
+(jsx_closing_element (identifier) @tag (#match? @tag "^[a-z][^.]*$"))
+(jsx_self_closing_element (identifier) @tag (#match? @tag "^[a-z][^.]*$"))
+
+(jsx_attribute (property_identifier) @attribute)
+(jsx_opening_element (["<" ">"]) @punctuation.bracket)
+(jsx_closing_element (["<" "/" ">"]) @punctuation.bracket)
+(jsx_self_closing_element (["<" "/" ">"]) @punctuation.bracket)

crates/zed/src/languages/tsx/highlights.scm πŸ”—

@@ -0,0 +1,231 @@
+; Variables
+
+(identifier) @variable
+
+; Properties
+
+(property_identifier) @property
+
+; Function and method calls
+
+(call_expression
+  function: (identifier) @function)
+
+(call_expression
+  function: (member_expression
+    property: (property_identifier) @function.method))
+
+; Function and method definitions
+
+(function
+  name: (identifier) @function)
+(function_declaration
+  name: (identifier) @function)
+(method_definition
+  name: (property_identifier) @function.method)
+
+(pair
+  key: (property_identifier) @function.method
+  value: [(function) (arrow_function)])
+
+(assignment_expression
+  left: (member_expression
+    property: (property_identifier) @function.method)
+  right: [(function) (arrow_function)])
+
+(variable_declarator
+  name: (identifier) @function
+  value: [(function) (arrow_function)])
+
+(assignment_expression
+  left: (identifier) @function
+  right: [(function) (arrow_function)])
+
+; Special identifiers
+
+((identifier) @constructor
+ (#match? @constructor "^[A-Z]"))
+
+((identifier) @type
+ (#match? @type "^[A-Z]"))
+(type_identifier) @type
+(predefined_type) @type.builtin
+
+([
+  (identifier)
+  (shorthand_property_identifier)
+  (shorthand_property_identifier_pattern)
+ ] @constant
+ (#match? @constant "^_*[A-Z_][A-Z\\d_]*$"))
+
+; Literals
+
+(this) @variable.special
+(super) @variable.special
+
+[
+  (null)
+  (undefined)
+] @constant.builtin
+
+[
+  (true)
+  (false)
+] @boolean
+
+(comment) @comment
+
+[
+  (string)
+  (template_string)
+] @string
+
+(regex) @string.regex
+(number) @number
+
+; Tokens
+
+[
+  ";"
+  "?."
+  "."
+  ","
+  ":"
+] @punctuation.delimiter
+
+[
+  "-"
+  "--"
+  "-="
+  "+"
+  "++"
+  "+="
+  "*"
+  "*="
+  "**"
+  "**="
+  "/"
+  "/="
+  "%"
+  "%="
+  "<"
+  "<="
+  "<<"
+  "<<="
+  "="
+  "=="
+  "==="
+  "!"
+  "!="
+  "!=="
+  "=>"
+  ">"
+  ">="
+  ">>"
+  ">>="
+  ">>>"
+  ">>>="
+  "~"
+  "^"
+  "&"
+  "|"
+  "^="
+  "&="
+  "|="
+  "&&"
+  "||"
+  "??"
+  "&&="
+  "||="
+  "??="
+] @operator
+
+[
+  "("
+  ")"
+  "["
+  "]"
+  "{"
+  "}"
+]  @punctuation.bracket
+
+[
+  "as"
+  "async"
+  "await"
+  "break"
+  "case"
+  "catch"
+  "class"
+  "const"
+  "continue"
+  "debugger"
+  "default"
+  "delete"
+  "do"
+  "else"
+  "export"
+  "extends"
+  "finally"
+  "for"
+  "from"
+  "function"
+  "get"
+  "if"
+  "import"
+  "in"
+  "instanceof"
+  "let"
+  "new"
+  "of"
+  "return"
+  "satisfies"
+  "set"
+  "static"
+  "switch"
+  "target"
+  "throw"
+  "try"
+  "typeof"
+  "var"
+  "void"
+  "while"
+  "with"
+  "yield"
+] @keyword
+
+(template_substitution
+  "${" @punctuation.special
+  "}" @punctuation.special) @embedded
+
+(type_arguments
+  "<" @punctuation.bracket
+  ">" @punctuation.bracket)
+
+; Keywords
+
+[ "abstract"
+  "declare"
+  "enum"
+  "export"
+  "implements"
+  "interface"
+  "keyof"
+  "namespace"
+  "private"
+  "protected"
+  "public"
+  "type"
+  "readonly"
+  "override"
+] @keyword
+
+; JSX elements
+(jsx_opening_element (identifier) @tag (#match? @tag "^[a-z][^.]*$"))
+(jsx_closing_element (identifier) @tag (#match? @tag "^[a-z][^.]*$"))
+(jsx_self_closing_element (identifier) @tag (#match? @tag "^[a-z][^.]*$"))
+
+(jsx_attribute (property_identifier) @attribute)
+(jsx_opening_element (["<" ">"]) @punctuation.bracket)
+(jsx_closing_element (["<" "/" ">"]) @punctuation.bracket)
+(jsx_self_closing_element (["<" "/" ">"]) @punctuation.bracket)