diff --git a/bindings/node/gts.js b/bindings/node/gts.js
new file mode 100644
index 00000000..8eb37e65
--- /dev/null
+++ b/bindings/node/gts.js
@@ -0,0 +1 @@
+module.exports = require('.').gts;
diff --git a/bindings/node/index.js b/bindings/node/index.js
index 45f72986..8f2b2d92 100644
--- a/bindings/node/index.js
+++ b/bindings/node/index.js
@@ -5,4 +5,5 @@ module.exports = require("node-gyp-build")(root);
try {
module.exports.typescript.nodeTypeInfo = require("../../typescript/src/node-types.json");
module.exports.tsx.nodeTypeInfo = require("../../tsx/src/node-types.json");
+ module.exports.gts.nodeTypeInfo = require("../../gts/src/node-types.json");
} catch (_) { }
diff --git a/common/define-grammar.js b/common/define-grammar.js
index 3bd3297a..088a69df 100644
--- a/common/define-grammar.js
+++ b/common/define-grammar.js
@@ -114,10 +114,12 @@ module.exports = function defineGrammar(dialect) {
]).concat(
dialect === 'typescript' ? [
[$.primary_type, $.type_parameter],
- ] : [
+ ] : dialect === 'tsx' ? [
[$.jsx_opening_element, $.type_parameter],
[$.jsx_namespace_name, $.primary_type],
- ],
+ ] : dialect === 'gts' ? [
+ [$.glimmer_template, $.primary_type, $.type_parameter],
+ ] : [],
),
inline: ($, previous) => previous
@@ -215,15 +217,24 @@ module.exports = function defineGrammar(dialect) {
$.satisfies_expression,
$.instantiation_expression,
$.internal_module,
+ $.glimmer_template,
];
if (dialect === 'typescript') {
+ choices.push($.type_assertion);
+ choices.push(...previous.members.filter((member) => {
+ return member.name !== '_jsx_element' && member.name !== 'glimmer_template';
+ },
+ ));
+ } else if (dialect === 'gts') {
choices.push($.type_assertion);
choices.push(...previous.members.filter((member) =>
member.name !== '_jsx_element',
));
} else if (dialect === 'tsx') {
- choices.push(...previous.members);
+ choices.push(...previous.members.filter(member => {
+ return member.name !== 'glimmer_template';
+ }));
} else {
throw new Error(`Unknown dialect ${dialect}`);
}
@@ -231,6 +242,25 @@ module.exports = function defineGrammar(dialect) {
return choice(...choices);
},
+ // This rule is only referenced by expression when the dialect is 'gts'
+ // glimmer_template: $ => choice(
+ // seq(
+ // field('open_tag', $.glimmer_opening_tag),
+ // field('content', repeat($._glimmer_template_content)),
+ // field('close_tag', $.glimmer_closing_tag),
+ // ),
+ // // empty template has no content
+ // //
+ // seq(
+ // field('open_tag', $.glimmer_opening_tag),
+ // field('close_tag', $.glimmer_closing_tag),
+ // ),
+ // ),
+ //
+ // _glimmer_template_content: _ => /.{1,}/,
+ // glimmer_opening_tag: _ => '',
+ // glimmer_closing_tag: _ => '',
+
_jsx_start_opening_element: $ => seq(
'<',
optional(
@@ -419,6 +449,7 @@ module.exports = function defineGrammar(dialect) {
class_body: $ => seq(
'{',
repeat(choice(
+ field('template', $.glimmer_template),
seq(
repeat(field('decorator', $.decorator)),
$.method_definition,
diff --git a/gts/Makefile b/gts/Makefile
new file mode 100644
index 00000000..f411bfe2
--- /dev/null
+++ b/gts/Makefile
@@ -0,0 +1,3 @@
+LANGUAGE_NAME := tree-sitter-tsx
+
+include ../common/common.mak
diff --git a/gts/grammar.js b/gts/grammar.js
new file mode 100644
index 00000000..83a58a5f
--- /dev/null
+++ b/gts/grammar.js
@@ -0,0 +1,3 @@
+const defineGrammar = require('../common/define-grammar');
+
+module.exports = defineGrammar('gts');
diff --git a/gts/package.json b/gts/package.json
new file mode 100644
index 00000000..e317e9ac
--- /dev/null
+++ b/gts/package.json
@@ -0,0 +1,3 @@
+{
+ "main": "../bindings/node/gts"
+}
diff --git a/package.json b/package.json
index af312a24..e0529f42 100644
--- a/package.json
+++ b/package.json
@@ -45,16 +45,17 @@
"devDependencies": {
"eslint": ">=8.57.0",
"eslint-config-google": "^0.14.0",
+ "prebuildify": "^6.0.1",
"tree-sitter-cli": "^0.22.6",
- "tree-sitter-javascript": "^0.21.4",
- "prebuildify": "^6.0.1"
+ "tree-sitter-javascript": "^0.21.4"
},
"scripts": {
"install": "node-gyp-build",
"prebuildify": "prebuildify --napi --strip",
- "build": "npm run build-typescript && npm run build-tsx",
+ "build": "npm run build-typescript && npm run build-tsx && npm run build-gts",
"build-typescript": "cd typescript && npx tree-sitter generate --no-bindings",
"build-tsx": "cd tsx && npx tree-sitter generate --no-bindings",
+ "build-gts": "cd gts && npx tree-sitter generate --no-bindings",
"lint": "eslint common/define-grammar.js",
"parse": "tree-sitter parse",
"test": "tree-sitter test"
diff --git a/test/corpus/expressions.txt b/test/corpus/expressions.txt
index facc6de8..64c16b46 100644
--- a/test/corpus/expressions.txt
+++ b/test/corpus/expressions.txt
@@ -424,3 +424,28 @@ a ? function(){ return true } : b;
(return_statement
(true))))
(identifier))))
+
+==========================================================
+Class Component with content
+:language(gts)
+==========================================================
+
+export class Menu extends Component<{
+ Args: {
+ /* args here */
+ }
+}> {
+
+ {{#let (IsOpen) (TriggerElement) as |isOpen triggerEl|}}
+ {{/let}}
+
+}
+
+----
+
+(program
+ (expression_statement
+ (glimmer_template
+ (glimmer_opening_tag)
+ (glimmer_closing_tag)
+ )))