From c4d00cdd4e5a1619eeaf679d786d7db2aea72bdd Mon Sep 17 00:00:00 2001 From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com> Date: Mon, 4 Nov 2024 11:46:17 -0500 Subject: [PATCH] Copy code-mirror-lang-js to ts --- .../glimmer-ts/codemirror/.eslintignore | 8 ++ .../glimmer-ts/codemirror/.eslintrc.cjs | 18 +++ .../syntax/glimmer-ts/codemirror/.gitignore | 4 + .../glimmer-ts/codemirror/.prettierignore | 17 +++ .../glimmer-ts/codemirror/.prettierrc.cjs | 37 ++++++ .../syntax/glimmer-ts/codemirror/CHANGELOG.md | 45 +++++++ .../syntax/glimmer-ts/codemirror/README.md | 20 +++ .../glimmer-ts/codemirror/dev/.eslintignore | 8 ++ .../glimmer-ts/codemirror/dev/.eslintrc.cjs | 5 + .../glimmer-ts/codemirror/dev/.prettierignore | 17 +++ .../glimmer-ts/codemirror/dev/.prettierrc.cjs | 37 ++++++ .../glimmer-ts/codemirror/dev/CHANGELOG.md | 3 + .../glimmer-ts/codemirror/dev/index.html | 42 +++++++ .../glimmer-ts/codemirror/dev/package.json | 40 ++++++ .../glimmer-ts/codemirror/dev/preview.ts | 105 ++++++++++++++++ .../glimmer-ts/codemirror/dev/vite.config.ts | 9 ++ .../syntax/glimmer-ts/codemirror/package.json | 64 ++++++++++ .../glimmer-ts/codemirror/rollup.config.mjs | 12 ++ .../glimmer-ts/codemirror/src/highlight.ts | 8 ++ .../syntax/glimmer-ts/codemirror/src/index.ts | 42 +++++++ .../glimmer-ts/codemirror/src/syntax.grammar | 14 +++ .../codemirror/src/syntax.grammar.d.ts | 3 + .../codemirror/src/syntax.grammar.terms.d.ts | 3 + .../glimmer-ts/codemirror/src/tokens.ts | 43 +++++++ .../glimmer-ts/codemirror/test/comments.txt | 116 ++++++++++++++++++ .../glimmer-ts/codemirror/test/complex.txt | 24 ++++ .../glimmer-ts/codemirror/test/expression.txt | 95 ++++++++++++++ .../glimmer-ts/codemirror/test/literals.txt | 78 ++++++++++++ .../glimmer-ts/codemirror/test/numbers.txt | 88 +++++++++++++ .../codemirror/test/property-paths.txt | 79 ++++++++++++ .../glimmer-ts/codemirror/test/strings.txt | 64 ++++++++++ .../glimmer-ts/codemirror/tsconfig.json | 3 + 32 files changed, 1151 insertions(+) create mode 100644 packages/syntax/glimmer-ts/codemirror/.eslintignore create mode 100644 packages/syntax/glimmer-ts/codemirror/.eslintrc.cjs create mode 100644 packages/syntax/glimmer-ts/codemirror/.gitignore create mode 100644 packages/syntax/glimmer-ts/codemirror/.prettierignore create mode 100644 packages/syntax/glimmer-ts/codemirror/.prettierrc.cjs create mode 100644 packages/syntax/glimmer-ts/codemirror/CHANGELOG.md create mode 100644 packages/syntax/glimmer-ts/codemirror/README.md create mode 100644 packages/syntax/glimmer-ts/codemirror/dev/.eslintignore create mode 100644 packages/syntax/glimmer-ts/codemirror/dev/.eslintrc.cjs create mode 100644 packages/syntax/glimmer-ts/codemirror/dev/.prettierignore create mode 100644 packages/syntax/glimmer-ts/codemirror/dev/.prettierrc.cjs create mode 100644 packages/syntax/glimmer-ts/codemirror/dev/CHANGELOG.md create mode 100644 packages/syntax/glimmer-ts/codemirror/dev/index.html create mode 100644 packages/syntax/glimmer-ts/codemirror/dev/package.json create mode 100644 packages/syntax/glimmer-ts/codemirror/dev/preview.ts create mode 100644 packages/syntax/glimmer-ts/codemirror/dev/vite.config.ts create mode 100644 packages/syntax/glimmer-ts/codemirror/package.json create mode 100644 packages/syntax/glimmer-ts/codemirror/rollup.config.mjs create mode 100644 packages/syntax/glimmer-ts/codemirror/src/highlight.ts create mode 100644 packages/syntax/glimmer-ts/codemirror/src/index.ts create mode 100644 packages/syntax/glimmer-ts/codemirror/src/syntax.grammar create mode 100644 packages/syntax/glimmer-ts/codemirror/src/syntax.grammar.d.ts create mode 100644 packages/syntax/glimmer-ts/codemirror/src/syntax.grammar.terms.d.ts create mode 100644 packages/syntax/glimmer-ts/codemirror/src/tokens.ts create mode 100644 packages/syntax/glimmer-ts/codemirror/test/comments.txt create mode 100644 packages/syntax/glimmer-ts/codemirror/test/complex.txt create mode 100644 packages/syntax/glimmer-ts/codemirror/test/expression.txt create mode 100644 packages/syntax/glimmer-ts/codemirror/test/literals.txt create mode 100644 packages/syntax/glimmer-ts/codemirror/test/numbers.txt create mode 100644 packages/syntax/glimmer-ts/codemirror/test/property-paths.txt create mode 100644 packages/syntax/glimmer-ts/codemirror/test/strings.txt create mode 100644 packages/syntax/glimmer-ts/codemirror/tsconfig.json diff --git a/packages/syntax/glimmer-ts/codemirror/.eslintignore b/packages/syntax/glimmer-ts/codemirror/.eslintignore new file mode 100644 index 000000000..b9ef98ff5 --- /dev/null +++ b/packages/syntax/glimmer-ts/codemirror/.eslintignore @@ -0,0 +1,8 @@ +dist/ +declarations/ +node_modules/ +tmp/ +vendor/ +public/ +coverage/ +*.ember-try diff --git a/packages/syntax/glimmer-ts/codemirror/.eslintrc.cjs b/packages/syntax/glimmer-ts/codemirror/.eslintrc.cjs new file mode 100644 index 000000000..6ab545d79 --- /dev/null +++ b/packages/syntax/glimmer-ts/codemirror/.eslintrc.cjs @@ -0,0 +1,18 @@ +'use strict'; + +const { configs } = require('@nullvoxpopuli/eslint-configs'); + +const config = configs.crossPlatform(); + +module.exports = { + ...config, + overrides: [ + ...config.overrides, + { + files: ['**/*.ts'], + rules: { + '@typescript-eslint/no-explicit-any': 'off', + }, + }, + ], +}; diff --git a/packages/syntax/glimmer-ts/codemirror/.gitignore b/packages/syntax/glimmer-ts/codemirror/.gitignore new file mode 100644 index 000000000..a1593dfc3 --- /dev/null +++ b/packages/syntax/glimmer-ts/codemirror/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/src/parser.* +/dist +.cache diff --git a/packages/syntax/glimmer-ts/codemirror/.prettierignore b/packages/syntax/glimmer-ts/codemirror/.prettierignore new file mode 100644 index 000000000..34961cc27 --- /dev/null +++ b/packages/syntax/glimmer-ts/codemirror/.prettierignore @@ -0,0 +1,17 @@ +*.yml +*.yaml +*.md +*.json +renovate.json5 +docs/ + +# errors at the moment on gts files in here +app/templates/ + +node_modules/ +dist/ +declarations/ +public/ +vendor/ +coverage/ +.lint-todo/ diff --git a/packages/syntax/glimmer-ts/codemirror/.prettierrc.cjs b/packages/syntax/glimmer-ts/codemirror/.prettierrc.cjs new file mode 100644 index 000000000..1ee45a09f --- /dev/null +++ b/packages/syntax/glimmer-ts/codemirror/.prettierrc.cjs @@ -0,0 +1,37 @@ +'use strict'; + +module.exports = { + printWidth: 100, + plugins: ['prettier-plugin-ember-template-tag'], + overrides: [ + { + // Lol, JavaScript + files: ['*.js', '*.ts', '*.cjs', '.mjs', '.cts', '.mts', '.cts'], + options: { + singleQuote: true, + trailingComma: 'es5', + }, + }, + { + files: ['*.json'], + options: { + singleQuote: false, + }, + }, + { + files: ['*.hbs'], + options: { + singleQuote: false, + }, + }, + { + files: ['*.gjs', '*.gts'], + options: { + parser: 'ember-template-tag', + singleQuote: true, + templateSingleQuote: false, + trailingComma: 'es5', + }, + }, + ], +}; diff --git a/packages/syntax/glimmer-ts/codemirror/CHANGELOG.md b/packages/syntax/glimmer-ts/codemirror/CHANGELOG.md new file mode 100644 index 000000000..254ee1cc4 --- /dev/null +++ b/packages/syntax/glimmer-ts/codemirror/CHANGELOG.md @@ -0,0 +1,45 @@ +# codemirror-lang-glimmer-js + +## 0.0.0 + +### Patch Changes + +- Updated dependencies []: + - codemirror-lang-glimmer@0.0.0 + +## 0.0.0-beta.4 + +### Patch Changes + +- 77ad072: Add and consume glimdown package, split gjs into gjs and gts +- 0071216: Dependency updates +- Updated dependencies [77ad072] +- Updated dependencies [0071216] + - codemirror-lang-glimmer@0.0.0-beta.4 + +## 0.0.0-beta.3 + +### Patch Changes + +- 20dab8a: Initial development pre-release +- Updated dependencies [20dab8a] + - codemirror-lang-glimmer@0.0.0-beta.3 + +## 0.0.0-beta.2 + +### Patch Changes + +- 40fd2df: Shipped built assets in the npm package +- Updated dependencies [40fd2df] + - codemirror-lang-glimmer@0.0.0-beta.2 + +## 0.0.0-beta.1 + +### Minor Changes + +- e02e2b0: Initial release + +### Patch Changes + +- Updated dependencies [e02e2b0] + - codemirror-lang-glimmer@0.0.0-beta.1 diff --git a/packages/syntax/glimmer-ts/codemirror/README.md b/packages/syntax/glimmer-ts/codemirror/README.md new file mode 100644 index 000000000..219d02ff0 --- /dev/null +++ b/packages/syntax/glimmer-ts/codemirror/README.md @@ -0,0 +1,20 @@ +# CodeMirror Glimmer + +This is a CodeMirror 6 plugin that adds support for Glimmer (gjs and gts). + +### Usage + +```typescript +import { EditorState } from '@codemirror/state'; +import { EditorView } from '@codemirror/view'; +import { glimmer } from 'tbd'; +import { basicSetup } from 'codemirror'; + +new EditorView({ + state: EditorState.create({ + doc: `
{a}
`, + extensions: [basicSetup, glimmer()], + }), + parent: document.querySelector('#editor'), +}); +``` diff --git a/packages/syntax/glimmer-ts/codemirror/dev/.eslintignore b/packages/syntax/glimmer-ts/codemirror/dev/.eslintignore new file mode 100644 index 000000000..b9ef98ff5 --- /dev/null +++ b/packages/syntax/glimmer-ts/codemirror/dev/.eslintignore @@ -0,0 +1,8 @@ +dist/ +declarations/ +node_modules/ +tmp/ +vendor/ +public/ +coverage/ +*.ember-try diff --git a/packages/syntax/glimmer-ts/codemirror/dev/.eslintrc.cjs b/packages/syntax/glimmer-ts/codemirror/dev/.eslintrc.cjs new file mode 100644 index 000000000..2559f1395 --- /dev/null +++ b/packages/syntax/glimmer-ts/codemirror/dev/.eslintrc.cjs @@ -0,0 +1,5 @@ +'use strict'; + +const { configs } = require('@nullvoxpopuli/eslint-configs'); + +module.exports = configs.crossPlatform(); diff --git a/packages/syntax/glimmer-ts/codemirror/dev/.prettierignore b/packages/syntax/glimmer-ts/codemirror/dev/.prettierignore new file mode 100644 index 000000000..34961cc27 --- /dev/null +++ b/packages/syntax/glimmer-ts/codemirror/dev/.prettierignore @@ -0,0 +1,17 @@ +*.yml +*.yaml +*.md +*.json +renovate.json5 +docs/ + +# errors at the moment on gts files in here +app/templates/ + +node_modules/ +dist/ +declarations/ +public/ +vendor/ +coverage/ +.lint-todo/ diff --git a/packages/syntax/glimmer-ts/codemirror/dev/.prettierrc.cjs b/packages/syntax/glimmer-ts/codemirror/dev/.prettierrc.cjs new file mode 100644 index 000000000..1ee45a09f --- /dev/null +++ b/packages/syntax/glimmer-ts/codemirror/dev/.prettierrc.cjs @@ -0,0 +1,37 @@ +'use strict'; + +module.exports = { + printWidth: 100, + plugins: ['prettier-plugin-ember-template-tag'], + overrides: [ + { + // Lol, JavaScript + files: ['*.js', '*.ts', '*.cjs', '.mjs', '.cts', '.mts', '.cts'], + options: { + singleQuote: true, + trailingComma: 'es5', + }, + }, + { + files: ['*.json'], + options: { + singleQuote: false, + }, + }, + { + files: ['*.hbs'], + options: { + singleQuote: false, + }, + }, + { + files: ['*.gjs', '*.gts'], + options: { + parser: 'ember-template-tag', + singleQuote: true, + templateSingleQuote: false, + trailingComma: 'es5', + }, + }, + ], +}; diff --git a/packages/syntax/glimmer-ts/codemirror/dev/CHANGELOG.md b/packages/syntax/glimmer-ts/codemirror/dev/CHANGELOG.md new file mode 100644 index 000000000..c12e143e9 --- /dev/null +++ b/packages/syntax/glimmer-ts/codemirror/dev/CHANGELOG.md @@ -0,0 +1,3 @@ +# @glimdown/glimmer-js-dev-preview + +## 0.0.1 diff --git a/packages/syntax/glimmer-ts/codemirror/dev/index.html b/packages/syntax/glimmer-ts/codemirror/dev/index.html new file mode 100644 index 000000000..fe4077d6f --- /dev/null +++ b/packages/syntax/glimmer-ts/codemirror/dev/index.html @@ -0,0 +1,42 @@ + + + + + + Vite App + + + + +
+
+
+
+ + + + diff --git a/packages/syntax/glimmer-ts/codemirror/dev/package.json b/packages/syntax/glimmer-ts/codemirror/dev/package.json new file mode 100644 index 000000000..68038c1c0 --- /dev/null +++ b/packages/syntax/glimmer-ts/codemirror/dev/package.json @@ -0,0 +1,40 @@ +{ + "name": "@glimdown/glimmer-js-dev-preview", + "version": "0.0.1", + "private": true, + "scripts": { + "dev": "vite .", + "lint": "pnpm -w exec lint", + "lint:fix": "pnpm -w exec lint fix", + "lint:js": "pnpm -w exec lint js", + "lint:js:fix": "pnpm -w exec lint js:fix", + "lint:prettier:fix": "pnpm -w exec lint prettier:fix", + "lint:prettier": "pnpm -w exec lint prettier" + }, + "devDependencies": { + "@babel/core": "^7.25.7", + "@babel/eslint-parser": "^7.25.7", + "@codemirror/language": "^6.10.3", + "@codemirror/state": "^6.4.0", + "@codemirror/theme-one-dark": "^6.1.2", + "@codemirror/view": "^6.34.1", + "@glimdown/codemirror-dev-preview": "workspace:*", + "@nullvoxpopuli/eslint-configs": "^4.0.0", + "@typescript-eslint/eslint-plugin": "^8.8.0", + "@typescript-eslint/parser": "^8.8.0", + "eslint": "^8.55.0", + "prettier": "^3.3.3", + "typescript": "^5.4.5", + "vite": "^5.4.8" + }, + "volta": { + "extends": "../../../../../package.json" + }, + "repository": { + "type": "git", + "url": "https://github.com/NullVoxPopuli/limber.git", + "directory": "packages/syntax/glimmer-js/codemirror/dev" + }, + "license": "MIT", + "author": "NullVoxPopuli" +} diff --git a/packages/syntax/glimmer-ts/codemirror/dev/preview.ts b/packages/syntax/glimmer-ts/codemirror/dev/preview.ts new file mode 100644 index 000000000..107f4e790 --- /dev/null +++ b/packages/syntax/glimmer-ts/codemirror/dev/preview.ts @@ -0,0 +1,105 @@ +import { syntaxTree } from '@codemirror/language'; +import { EditorState } from '@codemirror/state'; +import { oneDark } from '@codemirror/theme-one-dark'; +import { EditorView } from '@codemirror/view'; +import { basicSetup } from 'codemirror'; + +import { printTree } from '@glimdown/codemirror-dev-preview/print-tree'; + +import { gjs, gjsLanguage } from '../dist/'; + +const testDoc = ` +const Foo = ; + +class Bar { + greeting = "hello world!"; + + +} + +const code = (text) => JSON.stringify(text, null, 4); + + +`; + +const doc = testDoc; + +const syncAST = EditorView.updateListener.of((update) => { + if (update.docChanged || update.selectionSet) { + const { from: oldFrom, to: oldTo } = update.startState.selection.ranges[0]; + let { from, to } = update.state.selection.ranges[0]; + + const docChanged = update.docChanged; + const selectionChanged = !( + (from === to && oldFrom === oldTo) || + (from === oldFrom && to === oldTo) + ); + const hasSelection = from !== to; + + if (docChanged || selectionChanged) { + const glimmerAST = printTree( + syntaxTree(update.view.state), + update.state.doc.toString(), + hasSelection ? { from, to } : undefined + ); + + queueMicrotask(() => { + glimmerTree.dispatch({ + changes: { + from: 0, + to: glimmerTree.state.doc.length, + insert: glimmerAST, + }, + }); + }); + } + } +}); + +// Text Input +export const mainView = new EditorView({ + state: EditorState.create({ + doc, + extensions: [ + basicSetup, + gjs(), + // We can't use HTML as the hosting language + // (to overlay Glimmer on top of) + // Because in Glimmer, we can have spaces within double curlies, + // and in the HTML parser, this ends up escaping the attribute values, and other things + // htmlLanguage, + oneDark, + EditorView.lineWrapping, + syncAST, + ], + }), + parent: document.querySelector('#editor'), +}); + +// Glimmer Tree +const glimmerState = EditorState.create({ + doc: printTree(gjsLanguage.parser.parse(doc), doc), + extensions: [basicSetup, oneDark, EditorView.lineWrapping, EditorState.readOnly.of(true)], +}); +const glimmerTree = new EditorView({ + state: glimmerState, + parent: document.querySelector('#editor-ast'), +}); diff --git a/packages/syntax/glimmer-ts/codemirror/dev/vite.config.ts b/packages/syntax/glimmer-ts/codemirror/dev/vite.config.ts new file mode 100644 index 000000000..c372e8113 --- /dev/null +++ b/packages/syntax/glimmer-ts/codemirror/dev/vite.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from 'vite'; + +export default defineConfig({ + plugins: [], + root: 'dev', + server: { + host: '0.0.0.0', + }, +}); diff --git a/packages/syntax/glimmer-ts/codemirror/package.json b/packages/syntax/glimmer-ts/codemirror/package.json new file mode 100644 index 000000000..cb3ba2236 --- /dev/null +++ b/packages/syntax/glimmer-ts/codemirror/package.json @@ -0,0 +1,64 @@ +{ + "name": "codemirror-lang-glimmer-ts", + "version": "0.0.1", + "author": "NullVoxPopuli", + "license": "MIT", + "main": "dist/index.cjs", + "module": "dist/index.js", + "exports": { + "import": "./dist/index.js", + "require": "./dist/index.cjs" + }, + "types": "dist/index.d.ts", + "repository": { + "type": "git", + "url": "https://github.com/NullVoxPopuli/limber.git", + "directory": "packages/syntax/glimmer-js/codemirror" + }, + "devDependencies": { + "@babel/core": "^7.25.7", + "@babel/eslint-parser": "^7.25.7", + "@codemirror/buildhelper": "^1.0.1", + "@codemirror/view": "^6.34.1", + "@glimdown/lezer-infra": "workspace:*", + "@lezer/common": "^1.2.2", + "@lezer/generator": "^1.6.0", + "@nullvoxpopuli/eslint-configs": "^4.0.0", + "@tsconfig/ember": "^3.0.7", + "@typescript-eslint/eslint-plugin": "^8.8.0", + "@typescript-eslint/parser": "^8.8.0", + "codemirror": "^6.0.1", + "concurrently": "^9.0.1", + "eslint": "^8.55.0", + "prettier": "^3.3.3", + "rollup": "^4.24.0", + "rollup-plugin-ts": "^3.4.5", + "typescript": "^5.4.5" + }, + "dependencies": { + "@codemirror/lang-css": "^6.3.0", + "@codemirror/lang-html": "^6.4.9", + "@codemirror/lang-javascript": "^6.2.1", + "@codemirror/language": "^6.10.3", + "@lezer/highlight": "^1.2.1", + "@lezer/javascript": "^1.4.18", + "@lezer/lr": "^1.4.2", + "codemirror-lang-glimmer": "workspace:*" + }, + "scripts": { + "dev": "node ./dev/watch.cjs src/index.ts", + "build": "rollup -c", + "lint": "pnpm -w exec lint", + "lint:fix": "pnpm -w exec lint fix", + "lint:js": "pnpm -w exec lint js", + "lint:js:fix": "pnpm -w exec lint js:fix", + "lint:prettier:fix": "pnpm -w exec lint prettier:fix", + "lint:prettier": "pnpm -w exec lint prettier" + }, + "volta": { + "extends": "../../../../package.json" + }, + "peerDependencies": { + "@codemirror/view": "^6.22.3" + } +} diff --git a/packages/syntax/glimmer-ts/codemirror/rollup.config.mjs b/packages/syntax/glimmer-ts/codemirror/rollup.config.mjs new file mode 100644 index 000000000..b1ac036f7 --- /dev/null +++ b/packages/syntax/glimmer-ts/codemirror/rollup.config.mjs @@ -0,0 +1,12 @@ +import { lezer } from "@lezer/generator/rollup"; +import typescript from "rollup-plugin-ts"; + +export default { + input: "src/index.ts", + external: (id) => id != "tslib" && !/^(\.?\/|\w:)/.test(id), + output: [ + { file: "dist/index.cjs", format: "cjs" }, + { dir: "./dist", format: "es" }, + ], + plugins: [lezer(), typescript()], +}; diff --git a/packages/syntax/glimmer-ts/codemirror/src/highlight.ts b/packages/syntax/glimmer-ts/codemirror/src/highlight.ts new file mode 100644 index 000000000..127b3a1f9 --- /dev/null +++ b/packages/syntax/glimmer-ts/codemirror/src/highlight.ts @@ -0,0 +1,8 @@ +import { styleTags, tags as t } from '@lezer/highlight'; + +export const templateTagHighlighting = styleTags({ + TagName: t.tagName, + GlimmerTemplateTag: t.tagName, + TemplateTag: t.tagName, + Template: t.tagName, +}); diff --git a/packages/syntax/glimmer-ts/codemirror/src/index.ts b/packages/syntax/glimmer-ts/codemirror/src/index.ts new file mode 100644 index 000000000..c6978dbd9 --- /dev/null +++ b/packages/syntax/glimmer-ts/codemirror/src/index.ts @@ -0,0 +1,42 @@ +import { javascriptLanguage, typescriptLanguage } from '@codemirror/lang-javascript'; +import { LanguageSupport, LRLanguage } from '@codemirror/language'; +import { parseMixed } from '@lezer/common'; +import { glimmer, glimmerLanguage } from 'codemirror-lang-glimmer'; + +import { parser as metaParser } from './syntax.grammar'; + +export function gjs() { + return new LanguageSupport(gjsLanguage, [glimmer().support]); +} + +export function gts() { + return new LanguageSupport(gtsLanguage, [glimmer().support]); +} + +export const gtsLanguage = LRLanguage.define({ + parser: metaParser.configure({ + wrap: parseMixed((node) => { + if (node.type.name === 'Document') return null; + + if (node.type.name === 'GlimmerTemplateTag') { + return { parser: glimmerLanguage.parser }; + } + + return { parser: typescriptLanguage.parser }; + }), + }), +}); + +export const gjsLanguage = LRLanguage.define({ + parser: metaParser.configure({ + wrap: parseMixed((node) => { + if (node.type.name === 'Document') return null; + + if (node.type.name === 'GlimmerTemplateTag') { + return { parser: glimmerLanguage.parser }; + } + + return { parser: javascriptLanguage.parser }; + }), + }), +}); diff --git a/packages/syntax/glimmer-ts/codemirror/src/syntax.grammar b/packages/syntax/glimmer-ts/codemirror/src/syntax.grammar new file mode 100644 index 000000000..548503e17 --- /dev/null +++ b/packages/syntax/glimmer-ts/codemirror/src/syntax.grammar @@ -0,0 +1,14 @@ +@top Document { GlimmerTemplateTag* } + +GlimmerTemplateTag { + templateTagStart templateTagContent* templateTagEnd +} + +@external tokens templateTagContent from "./tokens.js" { templateTagContent } + +@tokens { + templateTagStart[@name="TemplateTag", closedBy=templateTagEnd] { "" } +} + +@external propSource templateTagHighlighting from "./highlight" diff --git a/packages/syntax/glimmer-ts/codemirror/src/syntax.grammar.d.ts b/packages/syntax/glimmer-ts/codemirror/src/syntax.grammar.d.ts new file mode 100644 index 000000000..748d451bd --- /dev/null +++ b/packages/syntax/glimmer-ts/codemirror/src/syntax.grammar.d.ts @@ -0,0 +1,3 @@ +import type { LRParser } from '@lezer/lr'; + +export declare const parser: LRParser; diff --git a/packages/syntax/glimmer-ts/codemirror/src/syntax.grammar.terms.d.ts b/packages/syntax/glimmer-ts/codemirror/src/syntax.grammar.terms.d.ts new file mode 100644 index 000000000..15d251c96 --- /dev/null +++ b/packages/syntax/glimmer-ts/codemirror/src/syntax.grammar.terms.d.ts @@ -0,0 +1,3 @@ +export const templateTagContent = 8, + Document = 1, + GlimmerTemplateTag = 2; diff --git a/packages/syntax/glimmer-ts/codemirror/src/tokens.ts b/packages/syntax/glimmer-ts/codemirror/src/tokens.ts new file mode 100644 index 000000000..51d908855 --- /dev/null +++ b/packages/syntax/glimmer-ts/codemirror/src/tokens.ts @@ -0,0 +1,43 @@ +import { ExternalTokenizer } from '@lezer/lr'; + +import { templateTagContent as templateTagToken } from './syntax.grammar.terms'; + +export function matchForComment(commentEndPattern: number[], commentToken: number, input: any) { + for (let found = 0, i = 0; ; i++) { + if (input.next < 0) { + if (i) input.acceptToken(commentToken); + + break; + } + + let hasMatch = commentEndPattern[found] === input.next; + + if (!hasMatch) { + found = 0; + input.advance(); + + break; + } + + if (found === commentEndPattern.length - 1) { + if (i > commentEndPattern.length - 1) { + input.acceptToken(commentToken, 1 - commentEndPattern.length); + + break; + } else { + console.warn('Reached end of comment but there is still content left'); + } + + break; + } + + found++; + input.advance(); + } +} + +const closingTemplateTag = ''.split('').map((char) => char.charCodeAt(0)); + +export const templateTagContent = new ExternalTokenizer((input) => { + return matchForComment(closingTemplateTag, templateTagToken, input); +}); diff --git a/packages/syntax/glimmer-ts/codemirror/test/comments.txt b/packages/syntax/glimmer-ts/codemirror/test/comments.txt new file mode 100644 index 000000000..296743219 --- /dev/null +++ b/packages/syntax/glimmer-ts/codemirror/test/comments.txt @@ -0,0 +1,116 @@ +# Long + +{{!-- text here --}} + +==> + +Glimmer( + BlockComment( + LongComment( + StartLongComment, + Text, + EndLongComment + ) + ) +) + + +# Short + +{{! text here }} + +==> + +Glimmer( + BlockComment( + ShortComment( + StartShortComment, + Text, + EndStache + ) + ) +) + + + +# Long multiline + +{{!-- + line 1 + line 2 + +weird indent + + line 4 + +--}} + +==> + +Glimmer( + BlockComment( + LongComment( + StartLongComment, + Text, + EndLongComment + ) + ) +) + +# Short multiline + +{{! + line 1 + line 2 + +weird indent + + line 4 + +}} + +==> + +Glimmer( + BlockComment( + ShortComment( + StartShortComment, + Text, + EndStache + ) + ) +) + + +# Long - empty + +{{!-- --}} + +==> + +Glimmer( + BlockComment( + LongComment( + StartLongComment, + Text, + EndLongComment + ) + ) +) + + +# Short - empty + +{{! }} + +==> + +Glimmer( + BlockComment( + ShortComment( + StartShortComment, + Text, + EndStache + ) + ) +) diff --git a/packages/syntax/glimmer-ts/codemirror/test/complex.txt b/packages/syntax/glimmer-ts/codemirror/test/complex.txt new file mode 100644 index 000000000..f823e7007 --- /dev/null +++ b/packages/syntax/glimmer-ts/codemirror/test/complex.txt @@ -0,0 +1,24 @@ +# Multi-Expression + +{{#each (someFn foo bar named=(foo bar)) as |a b c|}} + + {{a}} {{b}} -- {{c}} + + {{#if a}} + a + {{else if b}} + b + {{else}} + the else + {{/if}} +{{/each}} + +==> + +Glimmer( + Expression( + SubExpression( + Value(Argument) + ) + ) +) diff --git a/packages/syntax/glimmer-ts/codemirror/test/expression.txt b/packages/syntax/glimmer-ts/codemirror/test/expression.txt new file mode 100644 index 000000000..a78c904a5 --- /dev/null +++ b/packages/syntax/glimmer-ts/codemirror/test/expression.txt @@ -0,0 +1,95 @@ +# Minimal + +{{@foo}} + +==> + +Glimmer( + Expression( + StartStache, + SubExpression( + Value(Property(Argument)) + ), + EndStache + ) +) + +# Function invocation (compressed) + +{{(myFunction @foo)}} + +==> + +Glimmer( + Expression( + StartStache, + SubExpression( + Value( + Invocation( + SubExpStart, + SubExpression( + Value(Property), + Text, + Value(Property(Argument)) + ), + SubExpEnd + ) + ) + ), + EndStache + ) +) + + + +# Function invocation + +{{ (myFunction @foo) }} + +==> + +Glimmer( + Expression( + StartStache, + SubExpression( + Value( + Invocation( + SubExpStart, + SubExpression( + Value(PropertyPath(Property)), + Value(PropertyPath(Property(Argument))) + ), + SubExpEnd + ) + ) + ), + EndStache + ) +) + +# Iteration + +{{#each this.foo as |item|}} + {{item}} +{{/each}} + +==> + +Glimmer( + Expression(ArgumentReference) +) + + +# Multiple + +{{@foo}} {{@bar}} + +==> + +Glimmer( + Expression( + SubExpression( + Value(Argument) + ) + ) +) diff --git a/packages/syntax/glimmer-ts/codemirror/test/literals.txt b/packages/syntax/glimmer-ts/codemirror/test/literals.txt new file mode 100644 index 000000000..3ba6c72d9 --- /dev/null +++ b/packages/syntax/glimmer-ts/codemirror/test/literals.txt @@ -0,0 +1,78 @@ +# True + +{{true}} + +==> + +Glimmer( + Expression( + StartStache, + SubExpression( + Value( + BooleanLiteral + ) + ), + EndStache + ) +) + + + +# False + +{{false}} + +==> + +Glimmer( + Expression( + StartStache, + SubExpression( + Value( + BooleanLiteral + ) + ), + EndStache + ) +) + + + +# Null + +{{null}} + +==> + +Glimmer( + Expression( + StartStache, + SubExpression( + Value( + null + ) + ), + EndStache + ) +) + + +# Undefined + +{{undefined}} + +==> + +Glimmer( + Expression( + StartStache, + SubExpression( + Value( + undefined + ) + ), + EndStache + ) +) + + diff --git a/packages/syntax/glimmer-ts/codemirror/test/numbers.txt b/packages/syntax/glimmer-ts/codemirror/test/numbers.txt new file mode 100644 index 000000000..9fcff8cfc --- /dev/null +++ b/packages/syntax/glimmer-ts/codemirror/test/numbers.txt @@ -0,0 +1,88 @@ +# Simple Integer + +{{42}} + +==> + +Glimmer( + Expression( + StartStache, + SubExpression( + Value(Number) + ), + EndStache + ) +) + + + +# Decimal + +{{42.42}} + +==> + +Glimmer( + Expression( + StartStache, + SubExpression( + Value(Number) + ), + EndStache + ) +) + + +# Multiple Integer + +{{42}} {{24}} + +==> + +Glimmer( + Expression( + StartStache, + SubExpression( + Value(Number) + ), + EndStache + ), + + Expression( + StartStache, + SubExpression( + Value(Number) + ), + EndStache + ) +) + + +# Multiple with Text + +{{42}} and {{24}} + +==> + +Glimmer( + Expression( + StartStache, + SubExpression( + Value(Number) + ), + EndStache + ), + + Text, + + Expression( + StartStache, + SubExpression( + Value(Number) + ), + EndStache + ) +) + + + diff --git a/packages/syntax/glimmer-ts/codemirror/test/property-paths.txt b/packages/syntax/glimmer-ts/codemirror/test/property-paths.txt new file mode 100644 index 000000000..7ba7a2fca --- /dev/null +++ b/packages/syntax/glimmer-ts/codemirror/test/property-paths.txt @@ -0,0 +1,79 @@ +# foo.bar + +{{foo.bar}} + +==> + +Glimmer( + Expression( + StartStache, + SubExpression( + Value( + PropertyPath( + Property + ) + ) + ), + EndStache + ) +) + +# foo.bar.baz + +{{foo.bar.baz}} + +==> + +Glimmer( + Expression( + StartStache, + SubExpression( + Value( + PropertyPath( + Property + ) + ) + ), + EndStache + ) +) + +# this.bar + +{{this.bar}} + +==> + +Glimmer( + Expression( + StartStache, + SubExpression( + Value( + PropertyPath( + Property(this) + ) + ) + ), + EndStache + ) +) + +# @arg.bar + +{{@arg.bar}} + +==> + +Glimmer( + Expression( + StartStache, + SubExpression( + Value( + PropertyPath( + Property(Argument) + ) + ) + ), + EndStache + ) +) diff --git a/packages/syntax/glimmer-ts/codemirror/test/strings.txt b/packages/syntax/glimmer-ts/codemirror/test/strings.txt new file mode 100644 index 000000000..f953c7537 --- /dev/null +++ b/packages/syntax/glimmer-ts/codemirror/test/strings.txt @@ -0,0 +1,64 @@ +# Basic - Double + +{{"Some String"}} + +==> + +Glimmer( + Expression( + StartStache, + SubExpression( + Value(String) + ), + EndStache + ) +) + +# Basic - Single + +{{'Some String'}} + +==> + +Glimmer( + Expression( + StartStache, + SubExpression( + Value(String) + ), + EndStache + ) +) + +# Nested - Double + +{{"Some 'inner' String"}} + +==> + +Glimmer( + Expression( + StartStache, + SubExpression( + Value(String) + ), + EndStache + ) +) + +# Nested - Single + +{{'Some "inner" String'}} + +==> + +Glimmer( + Expression( + StartStache, + SubExpression( + Value(String) + ), + EndStache + ) +) + diff --git a/packages/syntax/glimmer-ts/codemirror/tsconfig.json b/packages/syntax/glimmer-ts/codemirror/tsconfig.json new file mode 100644 index 000000000..97c17feab --- /dev/null +++ b/packages/syntax/glimmer-ts/codemirror/tsconfig.json @@ -0,0 +1,3 @@ +{ + "extends": "@tsconfig/ember/tsconfig.json" +}