languages: Add injections for string and tagged template literals for JS/TS(X) (#44180)
Vitaly Slobodin
created 1 week ago
Hi! This pull request adds language injections for string and tagged
template literals for JS/TS(X).
This is similar to what [this
extension](https://marketplace.visualstudio.com/items?itemName=bierner.comment-tagged-templates)
provides for VSCode. This PR is inspired by this tweet
https://x.com/leaverou/status/1996306611208388953?s=46&t=foDQRPR8oIl1buTJ4kZoSQ
I've added injections queries for the following languages: HTML, CSS,
GraphQL and SQL.
This works for:
- String literals: `const cssString = /* css */'button { color: hotpink
!important; }';`
- Template literals: ```const cssString = /* css */`button { color:
hotpink !important; }`;```
All injections support the format with whitespaces inside, i.e. `/* html
*/` and without them `/*html*/`.
## Screenshots
|before|after|
|---------|-----------|
| <img width="1596" height="1476" alt="CleanShot 2025-12-04 at 21 12
00@2x"
src="https://github.com/user-attachments/assets/8e0fb758-41f0-43a8-93e6-ae28f79d7c8f"
/> | <img width="1576" height="1496" alt="CleanShot 2025-12-04 at 21 08
35@2x"
src="https://github.com/user-attachments/assets/b47bb9c1-224e-4a24-8f08-a459f1081449"
/>|
Release Notes:
- Added language injections for string and tagged template literals in
JS/TS(X)
Change summary
crates/languages/src/javascript/injections.scm | 43 ++++++++++++++++++++
crates/languages/src/tsx/injections.scm | 43 ++++++++++++++++++++
crates/languages/src/typescript/injections.scm | 43 ++++++++++++++++++++
3 files changed, 129 insertions(+)
Detailed changes
@@ -83,3 +83,46 @@
arguments: (arguments (template_string (string_fragment) @injection.content
(#set! injection.language "isograph")))
)
+
+; Parse the contents of strings and tagged template
+; literals with leading ECMAScript comments:
+; '/* html */' or '/*html*/'
+(
+ ((comment) @_ecma_comment [
+ (string (string_fragment) @injection.content)
+ (template_string (string_fragment) @injection.content)
+ ])
+ (#match? @_ecma_comment "^\\/\\*\\s*html\\s*\\*\\/")
+ (#set! injection.language "html")
+)
+
+; '/* sql */' or '/*sql*/'
+(
+ ((comment) @_ecma_comment [
+ (string (string_fragment) @injection.content)
+ (template_string (string_fragment) @injection.content)
+ ])
+ (#match? @_ecma_comment "^\\/\\*\\s*sql\\s*\\*\\/")
+ (#set! injection.language "sql")
+)
+
+; '/* gql */' or '/*gql*/'
+; '/* graphql */' or '/*graphql*/'
+(
+ ((comment) @_ecma_comment [
+ (string (string_fragment) @injection.content)
+ (template_string (string_fragment) @injection.content)
+ ])
+ (#match? @_ecma_comment "^\\/\\*\\s*(gql|graphql)\\s*\\*\\/")
+ (#set! injection.language "graphql")
+)
+
+; '/* css */' or '/*css*/'
+(
+ ((comment) @_ecma_comment [
+ (string (string_fragment) @injection.content)
+ (template_string (string_fragment) @injection.content)
+ ])
+ (#match? @_ecma_comment "^\\/\\*\\s*(css)\\s*\\*\\/")
+ (#set! injection.language "css")
+)
@@ -83,3 +83,46 @@
arguments: (arguments (template_string (string_fragment) @injection.content
(#set! injection.language "isograph")))
)
+
+; Parse the contents of strings and tagged template
+; literals with leading ECMAScript comments:
+; '/* html */' or '/*html*/'
+(
+ ((comment) @_ecma_comment [
+ (string (string_fragment) @injection.content)
+ (template_string (string_fragment) @injection.content)
+ ])
+ (#match? @_ecma_comment "^\\/\\*\\s*html\\s*\\*\\/")
+ (#set! injection.language "html")
+)
+
+; '/* sql */' or '/*sql*/'
+(
+ ((comment) @_ecma_comment [
+ (string (string_fragment) @injection.content)
+ (template_string (string_fragment) @injection.content)
+ ])
+ (#match? @_ecma_comment "^\\/\\*\\s*sql\\s*\\*\\/")
+ (#set! injection.language "sql")
+)
+
+; '/* gql */' or '/*gql*/'
+; '/* graphql */' or '/*graphql*/'
+(
+ ((comment) @_ecma_comment [
+ (string (string_fragment) @injection.content)
+ (template_string (string_fragment) @injection.content)
+ ])
+ (#match? @_ecma_comment "^\\/\\*\\s*(gql|graphql)\\s*\\*\\/")
+ (#set! injection.language "graphql")
+)
+
+; '/* css */' or '/*css*/'
+(
+ ((comment) @_ecma_comment [
+ (string (string_fragment) @injection.content)
+ (template_string (string_fragment) @injection.content)
+ ])
+ (#match? @_ecma_comment "^\\/\\*\\s*(css)\\s*\\*\\/")
+ (#set! injection.language "css")
+)
@@ -124,3 +124,46 @@
]
)))
(#set! injection.language "css"))
+
+; Parse the contents of strings and tagged template
+; literals with leading ECMAScript comments:
+; '/* html */' or '/*html*/'
+(
+ ((comment) @_ecma_comment [
+ (string (string_fragment) @injection.content)
+ (template_string (string_fragment) @injection.content)
+ ])
+ (#match? @_ecma_comment "^\\/\\*\\s*html\\s*\\*\\/")
+ (#set! injection.language "html")
+)
+
+; '/* sql */' or '/*sql*/'
+(
+ ((comment) @_ecma_comment [
+ (string (string_fragment) @injection.content)
+ (template_string (string_fragment) @injection.content)
+ ])
+ (#match? @_ecma_comment "^\\/\\*\\s*sql\\s*\\*\\/")
+ (#set! injection.language "sql")
+)
+
+; '/* gql */' or '/*gql*/'
+; '/* graphql */' or '/*graphql*/'
+(
+ ((comment) @_ecma_comment [
+ (string (string_fragment) @injection.content)
+ (template_string (string_fragment) @injection.content)
+ ])
+ (#match? @_ecma_comment "^\\/\\*\\s*(gql|graphql)\\s*\\*\\/")
+ (#set! injection.language "graphql")
+)
+
+; '/* css */' or '/*css*/'
+(
+ ((comment) @_ecma_comment [
+ (string (string_fragment) @injection.content)
+ (template_string (string_fragment) @injection.content)
+ ])
+ (#match? @_ecma_comment "^\\/\\*\\s*(css)\\s*\\*\\/")
+ (#set! injection.language "css")
+)