trueadm/ripple/main 2.3M tokens More Tools
```
├── .changeset/
   ├── README.md (100 tokens)
   ├── config.json (200 tokens)
├── .claude/
   ├── skills/
      ├── ripple.md
├── .codex/
   ├── skills/
      ├── ripple.md
├── .cursor/
   ├── environment.json
   ├── install.sh (300 tokens)
   ├── rules/
      ├── project.mdc (1200 tokens)
├── .editorconfig (omitted)
├── .gemini/
   ├── skills/
      ├── ripple.md
├── .gitattributes (omitted)
├── .github/
   ├── ISSUE_TEMPLATE/
      ├── bug-report.yml (500 tokens)
      ├── config.yml (100 tokens)
      ├── feature-request.yml (400 tokens)
   ├── agents/
      ├── ripple.agent.md (300 tokens)
   ├── copilot-instructions.md (1100 tokens)
   ├── workflows/
      ├── ci.yml (600 tokens)
      ├── copilot-setup-steps.yml (200 tokens)
      ├── livecodes-post-comment.yml (100 tokens)
      ├── livecodes-preview.yml (100 tokens)
      ├── pkg.pr.new.yml (700 tokens)
      ├── publish.yml (300 tokens)
      ├── release.yml (200 tokens)
      ├── rulesync.yml (100 tokens)
      ├── vsix-manual.yml (400 tokens)
      ├── vsix.yml (700 tokens)
├── .gitignore (200 tokens)
├── .livecodes/
   ├── playground.json (200 tokens)
├── .prettierignore (omitted)
├── .prettierrc (100 tokens)
├── .rulesync/
   ├── rules/
      ├── project.md (1200 tokens)
├── .vscode/
   ├── launch.json (1000 tokens)
   ├── settings.json (300 tokens)
   ├── tasks.json (200 tokens)
├── AGENTS.md (1200 tokens)
├── CLAUDE.md (1100 tokens)
├── CODE_OF_CONDUCT.md (400 tokens)
├── CONTRIBUTING.md (1600 tokens)
├── GEMINI.md (1200 tokens)
├── LICENSE (omitted)
├── README.md (2.3k tokens)
├── assets/
   ├── Ripple.tmbundle/
      ├── README.md (200 tokens)
      ├── Syntaxes/
         ├── ripple.tmLanguage (71.3k tokens)
      ├── info.plist
   ├── ripple-desktop.png
   ├── ripple-mobile.png
├── benchmarks/
   ├── package.json
   ├── tracked-values.js (800 tokens)
├── grammars/
   ├── textmate/
      ├── info.plist
      ├── ripple.tmLanguage.json (57.9k tokens)
   ├── tree-sitter/
      ├── .gitignore
      ├── Cargo.toml (100 tokens)
      ├── LICENSE (200 tokens)
      ├── README.md (100 tokens)
      ├── binding.gyp (100 tokens)
      ├── bindings/
         ├── node/
            ├── binding.cc (100 tokens)
      ├── grammar.js (5.5k tokens)
      ├── package.json (200 tokens)
      ├── queries/
         ├── brackets.scm (100 tokens)
         ├── folds.scm (100 tokens)
         ├── highlights.scm (900 tokens)
         ├── indents.nvim.scm (200 tokens)
         ├── indents.scm (100 tokens)
         ├── indents.zed.scm (200 tokens)
         ├── injections.scm (300 tokens)
         ├── locals.scm (200 tokens)
         ├── outline.scm (100 tokens)
         ├── textobjects.scm (300 tokens)
      ├── src/
         ├── grammar.json (35.1k tokens)
         ├── node-types.json (15.3k tokens)
         ├── parser.c (853.8k tokens)
         ├── scanner.c (900 tokens)
         ├── tree_sitter/
            ├── alloc.h (200 tokens)
            ├── array.h (2.7k tokens)
            ├── parser.h (1500 tokens)
      ├── test/
         ├── corpus/
            ├── components.txt (800 tokens)
            ├── control-flow.txt (1900 tokens)
            ├── javascript.txt (1300 tokens)
            ├── jsx.txt (1600 tokens)
            ├── main.txt
            ├── reactivity.txt (200 tokens)
      ├── tree-sitter.json (200 tokens)
├── package.json (900 tokens)
├── packages/
   ├── adapter-bun/
      ├── CHANGELOG.md (1700 tokens)
      ├── README.md (500 tokens)
      ├── package.json (200 tokens)
      ├── src/
         ├── index.js (1100 tokens)
      ├── tests/
         ├── serve.test.js (2.1k tokens)
         ├── types.test.js (200 tokens)
      ├── tsconfig.json
      ├── tsconfig.typecheck.json
      ├── types/
         ├── bun-shim.d.ts (omitted)
         ├── index.d.ts (omitted)
   ├── adapter-node/
      ├── CHANGELOG.md (1700 tokens)
      ├── README.md (600 tokens)
      ├── package.json (200 tokens)
      ├── src/
         ├── index.js (2.3k tokens)
      ├── tests/
         ├── serve.test.js (2.2k tokens)
         ├── types.test.js (200 tokens)
      ├── tsconfig.json
      ├── tsconfig.typecheck.json
      ├── types/
         ├── index.d.ts (omitted)
   ├── adapter-vercel/
      ├── CHANGELOG.md (1900 tokens)
      ├── README.md (1200 tokens)
      ├── package.json (200 tokens)
      ├── src/
         ├── adapt.js (2.7k tokens)
         ├── bin/
            ├── adapt.js (300 tokens)
         ├── index.js (100 tokens)
      ├── tests/
         ├── adapt.test.js (2.7k tokens)
         ├── types.test.js (600 tokens)
      ├── tsconfig.json
      ├── tsconfig.typecheck.json
      ├── types/
         ├── index.d.ts (omitted)
   ├── adapter/
      ├── CHANGELOG.md (500 tokens)
      ├── README.md (200 tokens)
      ├── package.json (200 tokens)
      ├── src/
         ├── index.js (600 tokens)
         ├── rpc.js (1400 tokens)
      ├── tests/
         ├── index.test.js (600 tokens)
         ├── types.test.js (100 tokens)
      ├── tsconfig.json
      ├── tsconfig.typecheck.json
      ├── types/
         ├── index.d.ts (omitted)
         ├── rpc.d.ts (omitted)
   ├── bun-plugin-preact/
      ├── CHANGELOG.md (1100 tokens)
      ├── README.md (200 tokens)
      ├── package.json (200 tokens)
      ├── src/
         ├── index.js (800 tokens)
      ├── tests/
         ├── basic.test.js (1200 tokens)
      ├── tsconfig.json (100 tokens)
      ├── tsconfig.typecheck.json
      ├── types/
         ├── index.d.ts (omitted)
   ├── bun-plugin-react/
      ├── CHANGELOG.md (1100 tokens)
      ├── README.md (200 tokens)
      ├── package.json (200 tokens)
      ├── src/
         ├── index.js (700 tokens)
      ├── tests/
         ├── basic.test.js (1200 tokens)
      ├── tsconfig.json (100 tokens)
      ├── tsconfig.typecheck.json
      ├── types/
         ├── index.d.ts (omitted)
   ├── bun-plugin-solid/
      ├── CHANGELOG.md (200 tokens)
      ├── README.md (200 tokens)
      ├── package.json (200 tokens)
      ├── src/
         ├── index.js (700 tokens)
      ├── tests/
         ├── basic.test.js (1100 tokens)
      ├── tsconfig.json (100 tokens)
      ├── tsconfig.typecheck.json
      ├── types/
         ├── index.d.ts (omitted)
   ├── bun-plugin-vue/
      ├── CHANGELOG.md (700 tokens)
      ├── README.md (200 tokens)
      ├── package.json (200 tokens)
      ├── src/
         ├── index.js (1100 tokens)
      ├── tests/
         ├── basic.test.js (1700 tokens)
      ├── tsconfig.json (100 tokens)
      ├── tsconfig.typecheck.json
      ├── types/
         ├── index.d.ts (omitted)
   ├── cli/
      ├── CHANGELOG.md (600 tokens)
      ├── LICENSE (200 tokens)
      ├── README.md (400 tokens)
      ├── package.json (300 tokens)
      ├── src/
         ├── commands/
            ├── create.js (1100 tokens)
         ├── constants.js (100 tokens)
         ├── index.js (400 tokens)
         ├── lib/
            ├── is-folder-empty.js (500 tokens)
            ├── package-manager.js (300 tokens)
            ├── project-creator.js (2k tokens)
            ├── prompts.js (800 tokens)
            ├── templates.js (700 tokens)
            ├── validation.js (700 tokens)
      ├── tests/
         ├── integration/
            ├── cli.test.js (1700 tokens)
            ├── project-creator.test.js (2.2k tokens)
         ├── unit/
            ├── prompts.test.js (1700 tokens)
            ├── templates.test.js (900 tokens)
            ├── validation.test.js (1200 tokens)
      ├── tsconfig.json
      ├── tsdown.config.js (100 tokens)
      ├── vitest.config.js (100 tokens)
   ├── compat-react/
      ├── CHANGELOG.md (2.7k tokens)
      ├── LICENSE (200 tokens)
      ├── package.json (200 tokens)
      ├── src/
         ├── index.js (2.3k tokens)
      ├── tests/
         ├── client.d.ts (omitted)
         ├── index.test.tsrx (4.3k tokens)
         ├── setup.js (300 tokens)
      ├── tsconfig.json (100 tokens)
      ├── tsconfig.typecheck.json
      ├── types/
         ├── index.d.ts (omitted)
   ├── create-ripple/
      ├── CHANGELOG.md (1600 tokens)
      ├── README.md (300 tokens)
      ├── package.json (200 tokens)
      ├── src/
         ├── index.js
      ├── tsconfig.json
      ├── tsdown.config.js (100 tokens)
   ├── eslint-parser/
      ├── .npmignore
      ├── CHANGELOG.md (1700 tokens)
      ├── README.md (500 tokens)
      ├── package.json (300 tokens)
      ├── src/
         ├── index.ts (1000 tokens)
      ├── tsconfig.json (100 tokens)
      ├── tsdown.config.js (100 tokens)
   ├── eslint-plugin/
      ├── .npmignore
      ├── CHANGELOG.md (2k tokens)
      ├── README.md (1100 tokens)
      ├── package.json (300 tokens)
      ├── src/
         ├── index.ts (500 tokens)
         ├── rules/
            ├── control-flow-jsx.ts (500 tokens)
            ├── no-lazy-destructuring-in-modules.ts (200 tokens)
            ├── no-module-scope-track.ts (300 tokens)
            ├── no-return-in-component.ts (300 tokens)
            ├── prefer-oninput.ts (400 tokens)
            ├── valid-for-of-key.ts (700 tokens)
      ├── tests/
         ├── configs.test.ts (100 tokens)
         ├── rules/
            ├── control-flow-jsx.test.ts (600 tokens)
            ├── no-lazy-destructuring-in-modules.test.ts (600 tokens)
            ├── no-module-scope-track.test.ts (300 tokens)
            ├── no-return-in-component.test.ts (100 tokens)
            ├── prefer-oninput.test.ts (200 tokens)
            ├── valid-for-of-key.test.ts (400 tokens)
      ├── tsconfig.json (100 tokens)
      ├── tsdown.config.js (100 tokens)
      ├── vitest.config.ts
   ├── intellij-plugin/
      ├── .gitignore (100 tokens)
      ├── README.md (200 tokens)
      ├── build.gradle.kts (200 tokens)
      ├── gradle.properties (100 tokens)
      ├── gradle/
         ├── wrapper/
            ├── gradle-wrapper.jar
            ├── gradle-wrapper.properties
      ├── gradlew (1600 tokens)
      ├── gradlew.bat (500 tokens)
      ├── package.json
      ├── settings.gradle.kts
      ├── src/
         ├── main/
            ├── kotlin/
               ├── com/
                  ├── ripple_ts/
                     ├── intellij_plugin/
                        ├── RippleCommenter.kt (100 tokens)
                        ├── RippleFileType.kt (100 tokens)
                        ├── RippleIcons.kt
                        ├── RippleLanguage.kt
                        ├── RippleLanguageServer.kt (1700 tokens)
                        ├── RippleLspServerDescriptor.kt (200 tokens)
                        ├── RippleLspServerSupportProvider.kt (100 tokens)
                        ├── RippleTextMateBundleProvider.kt (800 tokens)
            ├── resources/
               ├── META-INF/
                  ├── plugin.xml (500 tokens)
                  ├── pluginIcon.svg (200 tokens)
                  ├── ripple-lsp.xml
               ├── icons/
                  ├── ripple.png
                  ├── ripple@2x.png
               ├── lsp-version.txt
   ├── language-server/
      ├── CHANGELOG.md (4.8k tokens)
      ├── LICENSE (200 tokens)
      ├── README.md (700 tokens)
      ├── package.json (200 tokens)
      ├── src/
         ├── autoInsertPlugin.js (900 tokens)
         ├── compileErrorDiagnosticPlugin.js (900 tokens)
         ├── completionPlugin.js (3.4k tokens)
         ├── definitionPlugin.js (1400 tokens)
         ├── documentHighlightPlugin.js (700 tokens)
         ├── hoverPlugin.js (800 tokens)
         ├── language-server.js
         ├── server.js (1000 tokens)
         ├── typescriptDiagnosticPlugin.js (800 tokens)
         ├── typescriptService.js (400 tokens)
         ├── utils.js (1000 tokens)
      ├── tsconfig.json (100 tokens)
      ├── tsconfig.typecheck.json
      ├── tsdown.config.js (200 tokens)
   ├── nvim-plugin/
      ├── LICENSE (200 tokens)
      ├── README.md (200 tokens)
      ├── lua/
         ├── ripple/
            ├── init.lua
            ├── lsp.lua (900 tokens)
            ├── treesitter.lua (200 tokens)
      ├── package.json (100 tokens)
      ├── plugin/
         ├── ripple.lua
      ├── queries/
         ├── ripple/
            ├── brackets.scm (100 tokens)
            ├── folds.scm (100 tokens)
            ├── highlights.scm (900 tokens)
            ├── indents.scm (200 tokens)
            ├── injections.scm (300 tokens)
            ├── locals.scm (200 tokens)
            ├── outline.scm (100 tokens)
            ├── textobjects.scm (300 tokens)
   ├── prettier-plugin/
      ├── CHANGELOG.md (4.9k tokens)
      ├── LICENSE (200 tokens)
      ├── README.md (100 tokens)
      ├── package.json (200 tokens)
      ├── src/
         ├── index.js (39.7k tokens)
         ├── index.test.js (30k tokens)
      ├── tsconfig.json (100 tokens)
      ├── tsconfig.typecheck.json
      ├── vitest-extensions.d.ts (omitted)
   ├── ripple/
      ├── CHANGELOG.md (8k tokens)
      ├── README.md (100 tokens)
      ├── package.json (500 tokens)
      ├── shims/
         ├── rollup-estree-types.d.ts (omitted)
      ├── src/
         ├── compiler/
            ├── index.js (100 tokens)
            ├── types/
               ├── import.d.ts (omitted)
         ├── constants.js (100 tokens)
         ├── helpers.d.ts (omitted)
         ├── html-tree-validation.js (1500 tokens)
         ├── jsx-runtime.d.ts (omitted)
         ├── jsx-runtime.js (300 tokens)
         ├── runtime/
            ├── array.js (500 tokens)
            ├── create-subscriber.js (200 tokens)
            ├── date.js (400 tokens)
            ├── element.js (100 tokens)
            ├── index-client.js (900 tokens)
            ├── index-server.js (500 tokens)
            ├── internal/
               ├── client/
                  ├── bindings.js (3.8k tokens)
                  ├── blocks.js (2k tokens)
                  ├── compat.js (200 tokens)
                  ├── composite.js (600 tokens)
                  ├── constants.js (400 tokens)
                  ├── context.js (300 tokens)
                  ├── css.js (300 tokens)
                  ├── events.js (2.2k tokens)
                  ├── expression.js (1500 tokens)
                  ├── for.js (3.7k tokens)
                  ├── head.js (400 tokens)
                  ├── hmr.js (500 tokens)
                  ├── html.js (700 tokens)
                  ├── hydration.js (400 tokens)
                  ├── if.js (200 tokens)
                  ├── index.js (500 tokens)
                  ├── operations.js (800 tokens)
                  ├── portal.js (500 tokens)
                  ├── render.js (2k tokens)
                  ├── rpc.js (200 tokens)
                  ├── runtime.js (8k tokens)
                  ├── script.js (100 tokens)
                  ├── switch.js (300 tokens)
                  ├── template.js (1400 tokens)
                  ├── try.js (2.1k tokens)
                  ├── types.d.ts (omitted)
                  ├── utils.js (200 tokens)
               ├── server/
                  ├── blocks.js (900 tokens)
                  ├── constants.js (100 tokens)
                  ├── context.js (300 tokens)
                  ├── css-registry.js (200 tokens)
                  ├── index.js (8.4k tokens)
                  ├── rpc.js (100 tokens)
                  ├── types.d.ts (omitted)
            ├── map.js (700 tokens)
            ├── media-query.js (300 tokens)
            ├── object.js (100 tokens)
            ├── proxy.js (1800 tokens)
            ├── reactive-value.js (200 tokens)
            ├── set.js (800 tokens)
            ├── url-search-params.js (600 tokens)
            ├── url.js (700 tokens)
         ├── server/
            ├── index.js (100 tokens)
         ├── utils/
            ├── async.js (200 tokens)
            ├── track-async-serialization.js (100 tokens)
      ├── tests/
         ├── client.d.ts (omitted)
         ├── client/
            ├── __snapshots__/
               ├── computed-properties.test.rsrx.snap
               ├── computed-properties.test.tsrx.snap
               ├── for.test.rsrx.snap
               ├── for.test.tsrx.snap
               ├── html.test.rsrx.snap
               ├── html.test.tsrx.snap
            ├── _etc.test.tsrx
            ├── array/
               ├── array.copy-within.test.tsrx (900 tokens)
               ├── array.derived.test.tsrx (3.2k tokens)
               ├── array.iteration.test.tsrx (700 tokens)
               ├── array.mutations.test.tsrx (2.5k tokens)
               ├── array.static.test.tsrx (1300 tokens)
               ├── array.to-methods.test.tsrx (600 tokens)
            ├── async-suspend.test.tsrx (4.1k tokens)
            ├── basic/
               ├── __snapshots__/
                  ├── basic.attributes.test.rsrx.snap
                  ├── basic.attributes.test.tsrx.snap
                  ├── basic.rendering.test.rsrx.snap
                  ├── basic.rendering.test.tsrx.snap
               ├── basic.attributes.test.tsrx (5k tokens)
               ├── basic.collections.test.tsrx (500 tokens)
               ├── basic.components.test.tsrx (2.9k tokens)
               ├── basic.errors.test.tsrx (1400 tokens)
               ├── basic.events.test.tsrx (1400 tokens)
               ├── basic.get-set.test.tsrx (1100 tokens)
               ├── basic.hmr.test.tsrx (500 tokens)
               ├── basic.reactivity.test.tsrx (1700 tokens)
               ├── basic.rendering.test.tsrx (1700 tokens)
               ├── basic.styling.test.tsrx (300 tokens)
               ├── basic.utilities.test.tsrx (100 tokens)
            ├── boundaries.test.tsrx (500 tokens)
            ├── capture-error.js
            ├── compiler/
               ├── __snapshots__/
                  ├── compiler.assignments.test.rsrx.snap
                  ├── compiler.assignments.test.tsrx.snap
                  ├── compiler.typescript.test.rsrx.snap
                  ├── compiler.typescript.test.tsrx.snap
               ├── compiler.assignments.test.tsrx (600 tokens)
               ├── compiler.attributes.test.tsrx (600 tokens)
               ├── compiler.basic.test.tsrx (6.1k tokens)
               ├── compiler.regex.test.tsrx (700 tokens)
               ├── compiler.tracked-access.test.tsrx (1200 tokens)
               ├── compiler.try-in-function.test.tsrx (900 tokens)
               ├── compiler.typescript.test.tsrx (300 tokens)
            ├── composite/
               ├── __snapshots__/
                  ├── composite.render.test.rsrx.snap
                  ├── composite.render.test.tsrx.snap
               ├── composite.dynamic-components.test.tsrx (400 tokens)
               ├── composite.generics.test.tsrx (1000 tokens)
               ├── composite.props.test.tsrx (900 tokens)
               ├── composite.reactivity.test.tsrx (1500 tokens)
               ├── composite.render.test.tsrx (1000 tokens)
            ├── computed-properties.test.tsrx (200 tokens)
            ├── context.test.tsrx (200 tokens)
            ├── css/
               ├── global-additional-cases.test.tsrx (3k tokens)
               ├── global-advanced-selectors.test.tsrx (900 tokens)
               ├── global-at-rules.test.tsrx (500 tokens)
               ├── global-basic.test.tsrx (600 tokens)
               ├── global-classes-ids.test.tsrx (700 tokens)
               ├── global-combinators.test.tsrx (500 tokens)
               ├── global-complex-nesting.test.tsrx (800 tokens)
               ├── global-edge-cases.test.tsrx (800 tokens)
               ├── global-keyframes.test.tsrx (700 tokens)
               ├── global-nested.test.tsrx (500 tokens)
               ├── global-pseudo.test.tsrx (600 tokens)
               ├── global-scoping.test.tsrx (900 tokens)
               ├── style-identifier.test.tsrx (2000 tokens)
            ├── date.test.tsrx (2000 tokens)
            ├── dynamic-elements.test.tsrx (4.2k tokens)
            ├── events.test.tsrx (3.5k tokens)
            ├── for.test.tsrx (1500 tokens)
            ├── function-overload-import.tsrx
            ├── function-overload.test.tsrx (200 tokens)
            ├── head.test.tsrx (800 tokens)
            ├── html.test.tsrx (300 tokens)
            ├── input-value.test.tsrx (20.4k tokens)
            ├── lazy-destructuring.test.tsrx (1800 tokens)
            ├── map.test.tsrx (1200 tokens)
            ├── media-query.test.tsrx (600 tokens)
            ├── object.test.tsrx (900 tokens)
            ├── portal.test.tsrx (900 tokens)
            ├── ref.test.tsrx (2.5k tokens)
            ├── return.test.tsrx (12.4k tokens)
            ├── set.test.tsrx (900 tokens)
            ├── svg.test.tsrx (2.8k tokens)
            ├── switch.test.tsrx (2.1k tokens)
            ├── track-async-hydration.test.tsrx (300 tokens)
            ├── try.test.tsrx (10k tokens)
            ├── tsconfig.json
            ├── tsx.test.tsrx (3.4k tokens)
            ├── typescript-generics.test.tsrx (800 tokens)
            ├── url-search-params/
               ├── url-search-params.derived.test.tsrx (500 tokens)
               ├── url-search-params.initialization.test.tsrx (400 tokens)
               ├── url-search-params.iteration.test.tsrx (900 tokens)
               ├── url-search-params.mutation.test.tsrx (2.2k tokens)
               ├── url-search-params.retrieval.test.tsrx (900 tokens)
               ├── url-search-params.serialization.test.tsrx (300 tokens)
               ├── url-search-params.tracked-url.test.tsrx (400 tokens)
            ├── url/
               ├── url.derived.test.tsrx (600 tokens)
               ├── url.parsing.test.tsrx (1100 tokens)
               ├── url.partial-removal.test.tsrx (1200 tokens)
               ├── url.reactivity.test.tsrx (3.1k tokens)
               ├── url.serialization.test.tsrx (300 tokens)
         ├── common.d.ts (omitted)
         ├── hydration.d.ts (omitted)
         ├── hydration/
            ├── basic.test.js (1200 tokens)
            ├── build-components.js (500 tokens)
            ├── compiled/
               ├── client/
                  ├── basic.js (2k tokens)
                  ├── composite.js (800 tokens)
                  ├── events.js (1000 tokens)
                  ├── for.js (5.9k tokens)
                  ├── head.js (1000 tokens)
                  ├── hmr.js (300 tokens)
                  ├── html-in-template.js (300 tokens)
                  ├── html.js (8.4k tokens)
                  ├── if-children.js (2k tokens)
                  ├── if.js (1300 tokens)
                  ├── mixed-control-flow.js (2k tokens)
                  ├── nested-control-flow.js (5.3k tokens)
                  ├── portal.js (700 tokens)
                  ├── reactivity.js (600 tokens)
                  ├── return.js (9.1k tokens)
                  ├── switch.js (1500 tokens)
                  ├── track-async-serialization.js (1800 tokens)
                  ├── try.js (500 tokens)
               ├── server/
                  ├── basic.js (2.3k tokens)
                  ├── composite.js (700 tokens)
                  ├── events.js (900 tokens)
                  ├── for.js (4.8k tokens)
                  ├── head.js (1200 tokens)
                  ├── hmr.js (300 tokens)
                  ├── html-in-template.js (400 tokens)
                  ├── html.js (9.2k tokens)
                  ├── if-children.js (2.5k tokens)
                  ├── if.js (1100 tokens)
                  ├── mixed-control-flow.js (1400 tokens)
                  ├── nested-control-flow.js (3.2k tokens)
                  ├── portal.js (900 tokens)
                  ├── reactivity.js (600 tokens)
                  ├── return.js (7.3k tokens)
                  ├── switch.js (1100 tokens)
                  ├── track-async-serialization.js (1800 tokens)
                  ├── try.js (500 tokens)
            ├── components/
               ├── basic.tsrx (700 tokens)
               ├── composite.tsrx (200 tokens)
               ├── events.tsrx (400 tokens)
               ├── for.tsrx (2.1k tokens)
               ├── head.tsrx (400 tokens)
               ├── hmr.tsrx (200 tokens)
               ├── html-in-template.tsrx (100 tokens)
               ├── html.tsrx (2.7k tokens)
               ├── if-children.tsrx (1100 tokens)
               ├── if.tsrx (400 tokens)
               ├── mixed-control-flow.tsrx (500 tokens)
               ├── nested-control-flow.tsrx (1300 tokens)
               ├── portal.tsrx (300 tokens)
               ├── reactivity.tsrx (200 tokens)
               ├── return.tsrx (2.1k tokens)
               ├── switch.tsrx (500 tokens)
               ├── track-async-serialization.tsrx (500 tokens)
               ├── try.tsrx (100 tokens)
            ├── composite.test.js (400 tokens)
            ├── events.test.js (700 tokens)
            ├── for.test.js (3.4k tokens)
            ├── head.test.js (800 tokens)
            ├── hmr.test.js (600 tokens)
            ├── html-in-template.test.js (400 tokens)
            ├── html.test.js (2000 tokens)
            ├── if-children.test.js (2k tokens)
            ├── if.test.js (700 tokens)
            ├── mixed-control-flow.test.js (600 tokens)
            ├── nested-control-flow.test.js (1700 tokens)
            ├── portal.test.js (500 tokens)
            ├── reactivity.test.js (300 tokens)
            ├── return.test.js (4.5k tokens)
            ├── switch.test.js (900 tokens)
            ├── track-async-serialization.test.js (1000 tokens)
            ├── try.test.js (500 tokens)
            ├── tsconfig.json
         ├── server.d.ts (omitted)
         ├── server/
            ├── __snapshots__/
               ├── compiler.test.tsrx.snap
            ├── await.test.tsrx (300 tokens)
            ├── basic.attributes.test.tsrx (2.9k tokens)
            ├── basic.components.test.tsrx (2.2k tokens)
            ├── basic.test.tsrx (1100 tokens)
            ├── compiler.test.tsrx (1700 tokens)
            ├── composite.props.test.tsrx (800 tokens)
            ├── composite.test.tsrx (1000 tokens)
            ├── context.test.tsrx (100 tokens)
            ├── dynamic-elements.test.tsrx (2.3k tokens)
            ├── for.test.tsrx (800 tokens)
            ├── head.test.tsrx (500 tokens)
            ├── html-nesting-validation.test.tsrx (1400 tokens)
            ├── if.test.tsrx (400 tokens)
            ├── lazy-destructuring.test.tsrx (2.8k tokens)
            ├── return.test.tsrx (5.7k tokens)
            ├── streaming-ssr.test.tsrx (600 tokens)
            ├── style-identifier.test.tsrx (1600 tokens)
            ├── switch.test.tsrx (500 tokens)
            ├── track-async-serialization.test.tsrx (1100 tokens)
            ├── try.test.tsrx (2.3k tokens)
            ├── tsconfig.json
         ├── setup-client.js (200 tokens)
         ├── setup-hydration.js (500 tokens)
         ├── setup-server.js (300 tokens)
         ├── utils/
            ├── compiler-compat-config.test.js (200 tokens)
            ├── runtime-imports.test.js (200 tokens)
            ├── vite-plugin-config.test.js (500 tokens)
            ├── vite-plugin-hmr.test.js (600 tokens)
      ├── tsconfig.json (100 tokens)
      ├── tsconfig.typecheck.json
      ├── types/
         ├── compiler.d.ts (omitted)
         ├── index.d.ts (omitted)
         ├── server.d.ts (omitted)
   ├── rollup-plugin/
      ├── CHANGELOG.md (1600 tokens)
      ├── LICENSE (200 tokens)
      ├── index.js (300 tokens)
      ├── package.json (200 tokens)
      ├── tsconfig.json
      ├── tsconfig.typecheck.json
   ├── rspack-plugin-preact/
      ├── CHANGELOG.md (1200 tokens)
      ├── package.json (200 tokens)
      ├── src/
         ├── css-loader.js (100 tokens)
         ├── index.js (500 tokens)
         ├── js-loader.js (200 tokens)
      ├── tests/
         ├── basic.test.js (1000 tokens)
      ├── tsconfig.json
      ├── types/
         ├── index.d.ts (omitted)
   ├── rspack-plugin-react/
      ├── CHANGELOG.md (1800 tokens)
      ├── package.json (200 tokens)
      ├── src/
         ├── css-loader.js (100 tokens)
         ├── index.js (500 tokens)
         ├── js-loader.js (200 tokens)
      ├── tests/
         ├── basic.test.js (900 tokens)
      ├── tsconfig.json
      ├── types/
         ├── index.d.ts (omitted)
         ├── rspack-core-shim.d.ts (omitted)
   ├── rspack-plugin-solid/
      ├── CHANGELOG.md (1000 tokens)
      ├── package.json (200 tokens)
      ├── src/
         ├── css-loader.js (100 tokens)
         ├── index.js (500 tokens)
         ├── js-loader.js (200 tokens)
      ├── tests/
         ├── basic.test.js (1000 tokens)
      ├── tsconfig.json
      ├── types/
         ├── index.d.ts (omitted)
   ├── rspack-plugin-vue/
      ├── CHANGELOG.md (1200 tokens)
      ├── package.json (200 tokens)
      ├── src/
         ├── css-loader.js (100 tokens)
         ├── index.js (500 tokens)
         ├── interop-loader.js
         ├── js-loader.js (200 tokens)
         ├── vapor-loader.js (600 tokens)
      ├── tests/
         ├── basic.test.js (1400 tokens)
      ├── tsconfig.json
      ├── types/
         ├── index.d.ts (omitted)
   ├── sublime-text-plugin/
      ├── .gitignore
      ├── package.json (100 tokens)
      ├── scripts/
         ├── build.js (100 tokens)
      ├── src/
         ├── .python-version
         ├── Ripple.sublime-settings
         ├── dependencies.json
         ├── language-server/
            ├── package-lock.json (3.2k tokens)
            ├── package.json
         ├── plugin.py (900 tokens)
   ├── tree-sitter/
      ├── build/
         ├── Makefile (2.8k tokens)
         ├── Release/
            ├── .deps/
               ├── Release/
                  ├── obj.target/
                     ├── tree_sitter_ripple_binding/
                        ├── bindings/
                           ├── node/
                              ├── binding.o.d (500 tokens)
                        ├── src/
                           ├── parser.o.d (300 tokens)
                           ├── scanner.o.d (300 tokens)
                  ├── tree_sitter_ripple_binding.node.d (100 tokens)
            ├── obj.target/
               ├── tree_sitter_ripple_binding/
                  ├── bindings/
                     ├── node/
                        ├── binding.o
                  ├── src/
                     ├── parser.o
                     ├── scanner.o
            ├── tree_sitter_ripple_binding.node
         ├── binding.Makefile
         ├── config.gypi (4.1k tokens)
         ├── gyp-mac-tool (6.1k tokens)
         ├── tree_sitter_ripple_binding.target.mk (1200 tokens)
   ├── tsrx-mcp/
      ├── CHANGELOG.md (2.1k tokens)
      ├── README.md (800 tokens)
      ├── package.json (200 tokens)
      ├── scripts/
         ├── generate-docs-index.js (2.3k tokens)
      ├── src/
         ├── analyze.js (1400 tokens)
         ├── authoring.js (3.2k tokens)
         ├── compile.js (1000 tokens)
         ├── docs.js (200 tokens)
         ├── format.js (700 tokens)
         ├── generated/
            ├── docs.js (1900 tokens)
         ├── http.js (600 tokens)
         ├── index.js (200 tokens)
         ├── inspect.js (1300 tokens)
         ├── schemas.js (800 tokens)
         ├── server.js (4.5k tokens)
         ├── stdio.js (100 tokens)
         ├── target.js (1100 tokens)
         ├── validate.js (500 tokens)
      ├── tests/
         ├── authoring.test.js (500 tokens)
         ├── compile.test.js (4.5k tokens)
         ├── docs.test.js (300 tokens)
         ├── fixtures/
            ├── preact-project/
               ├── package.json
            ├── react-project/
               ├── package.json (100 tokens)
               ├── src/
                  ├── Valid.tsrx
            ├── ripple-project/
               ├── package.json
            ├── solid-project/
               ├── package.json
            ├── vue-project/
               ├── package.json
         ├── http.test.js (1100 tokens)
         ├── package.test.js (400 tokens)
         ├── stdio.test.js (1900 tokens)
      ├── tsconfig.json (100 tokens)
      ├── tsconfig.typecheck.json
   ├── tsrx-preact/
      ├── CHANGELOG.md (6.6k tokens)
      ├── package.json (200 tokens)
      ├── src/
         ├── error-boundary.js (200 tokens)
         ├── index.js (500 tokens)
         ├── ref.js
         ├── runtime/
            ├── iterable.js
         ├── transform.js (300 tokens)
      ├── tests/
         ├── basic.test.js (2.1k tokens)
      ├── tsconfig.json
      ├── types/
         ├── error-boundary.d.ts (omitted)
         ├── index.d.ts (omitted)
         ├── ref.d.ts (omitted)
         ├── runtime/
            ├── iterable.d.ts (omitted)
   ├── tsrx-react/
      ├── CHANGELOG.md (7.8k tokens)
      ├── package.json (200 tokens)
      ├── src/
         ├── error-boundary.js (200 tokens)
         ├── index.js (500 tokens)
         ├── ref.js
         ├── runtime/
            ├── iterable.js
         ├── transform.js (200 tokens)
      ├── tests/
         ├── basic.test.js (12.2k tokens)
      ├── tsconfig.json
      ├── types/
         ├── error-boundary.d.ts (omitted)
         ├── index.d.ts (omitted)
         ├── ref.d.ts (omitted)
         ├── runtime/
            ├── iterable.d.ts (omitted)
   ├── tsrx-ripple/
      ├── CHANGELOG.md (4.5k tokens)
      ├── package.json (200 tokens)
      ├── src/
         ├── analyze/
            ├── index.js (15k tokens)
         ├── helpers.d.ts (omitted)
         ├── index.js (600 tokens)
         ├── transform/
            ├── client/
               ├── index.js (34.1k tokens)
            ├── server/
               ├── index.js (11.2k tokens)
         ├── utils.js (5.9k tokens)
      ├── tests/
         ├── basic.test.js (1800 tokens)
      ├── tsconfig.json (100 tokens)
      ├── types/
         ├── index.d.ts (omitted)
         ├── rpc.d.ts (omitted)
   ├── tsrx-solid/
      ├── CHANGELOG.md (7k tokens)
      ├── package.json (200 tokens)
      ├── src/
         ├── index.js (500 tokens)
         ├── ref.js
         ├── transform.js (12.6k tokens)
      ├── tests/
         ├── basic.test.js (5.4k tokens)
      ├── tsconfig.json
      ├── types/
         ├── index.d.ts (omitted)
         ├── ref.d.ts (omitted)
   ├── tsrx-vue/
      ├── CHANGELOG.md (4.7k tokens)
      ├── package.json (200 tokens)
      ├── src/
         ├── error-boundary.js (1000 tokens)
         ├── index.js (500 tokens)
         ├── interop.js (500 tokens)
         ├── ref.js
         ├── transform.js (6.9k tokens)
      ├── tests/
         ├── __snapshots__/
            ├── basic.test.js.snap
         ├── basic.test.js (6.4k tokens)
      ├── tsconfig.json
      ├── types/
         ├── error-boundary.d.ts (omitted)
         ├── index.d.ts (omitted)
         ├── interop.d.ts (omitted)
         ├── ref.d.ts (omitted)
   ├── tsrx/
      ├── CHANGELOG.md (8k tokens)
      ├── README.md (600 tokens)
      ├── package.json (600 tokens)
      ├── src/
         ├── analyze/
            ├── css-analyze.js (1000 tokens)
            ├── prune.js (6.5k tokens)
            ├── validation.js (1900 tokens)
         ├── comment-utils.js (500 tokens)
         ├── constants.js (100 tokens)
         ├── diagnostics.js (100 tokens)
         ├── errors.js (400 tokens)
         ├── helpers.d.ts (omitted)
         ├── identifier-utils.js (400 tokens)
         ├── index.js (1800 tokens)
         ├── parse/
            ├── index.js (5.7k tokens)
            ├── parse-module.js (100 tokens)
            ├── style.js (3.1k tokens)
         ├── plugin.js (21.6k tokens)
         ├── runtime/
            ├── events.js
            ├── hash.js
            ├── html.js
            ├── iterable.js (500 tokens)
            ├── language-helpers.js (400 tokens)
            ├── ref.js (1100 tokens)
         ├── scope.js (2.5k tokens)
         ├── source-map-utils.js (2.3k tokens)
         ├── transform/
            ├── await.js (300 tokens)
            ├── jsx-hoist.js (700 tokens)
            ├── jsx-interleave.js (600 tokens)
            ├── jsx/
               ├── ast-builders.js (2.9k tokens)
               ├── helpers.js (1700 tokens)
               ├── index.js (34.5k tokens)
            ├── lazy.js (6.4k tokens)
            ├── scoping.js (1500 tokens)
            ├── segments.js (14.7k tokens)
            ├── stylesheet.js (3.1k tokens)
         ├── utils.js (100 tokens)
         ├── utils/
            ├── ast.js (2000 tokens)
            ├── builders.js (7k tokens)
            ├── dom.js (500 tokens)
            ├── escaping.js (200 tokens)
            ├── events.js (600 tokens)
            ├── hashing.js (300 tokens)
            ├── normalize_css_property_name.js (100 tokens)
            ├── patterns.js (200 tokens)
            ├── sanitize_template_string.js
      ├── tests/
         ├── shared/
            ├── compile.js (22.5k tokens)
            ├── runtime/
               ├── switch-fallthrough-components.tsrx (400 tokens)
               ├── switch-fallthrough.js (1200 tokens)
            ├── source-mappings.js (9.3k tokens)
         ├── utils/
            ├── escaping.test.js (600 tokens)
            ├── events.test.js (1200 tokens)
            ├── normalize_css_property_name.test.js (400 tokens)
            ├── patterns.test.js (3.5k tokens)
            ├── ref-runtime.test.js (600 tokens)
            ├── ref-types.test.js (300 tokens)
            ├── sanitize_template_string.test.js (400 tokens)
      ├── tsconfig.json (100 tokens)
      ├── types/
         ├── acorn.d.ts (omitted)
         ├── estree-jsx.d.ts (omitted)
         ├── estree.d.ts (omitted)
         ├── index.d.ts (omitted)
         ├── jsx-platform.d.ts (omitted)
         ├── parse.d.ts (omitted)
         ├── runtime/
            ├── events.d.ts (omitted)
            ├── hash.d.ts (omitted)
            ├── html.d.ts (omitted)
            ├── iterable.d.ts (omitted)
            ├── language-helpers.d.ts (omitted)
            ├── ref.d.ts (omitted)
   ├── turbopack-plugin-react/
      ├── CHANGELOG.md (1700 tokens)
      ├── package.json (200 tokens)
      ├── src/
         ├── css-loader.js (100 tokens)
         ├── index.js (600 tokens)
         ├── loader.js (600 tokens)
      ├── tests/
         ├── basic.test.js (1300 tokens)
      ├── tsconfig.json
      ├── types/
         ├── index.d.ts (omitted)
   ├── typescript-plugin/
      ├── CHANGELOG.md (4.7k tokens)
      ├── LICENSE (200 tokens)
      ├── README.md (300 tokens)
      ├── package.json (300 tokens)
      ├── src/
         ├── index.js (100 tokens)
         ├── language.js (5.9k tokens)
         ├── tsc.js (100 tokens)
         ├── utils.js (300 tokens)
      ├── tests/
         ├── compiler-resolution.test.js (1700 tokens)
         ├── fixtures/
            ├── workspaces/
               ├── both-react/
                  ├── package.json
               ├── both/
                  ├── package.json
               ├── react-only/
                  ├── package.json
               ├── ripple-only/
                  ├── package.json
         ├── plugin-integration.test.js (1100 tokens)
         ├── workspace-fixtures.js (1400 tokens)
      ├── tsconfig.json (100 tokens)
      ├── tsconfig.typecheck.json
      ├── tsdown.config.js (200 tokens)
   ├── vite-plugin-preact/
      ├── CHANGELOG.md (1500 tokens)
      ├── package.json (200 tokens)
      ├── src/
         ├── index.js (600 tokens)
      ├── tests/
         ├── basic.test.js (300 tokens)
         ├── runtime.test.tsrx (2.6k tokens)
         ├── setup.js (100 tokens)
         ├── tsconfig.json (100 tokens)
         ├── types.d.ts (omitted)
      ├── tsconfig.json
      ├── types/
         ├── index.d.ts (omitted)
   ├── vite-plugin-react/
      ├── CHANGELOG.md (1900 tokens)
      ├── package.json (200 tokens)
      ├── src/
         ├── index.js (500 tokens)
      ├── tests/
         ├── basic.test.js (300 tokens)
         ├── fixtures/
            ├── react-aria/
               ├── App.tsrx (300 tokens)
               ├── AriaActionButton.tsx (200 tokens)
               ├── runtime.test.tsrx (200 tokens)
               ├── tsconfig.json
               ├── typecheck.test.js (300 tokens)
               ├── types.ts (100 tokens)
            ├── react-query/
               ├── App.tsrx (200 tokens)
               ├── QueryFixtureShell.tsx (600 tokens)
               ├── runtime.test.tsrx (600 tokens)
               ├── tsconfig.json
               ├── typecheck.test.js (300 tokens)
               ├── types.ts (100 tokens)
            ├── react-router/
               ├── App.tsrx (100 tokens)
               ├── RouterFixtureShell.tsx (300 tokens)
               ├── runtime.test.tsrx (200 tokens)
               ├── tsconfig.json
               ├── typecheck.test.js (300 tokens)
               ├── types.ts
         ├── runtime.test.tsrx (10.1k tokens)
         ├── setup.js (200 tokens)
         ├── tsconfig.json (100 tokens)
         ├── types.d.ts (omitted)
      ├── tsconfig.json
      ├── types/
         ├── index.d.ts (omitted)
   ├── vite-plugin-solid/
      ├── CHANGELOG.md (2000 tokens)
      ├── package.json (200 tokens)
      ├── src/
         ├── index.js (1200 tokens)
      ├── tests/
         ├── plugin.test.js (500 tokens)
         ├── runtime.test.tsrx (8.7k tokens)
         ├── setup.js (400 tokens)
         ├── tsconfig.json (100 tokens)
         ├── types.d.ts (omitted)
      ├── tsconfig.json
      ├── types/
         ├── index.d.ts (omitted)
   ├── vite-plugin-vue/
      ├── CHANGELOG.md (1300 tokens)
      ├── package.json (200 tokens)
      ├── src/
         ├── index.js (1300 tokens)
         ├── interop.js (200 tokens)
      ├── tests/
         ├── runtime.test.tsrx (8.3k tokens)
         ├── setup.js (200 tokens)
         ├── tsconfig.json (100 tokens)
         ├── types.d.ts (omitted)
         ├── vue-jsx-vapor-jsx-runtime-shim.js (100 tokens)
         ├── vue-jsx-vapor-shim.js (1900 tokens)
         ├── vue-runtime-shim.js
      ├── tsconfig.json
      ├── types/
         ├── index.d.ts (omitted)
   ├── vite-plugin/
      ├── CHANGELOG.md (3k tokens)
      ├── LICENSE (200 tokens)
      ├── package.json (200 tokens)
      ├── src/
         ├── bin/
            ├── preview.js (200 tokens)
         ├── constants.js
         ├── index.js (9.1k tokens)
         ├── load-config.js (1500 tokens)
         ├── routes.js (300 tokens)
         ├── server/
            ├── component-wrappers.js (300 tokens)
            ├── middleware.js (700 tokens)
            ├── production.js (1600 tokens)
            ├── render-route.js (1100 tokens)
            ├── router.js (600 tokens)
            ├── server-route.js (200 tokens)
            ├── virtual-entry.js (1400 tokens)
      ├── tests/
         ├── configure-server.test.js (1600 tokens)
         ├── render-route-props.test.js (800 tokens)
      ├── tsconfig.json (100 tokens)
      ├── tsconfig.typecheck.json
      ├── types/
         ├── index.d.ts (omitted)
         ├── production.d.ts (omitted)
   ├── vscode-plugin/
      ├── .gitignore
      ├── .vscodeignore
      ├── CHANGELOG.md (5.4k tokens)
      ├── LICENSE (200 tokens)
      ├── README.md
      ├── icons/
         ├── image.png
         ├── logo.png
      ├── language-configuration.json (900 tokens)
      ├── package.json (1200 tokens)
      ├── scripts/
         ├── repack-vsix.js (700 tokens)
      ├── src/
         ├── extension.js (4.9k tokens)
         ├── server.js
      ├── tsconfig.json (100 tokens)
      ├── tsconfig.typecheck.json
      ├── tsdown.config.js (500 tokens)
   ├── zed-plugin/
      ├── .gitignore
      ├── Cargo.lock (omitted)
      ├── Cargo.toml
      ├── DEVELOPMENT.md (700 tokens)
      ├── LICENSE (200 tokens)
      ├── README.md (300 tokens)
      ├── extension.toml (100 tokens)
      ├── languages/
         ├── tsrx/
            ├── brackets.scm (100 tokens)
            ├── config.toml (100 tokens)
            ├── folds.scm (100 tokens)
            ├── highlights.scm (900 tokens)
            ├── indents.scm (200 tokens)
            ├── injections.scm (300 tokens)
            ├── locals.scm (200 tokens)
            ├── outline.scm (100 tokens)
            ├── textobjects.scm (300 tokens)
      ├── package.json (100 tokens)
      ├── src/
         ├── lib.rs (2.2k tokens)
├── plans/
   ├── tsrx-double-quoted-text-children.md (600 tokens)
├── playground/
   ├── .vscode/
      ├── settings.json (100 tokens)
   ├── react/
      ├── CHANGELOG.md (300 tokens)
      ├── README.md (200 tokens)
      ├── index.html
      ├── package.json (200 tokens)
      ├── tsconfig.json (100 tokens)
      ├── vite.config.js
   ├── ripple/
      ├── demo.css (800 tokens)
      ├── eslint.config.js
      ├── index.html (100 tokens)
      ├── package.json (300 tokens)
      ├── ripple.config.ts
      ├── ssr-dev.js (600 tokens)
      ├── tsconfig.json (100 tokens)
      ├── vite.config.js (100 tokens)
   ├── solid/
      ├── CHANGELOG.md (300 tokens)
      ├── README.md (300 tokens)
      ├── index.html
      ├── package.json (200 tokens)
      ├── tsconfig.json (100 tokens)
      ├── vite.config.js
   ├── vue/
      ├── CHANGELOG.md (200 tokens)
      ├── README.md (200 tokens)
      ├── index.html
      ├── package.json (200 tokens)
      ├── src/
         ├── main.tsx
      ├── tsconfig.json (100 tokens)
      ├── vite.config.js
├── pnpm-lock.yaml (omitted)
├── pnpm-workspace.yaml (700 tokens)
├── rulesync.jsonc
├── scripts/
   ├── build-if-changed.js (700 tokens)
   ├── check-changesets.js (300 tokens)
   ├── check-zed-grammar-rev.js (400 tokens)
   ├── collect-external-deps.js (1000 tokens)
   ├── copy-external-deps.js (700 tokens)
   ├── copy-tree-sitter-queries.js (400 tokens)
   ├── debug-mode.js (500 tokens)
   ├── regenerate-textmate.js (800 tokens)
   ├── remove.js (200 tokens)
   ├── sync-zed-grammar-rev.js (300 tokens)
   ├── sync-zed-plugin-version.js (200 tokens)
   ├── transform-package.js (300 tokens)
├── templates/
   ├── basic/
      ├── .gitignore
      ├── .prettierignore
      ├── .prettierrc
      ├── README.md (200 tokens)
      ├── eslint.config.js
      ├── index.html (100 tokens)
      ├── package.json (200 tokens)
      ├── src/
         ├── App.tsrx (600 tokens)
         ├── assets/
            ├── favicon.ico
            ├── ripple-logo-horizontal.png
         ├── index.ts
      ├── tsconfig.json (100 tokens)
      ├── vite.config.js
├── tree-sitter
├── vitest.config.js (2.2k tokens)
├── website-mcp/
   ├── CHANGELOG.md (1600 tokens)
   ├── README.md (200 tokens)
   ├── api/
      ├── mcp.js
   ├── package.json (100 tokens)
   ├── public/
      ├── index.html (200 tokens)
   ├── scripts/
      ├── build.js
   ├── src/
      ├── handler.js (100 tokens)
      ├── server.js (200 tokens)
   ├── vercel.json (100 tokens)
├── website-new/
   ├── CHANGELOG.md (1500 tokens)
   ├── api/
      ├── handler.js (200 tokens)
   ├── docs/
      ├── best-practices.md (100 tokens)
      ├── comparison.md (100 tokens)
      ├── examples.ts (3.2k tokens)
      ├── guide/
         ├── application.md (700 tokens)
         ├── bindings.md (3.4k tokens)
         ├── components.md (1200 tokens)
         ├── control-flow.md (1400 tokens)
         ├── dom-refs.md (500 tokens)
         ├── events.md (1300 tokens)
         ├── head-management.md (100 tokens)
         ├── reactivity.md (3.1k tokens)
         ├── state-management.md (500 tokens)
         ├── styling.md (1400 tokens)
         ├── syntax.md (2k tokens)
      ├── introduction.md (600 tokens)
      ├── libraries.md (100 tokens)
      ├── quick-start.md (900 tokens)
      ├── troubleshooting.md (300 tokens)
   ├── index.html (300 tokens)
   ├── package.json (100 tokens)
   ├── playground.md
   ├── public/
      ├── 404.html (900 tokens)
      ├── favicon.ico
      ├── favicon.svg (200 tokens)
      ├── images/
         ├── favicon.ico
         ├── favicon.svg (200 tokens)
         ├── ripple-logo-horizontal.png
         ├── ripple-social.png
      ├── llms.txt (10.6k tokens)
      ├── ripple-logo-horizontal.png
      ├── ripple-social.png
      ├── robots.txt
      ├── sitemap.xml (100 tokens)
   ├── ripple.config.ts (100 tokens)
   ├── src/
      ├── components/
         ├── actions.tsrx (1000 tokens)
         ├── content.tsrx (500 tokens)
         ├── doc-badge.tsrx
         ├── doc-callout.tsrx (100 tokens)
         ├── doc-code-block.tsrx (200 tokens)
         ├── doc-heading.tsrx (100 tokens)
         ├── docs-footer.tsrx (100 tokens)
         ├── docs-header.tsrx (2.5k tokens)
         ├── docs-layout.tsrx (4k tokens)
         ├── editor.tsrx (1000 tokens)
         ├── header.tsrx (200 tokens)
         ├── layout.tsrx (700 tokens)
         ├── sidebar.tsrx (1900 tokens)
      ├── lib/
         ├── markdown.js (2000 tokens)
      ├── middlewares.ts (100 tokens)
      ├── pages/
         ├── 404.tsrx
         ├── docs/
            ├── best-practices.tsrx (100 tokens)
            ├── comparison.tsrx (100 tokens)
            ├── guide/
               ├── application.tsrx (100 tokens)
               ├── bindings.tsrx (100 tokens)
               ├── components.tsrx (100 tokens)
               ├── control-flow.tsrx (100 tokens)
               ├── dom-refs.tsrx (100 tokens)
               ├── events.tsrx (100 tokens)
               ├── head-management.tsrx (100 tokens)
               ├── reactivity.tsrx (100 tokens)
               ├── state-management.tsrx (100 tokens)
               ├── styling.tsrx (100 tokens)
               ├── syntax.tsrx (100 tokens)
            ├── introduction.tsrx (1000 tokens)
            ├── libraries.tsrx (100 tokens)
            ├── quick-start.tsrx (100 tokens)
            ├── troubleshooting.tsrx (100 tokens)
         ├── index.tsrx (100 tokens)
      ├── routes.ts (2.2k tokens)
   ├── tsconfig.json (100 tokens)
   ├── vercel.json (300 tokens)
   ├── vite.config.ts (100 tokens)
├── website-tsrx/
   ├── CHANGELOG.md (3.7k tokens)
   ├── api/
      ├── handler.js (100 tokens)
   ├── index.html (400 tokens)
   ├── package.json (200 tokens)
   ├── public/
      ├── images/
         ├── tsrx-mark.svg (600 tokens)
      ├── llms.txt (7k tokens)
   ├── ripple.config.ts (100 tokens)
   ├── src/
      ├── components/
         ├── brand-logo.tsrx (100 tokens)
         ├── compiler-demo.tsrx (3.9k tokens)
         ├── layout.tsrx (200 tokens)
      ├── lib/
         ├── demo-snippets.ts (1100 tokens)
         ├── demo.ts (100 tokens)
         ├── shiki-codemirror.ts (600 tokens)
      ├── pages/
         ├── docs.tsrx (10.7k tokens)
         ├── features.tsrx (15.7k tokens)
         ├── getting-started.tsrx (11k tokens)
         ├── index.tsrx (6.2k tokens)
         ├── playground.tsrx (800 tokens)
         ├── specification.tsrx (8.1k tokens)
      ├── routes.ts (1200 tokens)
   ├── tsconfig.json (100 tokens)
   ├── vercel.json (300 tokens)
   ├── vite.config.ts (400 tokens)
├── website/
   ├── .vitepress/
      ├── components/
         ├── Code.vue (300 tokens)
         ├── LiveCodes.vue (4.7k tokens)
         ├── Playground.vue (100 tokens)
         ├── PlaygroundProps.ts (100 tokens)
      ├── config.js (900 tokens)
      ├── theme/
         ├── index.js (100 tokens)
         ├── styles.css (300 tokens)
   ├── docs/
      ├── best-practices.md (100 tokens)
      ├── comparison.md (100 tokens)
      ├── examples.ts (3.2k tokens)
      ├── guide/
         ├── application.md (700 tokens)
         ├── bindings.md (3.4k tokens)
         ├── components.md (1200 tokens)
         ├── control-flow.md (1400 tokens)
         ├── dom-refs.md (1200 tokens)
         ├── events.md (1300 tokens)
         ├── head-management.md (100 tokens)
         ├── reactivity.md (3.1k tokens)
         ├── state-management.md (500 tokens)
         ├── styling.md (1500 tokens)
         ├── syntax.md (2k tokens)
      ├── introduction.md (600 tokens)
      ├── libraries.md (100 tokens)
      ├── quick-start.md (900 tokens)
      ├── troubleshooting.md (300 tokens)
   ├── package.json (100 tokens)
   ├── playground.md
   ├── public/
      ├── 404.html (900 tokens)
      ├── favicon.ico
      ├── favicon.svg (200 tokens)
      ├── index.html (6.8k tokens)
      ├── llms.txt (10.6k tokens)
      ├── ripple-logo-horizontal.png
      ├── ripple-social.png
      ├── robots.txt
      ├── sitemap.xml (100 tokens)
   ├── vercel.json (200 tokens)
```


## /.changeset/README.md

# Changesets

Hello and welcome! This folder has been automatically generated by
`@changesets/cli`, a build tool that works with multi-package repos, or
single-package repos to help you version and publish your code. You can find the
full documentation for it
[in our repository](https://github.com/changesets/changesets)

We have a quick list of common questions to get you started engaging with this
project in
[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)


## /.changeset/config.json

```json path="/.changeset/config.json" 
{
  "$schema": "https://unpkg.com/@changesets/config@3.1.2/schema.json",
  "changelog": ["@changesets/changelog-github", { "repo": "Ripple-TS/ripple" }],
  "commit": false,
  "fixed": [
    [
      "@tsrx/core"
    ],
    [
      "@tsrx/ripple"
    ],
    [
      "ripple",
      "@ripple-ts/cli",
      "@ripple-ts/compat-react",
      "create-ripple",
      "@tsrx/eslint-parser",
      "@tsrx/eslint-plugin",
      "@ripple-ts/language-server",
      "@tsrx/prettier-plugin",
      "@ripple-ts/adapter",
      "@ripple-ts/adapter-node",
      "@ripple-ts/adapter-bun",
      "@ripple-ts/adapter-vercel",
      "@ripple-ts/rollup-plugin",
      "@tsrx/typescript-plugin",
      "@ripple-ts/vite-plugin"
    ]
  ],
  "linked": [],
  "access": "public",
  "baseBranch": "main",
  "updateInternalDependencies": "patch",
  "ignore": [
    "@ripple-ts/playground",
    "@ripple-ts/tree-sitter",
    "@ripple-ts/nvim-plugin",
    "@ripple-ts/intellij-plugin",
    "@ripple-ts/sublime-text-plugin",
    "@ripple-ts/zed-plugin"
  ]
}

```

## /.claude/skills/ripple.md

../../.agents/skills/ripple.md

## /.codex/skills/ripple.md

../../.agents/skills/ripple.md

## /.cursor/environment.json

```json path="/.cursor/environment.json" 
{
  "name": "ripple-monorepo",
  "install": "bash .cursor/install.sh"
}

```

## /.cursor/install.sh

```sh path="/.cursor/install.sh" 
#!/usr/bin/env bash
set -euo pipefail

WORKSPACE_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
LOCKFILE_PATH="${WORKSPACE_ROOT}/pnpm-lock.yaml"
LOCKFILE_HASH_PATH="${HOME}/.cache/cursor/ripple-pnpm-lock.sha256"
PACKAGE_MANAGER="$(node -p "JSON.parse(require('node:fs').readFileSync(process.argv[1], 'utf8')).packageManager" "${WORKSPACE_ROOT}/package.json")"
if [[ "${PACKAGE_MANAGER}" != pnpm@* ]]; then
	echo "Expected packageManager in package.json to be pnpm@<version>, got '${PACKAGE_MANAGER}'."
	exit 1
fi
REQUIRED_PNPM_VERSION="${PACKAGE_MANAGER#pnpm@}"

cd "${WORKSPACE_ROOT}"

if [ ! -f "${LOCKFILE_PATH}" ]; then
	echo "Expected lockfile at ${LOCKFILE_PATH}, but it was not found."
	exit 1
fi

pnpm_version=""
if command -v pnpm >/dev/null 2>&1; then
	pnpm_version="$(pnpm --version)"
fi

if [ "${pnpm_version}" != "${REQUIRED_PNPM_VERSION}" ]; then
	corepack enable
	corepack prepare "pnpm@${REQUIRED_PNPM_VERSION}" --activate >/dev/null
fi

lockfile_hash="$(sha256sum "${LOCKFILE_PATH}" | awk '{ print $1 }')"
cached_lockfile_hash=""

if [ -f "${LOCKFILE_HASH_PATH}" ]; then
	read -r cached_lockfile_hash < "${LOCKFILE_HASH_PATH}" || true
fi

if [ -d "${WORKSPACE_ROOT}/node_modules" ] \
	&& [ -x "${WORKSPACE_ROOT}/node_modules/.bin/vitest" ] \
	&& [ "${cached_lockfile_hash}" = "${lockfile_hash}" ]; then
	echo "pnpm dependencies are up to date; skipping install."
else
	pnpm install --frozen-lockfile --prefer-offline
	mkdir -p "$(dirname "${LOCKFILE_HASH_PATH}")"
	printf '%s\n' "${lockfile_hash}" > "${LOCKFILE_HASH_PATH}"
fi

# Warm command resolution so vitest-based test runs start quickly.
pnpm exec vitest --version >/dev/null

```

## /.cursor/rules/project.mdc

```mdc path="/.cursor/rules/project.mdc" 
---
description: Ripple project overview and development guidelines
globs: **/*
---

# Ripple Project Guide for AI Agents

Ripple is a TypeScript-first UI framework and monorepo maintained by Dominic
Gannaway. The current authoring format is centered on `.tsrx` files and the shared
TSRX compiler stack. Older `.ripple`-specific docs and compiler details still
exist in repo history and changelogs, but they are not the right default source of
truth for current work.

## Start From Current Sources

Use the nearest live source rather than historical summaries:

- `website/public/llms.txt` for current Ripple syntax, runtime APIs, and authoring
  guidance
- `README.md` for project overview, positioning, and quick-start examples
- `packages/*/README.md` for package-specific usage and public APIs
- `vitest.config.js` for the current test projects and file globs
- `package.json` for workspace-wide scripts such as `rules:generate`, `test`,
  `format`, `format:check`, and `typecheck`

If a guide in this repo conflicts with nearby code or package READMEs, trust the
nearby code and current package docs.

## RuleSync

This repository uses RuleSync as the single source of truth for shared AI agent
instructions. Edit `.rulesync/rules/` and regenerate derived files instead of
patching generated outputs directly.

Generated targets include:

- `AGENTS.md`
- `.github/copilot-instructions.md`
- `CLAUDE.md`
- `GEMINI.md`
- `.cursor/rules/project.mdc`

After changing RuleSync content, run:

\`\`\`bash
pnpm rules:generate
\`\`\`

## Monorepo Map

This is a pnpm monorepo. The current high-level layout is:

- `packages/tsrx/`: core parser, transforms, and shared compiler infrastructure
- `packages/tsrx-ripple/`, `packages/tsrx-react/`, `packages/tsrx-solid/`,
  `packages/tsrx-preact/`: target-specific compiler layers
- `packages/ripple/`: Ripple runtime, server helpers, and framework behavior
- `packages/vite-plugin/`, `packages/rollup-plugin/`,
  `packages/vite-plugin-react/`, `packages/vite-plugin-solid/`,
  `packages/vite-plugin-preact/`, `packages/rspack-plugin-react/`,
  `packages/turbopack-plugin-react/`: bundler integrations
- `packages/adapter/`, `packages/adapter-node/`, `packages/adapter-bun/`,
  `packages/adapter-vercel/`: deployment and platform adapters
- `packages/language-server/`, `packages/typescript-plugin/`,
  `packages/vscode-plugin/`, `packages/intellij-plugin/`, `packages/nvim-plugin/`,
  `packages/sublime-text-plugin/`, `packages/zed-plugin/`: editor and language
  tooling
- `packages/eslint-parser/`, `packages/eslint-plugin/`,
  `packages/prettier-plugin/`, `packages/prettier-plugin-ripple/`: linting and
  formatting
- `packages/create-ripple/`, `templates/`, `playground/`: scaffolding and local
  examples
- `website/`, `website-new/`, `website-tsrx/`: documentation and website work

When routing a change, prefer the package that directly owns the behavior rather
than editing generated output, tests, or editor integrations first.

## Current Working Assumptions

- Default component files are `.tsrx`. Do not describe the project as primarily
  using `.ripple` files unless the local file you are editing actually does.
- Some packages still preserve compatibility or historical references. Treat them
  as compatibility context, not the default architecture description.
- Use `pnpm` for all package management and workspace scripts.
- Follow the conventions of the package you are changing. This repo mixes plain
  JavaScript, JSDoc-typed JavaScript, and TypeScript depending on package.
- Match nearby naming, file layout, and test style instead of applying a single
  convention repo-wide.

## Finding The Right Package

Use these rough routing rules:

- Ripple syntax, parsing, source transforms, or shared AST behavior:
  `packages/tsrx/` and the relevant target package under `packages/tsrx-*`
- Ripple runtime behavior, hydration, reactivity, DOM updates, or server output:
  `packages/ripple/`
- Vite, Rollup, Rspack, Turbopack, or adapter behavior: the relevant plugin or
  adapter package in `packages/`
- Diagnostics, completions, hover, definitions, or editor integration:
  `packages/language-server/`, `packages/typescript-plugin/`, and editor plugin
  packages
- Formatting or lint behavior: `packages/prettier-plugin/`,
  `packages/prettier-plugin-ripple/`, `packages/eslint-parser/`, or
  `packages/eslint-plugin/`

## Validation

Prefer the smallest validation that covers the touched surface.

Common workspace commands:

\`\`\`bash
pnpm rules:generate
pnpm format:check
pnpm test
pnpm test --project ripple-client
pnpm test --project ripple-server
pnpm typecheck
\`\`\`

Current Vitest projects are defined in `vitest.config.js`. Ripple runtime suites
use `.test.tsrx` files for many client, server, and compat tests, while tooling
packages often use `.test.js` or `.test.ts`.

## Changesets

Add a changeset for user-facing package changes. Skip changesets for docs-only,
test-only, and internal tooling updates.

Only use `patch` changesets. Do not use `minor` or `major` bump types in this
repo; prerelease packages must stay on the patch track until a release plan
explicitly changes that policy.

\`\`\`bash
pnpm changeset
\`\`\`

Validate pending changesets before versioning or publishing:

\`\`\`bash
pnpm changeset:check
\`\`\`

## Practical Guidance For Agents

- Prefer the current docs in `website/public/llms.txt` over stale architectural
  summaries.
- Avoid copying removed compiler APIs, old package layouts, or legacy `.ripple`
  examples into new guidance.
- If you need exact behavior, read the owning package and its tests instead of
  relying on a repo-wide summary.
- Keep documentation updates short and durable. High-level guidance ages better
  than detailed internal call lists.

```

## /.gemini/skills/ripple.md

../../.agents/skills/ripple.md

## /.github/ISSUE_TEMPLATE/bug-report.yml

```yml path="/.github/ISSUE_TEMPLATE/bug-report.yml" 
name: "🐛 Bug Report"
description: "Report a bug or unexpected behavior in Ripple"
title: "[Bug]: "
labels: ["bug", "triage"]
body:
  - type: markdown
    attributes:
      value: |
        Thanks for taking the time to report this issue! Please search existing issues first to avoid duplicates.

  - type: dropdown
    id: category
    attributes:
      label: "Issue Category"
      description: "What type of issue is this?"
      options:
        - "Compilation Bug"
        - "Behavioral Bug"
        - "Performance Issue"
        - "Documentation Issue"
        - "Security Concern"
        - "Other"
    validations:
      required: true

  - type: textarea
    id: description
    attributes:
      label: "Bug Description"
      description: "A clear description of what the bug is and what you expected to happen."
      placeholder: "When I do X, Y happens, but I expected Z..."
    validations:
      required: true

  - type: textarea
    id: reproduction
    attributes:
      label: "Reproduction Steps"
      description: "Provide a minimal reproducible example. Link to a repo, StackBlitz, or detailed steps."
      placeholder: |
        1. Go to...
        2. Click on...
        3. See error...

        OR provide a link to reproduction: https://...
    validations:
      required: true

  - type: textarea
    id: environment
    attributes:
      label: "Environment"
      description: "Share relevant environment details"
      placeholder: |
        - OS: [e.g. macOS 13.1, Windows 11, Ubuntu 22.04]
        - Browser: [e.g. Chrome 118, Firefox 119, Safari 16]
        - Ripple Version: [e.g. 1.2.3]
        - Node Version: [e.g. 22.19.0]
      render: markdown
    validations:
      required: false

  - type: textarea
    id: additional-context
    attributes:
      label: "Additional Context"
      description: "Screenshots, logs, or any other context that might help"
      placeholder: "Add any other context, screenshots, or logs here..."
    validations:
      required: false

  - type: checkboxes
    id: checklist
    attributes:
      label: "Checklist"
      options:
        - label: "I've searched for existing issues"
          required: true
        - label: "I'm willing to help implement a fix"
          required: false

```

## /.github/ISSUE_TEMPLATE/config.yml

```yml path="/.github/ISSUE_TEMPLATE/config.yml" 
blank_issues_enabled: true
contact_links:
  - name: Discord Chat
    url: https://discord.gg/JBF2ySrh2W
    about: Ask questions and discuss ideas with other users real-time
  - name: "Discussions"
    url: "https://github.com/Ripple-TS/ripple/discussions"
    about: "Ask questions and discuss ideas with the community"

```

## /.github/ISSUE_TEMPLATE/feature-request.yml

```yml path="/.github/ISSUE_TEMPLATE/feature-request.yml" 
name: "✨ Feature Request"
description: "Suggest a new feature or enhancement for Ripple"
title: "[Feature]: "
labels: ["enhancement", "triage"]
body:
  - type: markdown
    attributes:
      value: |
        Thanks for suggesting a new feature! Please check existing issues and discussions first.

  - type: dropdown
    id: category
    attributes:
      label: "Feature Category"
      description: "What area does this feature relate to?"
      options:
        - "Performance Enhancement"
        - "Developer Experience"
        - "Syntax/Language Improvement"
        - "Tooling Integration"
        - "Documentation"
        - "Testing/Quality"
        - "Other"
    validations:
      required: true

  - type: textarea
    id: problem
    attributes:
      label: "Problem Statement"
      description: "What problem does this feature solve? What's the use case?"
      placeholder: "As a user, I want to... so that I can..."
    validations:
      required: true

  - type: textarea
    id: solution
    attributes:
      label: "Proposed Solution"
      description: "Describe your proposed solution or feature"
      placeholder: "I would like to see... This could work by..."
    validations:
      required: true

  - type: textarea
    id: alternatives
    attributes:
      label: "Alternatives Considered"
      description: "What other approaches have you considered? Any workarounds you're currently using?"
      placeholder: "I considered... but this doesn't work because..."
    validations:
      required: false

  - type: textarea
    id: examples
    attributes:
      label: "Examples & References"
      description: "Links to similar features in other tools, mockups, or code examples"
      placeholder: "Similar to how X does Y... Here's a mockup/example..."
    validations:
      required: false

  - type: checkboxes
    id: checklist
    attributes:
      label: "Checklist"
      options:
        - label: "I've searched for existing feature requests"
          required: true
        - label: "I'm willing to help implement this feature"
          required: false

```

## /.github/agents/ripple.agent.md

---
name: Ripple
description: An AI assistant specialized in the Ripple TypeScript UI framework
---

You are a helpful assistant specialized in **Ripple**, a TypeScript UI framework
that combines the best parts of React, Solid, and Svelte.

## Your Expertise

- Ripple component syntax and `.ripple` files
- Reactivity system: `track()`, `RippleArray`, `RippleMap`, etc. (imported from
  `ripple`)
- Compiler architecture (parse → analyze → transform)
- SSR and hydration mechanisms
- Runtime internals (blocks, events, DOM operations)
- Editor tooling (language server, Prettier plugin, ESLint plugin)

## Key Resources

For detailed documentation, refer to:

- [AGENTS.md](../AGENTS.md) - Full project guide
- [website/public/llms.txt](../../website/public/llms.txt) - Comprehensive Ripple
  documentation

## Code Conventions

- Use `snake_case` for variables and functions
- Use `SCREAMING_SNAKE_CASE` for constants
- Internal code is JavaScript with JSDoc annotations (not TypeScript)
- **Always use pnpm** - never npm or yarn

## Common Tasks

### Creating a Component

```ripple
component Button(label: string, onClick: () => void) {
  <button onclick={onClick}>{label}</button>
}
```

### Reactive State

```ripple
import { track } from 'ripple';

let count = track(0); // tracked value
let doubled = track(() => @count * 2); // derived value
```

### Validation Commands

```bash
pnpm test           # Run all tests
pnpm format         # Format code
pnpm format:check   # Check formatting
```


## /.github/copilot-instructions.md

# Ripple Project Guide for AI Agents

Ripple is a TypeScript-first UI framework and monorepo maintained by Dominic
Gannaway. The current authoring format is centered on `.tsrx` files and the shared
TSRX compiler stack. Older `.ripple`-specific docs and compiler details still
exist in repo history and changelogs, but they are not the right default source of
truth for current work.

## Start From Current Sources

Use the nearest live source rather than historical summaries:

- `website/public/llms.txt` for current Ripple syntax, runtime APIs, and authoring
  guidance
- `README.md` for project overview, positioning, and quick-start examples
- `packages/*/README.md` for package-specific usage and public APIs
- `vitest.config.js` for the current test projects and file globs
- `package.json` for workspace-wide scripts such as `rules:generate`, `test`,
  `format`, `format:check`, and `typecheck`

If a guide in this repo conflicts with nearby code or package READMEs, trust the
nearby code and current package docs.

## RuleSync

This repository uses RuleSync as the single source of truth for shared AI agent
instructions. Edit `.rulesync/rules/` and regenerate derived files instead of
patching generated outputs directly.

Generated targets include:

- `AGENTS.md`
- `.github/copilot-instructions.md`
- `CLAUDE.md`
- `GEMINI.md`
- `.cursor/rules/project.mdc`

After changing RuleSync content, run:

```bash
pnpm rules:generate
```

## Monorepo Map

This is a pnpm monorepo. The current high-level layout is:

- `packages/tsrx/`: core parser, transforms, and shared compiler infrastructure
- `packages/tsrx-ripple/`, `packages/tsrx-react/`, `packages/tsrx-solid/`,
  `packages/tsrx-preact/`: target-specific compiler layers
- `packages/ripple/`: Ripple runtime, server helpers, and framework behavior
- `packages/vite-plugin/`, `packages/rollup-plugin/`,
  `packages/vite-plugin-react/`, `packages/vite-plugin-solid/`,
  `packages/vite-plugin-preact/`, `packages/rspack-plugin-react/`,
  `packages/turbopack-plugin-react/`: bundler integrations
- `packages/adapter/`, `packages/adapter-node/`, `packages/adapter-bun/`,
  `packages/adapter-vercel/`: deployment and platform adapters
- `packages/language-server/`, `packages/typescript-plugin/`,
  `packages/vscode-plugin/`, `packages/intellij-plugin/`, `packages/nvim-plugin/`,
  `packages/sublime-text-plugin/`, `packages/zed-plugin/`: editor and language
  tooling
- `packages/eslint-parser/`, `packages/eslint-plugin/`,
  `packages/prettier-plugin/`, `packages/prettier-plugin-ripple/`: linting and
  formatting
- `packages/create-ripple/`, `templates/`, `playground/`: scaffolding and local
  examples
- `website/`, `website-new/`, `website-tsrx/`: documentation and website work

When routing a change, prefer the package that directly owns the behavior rather
than editing generated output, tests, or editor integrations first.

## Current Working Assumptions

- Default component files are `.tsrx`. Do not describe the project as primarily
  using `.ripple` files unless the local file you are editing actually does.
- Some packages still preserve compatibility or historical references. Treat them
  as compatibility context, not the default architecture description.
- Use `pnpm` for all package management and workspace scripts.
- Follow the conventions of the package you are changing. This repo mixes plain
  JavaScript, JSDoc-typed JavaScript, and TypeScript depending on package.
- Match nearby naming, file layout, and test style instead of applying a single
  convention repo-wide.

## Finding The Right Package

Use these rough routing rules:

- Ripple syntax, parsing, source transforms, or shared AST behavior:
  `packages/tsrx/` and the relevant target package under `packages/tsrx-*`
- Ripple runtime behavior, hydration, reactivity, DOM updates, or server output:
  `packages/ripple/`
- Vite, Rollup, Rspack, Turbopack, or adapter behavior: the relevant plugin or
  adapter package in `packages/`
- Diagnostics, completions, hover, definitions, or editor integration:
  `packages/language-server/`, `packages/typescript-plugin/`, and editor plugin
  packages
- Formatting or lint behavior: `packages/prettier-plugin/`,
  `packages/prettier-plugin-ripple/`, `packages/eslint-parser/`, or
  `packages/eslint-plugin/`

## Validation

Prefer the smallest validation that covers the touched surface.

Common workspace commands:

```bash
pnpm rules:generate
pnpm format:check
pnpm test
pnpm test --project ripple-client
pnpm test --project ripple-server
pnpm typecheck
```

Current Vitest projects are defined in `vitest.config.js`. Ripple runtime suites
use `.test.tsrx` files for many client, server, and compat tests, while tooling
packages often use `.test.js` or `.test.ts`.

## Changesets

Add a changeset for user-facing package changes. Skip changesets for docs-only,
test-only, and internal tooling updates.

Only use `patch` changesets. Do not use `minor` or `major` bump types in this
repo; prerelease packages must stay on the patch track until a release plan
explicitly changes that policy.

```bash
pnpm changeset
```

Validate pending changesets before versioning or publishing:

```bash
pnpm changeset:check
```

## Practical Guidance For Agents

- Prefer the current docs in `website/public/llms.txt` over stale architectural
  summaries.
- Avoid copying removed compiler APIs, old package layouts, or legacy `.ripple`
  examples into new guidance.
- If you need exact behavior, read the owning package and its tests instead of
  relying on a repo-wide summary.
- Keep documentation updates short and durable. High-level guidance ages better
  than detailed internal call lists.


## /.github/workflows/ci.yml

```yml path="/.github/workflows/ci.yml" 
name: CI

on:
  push:
    branches: [main, develop]
    tags: ["!**"]
    paths:
      - "packages/**"
      - "package.json"
      - "pnpm-lock.yaml"
      - "pnpm-workspace.yaml"
      - "scripts/**"
      - "vitest.config.js"
      - ".changeset/**"
      - ".github/workflows/ci.yml"

  pull_request:
    branches: [main, develop]
    paths:
      - "packages/**"
      - "package.json"
      - "pnpm-lock.yaml"
      - "pnpm-workspace.yaml"
      - "scripts/**"
      - "vitest.config.js"
      - ".changeset/**"
      - ".github/workflows/ci.yml"

jobs:
  test:
    runs-on: ubuntu-latest

    strategy:
      matrix:
        node-version: [22, 24, 26]

    steps:
      - name: Checkout code
        uses: actions/checkout@v6

      - name: Install pnpm
        uses: pnpm/action-setup@v6

      - name: Setup Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v6
        with:
          node-version: ${{ matrix.node-version }}
          cache: "pnpm"

      - name: Install dependencies
        run: pnpm install --prod false --frozen-lockfile

      - name: Build cli
        working-directory: ./packages/cli
        run: pnpm build

      - name: Build eslint-parser
        working-directory: ./packages/eslint-parser
        run: pnpm build

      - name: Run tests
        run: pnpm test

      - name: Upload test results
        uses: actions/upload-artifact@v7
        if: failure()
        with:
          name: test-results-node-${{ matrix.node-version }}
          path: |
            packages/ripple/tests/__snapshots__/
            coverage/
          retention-days: 30

  lint:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v6

      - name: Install pnpm
        uses: pnpm/action-setup@v6

      - name: Setup Node.js
        uses: actions/setup-node@v6
        with:
          node-version: 24
          cache: "pnpm"

      - name: Install dependencies
        run: pnpm install --frozen-lockfile

      - name: Check formatting
        run: pnpm format:check

  changeset-check:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v6

      - name: Setup Node.js
        uses: actions/setup-node@v6
        with:
          node-version: 24

      - name: Disallow major and minor bumps in changesets
        run: node scripts/check-changesets.js

  typecheck:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v6

      - name: Install pnpm
        uses: pnpm/action-setup@v6

      - name: Setup Node.js
        uses: actions/setup-node@v6
        with:
          node-version: 24
          cache: "pnpm"

      - name: Install dependencies
        run: pnpm install --frozen-lockfile

      - name: Type check
        run: pnpm typecheck

```

## /.github/workflows/copilot-setup-steps.yml

```yml path="/.github/workflows/copilot-setup-steps.yml" 
# GitHub Copilot agent environment setup
# See: https://gh.io/copilot/actions-setup-steps

name: Copilot Setup Steps

on: workflow_dispatch

jobs:
  copilot-setup-steps:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v6

      - name: Install pnpm
        uses: pnpm/action-setup@v6

      - name: Setup Node.js
        uses: actions/setup-node@v6
        with:
          node-version: "24"
          cache: "pnpm"

      - name: Install dependencies
        run: pnpm install --frozen-lockfile

      - name: Build CLI
        working-directory: ./packages/cli
        run: pnpm build

      - name: Build ESLint parser
        working-directory: ./packages/eslint-parser
        run: pnpm build

      - name: Sync agent configurations
        run: pnpm agents:sync

```

## /.github/workflows/livecodes-post-comment.yml

```yml path="/.github/workflows/livecodes-post-comment.yml" 
name: comment

on:
  workflow_run:
    workflows: ["livecodes"] # the workflow that created the artifact
    types:
      - completed

jobs:
  upload:
    runs-on: ubuntu-latest
    permissions:
      pull-requests: write
    if: >
      github.event.workflow_run.event == 'pull_request' &&
      github.event.workflow_run.conclusion == 'success'

    steps:
      - uses: live-codes/pr-comment-from-artifact@v1
        with:
          GITHUB_TOKEN: ${{ github.token }}

```

## /.github/workflows/livecodes-preview.yml

```yml path="/.github/workflows/livecodes-preview.yml" 
name: livecodes

on:
  workflow_run:
    workflows: ["Publish to pkg.pr.new"]
    types:
      - completed

jobs:
  build_and_prepare:
    runs-on: ubuntu-latest
    if: >
      github.event.workflow_run.conclusion == 'success' &&
      github.event.workflow_run.jobs[1].steps['Publish'].outcome == 'success'
    name: Generate Playground
    steps:
      - name: Checkout
        uses: actions/checkout@v6

      - name: Build and generate
        uses: live-codes/preview-in-livecodes@v1

```

## /.github/workflows/pkg.pr.new.yml

```yml path="/.github/workflows/pkg.pr.new.yml" 
name: Publish to pkg.pr.new
on:
  push:
    branches: [main, develop]
    tags: ["!**"]
    paths: ["packages/**"]
  pull_request:
    types: [opened, synchronize]
    paths: ["packages/**"]
  pull_request_review:
    types: [submitted]
  workflow_dispatch:

permissions:
  contents: read
  pull-requests: write

jobs:
  approval-check:
    name: Check for Collaborator Approval
    # Github doesn't support conditional needs, so this needs to run no matter what. :')
    # if: github.event_name == 'pull_request'
    runs-on: ubuntu-latest
    outputs:
      is_approved: ${{ steps.check_for_approval.outputs.result }}
    steps:
      - name: Check for approval by a collaborator
        id: check_for_approval
        uses: actions/github-script@v8
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          result-encoding: string
          script: |
            const pr = context.payload.pull_request;
            if (!pr) {
              // This can happen on events that don't have a PR context.
              return 'false';
            }
            const reviews = await github.rest.pulls.listReviews({
              owner: context.repo.owner,
              repo: context.repo.repo,
              pull_number: pr.number
            });
            const isApproved = reviews.data.some(review =>
              review.state === 'APPROVED' &&
              ['MEMBER', 'OWNER', 'COLLABORATOR'].includes(review.author_association)
            );
            console.log(`PR is approved by collaborator: ${isApproved}`);
            return isApproved.toString();

  publish:
    # Only run if pushed to main, is a PR by a collaborator,
    # or an external PR approved by a collaborator.
    needs: approval-check
    if: >-
      (github.event_name == 'push') ||
      (github.event_name == 'pull_request' && (
        github.event.pull_request.author_association == 'MEMBER' ||
        github.event.pull_request.author_association == 'OWNER' ||
        github.event.pull_request.author_association == 'COLLABORATOR'
      )) ||
      (needs.approval-check.outputs.is_approved == 'true') ||
      (github.event_name == 'pull_request_review' &&
       github.event.review.state == 'approved' && (
        github.event.review.author_association == 'MEMBER' ||
        github.event.review.author_association == 'OWNER' ||
        github.event.review.author_association == 'COLLABORATOR'
      ))

    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v6

      - name: Install pnpm
        uses: pnpm/action-setup@v6

      - name: Setup Node.js
        uses: actions/setup-node@v6
        with:
          node-version: 24
          cache: "pnpm"

      - name: Install dependencies
        run: pnpm install --prod false --frozen-lockfile

      - name: Build cli
        working-directory: ./packages/cli
        run: pnpm build

      - name: Publish
        run: |
          pnpm dlx pkg-pr-new publish \
            './packages/eslint-plugin' \
            './packages/eslint-parser' \
            './packages/typescript-plugin' \
            './packages/create-ripple' \
            './packages/prettier-plugin' \
            './packages/ripple' \
            './packages/adapter' \
            './packages/adapter-node' \
            './packages/adapter-bun' \
            './packages/rollup-plugin' \
            './packages/vite-plugin' \
            './packages/cli' \
            --compact \
            --comment=update \
            --packageManager=pnpm \
            --pnpm \
            --template './templates/basic'

```

## /.github/workflows/publish.yml

```yml path="/.github/workflows/publish.yml" 
name: Publish

on:
  push:
    branches:
      - main

concurrency:
  group: ${{ github.workflow }}

permissions: {}

jobs:
  publish:
    if: github.repository == 'Ripple-TS/ripple' && contains(github.event.head_commit.message, 'Version Packages')
    permissions:
      contents: write
      id-token: write
    name: Publish
    runs-on: ubuntu-latest
    steps:
      - name: Checkout Repo
        uses: actions/checkout@v6
        with:
          fetch-depth: 0

      - name: Install pnpm
        uses: pnpm/action-setup@v6

      - name: Setup Node.js
        uses: actions/setup-node@v6
        with:
          node-version: 24.x
          # Do not enable dependency caching in this workflow. This job has
          # id-token: write and publishes to npm, so restoring shared Actions
          # cache here can turn cache poisoning into a trusted publish compromise.

      - name: Install dependencies
        run: pnpm install --frozen-lockfile

      - name: Disallow major and minor bumps in changesets
        run: pnpm changeset:check

      - name: Publish to npm
        id: changesets
        uses: changesets/action@v1
        with:
          publish: pnpm changeset:publish
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          PNPM_CONFIG_PROVENANCE: true
          # keep for now just in case
          NPM_CONFIG_PROVENANCE: true

```

## /.github/workflows/release.yml

```yml path="/.github/workflows/release.yml" 
name: Release PR

on:
  push:
    branches:
      - main

concurrency:
  group: ${{ github.workflow }}

permissions: {}

jobs:
  release-pr:
    if: github.repository == 'Ripple-TS/ripple'
    permissions:
      contents: write
      pull-requests: write
    name: Release PR
    runs-on: ubuntu-latest
    steps:
      - name: Checkout Repo
        uses: actions/checkout@v6
        with:
          fetch-depth: 0

      - name: Install pnpm
        uses: pnpm/action-setup@v6

      - name: Setup Node.js
        uses: actions/setup-node@v6
        with:
          node-version: 24.x
          cache: pnpm

      - name: Install dependencies
        run: pnpm install --frozen-lockfile

      - name: Disallow major and minor bumps in changesets
        run: pnpm changeset:check

      - name: Create or update release pull request
        id: changesets
        uses: changesets/action@v1
        with:
          version: pnpm changeset:version
          commit: Version Packages
          title: Version Packages
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

```

## /.github/workflows/rulesync.yml

```yml path="/.github/workflows/rulesync.yml" 
name: RuleSync Check

on:
  pull_request:
    paths:
      - ".rulesync/**"
      - "rulesync.jsonc"
      - "CLAUDE.md"
      - "GEMINI.md"
      - "AGENTS.md"
      - ".github/copilot-instructions.md"
      - ".cursor/rules/**"

permissions:
  contents: read

jobs:
  check:
    name: Check RuleSync
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6

      - name: Install pnpm
        uses: pnpm/action-setup@v6

      - name: Setup Node.js
        uses: actions/setup-node@v6
        with:
          node-version: 24
          cache: pnpm

      - name: Install dependencies
        run: pnpm install --frozen-lockfile

      - name: Check RuleSync is up to date
        run: pnpm rules:check

```

## /.github/workflows/vsix-manual.yml

```yml path="/.github/workflows/vsix-manual.yml" 
on: workflow_dispatch

name: Publish VSC Extension (Manual)
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v6

      - name: Install pnpm
        uses: pnpm/action-setup@v6

      - name: Setup Node.js
        uses: actions/setup-node@v6
        with:
          node-version: 24.x

      - name: Install deps w/ pnpm
        working-directory: ./packages/vscode-plugin
        run: pnpm install --frozen-lockfile

      - name: Build VSIX
        working-directory: ./packages/vscode-plugin
        run: pnpm run build-and-package

      - name: Upload VSIX
        uses: actions/upload-artifact@v7
        with:
          name: vscode-plugin VSIX
          path: ./packages/vscode-plugin/*.vsix

  publish-vsm:
    runs-on: ubuntu-latest
    needs: build
    steps:
      - name: Checkout code
        uses: actions/checkout@v6

      - name: Download VSIX
        uses: actions/download-artifact@v7
        with:
          name: vscode-plugin VSIX
          path: ./packages/vscode-plugin

      - name: Install pnpm
        uses: pnpm/action-setup@v6

      - name: Setup Node.js
        uses: actions/setup-node@v6
        with:
          node-version: 24.x

      - name: Install deps w/ pnpm
        run: pnpm install --frozen-lockfile

      - name: Publish to VSM
        working-directory: ./packages/vscode-plugin
        run: pnpm exec vsce publish -i *.vsix
        env:
          VSCE_PAT: ${{ secrets.VSM_TOKEN }}

  publish-ovsx:
    runs-on: ubuntu-latest
    needs: build
    steps:
      - name: Checkout code
        uses: actions/checkout@v6

      - name: Download VSIX
        uses: actions/download-artifact@v7
        with:
          name: vscode-plugin VSIX
          path: ./packages/vscode-plugin

      - name: Install pnpm
        uses: pnpm/action-setup@v6

      - name: Setup Node.js
        uses: actions/setup-node@v6
        with:
          node-version: 24.x

      - name: Install deps w/ pnpm
        run: pnpm install --frozen-lockfile

      - name: Publish to OVSX
        working-directory: ./packages/vscode-plugin
        run: pnpm exec ovsx publish *.vsix
        env:
          OVSX_PAT: ${{ secrets.OVSX_TOKEN }}

```

## /.github/workflows/vsix.yml

```yml path="/.github/workflows/vsix.yml" 
on:
  push:
    branches: [main]
    tags: ["!**"]
    paths: ["packages/vscode-plugin/**"]

name: Publish VSC Extension
jobs:
  # Note: this doesn't parse the versions, rather, it only checks if the versions are different.
  version-check:
    name: "Verify version change"
    runs-on: ubuntu-latest
    outputs:
      version-changed: ${{ steps.compare_versions.outputs.changed }}

    steps:
      - name: Checkout Code
        uses: actions/checkout@v6
        with:
          fetch-depth: 2

      - name: Compare package.json versions
        working-directory: ./packages/vscode-plugin
        id: compare_versions
        run: |
          # jq -r returns raw string
          CURRENT_VERSION=$(jq -r .version package.json)
          PREVIOUS_VERSION=$(git show HEAD~1:./package.json | jq -r .version)

          echo "Current version:  ${CURRENT_VERSION}"
          echo "Previous version: ${PREVIOUS_VERSION}"

          if [ "${CURRENT_VERSION}" == "${PREVIOUS_VERSION}" ]; then
            echo "::notice::Version number not changed, skipping publish..."
            echo "changed=false" >> "$GITHUB_OUTPUT"
          else
            echo "::notice::Version was changed: ${PREVIOUS_VERSION} -> ${CURRENT_VERSION}"
            echo "changed=true" >> "$GITHUB_OUTPUT"
          fi

  build:
    needs: version-check
    if: needs.version-check.outputs.version-changed == 'true'
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v6

      - name: Install pnpm
        uses: pnpm/action-setup@v6

      - name: Setup Node.js
        uses: actions/setup-node@v6
        with:
          node-version: 24.x

      - name: Install deps w/ pnpm
        working-directory: ./packages/vscode-plugin
        run: pnpm install --frozen-lockfile

      - name: Build VSIX
        working-directory: ./packages/vscode-plugin
        run: pnpm run build-and-package

      - name: Upload VSIX
        uses: actions/upload-artifact@v7
        with:
          name: vscode-plugin VSIX
          path: ./packages/vscode-plugin/*.vsix

  publish-vsm:
    runs-on: ubuntu-latest
    needs: build
    steps:
      - name: Checkout code
        uses: actions/checkout@v6

      - name: Download VSIX
        uses: actions/download-artifact@v7
        with:
          name: vscode-plugin VSIX
          path: ./packages/vscode-plugin

      - name: Install pnpm
        uses: pnpm/action-setup@v6

      - name: Setup Node.js
        uses: actions/setup-node@v6
        with:
          node-version: 24.x

      - name: Install deps w/ pnpm
        run: pnpm install --frozen-lockfile

      - name: Publish to VSM
        working-directory: ./packages/vscode-plugin
        run: pnpm exec vsce publish -i *.vsix
        env:
          VSCE_PAT: ${{ secrets.VSM_TOKEN }}

  publish-ovsx:
    runs-on: ubuntu-latest
    needs: build
    steps:
      - name: Checkout code
        uses: actions/checkout@v6

      - name: Download VSIX
        uses: actions/download-artifact@v7
        with:
          name: vscode-plugin VSIX
          path: ./packages/vscode-plugin

      - name: Install pnpm
        uses: pnpm/action-setup@v6

      - name: Setup Node.js
        uses: actions/setup-node@v6
        with:
          node-version: 24.x

      - name: Install deps w/ pnpm
        run: pnpm install --frozen-lockfile

      - name: Publish to OVSX
        working-directory: ./packages/vscode-plugin
        run: pnpm exec ovsx publish *.vsix
        env:
          OVSX_PAT: ${{ secrets.OVSX_TOKEN }}

```

## /.gitignore

```gitignore path="/.gitignore" 
# Dependency directories
node_modules/

# IDE related
.idea

# Test coverage
coverage
*.lcov

# Local settings
*.local.json

.claude/settings.json

packages/vscode-plugin/*.vsix
playground/src
playground/ripple/src
playground/react/src
playground/solid/src
playground/vue/src

website/.vitepress/dist/
website/.vitepress/cache/
website/.vitepress/.temp/

# Optional eslint cache
.eslintcache

# dotenv environment variables file
.env
.env.test

# build output
.vercel

# OS-specific
.DS_Store

# VS Code settings
.vscode/
!.vscode/settings.json
!.vscode/launch.json
!.vscode/tasks.json
# But include playground/.vscode/settings.json
!playground/.vscode/
playground/.vscode/*
!playground/.vscode/settings.json

# Chrome Debugger
.chrome-debug-profile/

tmp
dist
debug
.build-hash
.build-hash-built
**/*.d.tsrx.ts

# Temporary folders
tmp/
temp/

```

## /.livecodes/playground.json

```json path="/.livecodes/playground.json" 
{
  "appUrl": "https://ripple.livecodes.pages.dev",
  "config": {
    "customSettings": {
      "ripple": { "version": "pr:ripple@{{LC::SHORT_SHA}}" }
    },
    "title": "Ripple Playground: {{LC::SHORT_SHA}}",
    "activeEditor": "script",
    "script": {
      "language": "ripple",
      "content": "import type { Component } from \"ripple\"\nimport { track } from \"ripple\"\n\nexport default component App() {\n  <div class=\"container\">\n    let &[count] = track(0);\n\n    <button onClick={() => count++}>{count}</button>\n\n    if (count > 1) {\n      <div>{'Greater than 1!'}</div>\n    }\n  </div>\n\n  <style>\n    button {\n      padding: 1rem;\n      font-size: 1rem;\n      cursor: pointer;\n    }\n  </style>\n}\n"
    },
    "style": {
      "language": "css",
      "content": "body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; background: hsl(0, 0%, 18%); color: #fff }"
    }
  }
}

```

## /.prettierrc

```prettierrc path="/.prettierrc" 
{
	"useTabs": true,
	"tabWidth": 2,
	"singleQuote": true,
	"jsxSingleQuote": false,
	"printWidth": 100,
	"plugins": ["@tsrx/prettier-plugin"],
	"overrides": [
		{
			"files": ["*.tsrx"],
			"options": {
				"bracketSameLine": false,
				"parser": "ripple"
			}
		},
		{
			"files": ["**/*.md"],
			"options": {
				"useTabs": false,
				"printWidth": 82,
				"proseWrap": "always"
			}
		},
		{
			"files": ["website/docs/**/*.md", "website-new/docs/**/*.md"],
			"options": {
				"proseWrap": "preserve",
				"embeddedLanguageFormatting": "off"
			}
		},
		{
			"files": ["**/*.json"],
			"options": {
				"useTabs": false
			}
		},
		{
			"files": ["**/*.yml", "**/*.yaml"],
			"options": {
				"singleQuote": false
			}
		}
	]
}

```

## /.rulesync/rules/project.md

---
root: true
targets: ['*']
description: 'Ripple project overview and development guidelines'
globs: ['**/*']
---

# Ripple Project Guide for AI Agents

Ripple is a TypeScript-first UI framework and monorepo maintained by Dominic
Gannaway. The current authoring format is centered on `.tsrx` files and the shared
TSRX compiler stack. Older `.ripple`-specific docs and compiler details still
exist in repo history and changelogs, but they are not the right default source of
truth for current work.

## Start From Current Sources

Use the nearest live source rather than historical summaries:

- `website/public/llms.txt` for current Ripple syntax, runtime APIs, and authoring
  guidance
- `README.md` for project overview, positioning, and quick-start examples
- `packages/*/README.md` for package-specific usage and public APIs
- `vitest.config.js` for the current test projects and file globs
- `package.json` for workspace-wide scripts such as `rules:generate`, `test`,
  `format`, `format:check`, and `typecheck`

If a guide in this repo conflicts with nearby code or package READMEs, trust the
nearby code and current package docs.

## RuleSync

This repository uses RuleSync as the single source of truth for shared AI agent
instructions. Edit `.rulesync/rules/` and regenerate derived files instead of
patching generated outputs directly.

Generated targets include:

- `AGENTS.md`
- `.github/copilot-instructions.md`
- `CLAUDE.md`
- `GEMINI.md`
- `.cursor/rules/project.mdc`

After changing RuleSync content, run:

```bash
pnpm rules:generate
```

## Monorepo Map

This is a pnpm monorepo. The current high-level layout is:

- `packages/tsrx/`: core parser, transforms, and shared compiler infrastructure
- `packages/tsrx-ripple/`, `packages/tsrx-react/`, `packages/tsrx-solid/`,
  `packages/tsrx-preact/`: target-specific compiler layers
- `packages/ripple/`: Ripple runtime, server helpers, and framework behavior
- `packages/vite-plugin/`, `packages/rollup-plugin/`,
  `packages/vite-plugin-react/`, `packages/vite-plugin-solid/`,
  `packages/vite-plugin-preact/`, `packages/rspack-plugin-react/`,
  `packages/turbopack-plugin-react/`: bundler integrations
- `packages/adapter/`, `packages/adapter-node/`, `packages/adapter-bun/`,
  `packages/adapter-vercel/`: deployment and platform adapters
- `packages/language-server/`, `packages/typescript-plugin/`,
  `packages/vscode-plugin/`, `packages/intellij-plugin/`, `packages/nvim-plugin/`,
  `packages/sublime-text-plugin/`, `packages/zed-plugin/`: editor and language
  tooling
- `packages/eslint-parser/`, `packages/eslint-plugin/`,
  `packages/prettier-plugin/`, `packages/prettier-plugin-ripple/`: linting and
  formatting
- `packages/create-ripple/`, `templates/`, `playground/`: scaffolding and local
  examples
- `website/`, `website-new/`, `website-tsrx/`: documentation and website work

When routing a change, prefer the package that directly owns the behavior rather
than editing generated output, tests, or editor integrations first.

## Current Working Assumptions

- Default component files are `.tsrx`. Do not describe the project as primarily
  using `.ripple` files unless the local file you are editing actually does.
- Some packages still preserve compatibility or historical references. Treat them
  as compatibility context, not the default architecture description.
- Use `pnpm` for all package management and workspace scripts.
- Follow the conventions of the package you are changing. This repo mixes plain
  JavaScript, JSDoc-typed JavaScript, and TypeScript depending on package.
- Match nearby naming, file layout, and test style instead of applying a single
  convention repo-wide.

## Finding The Right Package

Use these rough routing rules:

- Ripple syntax, parsing, source transforms, or shared AST behavior:
  `packages/tsrx/` and the relevant target package under `packages/tsrx-*`
- Ripple runtime behavior, hydration, reactivity, DOM updates, or server output:
  `packages/ripple/`
- Vite, Rollup, Rspack, Turbopack, or adapter behavior: the relevant plugin or
  adapter package in `packages/`
- Diagnostics, completions, hover, definitions, or editor integration:
  `packages/language-server/`, `packages/typescript-plugin/`, and editor plugin
  packages
- Formatting or lint behavior: `packages/prettier-plugin/`,
  `packages/prettier-plugin-ripple/`, `packages/eslint-parser/`, or
  `packages/eslint-plugin/`

## Validation

Prefer the smallest validation that covers the touched surface.

Common workspace commands:

```bash
pnpm rules:generate
pnpm format:check
pnpm test
pnpm test --project ripple-client
pnpm test --project ripple-server
pnpm typecheck
```

Current Vitest projects are defined in `vitest.config.js`. Ripple runtime suites
use `.test.tsrx` files for many client, server, and compat tests, while tooling
packages often use `.test.js` or `.test.ts`.

## Changesets

Add a changeset for user-facing package changes. Skip changesets for docs-only,
test-only, and internal tooling updates.

Only use `patch` changesets. Do not use `minor` or `major` bump types in this
repo; prerelease packages must stay on the patch track until a release plan
explicitly changes that policy.

```bash
pnpm changeset
```

Validate pending changesets before versioning or publishing:

```bash
pnpm changeset:check
```

## Practical Guidance For Agents

- Prefer the current docs in `website/public/llms.txt` over stale architectural
  summaries.
- Avoid copying removed compiler APIs, old package layouts, or legacy `.ripple`
  examples into new guidance.
- If you need exact behavior, read the owning package and its tests instead of
  relying on a repo-wide summary.
- Keep documentation updates short and durable. High-level guidance ages better
  than detailed internal call lists.


## /.vscode/launch.json

```json path="/.vscode/launch.json" 
{
  "version": "0.2.1",
  "configurations": [
    {
      "name": "VSCode Extension",
      "type": "extensionHost",
      "request": "launch",
      "autoAttachChildProcesses": true,
      "preLaunchTask": "build-vscode-plugin",
      "args": [
        "--disable-extension=ripple-ts.ripple-ts-vscode-plugin",
        "--extensionDevelopmentPath=${workspaceFolder}/packages/vscode-plugin/",
        "${workspaceFolder}/playground"
      ],
      "outFiles": ["${workspaceFolder}/packages/vscode-plugin/dist/**/*.js"],
      "sourceMaps": true,
      "env": {
        "RIPPLE_DEBUG": "true"
      }
    },
    {
      "name": "Ripple Tests - Current Tab",
      "type": "node",
      "request": "launch",
      "runtimeExecutable": "pnpm",
      "runtimeArgs": [
        "run",
        "test",
        "${relativeFile}",
        "-t",
        "${input:rippeTestNamePattern}",
        "--",
        "--inspect-brk",
        "--no-file-parallelism"
      ],
      "console": "integratedTerminal",
      "internalConsoleOptions": "neverOpen",
      "skipFiles": ["<node_internals>/**"]
    },
    {
      "name": "Ripple Tests - File Path",
      "type": "node",
      "request": "launch",
      "runtimeExecutable": "pnpm",
      "runtimeArgs": [
        "run",
        "test",
        "${input:rippleTestFile}",
        "-t",
        "${input:rippeTestNamePattern}",
        "--",
        "--inspect-brk",
        "--no-file-parallelism"
      ],
      "console": "integratedTerminal",
      "internalConsoleOptions": "neverOpen",
      "skipFiles": ["<node_internals>/**"]
    },
    {
      "name": "Volar Codegen / Mappings",
      "type": "node",
      "request": "launch",
      "cwd": "${workspaceFolder}/playground",
      "runtimeExecutable": "pnpm",
      "runtimeArgs": ["run", "debug-volar"],
      "console": "integratedTerminal",
      "internalConsoleOptions": "neverOpen",
      "skipFiles": ["<node_internals>/**"]
    },
    {
      "name": "SSR Rendering",
      "type": "node",
      "request": "launch",
      "cwd": "${workspaceFolder}/playground",
      "runtimeExecutable": "pnpm",
      "runtimeArgs": ["run", "debug-ssr"],
      "console": "integratedTerminal",
      "internalConsoleOptions": "neverOpen",
      "skipFiles": ["<node_internals>/**"]
    },
    {
      "name": "SSR Runtime - From Compiled",
      "type": "node",
      "request": "launch",
      "cwd": "${workspaceFolder}/playground",
      "program": "${workspaceFolder}/playground/ssr-dev.js",
      "env": {
        "DEBUG_APP": "true"
      },
      "console": "integratedTerminal",
      "internalConsoleOptions": "neverOpen",
      "skipFiles": ["<node_internals>/**"]
    },
    {
      "name": "Client Rendering",
      "type": "node",
      "request": "launch",
      "cwd": "${workspaceFolder}/playground",
      "runtimeExecutable": "pnpm",
      "runtimeArgs": ["run", "debug-client"],
      "console": "integratedTerminal",
      "internalConsoleOptions": "neverOpen",
      "skipFiles": ["<node_internals>/**"]
    },
    {
      "name": "Client Runtime - Vite",
      "type": "node",
      "request": "launch",
      "cwd": "${workspaceFolder}/playground",
      "runtimeExecutable": "pnpm",
      "runtimeArgs": ["run", "dev"],
      "console": "integratedTerminal",
      "internalConsoleOptions": "neverOpen",
      "presentation": {
        "hidden": true
      }
    },
    {
      "name": "Client Runtime - Browser",
      "type": "chrome",
      "request": "launch",
      "url": "http://localhost:5173",
      "webRoot": "${workspaceFolder}/playground",
      "runtimeArgs": [
        "--auto-open-devtools-for-tabs",
        "--user-data-dir=${workspaceFolder}/.vscode/chrome-client-debug-profile"
      ],
      "pathMapping": {
        "/@fs/": "/"
      },
      "resolveSourceMapLocations": null,
      "presentation": {
        "hidden": true
      },
      "preLaunchTask": "client-runtime-prelaunch"
    },
    {
      "name": "Vite Plugin",
      "type": "node",
      "request": "launch",
      "console": "integratedTerminal",
      "cwd": "${workspaceFolder}/playground",
      "runtimeExecutable": "node",
      "runtimeArgs": ["--inspect"],
      "program": "${workspaceFolder}/playground/node_modules/vite/bin/vite.js",
      "args": ["--host"],
      "autoAttachChildProcesses": true,
      "skipFiles": ["<node_internals>/**"],
      "sourceMaps": true,
      "presentation": {
        "hidden": true
      }
    }
  ],
  "compounds": [
    {
      "name": "Client Runtime - From Source",
      "configurations": ["Client Runtime - Vite", "Client Runtime - Browser"],
      "stopAll": true
    },
    {
      "name": "Vite Plugin - Client",
      "configurations": ["Vite Plugin"],
      "stopAll": true
    }
  ],
  "inputs": [
    {
      "id": "rippleTestFile",
      "type": "promptString",
      "description": "Test file path",
      "default": "${relativeFile}"
    },
    {
      "id": "rippeTestNamePattern",
      "type": "promptString",
      "description": "(Optional): Test name pattern to match",
      "default": ""
    }
  ]
}

```

## /.vscode/settings.json

```json path="/.vscode/settings.json" 
{
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  "editor.detectIndentation": false,
  "editor.formatOnSave": true,
  "editor.insertSpaces": false,
  "editor.tabSize": 2,
  "files.insertFinalNewline": true,
  "files.trimFinalNewlines": true,
  "files.trimTrailingWhitespace": true,
  "files.exclude": {
    "**/.build-hash": true,
    "**/.build-hash-built": true
  },
  "prettier.requireConfig": true,
  "js/ts.implicitProjectConfig.checkJs": true,
  "js/ts.preferences.preferTypeOnlyAutoImports": true,
  "js/ts.preferences.useAliasesForRenames": false,
  "js/ts.preferences.importModuleSpecifierEnding": "js",
  "js/ts.experimental.useTsgo": true,

  "[json]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode",
    "editor.insertSpaces": true
  },
  "[jsonc]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode",
    "editor.insertSpaces": true
  },
  "[markdown]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode",
    "editor.insertSpaces": true
  },
  "[javascript]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[typescript]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[typescriptreact]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "cSpell.words": ["esrap", "tsrx", "tstc", "tstt", "zimmerframe"]
}

```

## /.vscode/tasks.json

```json path="/.vscode/tasks.json" 
{
  "version": "2.0.0",
  "tasks": [
    {
      "label": "wait-for-vite",
      "type": "process",
      "command": "pnpm",
      "args": ["exec", "wait-on", "tcp:5173", "-d", "0"],
      "problemMatcher": []
    },
    {
      "label": "delete-client-chrome-debug-profile",
      "type": "shell",
      "command": "rm -rf .vscode/chrome-client-debug-profile"
    },
    {
      "label": "client-runtime-prelaunch",
      "dependsOn": ["delete-client-chrome-debug-profile", "wait-for-vite"],
      "dependsOrder": "parallel"
    },
    {
      "label": "build-vscode-plugin",
      "type": "shell",
      "command": "node scripts/build-if-changed.js packages/typescript-plugin packages/language-server packages/vscode-plugin",
      "options": {
        "shell": {
          "args": ["-i", "-c"]
        }
      },
      "group": "build",
      "problemMatcher": []
    }
  ]
}

```

## /AGENTS.md

# Additional Conventions Beyond the Built-in Functions

As this project's AI coding tool, you must follow the additional conventions below, in addition to the built-in functions.

# Ripple Project Guide for AI Agents

Ripple is a TypeScript-first UI framework and monorepo maintained by Dominic
Gannaway. The current authoring format is centered on `.tsrx` files and the shared
TSRX compiler stack. Older `.ripple`-specific docs and compiler details still
exist in repo history and changelogs, but they are not the right default source of
truth for current work.

## Start From Current Sources

Use the nearest live source rather than historical summaries:

- `website/public/llms.txt` for current Ripple syntax, runtime APIs, and authoring
  guidance
- `README.md` for project overview, positioning, and quick-start examples
- `packages/*/README.md` for package-specific usage and public APIs
- `vitest.config.js` for the current test projects and file globs
- `package.json` for workspace-wide scripts such as `rules:generate`, `test`,
  `format`, `format:check`, and `typecheck`

If a guide in this repo conflicts with nearby code or package READMEs, trust the
nearby code and current package docs.

## RuleSync

This repository uses RuleSync as the single source of truth for shared AI agent
instructions. Edit `.rulesync/rules/` and regenerate derived files instead of
patching generated outputs directly.

Generated targets include:

- `AGENTS.md`
- `.github/copilot-instructions.md`
- `CLAUDE.md`
- `GEMINI.md`
- `.cursor/rules/project.mdc`

After changing RuleSync content, run:

```bash
pnpm rules:generate
```

## Monorepo Map

This is a pnpm monorepo. The current high-level layout is:

- `packages/tsrx/`: core parser, transforms, and shared compiler infrastructure
- `packages/tsrx-ripple/`, `packages/tsrx-react/`, `packages/tsrx-solid/`,
  `packages/tsrx-preact/`: target-specific compiler layers
- `packages/ripple/`: Ripple runtime, server helpers, and framework behavior
- `packages/vite-plugin/`, `packages/rollup-plugin/`,
  `packages/vite-plugin-react/`, `packages/vite-plugin-solid/`,
  `packages/vite-plugin-preact/`, `packages/rspack-plugin-react/`,
  `packages/turbopack-plugin-react/`: bundler integrations
- `packages/adapter/`, `packages/adapter-node/`, `packages/adapter-bun/`,
  `packages/adapter-vercel/`: deployment and platform adapters
- `packages/language-server/`, `packages/typescript-plugin/`,
  `packages/vscode-plugin/`, `packages/intellij-plugin/`, `packages/nvim-plugin/`,
  `packages/sublime-text-plugin/`, `packages/zed-plugin/`: editor and language
  tooling
- `packages/eslint-parser/`, `packages/eslint-plugin/`,
  `packages/prettier-plugin/`, `packages/prettier-plugin-ripple/`: linting and
  formatting
- `packages/create-ripple/`, `templates/`, `playground/`: scaffolding and local
  examples
- `website/`, `website-new/`, `website-tsrx/`: documentation and website work

When routing a change, prefer the package that directly owns the behavior rather
than editing generated output, tests, or editor integrations first.

## Current Working Assumptions

- Default component files are `.tsrx`. Do not describe the project as primarily
  using `.ripple` files unless the local file you are editing actually does.
- Some packages still preserve compatibility or historical references. Treat them
  as compatibility context, not the default architecture description.
- Use `pnpm` for all package management and workspace scripts.
- Follow the conventions of the package you are changing. This repo mixes plain
  JavaScript, JSDoc-typed JavaScript, and TypeScript depending on package.
- Match nearby naming, file layout, and test style instead of applying a single
  convention repo-wide.

## Finding The Right Package

Use these rough routing rules:

- Ripple syntax, parsing, source transforms, or shared AST behavior:
  `packages/tsrx/` and the relevant target package under `packages/tsrx-*`
- Ripple runtime behavior, hydration, reactivity, DOM updates, or server output:
  `packages/ripple/`
- Vite, Rollup, Rspack, Turbopack, or adapter behavior: the relevant plugin or
  adapter package in `packages/`
- Diagnostics, completions, hover, definitions, or editor integration:
  `packages/language-server/`, `packages/typescript-plugin/`, and editor plugin
  packages
- Formatting or lint behavior: `packages/prettier-plugin/`,
  `packages/prettier-plugin-ripple/`, `packages/eslint-parser/`, or
  `packages/eslint-plugin/`

## Validation

Prefer the smallest validation that covers the touched surface.

Common workspace commands:

```bash
pnpm rules:generate
pnpm format:check
pnpm test
pnpm test --project ripple-client
pnpm test --project ripple-server
pnpm typecheck
```

Current Vitest projects are defined in `vitest.config.js`. Ripple runtime suites
use `.test.tsrx` files for many client, server, and compat tests, while tooling
packages often use `.test.js` or `.test.ts`.

## Changesets

Add a changeset for user-facing package changes. Skip changesets for docs-only,
test-only, and internal tooling updates.

Only use `patch` changesets. Do not use `minor` or `major` bump types in this
repo; prerelease packages must stay on the patch track until a release plan
explicitly changes that policy.

```bash
pnpm changeset
```

Validate pending changesets before versioning or publishing:

```bash
pnpm changeset:check
```

## Practical Guidance For Agents

- Prefer the current docs in `website/public/llms.txt` over stale architectural
  summaries.
- Avoid copying removed compiler APIs, old package layouts, or legacy `.ripple`
  examples into new guidance.
- If you need exact behavior, read the owning package and its tests instead of
  relying on a repo-wide summary.
- Keep documentation updates short and durable. High-level guidance ages better
  than detailed internal call lists.


## /CLAUDE.md

# Ripple Project Guide for AI Agents

Ripple is a TypeScript-first UI framework and monorepo maintained by Dominic
Gannaway. The current authoring format is centered on `.tsrx` files and the shared
TSRX compiler stack. Older `.ripple`-specific docs and compiler details still
exist in repo history and changelogs, but they are not the right default source of
truth for current work.

## Start From Current Sources

Use the nearest live source rather than historical summaries:

- `website/public/llms.txt` for current Ripple syntax, runtime APIs, and authoring
  guidance
- `README.md` for project overview, positioning, and quick-start examples
- `packages/*/README.md` for package-specific usage and public APIs
- `vitest.config.js` for the current test projects and file globs
- `package.json` for workspace-wide scripts such as `rules:generate`, `test`,
  `format`, `format:check`, and `typecheck`

If a guide in this repo conflicts with nearby code or package READMEs, trust the
nearby code and current package docs.

## RuleSync

This repository uses RuleSync as the single source of truth for shared AI agent
instructions. Edit `.rulesync/rules/` and regenerate derived files instead of
patching generated outputs directly.

Generated targets include:

- `AGENTS.md`
- `.github/copilot-instructions.md`
- `CLAUDE.md`
- `GEMINI.md`
- `.cursor/rules/project.mdc`

After changing RuleSync content, run:

```bash
pnpm rules:generate
```

## Monorepo Map

This is a pnpm monorepo. The current high-level layout is:

- `packages/tsrx/`: core parser, transforms, and shared compiler infrastructure
- `packages/tsrx-ripple/`, `packages/tsrx-react/`, `packages/tsrx-solid/`,
  `packages/tsrx-preact/`: target-specific compiler layers
- `packages/ripple/`: Ripple runtime, server helpers, and framework behavior
- `packages/vite-plugin/`, `packages/rollup-plugin/`,
  `packages/vite-plugin-react/`, `packages/vite-plugin-solid/`,
  `packages/vite-plugin-preact/`, `packages/rspack-plugin-react/`,
  `packages/turbopack-plugin-react/`: bundler integrations
- `packages/adapter/`, `packages/adapter-node/`, `packages/adapter-bun/`,
  `packages/adapter-vercel/`: deployment and platform adapters
- `packages/language-server/`, `packages/typescript-plugin/`,
  `packages/vscode-plugin/`, `packages/intellij-plugin/`, `packages/nvim-plugin/`,
  `packages/sublime-text-plugin/`, `packages/zed-plugin/`: editor and language
  tooling
- `packages/eslint-parser/`, `packages/eslint-plugin/`,
  `packages/prettier-plugin/`, `packages/prettier-plugin-ripple/`: linting and
  formatting
- `packages/create-ripple/`, `templates/`, `playground/`: scaffolding and local
  examples
- `website/`, `website-new/`, `website-tsrx/`: documentation and website work

When routing a change, prefer the package that directly owns the behavior rather
than editing generated output, tests, or editor integrations first.

## Current Working Assumptions

- Default component files are `.tsrx`. Do not describe the project as primarily
  using `.ripple` files unless the local file you are editing actually does.
- Some packages still preserve compatibility or historical references. Treat them
  as compatibility context, not the default architecture description.
- Use `pnpm` for all package management and workspace scripts.
- Follow the conventions of the package you are changing. This repo mixes plain
  JavaScript, JSDoc-typed JavaScript, and TypeScript depending on package.
- Match nearby naming, file layout, and test style instead of applying a single
  convention repo-wide.

## Finding The Right Package

Use these rough routing rules:

- Ripple syntax, parsing, source transforms, or shared AST behavior:
  `packages/tsrx/` and the relevant target package under `packages/tsrx-*`
- Ripple runtime behavior, hydration, reactivity, DOM updates, or server output:
  `packages/ripple/`
- Vite, Rollup, Rspack, Turbopack, or adapter behavior: the relevant plugin or
  adapter package in `packages/`
- Diagnostics, completions, hover, definitions, or editor integration:
  `packages/language-server/`, `packages/typescript-plugin/`, and editor plugin
  packages
- Formatting or lint behavior: `packages/prettier-plugin/`,
  `packages/prettier-plugin-ripple/`, `packages/eslint-parser/`, or
  `packages/eslint-plugin/`

## Validation

Prefer the smallest validation that covers the touched surface.

Common workspace commands:

```bash
pnpm rules:generate
pnpm format:check
pnpm test
pnpm test --project ripple-client
pnpm test --project ripple-server
pnpm typecheck
```

Current Vitest projects are defined in `vitest.config.js`. Ripple runtime suites
use `.test.tsrx` files for many client, server, and compat tests, while tooling
packages often use `.test.js` or `.test.ts`.

## Changesets

Add a changeset for user-facing package changes. Skip changesets for docs-only,
test-only, and internal tooling updates.

Only use `patch` changesets. Do not use `minor` or `major` bump types in this
repo; prerelease packages must stay on the patch track until a release plan
explicitly changes that policy.

```bash
pnpm changeset
```

Validate pending changesets before versioning or publishing:

```bash
pnpm changeset:check
```

## Practical Guidance For Agents

- Prefer the current docs in `website/public/llms.txt` over stale architectural
  summaries.
- Avoid copying removed compiler APIs, old package layouts, or legacy `.ripple`
  examples into new guidance.
- If you need exact behavior, read the owning package and its tests instead of
  relying on a repo-wide summary.
- Keep documentation updates short and durable. High-level guidance ages better
  than detailed internal call lists.


## /CODE_OF_CONDUCT.md

# Code of Conduct

This project is built by people who want to create something cool together. Let's
keep it fun, welcoming, focused, and worth everyone's time.

### Do

- **Be respectful** — Treat everyone with kindness. We're all here because we care
  about the project.
- **Bring real value** — Make contributions that help the project move forward:
  thoughtful code, clear docs, useful bug reports, or constructive ideas. When
  submitting pull requests, focus on solving real problems or improving things for
  users/maintainers—not just adding your name to the contributors list. Small,
  high-quality changes beat big, low-effort ones every time.
- **Own your code** — If you're using AI tools to help write or suggest code,
  review it carefully, understand it fully, test it, and make it your own.
  Unreviewed or barely-touched AI output is just noise—don't spam the project with
  it.
- **Stay on topic** — Keep discussions, issues, and PRs related to the project.
  Save off-topic stuff for somewhere else.
- **Give constructive feedback** — Point out problems kindly and suggest fixes
  when you can. We're all learning.
- **Assume good intent** — People usually mean well. If something feels off, ask
  for clarification before assuming the worst.
- **Have fun and be excellent to each other** — Celebrate wins, thank people, and
  enjoy the ride.

### Don't

- **Spam** — No drive-by comments, promo links, unrelated noise, or low-effort PRs
  (including untouched AI-generated ones).
- **Harass or attack** — No insults, slurs, threats, personal attacks, or
  unwelcome advances. Ever.
- **Troll** — Don't derail conversations or pick fights.
- **Push big drama** — If there's conflict, try to resolve it privately or with a
  maintainer first.

### If something goes wrong

If you see behavior that breaks these guidelines, or you feel uncomfortable, reach
out on Discord: https://discord.gg/JBF2ySrh2W. We'll listen, handle it fairly, and
keep things confidential if needed. Maintainers can warn, remove comments/PRs, or
ban repeat offenders.

Thanks for helping make this a great place to collaborate. Let's build something
awesome together!


## /CONTRIBUTING.md

# Contributing to Ripple

Ripple is a TypeScript UI framework that combines the best parts of React, Solid,
and Svelte into one cohesive package. Built as a love letter to frontend
development, Ripple introduces a JS/TS-first approach with `.ripple` modules that
provide an excellent developer experience for both humans and LLMs.

The [Open Source Guides](https://opensource.guide/) website offers valuable
resources for individuals, communities, and companies looking to contribute to
open source projects. Both newcomers and experienced contributors will find these
guides particularly helpful:

- [How to Contribute to Open Source](https://opensource.guide/how-to-contribute/)
- [Building Welcoming Communities](https://opensource.guide/building-community/)

## Ways to Get Involved

There are numerous ways to contribute to Ripple, and many don't require writing
code. Here are some ideas to get started:

- **Start experimenting with Ripple**: Try out the
  [Ripple Playground](https://www.ripplejs.com/playground) and see how it works.
  If you encounter issues or unexpected behavior, we'd love to hear about it
  through [opening an issue](#reporting-issues).
- **Browse existing issues**: Check out our
  [open issues](https://github.com/Ripple-TS/ripple/issues). You can help by
  providing workarounds or asking clarifying questions.
- **Submit fixes**: Found an issue you'd like to tackle? Consider
  [opening a pull request](#pull-requests).
- **Help with documentation**: As Ripple grows, we'll need comprehensive
  documentation. Any help improving clarity or filling gaps would be greatly
  appreciated.

We welcome all contributions! If you need guidance in planning your contribution,
please reach out on our Discord server and let us know you're looking for some
direction.

### Issue Triage

A fantastic way to contribute without coding is helping triage issues and pull
requests:

- Request additional information when issues lack sufficient detail for
  resolution.
- Identify stale issues that should be updated or closed.
- Review code and suggest improvements.
- Help organize and categorize incoming issues.

## Development Process

### Planning Major Changes

For significant new features or substantial changes, we encourage discussion
before implementation. While we don't have a formal RFC process yet, please open
an issue to discuss your ideas with the maintainers and community first.

### Current Focus

Ripple is in early alpha, so our priorities are:

1. Stabilizing core functionality
2. Improving TypeScript integration (note that the internal codebase is still
   being migrated from JS, so some TypeScript errors are expected)
3. Expanding test coverage
4. Building and maintaining essential tooling

Keep in mind that this is a very early-stage project, so expect frequent changes
and some rough edges.

### Communication

Since Ripple is a new project with a small team, we'll do our best to respond to
issues and PRs promptly. Join [our Discord server](https://discord.gg/JBF2ySrh2W)
for real-time discussion and updates.

## Reporting Issues

We track bugs using [GitHub issues](https://github.com/Ripple-TS/ripple/issues).
Before reporting a new issue, please check if someone has already reported the
same problem.

For questions about using Ripple, our Discord server is the best place to get help
and connect with other developers.

### Creating Bug Reports

When [opening a new issue](https://github.com/Ripple-TS/ripple/issues/new), please
include:

- **Clear description**: Explain what you expected to happen and what actually
  occurred.
- **Reproduction steps**: Provide step-by-step instructions to reproduce the
  issue.
- **Environment details**: Include your operating system, Node.js version, and any
  relevant setup information.
- **Minimal example**: If possible, create a minimal reproduction case that
  demonstrates the problem.

**Important guidelines:**

- Report one bug per issue
- Be as specific as possible
- Include code samples when relevant

## Pull Requests

### Before You Start

For bug fixes, feel free to submit a pull request directly, but we recommend
filing an issue first to discuss the problem and proposed solution.

For new features, please open an issue to discuss the implementation before
starting work. This helps ensure your contribution aligns with the project's
direction.

Keep pull requests focused and reasonably sized for easier review.

### Development Setup

You'll need [Node.js](https://nodejs.org/) and
[pnpm](https://pnpm.io/installation) installed.

1. Fork the repository
2. Clone your fork locally
3. Run `pnpm install` to install dependencies
4. Create a new branch from `main` for your changes

### Development Workflow

Since Ripple is in development, the build process may evolve. Currently:

- Run development builds and watch for changes as needed
- Test your changes thoroughly
- Ensure TypeScript compilation succeeds (if working with TS code)

### Testing

While our test suite is still being developed, please:

- Test your changes manually
- Verify that existing functionality still works
- Include test cases for new features when possible
- Document your testing approach in the PR description

### Code Style

We'll be implementing consistent code formatting soon. For now:

- Follow existing code patterns in the repository
- Use meaningful variable and function names
- Include appropriate comments for complex logic
- Maintain TypeScript types where applicable

### Submitting Your PR

Before submitting:

1. **Test thoroughly**: Ensure your changes work as expected
2. **Write clear commit messages**: Describe what and why, not just what
3. **Update documentation**: If you've changed APIs or added features
4. **Add a changeset**: For user-facing changes (see below)
5. **Target the main branch**: All PRs should be opened against `main`
6. **Keep it focused**: One feature or fix per PR

### Changesets

We use [Changesets](https://github.com/changesets/changesets) to manage versioning
and changelogs. If your PR includes user-facing changes (bug fixes, new features,
breaking changes), you should add a changeset:

```bash
pnpm changeset
```

This will prompt you to:

1. Select the packages affected by your change
2. Choose the semver bump type (patch/minor/major)
3. Write a summary of your changes (this becomes the changelog entry)

The command creates a markdown file in `.changeset/` that should be committed with
your PR. When your PR is merged, the release workflow will automatically:

1. Aggregate all changesets into a "Version Packages" PR
2. When that PR is merged, publish to npm

**When to add a changeset:**

- Bug fixes → `patch`
- New features (backwards compatible) → `minor`
- Breaking changes → `major`

**When NOT to add a changeset:**

- Documentation-only changes
- Internal refactoring with no user-facing impact
- Test-only changes
- CI/tooling changes

Include in your PR description:

- Summary of changes
- Testing performed
- Any breaking changes
- Related issue numbers

## Development Guidelines

### Code Conventions

Since Ripple is TypeScript-first:

- Prioritize type safety
- Use descriptive names for variables and functions
- Follow existing patterns in the codebase
- Comment complex logic clearly

### Commit Messages

Write clear, descriptive commit messages that explain both what changed and why.

## License

By contributing to Ripple, you agree that your contributions will be licensed
under the same license as the project. [MIT License](./LICENSE)

## Getting Help

- **Discord**: Join [our community server](https://discord.gg/JBF2ySrh2W) for
  real-time discussion
- **GitHub Issues**: For bugs and feature requests
- **GitHub Discussions**: For general questions and ideas (when available)

We're excited to have you contribute to Ripple's development! Even though the
project is young, every contribution helps shape its future.


## /GEMINI.md

# Additional Conventions Beyond the Built-in Functions

As this project's AI coding tool, you must follow the additional conventions below, in addition to the built-in functions.

# Ripple Project Guide for AI Agents

Ripple is a TypeScript-first UI framework and monorepo maintained by Dominic
Gannaway. The current authoring format is centered on `.tsrx` files and the shared
TSRX compiler stack. Older `.ripple`-specific docs and compiler details still
exist in repo history and changelogs, but they are not the right default source of
truth for current work.

## Start From Current Sources

Use the nearest live source rather than historical summaries:

- `website/public/llms.txt` for current Ripple syntax, runtime APIs, and authoring
  guidance
- `README.md` for project overview, positioning, and quick-start examples
- `packages/*/README.md` for package-specific usage and public APIs
- `vitest.config.js` for the current test projects and file globs
- `package.json` for workspace-wide scripts such as `rules:generate`, `test`,
  `format`, `format:check`, and `typecheck`

If a guide in this repo conflicts with nearby code or package READMEs, trust the
nearby code and current package docs.

## RuleSync

This repository uses RuleSync as the single source of truth for shared AI agent
instructions. Edit `.rulesync/rules/` and regenerate derived files instead of
patching generated outputs directly.

Generated targets include:

- `AGENTS.md`
- `.github/copilot-instructions.md`
- `CLAUDE.md`
- `GEMINI.md`
- `.cursor/rules/project.mdc`

After changing RuleSync content, run:

```bash
pnpm rules:generate
```

## Monorepo Map

This is a pnpm monorepo. The current high-level layout is:

- `packages/tsrx/`: core parser, transforms, and shared compiler infrastructure
- `packages/tsrx-ripple/`, `packages/tsrx-react/`, `packages/tsrx-solid/`,
  `packages/tsrx-preact/`: target-specific compiler layers
- `packages/ripple/`: Ripple runtime, server helpers, and framework behavior
- `packages/vite-plugin/`, `packages/rollup-plugin/`,
  `packages/vite-plugin-react/`, `packages/vite-plugin-solid/`,
  `packages/vite-plugin-preact/`, `packages/rspack-plugin-react/`,
  `packages/turbopack-plugin-react/`: bundler integrations
- `packages/adapter/`, `packages/adapter-node/`, `packages/adapter-bun/`,
  `packages/adapter-vercel/`: deployment and platform adapters
- `packages/language-server/`, `packages/typescript-plugin/`,
  `packages/vscode-plugin/`, `packages/intellij-plugin/`, `packages/nvim-plugin/`,
  `packages/sublime-text-plugin/`, `packages/zed-plugin/`: editor and language
  tooling
- `packages/eslint-parser/`, `packages/eslint-plugin/`,
  `packages/prettier-plugin/`, `packages/prettier-plugin-ripple/`: linting and
  formatting
- `packages/create-ripple/`, `templates/`, `playground/`: scaffolding and local
  examples
- `website/`, `website-new/`, `website-tsrx/`: documentation and website work

When routing a change, prefer the package that directly owns the behavior rather
than editing generated output, tests, or editor integrations first.

## Current Working Assumptions

- Default component files are `.tsrx`. Do not describe the project as primarily
  using `.ripple` files unless the local file you are editing actually does.
- Some packages still preserve compatibility or historical references. Treat them
  as compatibility context, not the default architecture description.
- Use `pnpm` for all package management and workspace scripts.
- Follow the conventions of the package you are changing. This repo mixes plain
  JavaScript, JSDoc-typed JavaScript, and TypeScript depending on package.
- Match nearby naming, file layout, and test style instead of applying a single
  convention repo-wide.

## Finding The Right Package

Use these rough routing rules:

- Ripple syntax, parsing, source transforms, or shared AST behavior:
  `packages/tsrx/` and the relevant target package under `packages/tsrx-*`
- Ripple runtime behavior, hydration, reactivity, DOM updates, or server output:
  `packages/ripple/`
- Vite, Rollup, Rspack, Turbopack, or adapter behavior: the relevant plugin or
  adapter package in `packages/`
- Diagnostics, completions, hover, definitions, or editor integration:
  `packages/language-server/`, `packages/typescript-plugin/`, and editor plugin
  packages
- Formatting or lint behavior: `packages/prettier-plugin/`,
  `packages/prettier-plugin-ripple/`, `packages/eslint-parser/`, or
  `packages/eslint-plugin/`

## Validation

Prefer the smallest validation that covers the touched surface.

Common workspace commands:

```bash
pnpm rules:generate
pnpm format:check
pnpm test
pnpm test --project ripple-client
pnpm test --project ripple-server
pnpm typecheck
```

Current Vitest projects are defined in `vitest.config.js`. Ripple runtime suites
use `.test.tsrx` files for many client, server, and compat tests, while tooling
packages often use `.test.js` or `.test.ts`.

## Changesets

Add a changeset for user-facing package changes. Skip changesets for docs-only,
test-only, and internal tooling updates.

Only use `patch` changesets. Do not use `minor` or `major` bump types in this
repo; prerelease packages must stay on the patch track until a release plan
explicitly changes that policy.

```bash
pnpm changeset
```

Validate pending changesets before versioning or publishing:

```bash
pnpm changeset:check
```

## Practical Guidance For Agents

- Prefer the current docs in `website/public/llms.txt` over stale architectural
  summaries.
- Avoid copying removed compiler APIs, old package layouts, or legacy `.ripple`
  examples into new guidance.
- If you need exact behavior, read the owning package and its tests instead of
  relying on a repo-wide summary.
- Keep documentation updates short and durable. High-level guidance ages better
  than detailed internal call lists.


## /README.md

<a href="https://ripplejs.com">
  <picture>
    <source media="(min-width: 768px)" srcset="assets/ripple-desktop.png">
    <img src="assets/ripple-mobile.png" alt="Ripple - the elegant TypeScript UI framework" />
  </picture>
</a>

[![CI](https://github.com/Ripple-TS/ripple/actions/workflows/ci.yml/badge.svg)](https://github.com/Ripple-TS/ripple/actions/workflows/ci.yml)
[![Discord](https://img.shields.io/badge/Discord-Join%20Server-7289da?logo=discord&logoColor=white)](https://discord.gg/JBF2ySrh2W)
[![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz_small.svg)](https://stackblitz.com/github/Ripple-TS/ripple/tree/main/templates/basic)

# Ripple TS

Ripple is a TypeScript UI framework that combines the best parts of React, Solid,
and Svelte. Created by [@trueadm](https://github.com/trueadm), who has contributed
to [Inferno](https://github.com/infernojs/inferno),
[React](https://github.com/facebook/react),
[Lexical](https://github.com/facebook/lexical), and
[Svelte 5](https://github.com/sveltejs/svelte).

**Key Philosophy:** Ripple is TS-first with `.tsrx` as its default component file
extension. This allows seamless TypeScript integration and a unique syntax that
enhances both human and LLM developer experience.

> **`.tsrx` is also a standalone language:** the same source can now compile to
> React, Solid, or Ripple via [TSRX](https://tsrx.dev) — a TypeScript language
> extension that treats Ripple as one of several target runtimes. If you want the
> authoring ergonomics without committing to Ripple's runtime, start there.

📚 **[Ripple Docs](https://www.ripple-ts.com/docs)** | 🎮
**[Ripple Playground](https://www.ripple-ts.com/playground)** | 🧩
**[TSRX Website](https://tsrx.dev)**

## Features

- ⚡ **Fine-grained Reactivity**: `track` with lazy destructuring for a unique
  reactivity system
- 🔥 **Performance**: Industry-leading rendering speed, bundle size, and memory
  usage
- 📦 **Reactive Collections**: `RippleArray`, `RippleObject`, `RippleMap`,
  `RippleSet` imported from `'ripple'` with full reactivity
- 🎯 **TypeScript First**: Complete type safety with the default `.tsrx` component
  extension
- 🛠️ **Developer Tools**: VSCode extension, Prettier, and ESLint support
- 🎨 **Scoped Styling**: Component-level CSS with automatic scoping

## 🚀 Quick Start

### Using CLI (Recommended)

```bash
npx create-ripple
cd my-app
npm install && npm run dev
```

### Using Template

```bash
npx degit Ripple-TS/ripple/templates/basic my-app
cd my-app
npm install && npm run dev
```

### Add to Existing Project

```bash
npm install ripple @ripple-ts/vite-plugin
```

> **Note:** You can use `npm`, `pnpm`, `yarn`, or `bun` package managers.

**[→ Full Installation Guide](https://www.ripple-ts.com/docs/quick-start)**

### Mounting Your App

```ts
// index.ts
import { mount } from 'ripple';
import { App } from './App.tsrx';

mount(App, {
  props: { title: 'Hello world!' },
  target: document.getElementById('root'),
});
```

## 🔧 VSCode Extension

Install the
[Ripple VSCode extension](https://marketplace.visualstudio.com/items?itemName=Ripple-TS.ripple-ts-vscode-plugin)
for:

- Syntax highlighting
- TypeScript integration
- Real-time diagnostics
- IntelliSense autocomplete

**[→ Editor Setup Guide](https://www.ripple-ts.com/docs/quick-start#vs-code)**

## Core Concepts

### Components

Define components with the `component` keyword. Unlike React, you don't return
JSX—you write it directly:

```jsx
component Button(props: { text: string, onClick: () => void }) {
  <button onClick={props.onClick}>
    {props.text}
  </button>
}

export component App() {
  <Button text="Click me" onClick={() => console.log("Clicked!")} />
}
```

**[→ Component Guide](https://www.ripple-ts.com/docs/guide/components)**

### Reactivity

Create reactive state with `track` and use lazy destructuring (`&[]`) to access
the value directly:

```jsx
import { track } from 'ripple';

export component App() {
  let &[count] = track(0);

  <div>
    <p>"Count: "{count}</p>
    <button onClick={() => count++}>"Increment"</button>
  </div>
}
```

You can also pass around the tracked value object from the second argument:

```jsx
import { track } from 'ripple';

export component App() {
  let &[count, trackedCount] = track(0);

  <div>{count}</div>
  <IncrementButton {trackedCount} />
}
```

Alternatively, you can read and write tracked values directly using the `.value`
property on the `Tracked<V>` object:

```jsx
import { track } from 'ripple';

export component App() {
  const count = track(0);

  <div>{count.value}</div>
  <button onClick={() => count.value++}>"Increment"</button>
}
```

Using `&[...]` is preferred in most cases for cleaner code, but `.value` is useful
when you need to keep the `Tracked<V>` object around — for example, when storing
tracked values in data structures or passing them as `Tracked<T>` props.

**Derived values** automatically update:

```jsx
import { track } from 'ripple';

export component App() {
  let &[count] = track(0);
  let &[double] = track(() => count * 2);
  let &[quadruple] = track(() => double * 2);

  <div>
    <p>"Count: "{count}</p>
    <p>"Double: "{double}</p>
    <p>"Quadruple: "{quadruple}</p>
    <button onClick={() => count++}>"Increment"</button>
  </div>
}
```

**Reactive collections** with full reactivity:

```jsx
import { RippleArray, RippleObject, RippleMap, RippleSet } from 'ripple';

export component App() {
  const items = new RippleArray(1, 2, 3);          // RippleArray
  const obj = new RippleObject({ a: 1, b: 2 });    // RippleObject
  const map = new RippleMap([['k', 'v']]);          // RippleMap
  const set = new RippleSet([1, 2, 3]);             // RippleSet

  <div>
    <p>"Items: "{items.join(', ')}</p>
    <p>"Object: a="{obj.a}", b="{obj.b}", c="{obj.c}</p>
    <button onClick={() => items.push(items.length + 1)}>"Add Item"</button>
    <button onClick={() => obj.c = (obj.c ?? 0) + 1}>"Increment c"</button>
  </div>
}
```

**[→ Reactivity Guide](https://www.ripple-ts.com/docs/guide/reactivity)**

### Transporting Reactivity

Pass the tracked ref (second element) across function boundaries:

```jsx
import { track } from 'ripple';

function createDouble(&[count]) {
  return track(() => count * 2);
}

export component App() {
  let &[count, countTracked] = track(0);
  const &[double] = createDouble(countTracked);

  <div>
    <p>"Double: "{double}</p>
    <button onClick={() => count++}>"Increment"</button>
  </div>
}
```

**[→ Transporting Reactivity Guide](https://www.ripple-ts.com/docs/guide/reactivity#transporting-reactivity)**

### Effects & Side Effects

```jsx
import { track, effect } from 'ripple';

export component App() {
  let &[count] = track(0);

  effect(() => {
    console.log('Count changed:', count);
  });

  <button onClick={() => count++}>"Increment"</button>
}
```

**[→ Effects & Reactivity Guide](https://www.ripple-ts.com/docs/guide/reactivity#effects)**

### Control Flow

**Conditionals:**

```jsx
import { track } from 'ripple';

export component App() {
  let &[condition] = track(true);

  <div>
    if (condition) {
      <div>"True"</div>
    } else {
      <div>"False"</div>
    }
    <button onClick={() => condition = !condition}>"Toggle"</button>
  </div>
}
```

**Loops:**

```jsx
import { RippleArray } from 'ripple';

export component App() {
  const items = new RippleArray(
    {id: 1, name: 'Item 1'},
    {id: 2, name: 'Item 2'},
    {id: 3, name: 'Item 3'}
  );

  <div>
    for (const item of items; index i; key item.id) {
      <div>{item.name}" (index: "{i}")"</div>
    }
    <button onClick={() => items.push({id: items.length + 1, name: `Item ${items.length + 1}`})}>"Add Item"</button>
  </div>
}
```

**Error Boundaries:**

```jsx
component ComponentThatMayFail(props: { shouldFail: boolean }) {
  if (props.shouldFail) {
    throw new Error('Component failed!');
    "This will never render"
  }

  <div>"Component working fine"</div>
}

import { track } from 'ripple';

export component App() {
  let &[shouldFail] = track(false);

  <div>
    try {
      <ComponentThatMayFail {shouldFail} />
    } catch (e) {
      <div>"Error: "{e.message}</div>
    }
    <button onClick={() => shouldFail = !shouldFail}>"Toggle Error"</button>
  </div>
}
```

**[→ Control Flow Guide](https://www.ripple-ts.com/docs/guide/control-flow)**

### DOM Refs

Capture DOM elements with the `{ref fn}` syntax:

```jsx
export component App() {
  <div {ref (node) => console.log(node)}>"Hello"</div>
}
```

**[→ DOM Refs Guide](https://www.ripple-ts.com/docs/guide/dom-refs)**

### Events

Use React-style event handlers:

```jsx
import { track } from 'ripple';

export component App() {
  let &[value] = track('');

  <div>
    <button onClick={() => console.log('Clicked')}>"Click"</button>
    <input onInput={(e) => value = e.target.value} />
    <p>"You typed: "{value}</p>
  </div>
}
```

**[→ Events Guide](https://www.ripple-ts.com/docs/guide/events)**

### Styling

**Scoped CSS:**

```jsx
export component App() {
  <div class="container">"Content"</div>

  <style>
    .container {
      padding: 1rem;
      background: lightblue;
      border-radius: 8px;
    }
  </style>
}
```

**Dynamic styles:**

```jsx
import { track } from 'ripple';

export component App() {
  let &[color] = track('red');

  <div>
    <div style={{ color, fontWeight: 'bold' }}>"Styled text"</div>
    <button onClick={() => color = color === 'red' ? 'blue' : 'red'}>"Toggle Color"</button>
  </div>
}
```

**[→ Styling Guide](https://www.ripple-ts.com/docs/guide/styling)**

## Advanced Features

### Context API

Share state across the component tree:

```jsx
import { Context, track } from 'ripple';

const ThemeContext = new Context();

component Child() {
  const &[theme] = ThemeContext.get();
  <div>"Theme: "{theme}</div>
}

export component App() {
  let &[theme, themeTracked] = track('light');

  ThemeContext.set(themeTracked);

  <div>
    <Child />
    <button onClick={() => theme = theme === 'light' ? 'dark' : 'light'}>"Toggle Theme"</button>
  </div>
}
```

**[→ State Management Guide](https://www.ripple-ts.com/docs/guide/state-management#context)**

### Portals

Render content outside the component hierarchy:

```jsx
import { Portal, track } from 'ripple';

export component App() {
  let &[showModal] = track(false);

  <div>
    <button onClick={() => showModal = !showModal}>"Toggle Modal"</button>

    if (showModal) {
      <Portal target={document.body}>
        <div class="modal">
          <p>"Modal content"</p>
          <button onClick={() => showModal = false}>"Close"</button>
        </div>
      </Portal>
    }
  </div>
}
```

**[→ Portal & Component Guide](https://www.ripple-ts.com/docs/guide/components#portal-component)**

## Resources

- 📚 **[Full Documentation](https://www.ripple-ts.com/docs)** - Complete guide and
  API reference
- 🎮 **[Interactive Playground](https://www.ripple-ts.com/playground)** - Try
  Ripple in your browser
- 🧩 **[TSRX Website](https://tsrx.dev)** - Author `.tsrx` once, compile to React,
  Solid, or Ripple
- 🐛 **[GitHub Issues](https://github.com/Ripple-TS/ripple/issues)** - Report bugs
  or request features
- 💬 **[Discord Community](https://discord.gg/JBF2ySrh2W)** - Get help and discuss
  Ripple
- 📦 **[npm Package](https://www.npmjs.com/package/ripple)** - Install from npm

## Contributing

Contributions are welcome! Please see our
[contributing guidelines](CONTRIBUTING.md).

## License

MIT License - see [LICENSE](LICENSE) for details.


## /assets/Ripple.tmbundle/README.md

This provides syntax highlighting for Ripple files in editors that support
TextMate grammars, such as WebStorm/IntelliJ and Sublime Text.

# Installation

1. Create a directory named `Ripple.tmbundle`.
2. Create a directory named `Syntaxes` inside the `Ripple.tmbundle` directory.
3. Save the [`ripple.tmLanguage`](./Syntaxes/ripple.tmLanguage) file into the
   `Syntaxes` directory.
4. Install it:
   - **WebStorm/IntelliJ**:
     1. Save the [`info.plist`](./info.plist) file into the `Ripple.tmbundle`
        directory.
     2. Go to `Settings` > `Editor` > `TextMate Bundles`, click the `+` icon, and
        select the `Ripple.tmbundle` directory.
     3. All `.ripple` files should now have syntax highlighting.
   - **Sublime Text**:
     1. Go to `Preferences` > `Browse Packages`, and move the `Ripple.tmbundle`
        directory into the opened folder.
     2. You should now be able to select `Ripple` in `View` > `Syntax`.


## /assets/Ripple.tmbundle/info.plist

```plist path="/assets/Ripple.tmbundle/info.plist" 
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
  "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>name</key><string>Ripple</string>
</dict>
</plist>

```

## /assets/ripple-desktop.png

Binary file available at https://raw.githubusercontent.com/trueadm/ripple/refs/heads/main/assets/ripple-desktop.png

## /assets/ripple-mobile.png

Binary file available at https://raw.githubusercontent.com/trueadm/ripple/refs/heads/main/assets/ripple-mobile.png

## /benchmarks/package.json

```json path="/benchmarks/package.json" 
{
  "name": "ripple-benchmarks",
  "private": true,
  "type": "module",
  "scripts": {
    "bench": "node tracked-values.js"
  },
  "dependencies": {
    "ripple": "workspace:*",
    "tinybench": "^2.9.0"
  }
}

```

## /benchmarks/tracked-values.js

```js path="/benchmarks/tracked-values.js" 
import { Bench } from 'tinybench';
import { tracked, derived, get, set, root } from 'ripple/internal/client';

const SCALES = [10, 100, 1_000, 10_000, 100_000];

/**
 * Run benchmarks for tracked value operations at a given scale.
 * @param {number} n - Number of tracked values to create
 */
async function run_suite(n) {
	console.log(`\n${'='.repeat(60)}`);
	console.log(`  Tracked Values Benchmark — n = ${n.toLocaleString()}`);
	console.log(`${'='.repeat(60)}\n`);

	/** @type {import('ripple/internal/client').Block} */
	let block;

	// Create a root block context (required by tracked/derived)
	root(() => {
		// Grab the block from the first tracked value we create inside root
		const probe = tracked(0);
		block = probe.b;
	});

	const bench = new Bench({
		warmupIterations: 100,
		iterations: 1000,
		time: 2000,
	});

	// Pre-allocate arrays for setup/teardown
	let values;

	// ── Creation ──────────────────────────────────────────────
	bench.add(`create ${n.toLocaleString()} tracked values`, () => {
		const arr = new Array(n);
		for (let i = 0; i < n; i++) {
			arr[i] = tracked(i, block);
		}
		values = arr;
	});

	// ── Read ─────────────────────────────────────────────────
	bench.add(
		`read ${n.toLocaleString()} tracked values`,
		() => {
			let sum = 0;
			for (let i = 0; i < values.length; i++) {
				sum += get(values[i]);
			}
			return sum;
		},
		{
			beforeAll() {
				values = new Array(n);
				for (let i = 0; i < n; i++) {
					values[i] = tracked(i, block);
				}
			},
		},
	);

	// ── Write ────────────────────────────────────────────────
	bench.add(
		`write ${n.toLocaleString()} tracked values`,
		() => {
			for (let i = 0; i < values.length; i++) {
				set(values[i], i + 1);
			}
		},
		{
			beforeAll() {
				values = new Array(n);
				for (let i = 0; i < n; i++) {
					values[i] = tracked(i, block);
				}
			},
			beforeEach() {
				// Reset values so set() detects a change each iteration
				for (let i = 0; i < values.length; i++) {
					values[i].__v = i;
				}
			},
		},
	);

	// ── Write then Read (dirty-check path) ───────────────────
	bench.add(
		`write+read ${n.toLocaleString()} tracked values`,
		() => {
			for (let i = 0; i < values.length; i++) {
				set(values[i], i + 1);
			}
			let sum = 0;
			for (let i = 0; i < values.length; i++) {
				sum += get(values[i]);
			}
			return sum;
		},
		{
			beforeAll() {
				values = new Array(n);
				for (let i = 0; i < n; i++) {
					values[i] = tracked(i, block);
				}
			},
			beforeEach() {
				for (let i = 0; i < values.length; i++) {
					values[i].__v = i;
				}
			},
		},
	);

	// ── Derived creation + read ──────────────────────────────
	bench.add(
		`create+read ${n.toLocaleString()} derived values`,
		() => {
			const arr = new Array(n);
			for (let i = 0; i < n; i++) {
				arr[i] = derived(() => get(values[i]) * 2, block);
			}
			let sum = 0;
			for (let i = 0; i < arr.length; i++) {
				sum += get(arr[i]);
			}
			return sum;
		},
		{
			beforeAll() {
				values = new Array(n);
				for (let i = 0; i < n; i++) {
					values[i] = tracked(i, block);
				}
			},
		},
	);

	await bench.run();

	console.table(
		bench.tasks.map((task) => ({
			Task: task.name,
			'ops/sec': Math.round(task.result.hz).toLocaleString(),
			'Mean (ms)': task.result.mean.toFixed(4),
			'P75 (ms)': task.result.p75.toFixed(4),
			'P99 (ms)': task.result.p99.toFixed(4),
			Margin: `±${task.result.rme.toFixed(2)}%`,
			Samples: task.result.samples.length,
		})),
	);

	// ── Sanity check ─────────────────────────────────────────
	const t = tracked(42, block);
	if (get(t) !== 42) throw new Error('Sanity check failed: initial get');
	set(t, 99);
	if (get(t) !== 99) throw new Error('Sanity check failed: get after set');

	const d = derived(() => get(t) * 2, block);
	if (get(d) !== 198) throw new Error('Sanity check failed: derived get');
}

// ── Main ──────────────────────────────────────────────────────
console.log('Ripple Tracked Values Benchmark');
console.log(`Node ${process.version} — ${process.platform} ${process.arch}`);
console.log(`Date: ${new Date().toISOString()}`);

for (const n of SCALES) {
	await run_suite(n);
}

console.log('\nDone.');

```

## /grammars/textmate/info.plist

```plist path="/grammars/textmate/info.plist" 
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
  "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>name</key><string>Ripple</string>
</dict>
</plist>

```

## /grammars/tree-sitter/.gitignore

```gitignore path="/grammars/tree-sitter/.gitignore" 
node_modules/
build/
*.log
package-lock.json
yarn.lock
*.exp
*.lib
*.obj
*.dll
*.so

```

## /grammars/tree-sitter/Cargo.toml

```toml path="/grammars/tree-sitter/Cargo.toml" 
[package]
name = "tree-sitter"
description = "Ripple grammar for tree-sitter"
version = "0.0.1"
keywords = ["incremental", "parsing", "ripple"]
categories = ["parsing", "text-editors"]
repository = "https://github.com/trueadm/ripple"
edition = "2021"
license = "MIT"

[lib]
path = "bindings/rust/lib.rs"

[dependencies]
tree-sitter = "~0.22"

[build-dependencies]
cc = "1.0"

```

## /grammars/tree-sitter/LICENSE

``` path="/grammars/tree-sitter/LICENSE" 
MIT License

Copyright (c) 2025 Ripple Contributors

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


```

## /grammars/tree-sitter/README.md

# @ripple-ts/tree-sitter

Tree-sitter grammar for [Ripple](https://www.ripplejs.com).

## Overview

Ripple is a JS/TS-first UI framework that extends TypeScript with component syntax
and reactive primitives. This Tree-sitter grammar provides parsing support for it.


## /grammars/tree-sitter/binding.gyp

```gyp path="/grammars/tree-sitter/binding.gyp" 
{
  "targets": [
    {
      "target_name": "tree_sitter_ripple_binding",
      "include_dirs": [
        "node_modules/node-addon-api",
        "src"
      ],
      "sources": [
        "bindings/node/binding.cc",
        "src/parser.c",
        "src/scanner.c"
      ],
      "cflags_c": [
        "-std=c99"
      ],
      "defines": ["NAPI_VERSION=6", "NAPI_DISABLE_CPP_EXCEPTIONS"]
    }
  ]
}


```

## /grammars/tree-sitter/bindings/node/binding.cc

```cc path="/grammars/tree-sitter/bindings/node/binding.cc" 
#include "napi.h"

typedef struct TSLanguage TSLanguage;

extern "C" TSLanguage *tree_sitter_ripple();

Napi::Object Init(Napi::Env env, Napi::Object exports) {
	exports["language"] = Napi::External<TSLanguage>::New(env, tree_sitter_ripple());
	return exports;
}

NODE_API_MODULE(tree_sitter_ripple_binding, Init)

```

## /grammars/tree-sitter/grammar.js

```js path="/grammars/tree-sitter/grammar.js" 
const PREC = {
	COMMA: -1,
	DECLARATION: 1,
	ASSIGN: 0,
	OBJECT: 1,
	TERNARY: 1,
	OR: 2,
	AND: 3,
	REL: 4,
	PLUS: 5,
	TIMES: 6,
	EXP: 7,
	TYPEOF: 8,
	DELETE: 8,
	VOID: 8,
	NOT: 9,
	NEG: 10,
	INC: 11,
	CALL: 12,
	NEW: 13,
	MEMBER: 14,
};

module.exports = grammar({
	name: 'ripple',

	externals: ($) => [$._automatic_semicolon, $._template_chars, $._ternary_qmark, $.jsx_text],

	extras: ($) => [/\s/, $.comment],

	supertypes: ($) => [$.statement, $.declaration, $.expression, $.primary_expression, $.pattern],

	inline: ($) => [
		$._formal_parameter,
		$.statement,
		$._semicolon,
		$._reserved_identifier,
		$._jsx_attribute,
		$._jsx_child,
		$._jsx_attribute_value,
	],

	word: ($) => $.identifier,

	conflicts: ($) => [
		[$.primary_expression, $.pattern],
		[$.array_pattern, $.array],
		[$.object_pattern, $.object],
		[$.expression, $.jsx_element_name],
		[$.statement_block, $.object],
		[$.method_definition, $.arrow_function],
		[$.shorthand_property_identifier, $.shorthand_property_identifier_pattern],
		[$.labeled_statement, $.arrow_function, $.property_name],
		[$.primary_expression, $.property_name],
		[$.assignment_expression, $.shorthand_property_identifier_pattern],
		[$.import_statement],
		[$.required_parameter, $.primary_expression],
		[$.pattern, $.assignment_expression],
		[$.jsx_element_name, $.jsx_non_namespaced_element_name],
		[$.primary_expression, $.jsx_element_name],
		[$.primary_expression, $.jsx_member_name],
		[$.rest_pattern, $.primary_expression],
		[$.variable_declaration, $.lexical_declaration],
		[$.field_definition, $.method_definition],
		[$.type, $.type_identifier],
		[$.class_declaration, $.class_expression],
		[$.primary_expression, $.literal_type],
		[$.primary_expression, $.type, $.type_identifier],
		[$.primary_expression, $.generic_type],
		[$.primary_expression, $.nested_type_identifier],
		[$.arrow_function, $.type, $.type_identifier],
		[$.primary_expression, $.arrow_function],
		[$.component_declaration],
		[$.fragment_declaration],
		[$.computed_property_name, $.array],
		[$.assignment_expression, $.initializer],
		[$.do_statement],
		[$.component_statement, $.primary_expression],
		[$.function_declaration, $.function_expression],
		[$.required_parameter, $.type, $.type_identifier],
		[$.statement_block, $.object, $.object_type],
		[$.object, $.object_type],
		[$.method_definition, $.property_signature],
		[$.required_parameter, $.primary_expression, $.type, $.type_identifier],
		[$.pattern, $.primary_expression, $.type, $.type_identifier],
		[$.primary_expression, $.jsx_element_name, $.type_parameter],
		[$.spread_element, $.jsx_expression],
		[$.if_statement],
		[$.switch_default],
		[$.switch_case],
		[$.object_pattern, $.object_type],
		[$.object_pattern, $.object, $.object_type],
		[$.pattern, $.type, $.type_identifier],
		[$.array_type, $.function_type],
		[$.intersection_type, $.function_type],
		[$.union_type, $.function_type],
		[$.for_in_statement, $.primary_expression],
	],

	rules: {
		program: ($) => seq(optional($.hash_bang_line), repeat($.statement)),

		hash_bang_line: ($) => /#!.*/,

		export_statement: ($) =>
			choice(
				seq(
					'export',
					choice(
						seq('*', $.from_clause),
						seq($.namespace_export, $.from_clause),
						seq($.export_clause, optional($.from_clause)),
						seq('default', choice($.declaration, seq($.expression, $._semicolon))),
						$.declaration,
					),
					$._semicolon,
				),
				seq(
					'export',
					'type',
					choice(seq('*', $.from_clause), seq($.export_clause, optional($.from_clause))),
					$._semicolon,
				),
			),

		namespace_export: ($) => seq('*', 'as', $.identifier),

		export_clause: ($) => seq('{', commaSep($.export_specifier), optional(','), '}'),

		export_specifier: ($) =>
			seq(
				optional('type'),
				field('name', $.identifier),
				optional(seq('as', field('alias', $.identifier))),
			),

		import_statement: ($) =>
			seq(
				'import',
				optional('type'),
				choice(seq($.import_clause, $.from_clause), $.string),
				optional($._semicolon),
			),

		import_clause: ($) =>
			choice(
				$.namespace_import,
				$.named_imports,
				seq($.identifier, optional(seq(',', choice($.namespace_import, $.named_imports)))),
			),

		from_clause: ($) => seq('from', choice($.string, $.identifier)),

		namespace_import: ($) => seq('*', 'as', $.identifier),

		named_imports: ($) => seq('{', commaSep($.import_specifier), optional(','), '}'),

		import_specifier: ($) =>
			seq(
				optional('type'),
				field('name', choice($.identifier, $.string)),
				optional(seq('as', field('alias', $.identifier))),
			),

		statement: ($) =>
			choice(
				$.export_statement,
				$.import_statement,
				$.declaration,
				$.module_declaration,
				$.expression_statement,
				$.if_statement,
				$.switch_statement,
				$.for_statement,
				$.for_in_statement,
				$.for_of_statement,
				$.while_statement,
				$.do_statement,
				$.try_statement,
				$.return_statement,
				$.throw_statement,
				$.break_statement,
				$.continue_statement,
				$.debugger_statement,
				$.labeled_statement,
				$.empty_statement,
				$.statement_block,
			),

		expression_statement: ($) => seq($.expression, $._semicolon),

		variable_declaration: ($) =>
			seq(choice('var', 'let', 'const'), commaSep1($.variable_declarator), $._semicolon),

		variable_declarator: ($) =>
			seq(
				field('name', choice($.identifier, $._destructuring_pattern)),
				optional($._type_annotation),
				optional($.initializer),
			),

		lexical_declaration: ($) =>
			seq(choice('let', 'const'), commaSep1($.variable_declarator), $._semicolon),

		statement_block: ($) => seq('{', repeat($.statement), '}'),

		if_statement: ($) =>
			seq(
				'if',
				field('condition', $.parenthesized_expression),
				field('consequence', $.statement),
				optional(seq('else', field('alternative', $.statement))),
			),

		switch_statement: ($) =>
			seq('switch', field('value', $.parenthesized_expression), field('body', $.switch_body)),

		switch_body: ($) => seq('{', repeat(choice($.switch_case, $.switch_default)), '}'),

		switch_case: ($) => seq('case', field('value', $.expression), ':', repeat($.statement)),

		switch_default: ($) => seq('default', ':', repeat($.statement)),

		for_statement: ($) =>
			seq(
				'for',
				optional('await'),
				'(',
				field(
					'initializer',
					choice(
						$.lexical_declaration,
						$.variable_declaration,
						$.expression_statement,
						$.empty_statement,
					),
				),
				field('condition', choice($.expression_statement, $.empty_statement)),
				field('increment', optional($.expression)),
				')',
				field('body', $.statement),
			),

		for_in_statement: ($) =>
			seq(
				'for',
				optional('await'),
				'(',
				choice(
					seq(choice('let', 'const', 'var'), choice($._destructuring_pattern, $.identifier)),
					$.identifier,
				),
				'in',
				field('right', $.expression),
				')',
				field('body', $.statement),
			),

		for_of_statement: ($) =>
			seq(
				'for',
				optional('await'),
				'(',
				choice(
					seq(choice('let', 'const', 'var'), choice($._destructuring_pattern, $.identifier)),
					$.identifier,
				),
				'of',
				field('right', $.expression),
				optional(seq(';', 'index', $.identifier)),
				optional(seq(';', 'key', $.expression)),
				')',
				field('body', $.statement),
			),

		while_statement: ($) =>
			seq('while', field('condition', $.parenthesized_expression), field('body', $.statement)),

		do_statement: ($) =>
			seq(
				'do',
				field('body', $.statement),
				'while',
				field('condition', $.parenthesized_expression),
				optional($._semicolon),
			),

		try_statement: ($) =>
			seq(
				'try',
				field('body', $.statement_block),
				optional(field('pending', $.pending_clause)),
				optional(field('handler', $.catch_clause)),
				optional(field('finalizer', $.finally_clause)),
			),

		pending_clause: ($) => seq('pending', field('body', $.statement_block)),

		catch_clause: ($) =>
			seq(
				'catch',
				optional(seq('(', field('parameter', choice($.identifier, $._destructuring_pattern)), ')')),
				field('body', $.statement_block),
			),

		finally_clause: ($) => seq('finally', field('body', $.statement_block)),

		return_statement: ($) => seq('return', optional($.expression), $._semicolon),

		throw_statement: ($) => seq('throw', $.expression, $._semicolon),

		break_statement: ($) => seq('break', optional($.identifier), $._semicolon),

		continue_statement: ($) => seq('continue', optional($.identifier), $._semicolon),

		debugger_statement: ($) => seq('debugger', $._semicolon),

		labeled_statement: ($) =>
			prec.dynamic(-1, seq(field('label', $.identifier), ':', field('body', $.statement))),

		empty_statement: ($) => ';',

		declaration: ($) =>
			choice(
				$.function_declaration,
				$.component_declaration,
				$.fragment_declaration,
				$.class_declaration,
				$.lexical_declaration,
				$.variable_declaration,
			),

		component_declaration: ($) =>
			prec.left(
				PREC.DECLARATION,
				seq(
					optional('export'),
					optional('default'),
					'component',
					optional(field('name', $.identifier)),
					optional(field('type_parameters', $.type_parameters)),
					field('parameters', $.formal_parameters),
					optional($._type_annotation),
					field('body', $.component_body),
				),
			),

		fragment_declaration: ($) =>
			prec.left(
				PREC.DECLARATION,
				seq(
					optional('export'),
					optional('default'),
					'fragment',
					optional(field('name', $.identifier)),
					optional(field('type_parameters', $.type_parameters)),
					field('parameters', $.formal_parameters),
					optional($._type_annotation),
					field('body', $.component_body),
				),
			),

		component_body: ($) => seq('{', repeat($.component_statement), '}'),

		component_statement: ($) =>
			choice(
				$.jsx_element,
				$.jsx_fragment,
				$.jsx_self_closing_element,
				$.variable_declaration,
				$.lexical_declaration,
				$.function_declaration,
				$.class_declaration,
				$.expression_statement,
				$.if_statement,
				$.switch_statement,
				$.for_statement,
				$.for_in_statement,
				$.for_of_statement,
				$.while_statement,
				$.do_statement,
				$.try_statement,
				$.return_statement,
				$.throw_statement,
				$.break_statement,
				$.continue_statement,
				$.debugger_statement,
				$.empty_statement,
				$.style_element,
			),

		style_element: ($) =>
			seq(
				'<style',
				repeat($._jsx_attribute),
				'>',
				optional(alias($._style_content, $.raw_text)),
				'</style>',
			),

		_style_content: ($) => /[^<]+/,

		function_declaration: ($) =>
			seq(
				optional('async'),
				'function',
				optional('*'),
				field('name', $.identifier),
				optional(field('type_parameters', $.type_parameters)),
				field('parameters', $.formal_parameters),
				optional($._type_annotation),
				field('body', $.statement_block),
			),

		class_declaration: ($) =>
			seq(
				optional('abstract'),
				'class',
				field('name', $.identifier),
				optional(field('type_parameters', $.type_parameters)),
				optional($.class_heritage),
				field('body', $.class_body),
			),

		class_heritage: ($) =>
			choice(
				seq('extends', $.expression),
				seq('implements', commaSep1($.type)),
				seq('extends', $.expression, 'implements', commaSep1($.type)),
			),

		class_body: ($) =>
			seq(
				'{',
				repeat(choice($.method_definition, $.field_definition, $.class_static_block, ';')),
				'}',
			),

		class_static_block: ($) => seq('static', $.statement_block),

		field_definition: ($) =>
			seq(
				repeat(choice('static', 'readonly', 'declare', 'abstract', 'override')),
				field('property', $.property_name),
				optional('?'),
				optional($._type_annotation),
				optional($.initializer),
				$._semicolon,
			),

		method_definition: ($) =>
			seq(
				repeat(choice('static', 'async', 'readonly', 'abstract', 'override')),
				optional(choice('get', 'set', '*')),
				field('name', $.property_name),
				optional(field('type_parameters', $.type_parameters)),
				field('parameters', $.formal_parameters),
				optional($._type_annotation),
				field('body', $.statement_block),
			),

		formal_parameters: ($) => seq('(', optional(commaSep($._formal_parameter)), optional(','), ')'),

		_formal_parameter: ($) => choice($.required_parameter, $.rest_parameter),

		required_parameter: ($) =>
			seq(
				field('pattern', choice($.identifier, $._destructuring_pattern)),
				optional('?'),
				optional($._type_annotation),
				optional($.initializer),
			),

		rest_parameter: ($) => seq('...', $.identifier, optional($._type_annotation)),

		_destructuring_pattern: ($) =>
			choice($.object_pattern, $.array_pattern, $.lazy_object_pattern, $.lazy_array_pattern),

		lazy_object_pattern: ($) => seq('&', $.object_pattern),

		lazy_array_pattern: ($) => seq('&', $.array_pattern),

		object_pattern: ($) =>
			seq(
				'{',
				commaSep(
					choice(
						$.pair_pattern,
						$.rest_pattern,
						$.object_assignment_pattern,
						$.shorthand_property_identifier_pattern,
					),
				),
				optional(','),
				'}',
			),

		pair_pattern: ($) =>
			seq(
				field('key', $.property_name),
				':',
				field('value', choice($.pattern, $.assignment_pattern)),
			),

		rest_pattern: ($) => seq('...', $.identifier),

		object_assignment_pattern: ($) =>
			seq(
				field('left', choice($.shorthand_property_identifier_pattern, $._reserved_identifier)),
				'=',
				field('right', $.expression),
			),

		array_pattern: ($) =>
			seq(
				'[',
				commaSep(choice($.pattern, $.assignment_pattern, $.rest_pattern)),
				optional(','),
				']',
			),

		assignment_pattern: ($) => seq(field('left', $.pattern), '=', field('right', $.expression)),

		pattern: ($) => choice($.identifier, $._reserved_identifier, $._destructuring_pattern),

		expression: ($) =>
			choice(
				$.primary_expression,
				$.assignment_expression,
				$.augmented_assignment_expression,
				$.await_expression,
				$.unary_expression,
				$.binary_expression,
				$.ternary_expression,
				$.update_expression,
				$.new_expression,
				$.yield_expression,
				$.parenthesized_expression,
			),

		primary_expression: ($) =>
			choice(
				$.this,
				$.super,
				$.identifier,
				$._reserved_identifier,
				$.number,
				$.string,
				$.template_string,
				$.regex,
				$.true,
				$.false,
				$.null,
				$.undefined,
				$.object,
				$.array,
				$.function_expression,
				$.arrow_function,
				$.class_expression,
				$.call_expression,
				$.member_expression,
				$.subscript_expression,
				$.jsx_element,
				$.jsx_fragment,
				$.jsx_self_closing_element,
			),

		module_declaration: ($) =>
			seq('module', field('name', $.identifier), field('body', $.module_body)),

		module_body: ($) => seq('{', repeat($.statement), '}'),

		yield_expression: ($) => prec.right(seq('yield', optional('*'), optional($.expression))),

		await_expression: ($) => prec.left(PREC.CALL, seq('await', $.expression)),

		parenthesized_expression: ($) => seq('(', $.expression, ')'),

		assignment_expression: ($) =>
			prec.right(
				PREC.ASSIGN,
				seq(
					field(
						'left',
						choice(
							$.identifier,
							$.member_expression,
							$.subscript_expression,
							$._destructuring_pattern,
						),
					),
					'=',
					field('right', $.expression),
				),
			),

		augmented_assignment_expression: ($) =>
			prec.right(
				PREC.ASSIGN,
				seq(
					field('left', choice($.identifier, $.member_expression, $.subscript_expression)),
					field(
						'operator',
						choice(
							'+=',
							'-=',
							'*=',
							'/=',
							'%=',
							'^=',
							'&=',
							'|=',
							'>>=',
							'>>>=',
							'<<=',
							'**=',
							'&&=',
							'||=',
							'??=',
						),
					),
					field('right', $.expression),
				),
			),

		ternary_expression: ($) =>
			prec.right(
				PREC.TERNARY,
				seq(
					field('condition', $.expression),
					$._ternary_qmark,
					field('consequence', $.expression),
					':',
					field('alternative', $.expression),
				),
			),

		binary_expression: ($) =>
			choice(
				...[
					['&&', PREC.AND],
					['||', PREC.OR],
					['??', PREC.OR],
					['>>', PREC.TIMES],
					['>>>', PREC.TIMES],
					['<<', PREC.TIMES],
					['&', PREC.AND],
					['^', PREC.OR],
					['|', PREC.OR],
					['+', PREC.PLUS],
					['-', PREC.PLUS],
					['*', PREC.TIMES],
					['/', PREC.TIMES],
					['%', PREC.TIMES],
					['**', PREC.EXP],
					['<', PREC.REL],
					['<=', PREC.REL],
					['==', PREC.REL],
					['===', PREC.REL],
					['!=', PREC.REL],
					['!==', PREC.REL],
					['>=', PREC.REL],
					['>', PREC.REL],
					['instanceof', PREC.REL],
					['in', PREC.REL],
				].map(([operator, precedence]) =>
					prec.left(
						precedence,
						seq(
							field('left', $.expression),
							field('operator', operator),
							field('right', $.expression),
						),
					),
				),
			),

		unary_expression: ($) =>
			prec.left(
				PREC.NOT,
				choice(
					...[
						['!', PREC.NOT],
						['~', PREC.NOT],
						['-', PREC.NEG],
						['+', PREC.NEG],
						['typeof', PREC.TYPEOF],
						['void', PREC.VOID],
						['delete', PREC.DELETE],
					].map(([operator, precedence]) =>
						prec.right(
							precedence,
							seq(field('operator', operator), field('argument', $.expression)),
						),
					),
				),
			),

		update_expression: ($) =>
			prec.left(
				PREC.INC,
				choice(
					seq(field('argument', $.expression), field('operator', choice('++', '--'))),
					seq(field('operator', choice('++', '--')), field('argument', $.expression)),
				),
			),

		call_expression: ($) =>
			prec(
				PREC.CALL,
				seq(
					field('function', choice($.expression, $.import)),
					field('arguments', choice($.arguments, $.template_string)),
				),
			),

		new_expression: ($) =>
			prec.right(
				PREC.NEW,
				seq(
					'new',
					field('constructor', $.primary_expression),
					optional(field('arguments', $.arguments)),
				),
			),

		member_expression: ($) =>
			prec(
				PREC.MEMBER,
				seq(
					field('object', choice($.expression, $.primary_expression)),
					choice('.', '?.'),
					field('property', choice($.identifier, $.private_property_identifier)),
				),
			),

		subscript_expression: ($) =>
			prec.right(
				PREC.MEMBER,
				seq(
					field('object', choice($.expression, $.primary_expression)),
					optional('?'),
					'[',
					field('index', $.expression),
					']',
				),
			),

		arguments: ($) =>
			seq('(', commaSep(choice($.expression, $.spread_element)), optional(','), ')'),

		function_expression: ($) =>
			seq(
				optional('async'),
				'function',
				optional('*'),
				optional(field('name', $.identifier)),
				optional(field('type_parameters', $.type_parameters)),
				field('parameters', $.formal_parameters),
				optional($._type_annotation),
				field('body', $.statement_block),
			),

		arrow_function: ($) =>
			seq(
				optional('async'),
				choice(field('parameter', $.identifier), field('parameters', $.formal_parameters)),
				optional($._type_annotation),
				'=>',
				field('body', choice($.expression, $.statement_block)),
			),

		class_expression: ($) =>
			seq(
				optional('abstract'),
				'class',
				optional(field('name', $.identifier)),
				optional(field('type_parameters', $.type_parameters)),
				optional($.class_heritage),
				field('body', $.class_body),
			),

		object: ($) =>
			seq(
				'{',
				commaSep(
					choice(
						$.pair,
						$.spread_element,
						$.method_definition,
						$.shorthand_property_identifier,
						$._reserved_identifier,
					),
				),
				optional(','),
				'}',
			),

		pair: ($) =>
			prec(PREC.OBJECT, seq(field('key', $.property_name), ':', field('value', $.expression))),

		spread_element: ($) => seq('...', $.expression),

		property_name: ($) =>
			choice(
				$.identifier,
				$.private_property_identifier,
				$.string,
				$.number,
				$.computed_property_name,
			),

		computed_property_name: ($) => seq('[', $.expression, ']'),

		shorthand_property_identifier: ($) =>
			alias($.identifier, $.shorthand_property_identifier_pattern),

		shorthand_property_identifier_pattern: ($) =>
			alias($.identifier, $.shorthand_property_identifier),

		array: ($) => seq('[', commaSep(choice($.expression, $.spread_element)), optional(','), ']'),

		template_string: ($) =>
			seq('`', repeat(choice($._template_chars, $.template_substitution)), '`'),

		template_substitution: ($) => seq('${', $.expression, '}'),

		jsx_element: ($) =>
			seq(
				field('open_tag', $.jsx_opening_element),
				repeat(field('children', $._jsx_child)),
				field('close_tag', $.jsx_closing_element),
			),

		jsx_fragment: ($) =>
			seq(
				field('open_tag', $.jsx_opening_fragment),
				repeat(field('children', $._jsx_child)),
				field('close_tag', $.jsx_closing_fragment),
			),

		jsx_opening_element: ($) =>
			seq(
				'<',
				optional('@'),
				field('name', $.jsx_element_name),
				repeat(field('attribute', $._jsx_attribute)),
				'>',
			),

		jsx_opening_fragment: () => seq('<', '>'),

		jsx_closing_element: ($) => seq('</', optional('@'), field('name', $.jsx_element_name), '>'),

		jsx_closing_fragment: () => seq('</', '>'),

		// In Ripple, namespaced TSX-compat elements like <tsx:react> cannot be self-closing
		// so we disallow jsx_namespace_name here by using a narrowed name rule.
		jsx_self_closing_element: ($) =>
			seq(
				'<',
				optional('@'),
				field('name', $.jsx_non_namespaced_element_name),
				repeat(field('attribute', $._jsx_attribute)),
				'/>',
			),

		jsx_element_name: ($) =>
			choice($.identifier, $.jsx_namespace_name, $.jsx_member_name, $.member_expression),

		// Non-namespaced variant (used for self-closing elements)
		jsx_non_namespaced_element_name: ($) =>
			choice($.identifier, $.jsx_member_name, $.member_expression),

		// Support dotted names in JSX element names (e.g. Namespace.Component)
		// Implemented iteratively to avoid left recursion
		jsx_member_name: ($) => seq($.identifier, repeat1(seq('.', $.identifier))),

		jsx_namespace_name: ($) => seq($.identifier, ':', $.identifier),

		jsx_hyphenated_name: ($) => seq($.identifier, repeat1(seq('-', $.identifier))),

		_jsx_attribute: ($) => choice($.jsx_attribute, $.jsx_expression),

		jsx_attribute: ($) =>
			seq(
				field('name', choice($.identifier, $.jsx_namespace_name, $.jsx_hyphenated_name)),
				optional(seq('=', field('value', $._jsx_attribute_value))),
			),

		jsx_expression: ($) =>
			seq(
				'{',
				optional(
					choice(
						$.expression,
						$.spread_element,
						seq('...', $.expression),
						seq('ref', choice($.identifier, $.arrow_function, $.function_expression)),
						seq('html', $.expression),
						seq('text', $.expression),
						$.style_directive,
						repeat1($.component_statement),
					),
				),
				'}',
			),

		style_directive: ($) => seq('style', $.string),

		_jsx_attribute_value: ($) =>
			choice($.string, $.jsx_expression, $.jsx_element, $.jsx_fragment, $.jsx_self_closing_element),

		_jsx_child: ($) =>
			choice(
				$.jsx_text,
				$.jsx_element,
				$.jsx_fragment,
				$.jsx_self_closing_element,
				$.jsx_expression,
			),

		this: ($) => 'this',
		super: ($) => 'super',
		true: ($) => 'true',
		false: ($) => 'false',
		null: ($) => 'null',
		undefined: ($) => 'undefined',
		import: ($) => 'import',

		identifier: ($) => {
			const alpha = /[^\x00-\x1F\s\p{Zs}0-9:;`"'@#.,|^&<=>+\-*/\\%?!~()\[\]{}\uFEFF\u2060\u200B]/;
			const alphanumeric =
				/[^\x00-\x1F\s\p{Zs}:;`"'@#.,|^&<=>+\-*/\\%?!~()\[\]{}\uFEFF\u2060\u200B]/;
			return token(seq(alpha, repeat(alphanumeric)));
		},

		private_property_identifier: ($) => /#[a-zA-Z_$][a-zA-Z0-9_$]*/,

		_reserved_identifier: ($) =>
			choice('arguments', 'await', 'component', 'fragment', 'track', 'untrack'),

		comment: ($) => token(choice(seq('//', /.*/), seq('/*', /[^*]*\*+([^/*][^*]*\*+)*/, '/'))),

		number: ($) => {
			const hex_literal = seq(choice('0x', '0X'), /[\da-fA-F](_?[\da-fA-F])*/);

			const decimal_digits = /\d(_?\d)*/;
			const signed_integer = seq(optional(choice('-', '+')), decimal_digits);
			const exponent_part = seq(choice('e', 'E'), signed_integer);

			const binary_literal = seq(choice('0b', '0B'), /[0-1](_?[0-1])*/);

			const octal_literal = seq(choice('0o', '0O'), /[0-7](_?[0-7])*/);

			const bigint_literal = seq(
				choice(hex_literal, binary_literal, octal_literal, decimal_digits),
				'n',
			);

			const decimal_integer_literal = choice(
				'0',
				seq(optional('0'), /[1-9]/, optional(seq(optional('_'), decimal_digits))),
			);

			const decimal_literal = choice(
				seq(decimal_integer_literal, '.', optional(decimal_digits), optional(exponent_part)),
				seq('.', decimal_digits, optional(exponent_part)),
				seq(decimal_integer_literal, exponent_part),
				decimal_digits,
			);

			return token(
				choice(hex_literal, decimal_literal, binary_literal, octal_literal, bigint_literal),
			);
		},

		string: ($) =>
			choice(
				seq('"', repeat(choice(token.immediate(prec(1, /[^"\\\n]+/)), $.escape_sequence)), '"'),
				seq("'", repeat(choice(token.immediate(prec(1, /[^'\\\n]+/)), $.escape_sequence)), "'"),
			),

		escape_sequence: ($) =>
			token.immediate(
				seq(
					'\\',
					choice(
						/[^xu0-7]/,
						/[0-7]{1,3}/,
						/x[0-9a-fA-F]{2}/,
						/u[0-9a-fA-F]{4}/,
						/u\{[0-9a-fA-F]+\}/,
						/[\r?][\n\u2028\u2029]/,
					),
				),
			),

		regex: ($) =>
			seq(
				'/',
				field('pattern', $.regex_pattern),
				token.immediate('/'),
				optional(field('flags', $.regex_flags)),
			),

		regex_pattern: ($) =>
			token.immediate(
				prec(
					-1,
					repeat1(
						choice(seq('[', repeat(choice(/[^\]\n\\]/, /\\./)), ']'), seq('\\', /./), /[^/\\\[\n]/),
					),
				),
			),

		regex_flags: ($) => token.immediate(/[a-z]+/),

		type_parameters: ($) => seq('<', commaSep1($.type_parameter), optional(','), '>'),

		type_parameter: ($) =>
			seq($.identifier, optional(seq('extends', $.type)), optional(seq('=', $.type))),

		_type_annotation: ($) => seq(':', $.type),

		type: ($) =>
			choice(
				$.identifier,
				$.predefined_type,
				$.type_identifier,
				$.nested_type_identifier,
				$.generic_type,
				$.object_type,
				$.array_type,
				$.tuple_type,
				$.union_type,
				$.intersection_type,
				$.function_type,
				$.literal_type,
				$.parenthesized_type,
			),

		predefined_type: ($) =>
			choice('any', 'number', 'boolean', 'string', 'symbol', 'void', 'unknown', 'never', 'object'),

		type_identifier: ($) => alias($.identifier, $.type_identifier),

		nested_type_identifier: ($) =>
			seq(choice($.identifier, $.nested_type_identifier), '.', $.type_identifier),

		generic_type: ($) => seq(choice($.identifier, $.nested_type_identifier), $.type_arguments),

		type_arguments: ($) => seq('<', commaSep1($.type), optional(','), '>'),

		object_type: ($) => seq('{', commaSep($.property_signature), optional(','), '}'),

		property_signature: ($) =>
			seq(optional('readonly'), field('name', $.property_name), optional('?'), $._type_annotation),

		array_type: ($) => seq($.type, '[', ']'),

		tuple_type: ($) => seq('[', commaSep1($.type), optional(','), ']'),

		union_type: ($) => prec.left(seq($.type, '|', $.type)),

		intersection_type: ($) => prec.left(seq($.type, '&', $.type)),

		function_type: ($) => seq(optional($.type_parameters), $.formal_parameters, '=>', $.type),

		literal_type: ($) => choice($.number, $.string, $.true, $.false, $.null),

		parenthesized_type: ($) => seq('(', $.type, ')'),

		initializer: ($) => seq('=', $.expression),

		_semicolon: ($) => choice($._automatic_semicolon, ';'),
	},
});

function commaSep(rule) {
	return optional(commaSep1(rule));
}

function commaSep1(rule) {
	return seq(rule, repeat(seq(',', rule)));
}

```

## /grammars/tree-sitter/package.json

```json path="/grammars/tree-sitter/package.json" 
{
  "name": "@ripple-ts/tree-sitter",
  "version": "0.2.208",
  "description": "Ripple grammar for tree-sitter",
  "private": true,
  "main": "bindings/node",
  "types": "bindings/node",
  "keywords": [
    "tree-sitter",
    "parser",
    "ripple"
  ],
  "author": "Dominic Gannaway",
  "license": "MIT",
  "dependencies": {
    "node-addon-api": "^8.6.0",
    "node-gyp-build": "^4.8.0"
  },
  "devDependencies": {
    "tree-sitter-cli": "^0.26.6",
    "prebuildify": "^6.0.0",
    "node-gyp": "^12.3.0"
  },
  "scripts": {
    "generate": "tree-sitter generate",
    "build": "tree-sitter generate && node-gyp rebuild",
    "install": "node-gyp-build",
    "prestart": "tree-sitter build --wasm",
    "start": "tree-sitter playground",
    "test": "tree-sitter test"
  },
  "tree-sitter": [
    {
      "scope": "source.tsrx",
      "file-types": [
        "ripple"
      ],
      "injection-regex": "ripple"
    }
  ],
  "gypfile": true
}

```

## /grammars/tree-sitter/queries/brackets.scm

```scm path="/grammars/tree-sitter/queries/brackets.scm" 
; Bracket pairs for cursor navigation
(jsx_opening_element
  "<" @open
  ">" @close)

(jsx_opening_fragment
  "<" @open
  ">" @close)

(jsx_closing_element
  "</" @open
  ">" @close)

(jsx_closing_fragment
  "</" @open
  ">" @close)

(jsx_self_closing_element
  "<" @open
  "/>" @close)

("(" @open ")" @close)
("[" @open "]" @close)
("{" @open "}" @close)

```

## /grammars/tree-sitter/queries/folds.scm

```scm path="/grammars/tree-sitter/queries/folds.scm" 
; Folds for code blocks
[
  (statement_block)
  (component_body)
  (class_body)
  (object)
  (object_pattern)
  (array)
  (array_pattern)
  (switch_body)
] @fold

; Fold multi-line JSX elements
(jsx_element) @fold
(jsx_fragment) @fold

; Fold style elements
(style_element) @fold

; Fold submodules
(module_declaration) @fold

; Fold comments
(comment) @fold

; Fold template strings
(template_string) @fold

```

## /grammars/tree-sitter/queries/highlights.scm

```scm path="/grammars/tree-sitter/queries/highlights.scm" 
; Keywords
(component_declaration "component" @keyword)
(fragment_declaration "fragment" @keyword)
(module_declaration
  "module" @keyword
  name: (identifier) @namespace)

; Lazy destructuring
(lazy_object_pattern "&" @operator)
(lazy_array_pattern "&" @operator)

(style_directive
  "style" @keyword
  (string) @string)

(jsx_expression "html" @keyword)

; Reserved identifiers
[
  "track"
  "untrack"
] @function.builtin

; Functions
(component_declaration
  name: (identifier) @function)

(fragment_declaration
  name: (identifier) @function)

(function_declaration
  name: (identifier) @function)

(class_declaration
  name: (identifier) @type)

(method_definition
  name: (property_name) @function.method)

(field_definition
  property: (property_name) @property)

(call_expression
  function: (identifier) @function.call)

(call_expression
  function: (member_expression
    property: (identifier) @function.method.call))

; Variables
(identifier) @variable

; Parameters
(required_parameter
  pattern: (identifier) @variable.parameter)

(rest_parameter
  (identifier) @variable.parameter)

; JSX/Components
(jsx_opening_element
  "<" @tag.delimiter
  name: (jsx_element_name) @tag
  ">" @tag.delimiter)

(jsx_opening_fragment
  "<" @tag.delimiter
  ">" @tag.delimiter)

(jsx_closing_element
  "</" @tag.delimiter
  name: (jsx_element_name) @tag
  ">" @tag.delimiter)

(jsx_closing_fragment
  "</" @tag.delimiter
  ">" @tag.delimiter)

(jsx_self_closing_element
  "<" @tag.delimiter
  name: (jsx_non_namespaced_element_name) @tag
  "/>" @tag.delimiter)

; Override identifier coloring for JSX element names
; These must come after the general (identifier) @variable pattern to have higher priority

; Regular element names (plain identifiers)
(jsx_opening_element
  name: (jsx_element_name (identifier) @tag))

(jsx_closing_element
  name: (jsx_element_name (identifier) @tag))

(jsx_self_closing_element
  name: (jsx_non_namespaced_element_name (identifier) @tag))

(jsx_attribute
  name: [(identifier) (jsx_namespace_name) (jsx_hyphenated_name)] @attribute)

(jsx_expression
  "{" @punctuation.bracket
  "}" @punctuation.bracket)

; Style elements
(style_element
  "<style" @tag
  ">" @tag.delimiter
  "</style>" @tag)

(style_element
  (raw_text) @string.special)

; Types
(type_identifier) @type
(predefined_type) @type.builtin
(type_parameter (identifier) @type.parameter)

; Type annotations (commented out - _type_annotation is hidden)
; The colon will be captured as punctuation.delimiter via other rules

; Literals
(string) @string
(template_string) @string

(number) @number
(true) @constant.builtin.boolean
(false) @constant.builtin.boolean
(null) @constant.builtin
(undefined) @constant.builtin

; Regex
(regex) @string.regexp
(regex_pattern) @string.regexp
(regex_flags) @string.regexp

; Comments
(comment) @comment

; Operators
(unary_expression operator: _ @operator)
(binary_expression operator: _ @operator)
(augmented_assignment_expression operator: _ @operator)
(update_expression operator: _ @operator)

; Control flow keywords
[
  "if"
  "else"
  "switch"
  "case"
  "default"
  "for"
  "while"
  "do"
  "break"
  "continue"
  "return"
  "throw"
  "try"
  "pending"
  "catch"
  "finally"
] @keyword.control

[
  "await"
  "async"
] @keyword.control.flow

[
  "import"
  "export"
  "from"
  "as"
] @keyword.control.import

; Other keywords
[
  "function"
  "class"
  "extends"
  "implements"
  "new"
  "typeof"
  "instanceof"
  "in"
  "of"
  "void"
  "delete"
  "yield"
  "static"
  "get"
  "set"
  "abstract"
  "readonly"
  "declare"
  "override"
] @keyword

[
  "let"
  "const"
  "var"
] @keyword.storage

; Special identifiers
[
  (this)
  (super)
] @variable.builtin

; Properties
(property_signature
  name: (property_name) @property)

(pair
  key: (property_name) @property)

(member_expression
  property: (identifier) @property)

(shorthand_property_identifier) @property
(shorthand_property_identifier_pattern) @property

; Private properties
(private_property_identifier) @property.private

; Punctuation
["(" ")" "[" "]" "{" "}"] @punctuation.bracket
["." "," ";" ":" "..."] @punctuation.delimiter
; Note: < and > are handled separately in JSX contexts as @tag.delimiter

(template_substitution
  "${" @punctuation.special
  "}" @punctuation.special)

; Special: Arrow function
"=>" @operator

; Hash bang
(hash_bang_line) @comment

```

## /grammars/tree-sitter/queries/indents.nvim.scm

```scm path="/grammars/tree-sitter/queries/indents.nvim.scm" 
; Neovim (nvim-treesitter) indentation rules.
[
  (statement_block "}" @indent.end)
  (component_body "}" @indent.end)
  (class_body "}" @indent.end)
  (switch_body "}" @indent.end)
  (object "}" @indent.end)
  (object_pattern "}" @indent.end)
  (array "]" @indent.end)
  (array_pattern "]" @indent.end)
  (arguments ")" @indent.end)
  (formal_parameters ")" @indent.end)
  (parenthesized_expression ")" @indent.end)
  (jsx_expression "}" @indent.end)
  (style_element "</style>" @indent.end)
  (module_body "}" @indent.end)
] @indent.begin

[
  (jsx_element)
  (jsx_fragment)
  (jsx_self_closing_element)
] @indent.begin

((jsx_opening_element) @indent.begin
  (#set! indent.immediate)
  (#set! indent.start_at_same_line))

((jsx_opening_fragment) @indent.begin
  (#set! indent.immediate)
  (#set! indent.start_at_same_line))

(jsx_closing_element ">" @indent.end)
(jsx_closing_fragment ">" @indent.end)
(jsx_self_closing_element "/>" @indent.end)

[
  "}"
  "]"
  ")"
  "</style>"
  (jsx_closing_element)
  (jsx_closing_fragment)
] @indent.branch

(jsx_self_closing_element "/>" @indent.branch)

```

## /grammars/tree-sitter/queries/indents.scm

```scm path="/grammars/tree-sitter/queries/indents.scm" 
; Helix indentation rules.
[
  (statement_block)
  (component_body)
  (class_body)
  (switch_body)
  (object)
  (object_pattern)
  (array)
  (array_pattern)
  (arguments)
  (formal_parameters)
  (parenthesized_expression)
  (jsx_element)
  (jsx_fragment)
  (jsx_self_closing_element)
  (style_element)
  (module_body)
] @indent

[
  "}"
  "]"
  ")"
  "</style>"
] @outdent

(jsx_closing_element) @outdent
(jsx_closing_fragment) @outdent

```

## /grammars/tree-sitter/queries/indents.zed.scm

```scm path="/grammars/tree-sitter/queries/indents.zed.scm" 
; Zed indents use @indent plus @end markers.
[
  (statement_block "}" @end)
  (component_body "}" @end)
  (class_body "}" @end)
  (switch_body "}" @end)
  (object "}" @end)
  (object_pattern "}" @end)
  (array "]" @end)
  (array_pattern "]" @end)
  (arguments ")" @end)
  (formal_parameters ")" @end)
  (parenthesized_expression ")" @end)
  (jsx_expression "}" @end)
  (style_element "</style>" @end)
  (module_body "}" @end)
  (jsx_self_closing_element "/>" @end)
] @indent

(_ "[" "]" @end) @indent
(_ "{" "}" @end) @indent
(_ "(" ")" @end) @indent

(jsx_opening_element ">" @end) @indent
(jsx_opening_fragment ">" @end) @indent

(jsx_element
  (jsx_opening_element) @start
  (jsx_closing_element)? @end) @indent

(jsx_fragment
  (jsx_opening_fragment) @start
  (jsx_closing_fragment)? @end) @indent

```

## /grammars/tree-sitter/queries/injections.scm

```scm path="/grammars/tree-sitter/queries/injections.scm" 
; Inject CSS into style elements
(style_element
  (raw_text) @injection.content
  (#set! injection.combined)
  (#set! injection.language "css"))

; Inject JavaScript/TypeScript into submodules
; Note: statement is inlined, so we need to match specific statement types
; Commenting out for now as it requires matching all concrete statement types

; Template string interpolations
(template_substitution
  (expression) @injection.content
  (#set! injection.language "typescript"))

; TSX expression islands. Shorthand fragments and <tsx> blocks use TSX syntax
; rather than Ripple template statements.
((jsx_fragment) @injection.content
  (#set! injection.language "tsx"))

((jsx_element
  open_tag: (jsx_opening_element
    name: (jsx_element_name (identifier) @_tsx_name))) @injection.content
  (#eq? @_tsx_name "tsx")
  (#set! injection.language "tsx"))

((jsx_element
  open_tag: (jsx_opening_element
    name: (jsx_element_name
      (jsx_namespace_name
        (identifier) @_tsx_namespace
        (identifier) @_tsx_name)))) @injection.content
  (#eq? @_tsx_namespace "tsx")
  (#eq? @_tsx_name "react")
  (#set! injection.language "tsx"))

; Inject Ripple into JSX text blocks so statement-like template code
; (e.g. const/if lines in JSX children) is highlighted consistently.
((jsx_text) @injection.content
  (#set! injection.language "ripple"))

```

## /grammars/tree-sitter/queries/locals.scm

```scm path="/grammars/tree-sitter/queries/locals.scm" 
; Scopes
[
  (statement_block)
  (function_declaration)
  (arrow_function)
  (function_expression)
  (component_declaration)
  (fragment_declaration)
  (class_declaration)
  (for_statement)
  (for_of_statement)
  (for_in_statement)
  (while_statement)
  (catch_clause)
] @local.scope

; Definitions
(component_declaration
  name: (identifier) @local.definition.function)

(fragment_declaration
  name: (identifier) @local.definition.function)

(function_declaration
  name: (identifier) @local.definition.function)

(class_declaration
  name: (identifier) @local.definition.type)

(method_definition
  name: (property_name) @local.definition.method)

(variable_declarator
  name: (identifier) @local.definition.var)

(required_parameter
  pattern: (identifier) @local.definition.parameter)

(rest_parameter
  (identifier) @local.definition.parameter)

; References
(identifier) @local.reference

; Imports
(import_specifier
  name: (identifier) @local.definition.import)

(namespace_import
  (identifier) @local.definition.namespace)

; Exports
(export_specifier
  name: (identifier) @local.definition.export)

```

## /grammars/tree-sitter/queries/outline.scm

```scm path="/grammars/tree-sitter/queries/outline.scm" 
; Code outline/structure for symbol navigation

; Components
(component_declaration
  name: (identifier) @name) @item

; Fragments
(fragment_declaration
  name: (identifier) @name) @item

; Functions
(function_declaration
  name: (identifier) @name) @item

; Classes
(class_declaration
  name: (identifier) @name) @item

; Methods
(method_definition
  name: (property_name) @name) @item

; Variables (const/let)
(variable_declarator
  name: (identifier) @name) @item

```

## /grammars/tree-sitter/queries/textobjects.scm

```scm path="/grammars/tree-sitter/queries/textobjects.scm" 
; Functions / components
(function_declaration) @function.around
(function_declaration) @function.outer
(function_declaration body: (statement_block) @function.inside)
(function_declaration body: (statement_block) @function.inner)

(component_declaration) @function.around
(component_declaration) @function.outer
(component_declaration body: (component_body) @function.inside)
(component_declaration body: (component_body) @function.inner)

(fragment_declaration) @function.around
(fragment_declaration) @function.outer
(fragment_declaration body: (component_body) @function.inside)
(fragment_declaration body: (component_body) @function.inner)

(method_definition) @function.around
(method_definition) @function.outer
(method_definition body: (statement_block) @function.inside)
(method_definition body: (statement_block) @function.inner)

; Classes / interfaces
(class_declaration) @class.around
(class_declaration) @class.outer
(class_declaration body: (class_body) @class.inside)
(class_declaration body: (class_body) @class.inner)

; Parameters
(required_parameter) @parameter.around
(required_parameter) @parameter.outer
(required_parameter pattern: (_) @parameter.inside)
(required_parameter pattern: (_) @parameter.inner)

(rest_parameter) @parameter.around
(rest_parameter) @parameter.outer
(rest_parameter (identifier) @parameter.inside)
(rest_parameter (identifier) @parameter.inner)

; Comments
(comment) @comment.around
(comment) @comment.outer
(comment) @comment.inside
(comment) @comment.inner

; Object entries
(pair) @entry.around
(pair) @entry.outer
(pair key: (_) @entry.inside)
(pair key: (_) @entry.inner)

```

## /grammars/tree-sitter/src/node-types.json

```json path="/grammars/tree-sitter/src/node-types.json" 
[
  {
    "type": "declaration",
    "named": true,
    "subtypes": [
      {
        "type": "class_declaration",
        "named": true
      },
      {
        "type": "component_declaration",
        "named": true
      },
      {
        "type": "fragment_declaration",
        "named": true
      },
      {
        "type": "function_declaration",
        "named": true
      },
      {
        "type": "lexical_declaration",
        "named": true
      },
      {
        "type": "variable_declaration",
        "named": true
      }
    ]
  },
  {
    "type": "expression",
    "named": true,
    "subtypes": [
      {
        "type": "assignment_expression",
        "named": true
      },
      {
        "type": "augmented_assignment_expression",
        "named": true
      },
      {
        "type": "await_expression",
        "named": true
      },
      {
        "type": "binary_expression",
        "named": true
      },
      {
        "type": "new_expression",
        "named": true
      },
      {
        "type": "parenthesized_expression",
        "named": true
      },
      {
        "type": "primary_expression",
        "named": true
      },
      {
        "type": "ternary_expression",
        "named": true
      },
      {
        "type": "unary_expression",
        "named": true
      },
      {
        "type": "update_expression",
        "named": true
      },
      {
        "type": "yield_expression",
        "named": true
      }
    ]
  },
  {
    "type": "pattern",
    "named": true,
    "subtypes": [
      {
        "type": "arguments",
        "named": false
      },
      {
        "type": "array_pattern",
        "named": true
      },
      {
        "type": "await",
        "named": false
      },
      {
        "type": "component",
        "named": false
      },
      {
        "type": "fragment",
        "named": false
      },
      {
        "type": "identifier",
        "named": true
      },
      {
        "type": "lazy_array_pattern",
        "named": true
      },
      {
        "type": "lazy_object_pattern",
        "named": true
      },
      {
        "type": "object_pattern",
        "named": true
      },
      {
        "type": "track",
        "named": false
      },
      {
        "type": "untrack",
        "named": false
      }
    ]
  },
  {
    "type": "primary_expression",
    "named": true,
    "subtypes": [
      {
        "type": "arguments",
        "named": false
      },
      {
        "type": "array",
        "named": true
      },
      {
        "type": "arrow_function",
        "named": true
      },
      {
        "type": "await",
        "named": false
      },
      {
        "type": "call_expression",
        "named": true
      },
      {
        "type": "class_expression",
        "named": true
      },
      {
        "type": "component",
        "named": false
      },
      {
        "type": "false",
        "named": true
      },
      {
        "type": "fragment",
        "named": false
      },
      {
        "type": "function_expression",
        "named": true
      },
      {
        "type": "identifier",
        "named": true
      },
      {
        "type": "jsx_element",
        "named": true
      },
      {
        "type": "jsx_fragment",
        "named": true
      },
      {
        "type": "jsx_self_closing_element",
        "named": true
      },
      {
        "type": "member_expression",
        "named": true
      },
      {
        "type": "null",
        "named": true
      },
      {
        "type": "number",
        "named": true
      },
      {
        "type": "object",
        "named": true
      },
      {
        "type": "regex",
        "named": true
      },
      {
        "type": "string",
        "named": true
      },
      {
        "type": "subscript_expression",
        "named": true
      },
      {
        "type": "super",
        "named": true
      },
      {
        "type": "template_string",
        "named": true
      },
      {
        "type": "this",
        "named": true
      },
      {
        "type": "track",
        "named": false
      },
      {
        "type": "true",
        "named": true
      },
      {
        "type": "undefined",
        "named": true
      },
      {
        "type": "untrack",
        "named": false
      }
    ]
  },
  {
    "type": "statement",
    "named": true,
    "subtypes": [
      {
        "type": "break_statement",
        "named": true
      },
      {
        "type": "continue_statement",
        "named": true
      },
      {
        "type": "debugger_statement",
        "named": true
      },
      {
        "type": "declaration",
        "named": true
      },
      {
        "type": "do_statement",
        "named": true
      },
      {
        "type": "empty_statement",
        "named": true
      },
      {
        "type": "export_statement",
        "named": true
      },
      {
        "type": "expression_statement",
        "named": true
      },
      {
        "type": "for_in_statement",
        "named": true
      },
      {
        "type": "for_of_statement",
        "named": true
      },
      {
        "type": "for_statement",
        "named": true
      },
      {
        "type": "if_statement",
        "named": true
      },
      {
        "type": "import_statement",
        "named": true
      },
      {
        "type": "labeled_statement",
        "named": true
      },
      {
        "type": "module_declaration",
        "named": true
      },
      {
        "type": "return_statement",
        "named": true
      },
      {
        "type": "statement_block",
        "named": true
      },
      {
        "type": "switch_statement",
        "named": true
      },
      {
        "type": "throw_statement",
        "named": true
      },
      {
        "type": "try_statement",
        "named": true
      },
      {
        "type": "while_statement",
        "named": true
      }
    ]
  },
  {
    "type": "arguments",
    "named": true,
    "fields": {},
    "children": {
      "multiple": true,
      "required": false,
      "types": [
        {
          "type": "expression",
          "named": true
        },
        {
          "type": "spread_element",
          "named": true
        }
      ]
    }
  },
  {
    "type": "array",
    "named": true,
    "fields": {},
    "children": {
      "multiple": true,
      "required": false,
      "types": [
        {
          "type": "expression",
          "named": true
        },
        {
          "type": "spread_element",
          "named": true
        }
      ]
    }
  },
  {
    "type": "array_pattern",
    "named": true,
    "fields": {},
    "children": {
      "multiple": true,
      "required": false,
      "types": [
        {
          "type": "assignment_pattern",
          "named": true
        },
        {
          "type": "pattern",
          "named": true
        },
        {
          "type": "rest_pattern",
          "named": true
        }
      ]
    }
  },
  {
    "type": "array_type",
    "named": true,
    "fields": {},
    "children": {
      "multiple": false,
      "required": true,
      "types": [
        {
          "type": "type",
          "named": true
        }
      ]
    }
  },
  {
    "type": "arrow_function",
    "named": true,
    "fields": {
      "body": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "expression",
            "named": true
          },
          {
            "type": "statement_block",
            "named": true
          }
        ]
      },
      "parameter": {
        "multiple": false,
        "required": false,
        "types": [
          {
            "type": "identifier",
            "named": true
          }
        ]
      },
      "parameters": {
        "multiple": false,
        "required": false,
        "types": [
          {
            "type": "formal_parameters",
            "named": true
          }
        ]
      }
    },
    "children": {
      "multiple": false,
      "required": false,
      "types": [
        {
          "type": "type",
          "named": true
        }
      ]
    }
  },
  {
    "type": "assignment_expression",
    "named": true,
    "fields": {
      "left": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "array_pattern",
            "named": true
          },
          {
            "type": "identifier",
            "named": true
          },
          {
            "type": "lazy_array_pattern",
            "named": true
          },
          {
            "type": "lazy_object_pattern",
            "named": true
          },
          {
            "type": "member_expression",
            "named": true
          },
          {
            "type": "object_pattern",
            "named": true
          },
          {
            "type": "subscript_expression",
            "named": true
          }
        ]
      },
      "right": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "expression",
            "named": true
          }
        ]
      }
    }
  },
  {
    "type": "assignment_pattern",
    "named": true,
    "fields": {
      "left": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "pattern",
            "named": true
          }
        ]
      },
      "right": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "expression",
            "named": true
          }
        ]
      }
    }
  },
  {
    "type": "augmented_assignment_expression",
    "named": true,
    "fields": {
      "left": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "identifier",
            "named": true
          },
          {
            "type": "member_expression",
            "named": true
          },
          {
            "type": "subscript_expression",
            "named": true
          }
        ]
      },
      "operator": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "%=",
            "named": false
          },
          {
            "type": "&&=",
            "named": false
          },
          {
            "type": "&=",
            "named": false
          },
          {
            "type": "**=",
            "named": false
          },
          {
            "type": "*=",
            "named": false
          },
          {
            "type": "+=",
            "named": false
          },
          {
            "type": "-=",
            "named": false
          },
          {
            "type": "/=",
            "named": false
          },
          {
            "type": "<<=",
            "named": false
          },
          {
            "type": ">>=",
            "named": false
          },
          {
            "type": ">>>=",
            "named": false
          },
          {
            "type": "??=",
            "named": false
          },
          {
            "type": "^=",
            "named": false
          },
          {
            "type": "|=",
            "named": false
          },
          {
            "type": "||=",
            "named": false
          }
        ]
      },
      "right": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "expression",
            "named": true
          }
        ]
      }
    }
  },
  {
    "type": "await_expression",
    "named": true,
    "fields": {},
    "children": {
      "multiple": false,
      "required": true,
      "types": [
        {
          "type": "expression",
          "named": true
        }
      ]
    }
  },
  {
    "type": "binary_expression",
    "named": true,
    "fields": {
      "left": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "expression",
            "named": true
          }
        ]
      },
      "operator": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "!=",
            "named": false
          },
          {
            "type": "!==",
            "named": false
          },
          {
            "type": "%",
            "named": false
          },
          {
            "type": "&",
            "named": false
          },
          {
            "type": "&&",
            "named": false
          },
          {
            "type": "*",
            "named": false
          },
          {
            "type": "**",
            "named": false
          },
          {
            "type": "+",
            "named": false
          },
          {
            "type": "-",
            "named": false
          },
          {
            "type": "/",
            "named": false
          },
          {
            "type": "<",
            "named": false
          },
          {
            "type": "<<",
            "named": false
          },
          {
            "type": "<=",
            "named": false
          },
          {
            "type": "==",
            "named": false
          },
          {
            "type": "===",
            "named": false
          },
          {
            "type": ">",
            "named": false
          },
          {
            "type": ">=",
            "named": false
          },
          {
            "type": ">>",
            "named": false
          },
          {
            "type": ">>>",
            "named": false
          },
          {
            "type": "??",
            "named": false
          },
          {
            "type": "^",
            "named": false
          },
          {
            "type": "in",
            "named": false
          },
          {
            "type": "instanceof",
            "named": false
          },
          {
            "type": "|",
            "named": false
          },
          {
            "type": "||",
            "named": false
          }
        ]
      },
      "right": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "expression",
            "named": true
          }
        ]
      }
    }
  },
  {
    "type": "break_statement",
    "named": true,
    "fields": {},
    "children": {
      "multiple": false,
      "required": false,
      "types": [
        {
          "type": "identifier",
          "named": true
        }
      ]
    }
  },
  {
    "type": "call_expression",
    "named": true,
    "fields": {
      "arguments": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "arguments",
            "named": true
          },
          {
            "type": "template_string",
            "named": true
          }
        ]
      },
      "function": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "expression",
            "named": true
          },
          {
            "type": "import",
            "named": true
          }
        ]
      }
    }
  },
  {
    "type": "catch_clause",
    "named": true,
    "fields": {
      "body": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "statement_block",
            "named": true
          }
        ]
      },
      "parameter": {
        "multiple": false,
        "required": false,
        "types": [
          {
            "type": "array_pattern",
            "named": true
          },
          {
            "type": "identifier",
            "named": true
          },
          {
            "type": "lazy_array_pattern",
            "named": true
          },
          {
            "type": "lazy_object_pattern",
            "named": true
          },
          {
            "type": "object_pattern",
            "named": true
          }
        ]
      }
    }
  },
  {
    "type": "class_body",
    "named": true,
    "fields": {},
    "children": {
      "multiple": true,
      "required": false,
      "types": [
        {
          "type": "class_static_block",
          "named": true
        },
        {
          "type": "field_definition",
          "named": true
        },
        {
          "type": "method_definition",
          "named": true
        }
      ]
    }
  },
  {
    "type": "class_declaration",
    "named": true,
    "fields": {
      "body": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "class_body",
            "named": true
          }
        ]
      },
      "name": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "identifier",
            "named": true
          }
        ]
      },
      "type_parameters": {
        "multiple": false,
        "required": false,
        "types": [
          {
            "type": "type_parameters",
            "named": true
          }
        ]
      }
    },
    "children": {
      "multiple": false,
      "required": false,
      "types": [
        {
          "type": "class_heritage",
          "named": true
        }
      ]
    }
  },
  {
    "type": "class_expression",
    "named": true,
    "fields": {
      "body": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "class_body",
            "named": true
          }
        ]
      },
      "name": {
        "multiple": false,
        "required": false,
        "types": [
          {
            "type": "identifier",
            "named": true
          }
        ]
      },
      "type_parameters": {
        "multiple": false,
        "required": false,
        "types": [
          {
            "type": "type_parameters",
            "named": true
          }
        ]
      }
    },
    "children": {
      "multiple": false,
      "required": false,
      "types": [
        {
          "type": "class_heritage",
          "named": true
        }
      ]
    }
  },
  {
    "type": "class_heritage",
    "named": true,
    "fields": {},
    "children": {
      "multiple": true,
      "required": true,
      "types": [
        {
          "type": "expression",
          "named": true
        },
        {
          "type": "type",
          "named": true
        }
      ]
    }
  },
  {
    "type": "class_static_block",
    "named": true,
    "fields": {},
    "children": {
      "multiple": false,
      "required": true,
      "types": [
        {
          "type": "statement_block",
          "named": true
        }
      ]
    }
  },
  {
    "type": "component_body",
    "named": true,
    "fields": {},
    "children": {
      "multiple": true,
      "required": false,
      "types": [
        {
          "type": "component_statement",
          "named": true
        }
      ]
    }
  },
  {
    "type": "component_declaration",
    "named": true,
    "fields": {
      "body": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "component_body",
            "named": true
          }
        ]
      },
      "name": {
        "multiple": false,
        "required": false,
        "types": [
          {
            "type": "identifier",
            "named": true
          }
        ]
      },
      "parameters": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "formal_parameters",
            "named": true
          }
        ]
      },
      "type_parameters": {
        "multiple": false,
        "required": false,
        "types": [
          {
            "type": "type_parameters",
            "named": true
          }
        ]
      }
    },
    "children": {
      "multiple": false,
      "required": false,
      "types": [
        {
          "type": "type",
          "named": true
        }
      ]
    }
  },
  {
    "type": "component_statement",
    "named": true,
    "fields": {},
    "children": {
      "multiple": false,
      "required": true,
      "types": [
        {
          "type": "break_statement",
          "named": true
        },
        {
          "type": "class_declaration",
          "named": true
        },
        {
          "type": "continue_statement",
          "named": true
        },
        {
          "type": "debugger_statement",
          "named": true
        },
        {
          "type": "do_statement",
          "named": true
        },
        {
          "type": "empty_statement",
          "named": true
        },
        {
          "type": "expression_statement",
          "named": true
        },
        {
          "type": "for_in_statement",
          "named": true
        },
        {
          "type": "for_of_statement",
          "named": true
        },
        {
          "type": "for_statement",
          "named": true
        },
        {
          "type": "function_declaration",
          "named": true
        },
        {
          "type": "if_statement",
          "named": true
        },
        {
          "type": "jsx_element",
          "named": true
        },
        {
          "type": "jsx_fragment",
          "named": true
        },
        {
          "type": "jsx_self_closing_element",
          "named": true
        },
        {
          "type": "lexical_declaration",
          "named": true
        },
        {
          "type": "return_statement",
          "named": true
        },
        {
          "type": "style_element",
          "named": true
        },
        {
          "type": "switch_statement",
          "named": true
        },
        {
          "type": "throw_statement",
          "named": true
        },
        {
          "type": "try_statement",
          "named": true
        },
        {
          "type": "variable_declaration",
          "named": true
        },
        {
          "type": "while_statement",
          "named": true
        }
      ]
    }
  },
  {
    "type": "computed_property_name",
    "named": true,
    "fields": {},
    "children": {
      "multiple": false,
      "required": true,
      "types": [
        {
          "type": "expression",
          "named": true
        }
      ]
    }
  },
  {
    "type": "continue_statement",
    "named": true,
    "fields": {},
    "children": {
      "multiple": false,
      "required": false,
      "types": [
        {
          "type": "identifier",
          "named": true
        }
      ]
    }
  },
  {
    "type": "debugger_statement",
    "named": true,
    "fields": {}
  },
  {
    "type": "do_statement",
    "named": true,
    "fields": {
      "body": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "statement",
            "named": true
          }
        ]
      },
      "condition": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "parenthesized_expression",
            "named": true
          }
        ]
      }
    }
  },
  {
    "type": "empty_statement",
    "named": true,
    "fields": {}
  },
  {
    "type": "export_clause",
    "named": true,
    "fields": {},
    "children": {
      "multiple": true,
      "required": false,
      "types": [
        {
          "type": "export_specifier",
          "named": true
        }
      ]
    }
  },
  {
    "type": "export_specifier",
    "named": true,
    "fields": {
      "alias": {
        "multiple": false,
        "required": false,
        "types": [
          {
            "type": "identifier",
            "named": true
          }
        ]
      },
      "name": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "identifier",
            "named": true
          }
        ]
      }
    }
  },
  {
    "type": "export_statement",
    "named": true,
    "fields": {},
    "children": {
      "multiple": true,
      "required": true,
      "types": [
        {
          "type": "declaration",
          "named": true
        },
        {
          "type": "export_clause",
          "named": true
        },
        {
          "type": "expression",
          "named": true
        },
        {
          "type": "from_clause",
          "named": true
        },
        {
          "type": "namespace_export",
          "named": true
        }
      ]
    }
  },
  {
    "type": "expression_statement",
    "named": true,
    "fields": {},
    "children": {
      "multiple": false,
      "required": true,
      "types": [
        {
          "type": "expression",
          "named": true
        }
      ]
    }
  },
  {
    "type": "field_definition",
    "named": true,
    "fields": {
      "property": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "property_name",
            "named": true
          }
        ]
      }
    },
    "children": {
      "multiple": true,
      "required": false,
      "types": [
        {
          "type": "initializer",
          "named": true
        },
        {
          "type": "type",
          "named": true
        }
      ]
    }
  },
  {
    "type": "finally_clause",
    "named": true,
    "fields": {
      "body": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "statement_block",
            "named": true
          }
        ]
      }
    }
  },
  {
    "type": "for_in_statement",
    "named": true,
    "fields": {
      "body": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "statement",
            "named": true
          }
        ]
      },
      "right": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "expression",
            "named": true
          }
        ]
      }
    },
    "children": {
      "multiple": false,
      "required": true,
      "types": [
        {
          "type": "array_pattern",
          "named": true
        },
        {
          "type": "identifier",
          "named": true
        },
        {
          "type": "lazy_array_pattern",
          "named": true
        },
        {
          "type": "lazy_object_pattern",
          "named": true
        },
        {
          "type": "object_pattern",
          "named": true
        }
      ]
    }
  },
  {
    "type": "for_of_statement",
    "named": true,
    "fields": {
      "body": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "statement",
            "named": true
          }
        ]
      },
      "right": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "expression",
            "named": true
          }
        ]
      }
    },
    "children": {
      "multiple": true,
      "required": true,
      "types": [
        {
          "type": "array_pattern",
          "named": true
        },
        {
          "type": "expression",
          "named": true
        },
        {
          "type": "identifier",
          "named": true
        },
        {
          "type": "lazy_array_pattern",
          "named": true
        },
        {
          "type": "lazy_object_pattern",
          "named": true
        },
        {
          "type": "object_pattern",
          "named": true
        }
      ]
    }
  },
  {
    "type": "for_statement",
    "named": true,
    "fields": {
      "body": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "statement",
            "named": true
          }
        ]
      },
      "condition": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "empty_statement",
            "named": true
          },
          {
            "type": "expression_statement",
            "named": true
          }
        ]
      },
      "increment": {
        "multiple": false,
        "required": false,
        "types": [
          {
            "type": "expression",
            "named": true
          }
        ]
      },
      "initializer": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "empty_statement",
            "named": true
          },
          {
            "type": "expression_statement",
            "named": true
          },
          {
            "type": "lexical_declaration",
            "named": true
          },
          {
            "type": "variable_declaration",
            "named": true
          }
        ]
      }
    }
  },
  {
    "type": "formal_parameters",
    "named": true,
    "fields": {},
    "children": {
      "multiple": true,
      "required": false,
      "types": [
        {
          "type": "required_parameter",
          "named": true
        },
        {
          "type": "rest_parameter",
          "named": true
        }
      ]
    }
  },
  {
    "type": "fragment_declaration",
    "named": true,
    "fields": {
      "body": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "component_body",
            "named": true
          }
        ]
      },
      "name": {
        "multiple": false,
        "required": false,
        "types": [
          {
            "type": "identifier",
            "named": true
          }
        ]
      },
      "parameters": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "formal_parameters",
            "named": true
          }
        ]
      },
      "type_parameters": {
        "multiple": false,
        "required": false,
        "types": [
          {
            "type": "type_parameters",
            "named": true
          }
        ]
      }
    },
    "children": {
      "multiple": false,
      "required": false,
      "types": [
        {
          "type": "type",
          "named": true
        }
      ]
    }
  },
  {
    "type": "from_clause",
    "named": true,
    "fields": {},
    "children": {
      "multiple": false,
      "required": true,
      "types": [
        {
          "type": "identifier",
          "named": true
        },
        {
          "type": "string",
          "named": true
        }
      ]
    }
  },
  {
    "type": "function_declaration",
    "named": true,
    "fields": {
      "body": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "statement_block",
            "named": true
          }
        ]
      },
      "name": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "identifier",
            "named": true
          }
        ]
      },
      "parameters": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "formal_parameters",
            "named": true
          }
        ]
      },
      "type_parameters": {
        "multiple": false,
        "required": false,
        "types": [
          {
            "type": "type_parameters",
            "named": true
          }
        ]
      }
    },
    "children": {
      "multiple": false,
      "required": false,
      "types": [
        {
          "type": "type",
          "named": true
        }
      ]
    }
  },
  {
    "type": "function_expression",
    "named": true,
    "fields": {
      "body": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "statement_block",
            "named": true
          }
        ]
      },
      "name": {
        "multiple": false,
        "required": false,
        "types": [
          {
            "type": "identifier",
            "named": true
          }
        ]
      },
      "parameters": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "formal_parameters",
            "named": true
          }
        ]
      },
      "type_parameters": {
        "multiple": false,
        "required": false,
        "types": [
          {
            "type": "type_parameters",
            "named": true
          }
        ]
      }
    },
    "children": {
      "multiple": false,
      "required": false,
      "types": [
        {
          "type": "type",
          "named": true
        }
      ]
    }
  },
  {
    "type": "function_type",
    "named": true,
    "fields": {},
    "children": {
      "multiple": true,
      "required": true,
      "types": [
        {
          "type": "formal_parameters",
          "named": true
        },
        {
          "type": "type",
          "named": true
        },
        {
          "type": "type_parameters",
          "named": true
        }
      ]
    }
  },
  {
    "type": "generic_type",
    "named": true,
    "fields": {},
    "children": {
      "multiple": true,
      "required": true,
      "types": [
        {
          "type": "identifier",
          "named": true
        },
        {
          "type": "nested_type_identifier",
          "named": true
        },
        {
          "type": "type_arguments",
          "named": true
        }
      ]
    }
  },
  {
    "type": "if_statement",
    "named": true,
    "fields": {
      "alternative": {
        "multiple": false,
        "required": false,
        "types": [
          {
            "type": "statement",
            "named": true
          }
        ]
      },
      "condition": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "parenthesized_expression",
            "named": true
          }
        ]
      },
      "consequence": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "statement",
            "named": true
          }
        ]
      }
    }
  },
  {
    "type": "import",
    "named": true,
    "fields": {}
  },
  {
    "type": "import_clause",
    "named": true,
    "fields": {},
    "children": {
      "multiple": true,
      "required": true,
      "types": [
        {
          "type": "identifier",
          "named": true
        },
        {
          "type": "named_imports",
          "named": true
        },
        {
          "type": "namespace_import",
          "named": true
        }
      ]
    }
  },
  {
    "type": "import_specifier",
    "named": true,
    "fields": {
      "alias": {
        "multiple": false,
        "required": false,
        "types": [
          {
            "type": "identifier",
            "named": true
          }
        ]
      },
      "name": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "identifier",
            "named": true
          },
          {
            "type": "string",
            "named": true
          }
        ]
      }
    }
  },
  {
    "type": "import_statement",
    "named": true,
    "fields": {},
    "children": {
      "multiple": true,
      "required": true,
      "types": [
        {
          "type": "from_clause",
          "named": true
        },
        {
          "type": "import_clause",
          "named": true
        },
        {
          "type": "string",
          "named": true
        }
      ]
    }
  },
  {
    "type": "initializer",
    "named": true,
    "fields": {},
    "children": {
      "multiple": false,
      "required": true,
      "types": [
        {
          "type": "expression",
          "named": true
        }
      ]
    }
  },
  {
    "type": "intersection_type",
    "named": true,
    "fields": {},
    "children": {
      "multiple": true,
      "required": true,
      "types": [
        {
          "type": "type",
          "named": true
        }
      ]
    }
  },
  {
    "type": "jsx_attribute",
    "named": true,
    "fields": {
      "name": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "identifier",
            "named": true
          },
          {
            "type": "jsx_hyphenated_name",
            "named": true
          },
          {
            "type": "jsx_namespace_name",
            "named": true
          }
        ]
      },
      "value": {
        "multiple": false,
        "required": false,
        "types": [
          {
            "type": "jsx_element",
            "named": true
          },
          {
            "type": "jsx_expression",
            "named": true
          },
          {
            "type": "jsx_fragment",
            "named": true
          },
          {
            "type": "jsx_self_closing_element",
            "named": true
          },
          {
            "type": "string",
            "named": true
          }
        ]
      }
    }
  },
  {
    "type": "jsx_closing_element",
    "named": true,
    "fields": {
      "name": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "jsx_element_name",
            "named": true
          }
        ]
      }
    }
  },
  {
    "type": "jsx_closing_fragment",
    "named": true,
    "fields": {}
  },
  {
    "type": "jsx_element",
    "named": true,
    "fields": {
      "children": {
        "multiple": true,
        "required": false,
        "types": [
          {
            "type": "jsx_element",
            "named": true
          },
          {
            "type": "jsx_expression",
            "named": true
          },
          {
            "type": "jsx_fragment",
            "named": true
          },
          {
            "type": "jsx_self_closing_element",
            "named": true
          },
          {
            "type": "jsx_text",
            "named": true
          }
        ]
      },
      "close_tag": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "jsx_closing_element",
            "named": true
          }
        ]
      },
      "open_tag": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "jsx_opening_element",
            "named": true
          }
        ]
      }
    }
  },
  {
    "type": "jsx_element_name",
    "named": true,
    "fields": {},
    "children": {
      "multiple": false,
      "required": true,
      "types": [
        {
          "type": "identifier",
          "named": true
        },
        {
          "type": "jsx_member_name",
          "named": true
        },
        {
          "type": "jsx_namespace_name",
          "named": true
        },
        {
          "type": "member_expression",
          "named": true
        }
      ]
    }
  },
  {
    "type": "jsx_expression",
    "named": true,
    "fields": {},
    "children": {
      "multiple": true,
      "required": false,
      "types": [
        {
          "type": "arrow_function",
          "named": true
        },
        {
          "type": "component_statement",
          "named": true
        },
        {
          "type": "expression",
          "named": true
        },
        {
          "type": "function_expression",
          "named": true
        },
        {
          "type": "identifier",
          "named": true
        },
        {
          "type": "spread_element",
          "named": true
        },
        {
          "type": "style_directive",
          "named": true
        }
      ]
    }
  },
  {
    "type": "jsx_fragment",
    "named": true,
    "fields": {
      "children": {
        "multiple": true,
        "required": false,
        "types": [
          {
            "type": "jsx_element",
            "named": true
          },
          {
            "type": "jsx_expression",
            "named": true
          },
          {
            "type": "jsx_fragment",
            "named": true
          },
          {
            "type": "jsx_self_closing_element",
            "named": true
          },
          {
            "type": "jsx_text",
            "named": true
          }
        ]
      },
      "close_tag": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "jsx_closing_fragment",
            "named": true
          }
        ]
      },
      "open_tag": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "jsx_opening_fragment",
            "named": true
          }
        ]
      }
    }
  },
  {
    "type": "jsx_hyphenated_name",
    "named": true,
    "fields": {},
    "children": {
      "multiple": true,
      "required": true,
      "types": [
        {
          "type": "identifier",
          "named": true
        }
      ]
    }
  },
  {
    "type": "jsx_member_name",
    "named": true,
    "fields": {},
    "children": {
      "multiple": true,
      "required": true,
      "types": [
        {
          "type": "identifier",
          "named": true
        }
      ]
    }
  },
  {
    "type": "jsx_namespace_name",
    "named": true,
    "fields": {},
    "children": {
      "multiple": true,
      "required": true,
      "types": [
        {
          "type": "identifier",
          "named": true
        }
      ]
    }
  },
  {
    "type": "jsx_non_namespaced_element_name",
    "named": true,
    "fields": {},
    "children": {
      "multiple": false,
      "required": true,
      "types": [
        {
          "type": "identifier",
          "named": true
        },
        {
          "type": "jsx_member_name",
          "named": true
        },
        {
          "type": "member_expression",
          "named": true
        }
      ]
    }
  },
  {
    "type": "jsx_opening_element",
    "named": true,
    "fields": {
      "attribute": {
        "multiple": true,
        "required": false,
        "types": [
          {
            "type": "jsx_attribute",
            "named": true
          },
          {
            "type": "jsx_expression",
            "named": true
          }
        ]
      },
      "name": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "jsx_element_name",
            "named": true
          }
        ]
      }
    }
  },
  {
    "type": "jsx_opening_fragment",
    "named": true,
    "fields": {}
  },
  {
    "type": "jsx_self_closing_element",
    "named": true,
    "fields": {
      "attribute": {
        "multiple": true,
        "required": false,
        "types": [
          {
            "type": "jsx_attribute",
            "named": true
          },
          {
            "type": "jsx_expression",
            "named": true
          }
        ]
      },
      "name": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "jsx_non_namespaced_element_name",
            "named": true
          }
        ]
      }
    }
  },
  {
    "type": "labeled_statement",
    "named": true,
    "fields": {
      "body": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "statement",
            "named": true
          }
        ]
      },
      "label": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "identifier",
            "named": true
          }
        ]
      }
    }
  },
  {
    "type": "lazy_array_pattern",
    "named": true,
    "fields": {},
    "children": {
      "multiple": false,
      "required": true,
      "types": [
        {
          "type": "array_pattern",
          "named": true
        }
      ]
    }
  },
  {
    "type": "lazy_object_pattern",
    "named": true,
    "fields": {},
    "children": {
      "multiple": false,
      "required": true,
      "types": [
        {
          "type": "object_pattern",
          "named": true
        }
      ]
    }
  },
  {
    "type": "lexical_declaration",
    "named": true,
    "fields": {},
    "children": {
      "multiple": true,
      "required": true,
      "types": [
        {
          "type": "variable_declarator",
          "named": true
        }
      ]
    }
  },
  {
    "type": "literal_type",
    "named": true,
    "fields": {},
    "children": {
      "multiple": false,
      "required": true,
      "types": [
        {
          "type": "false",
          "named": true
        },
        {
          "type": "null",
          "named": true
        },
        {
          "type": "number",
          "named": true
        },
        {
          "type": "string",
          "named": true
        },
        {
          "type": "true",
          "named": true
        }
      ]
    }
  },
  {
    "type": "member_expression",
    "named": true,
    "fields": {
      "object": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "expression",
            "named": true
          }
        ]
      },
      "property": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "identifier",
            "named": true
          },
          {
            "type": "private_property_identifier",
            "named": true
          }
        ]
      }
    }
  },
  {
    "type": "method_definition",
    "named": true,
    "fields": {
      "body": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "statement_block",
            "named": true
          }
        ]
      },
      "name": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "property_name",
            "named": true
          }
        ]
      },
      "parameters": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "formal_parameters",
            "named": true
          }
        ]
      },
      "type_parameters": {
        "multiple": false,
        "required": false,
        "types": [
          {
            "type": "type_parameters",
            "named": true
          }
        ]
      }
    },
    "children": {
      "multiple": false,
      "required": false,
      "types": [
        {
          "type": "type",
          "named": true
        }
      ]
    }
  },
  {
    "type": "module_body",
    "named": true,
    "fields": {},
    "children": {
      "multiple": true,
      "required": false,
      "types": [
        {
          "type": "statement",
          "named": true
        }
      ]
    }
  },
  {
    "type": "module_declaration",
    "named": true,
    "fields": {
      "body": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "module_body",
            "named": true
          }
        ]
      },
      "name": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "identifier",
            "named": true
          }
        ]
      }
    }
  },
  {
    "type": "named_imports",
    "named": true,
    "fields": {},
    "children": {
      "multiple": true,
      "required": false,
      "types": [
        {
          "type": "import_specifier",
          "named": true
        }
      ]
    }
  },
  {
    "type": "namespace_export",
    "named": true,
    "fields": {},
    "children": {
      "multiple": false,
      "required": true,
      "types": [
        {
          "type": "identifier",
          "named": true
        }
      ]
    }
  },
  {
    "type": "namespace_import",
    "named": true,
    "fields": {},
    "children": {
      "multiple": false,
      "required": true,
      "types": [
        {
          "type": "identifier",
          "named": true
        }
      ]
    }
  },
  {
    "type": "nested_type_identifier",
    "named": true,
    "fields": {},
    "children": {
      "multiple": true,
      "required": true,
      "types": [
        {
          "type": "identifier",
          "named": true
        },
        {
          "type": "nested_type_identifier",
          "named": true
        },
        {
          "type": "type_identifier",
          "named": true
        }
      ]
    }
  },
  {
    "type": "new_expression",
    "named": true,
    "fields": {
      "arguments": {
        "multiple": false,
        "required": false,
        "types": [
          {
            "type": "arguments",
            "named": true
          }
        ]
      },
      "constructor": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "primary_expression",
            "named": true
          }
        ]
      }
    }
  },
  {
    "type": "object",
    "named": true,
    "fields": {},
    "children": {
      "multiple": true,
      "required": false,
      "types": [
        {
          "type": "method_definition",
          "named": true
        },
        {
          "type": "pair",
          "named": true
        },
        {
          "type": "shorthand_property_identifier",
          "named": true
        },
        {
          "type": "spread_element",
          "named": true
        }
      ]
    }
  },
  {
    "type": "object_assignment_pattern",
    "named": true,
    "fields": {
      "left": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "arguments",
            "named": false
          },
          {
            "type": "await",
            "named": false
          },
          {
            "type": "component",
            "named": false
          },
          {
            "type": "fragment",
            "named": false
          },
          {
            "type": "shorthand_property_identifier_pattern",
            "named": true
          },
          {
            "type": "track",
            "named": false
          },
          {
            "type": "untrack",
            "named": false
          }
        ]
      },
      "right": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "expression",
            "named": true
          }
        ]
      }
    }
  },
  {
    "type": "object_pattern",
    "named": true,
    "fields": {},
    "children": {
      "multiple": true,
      "required": false,
      "types": [
        {
          "type": "object_assignment_pattern",
          "named": true
        },
        {
          "type": "pair_pattern",
          "named": true
        },
        {
          "type": "rest_pattern",
          "named": true
        },
        {
          "type": "shorthand_property_identifier_pattern",
          "named": true
        }
      ]
    }
  },
  {
    "type": "object_type",
    "named": true,
    "fields": {},
    "children": {
      "multiple": true,
      "required": false,
      "types": [
        {
          "type": "property_signature",
          "named": true
        }
      ]
    }
  },
  {
    "type": "pair",
    "named": true,
    "fields": {
      "key": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "property_name",
            "named": true
          }
        ]
      },
      "value": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "expression",
            "named": true
          }
        ]
      }
    }
  },
  {
    "type": "pair_pattern",
    "named": true,
    "fields": {
      "key": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "property_name",
            "named": true
          }
        ]
      },
      "value": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "assignment_pattern",
            "named": true
          },
          {
            "type": "pattern",
            "named": true
          }
        ]
      }
    }
  },
  {
    "type": "parenthesized_expression",
    "named": true,
    "fields": {},
    "children": {
      "multiple": false,
      "required": true,
      "types": [
        {
          "type": "expression",
          "named": true
        }
      ]
    }
  },
  {
    "type": "parenthesized_type",
    "named": true,
    "fields": {},
    "children": {
      "multiple": false,
      "required": true,
      "types": [
        {
          "type": "type",
          "named": true
        }
      ]
    }
  },
  {
    "type": "pending_clause",
    "named": true,
    "fields": {
      "body": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "statement_block",
            "named": true
          }
        ]
      }
    }
  },
  {
    "type": "predefined_type",
    "named": true,
    "fields": {}
  },
  {
    "type": "program",
    "named": true,
    "root": true,
    "fields": {},
    "children": {
      "multiple": true,
      "required": false,
      "types": [
        {
          "type": "hash_bang_line",
          "named": true
        },
        {
          "type": "statement",
          "named": true
        }
      ]
    }
  },
  {
    "type": "property_name",
    "named": true,
    "fields": {},
    "children": {
      "multiple": false,
      "required": true,
      "types": [
        {
          "type": "computed_property_name",
          "named": true
        },
        {
          "type": "identifier",
          "named": true
        },
        {
          "type": "number",
          "named": true
        },
        {
          "type": "private_property_identifier",
          "named": true
        },
        {
          "type": "string",
          "named": true
        }
      ]
    }
  },
  {
    "type": "property_signature",
    "named": true,
    "fields": {
      "name": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "property_name",
            "named": true
          }
        ]
      }
    },
    "children": {
      "multiple": false,
      "required": true,
      "types": [
        {
          "type": "type",
          "named": true
        }
      ]
    }
  },
  {
    "type": "regex",
    "named": true,
    "fields": {
      "flags": {
        "multiple": false,
        "required": false,
        "types": [
          {
            "type": "regex_flags",
            "named": true
          }
        ]
      },
      "pattern": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "regex_pattern",
            "named": true
          }
        ]
      }
    }
  },
  {
    "type": "required_parameter",
    "named": true,
    "fields": {
      "pattern": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "array_pattern",
            "named": true
          },
          {
            "type": "identifier",
            "named": true
          },
          {
            "type": "lazy_array_pattern",
            "named": true
          },
          {
            "type": "lazy_object_pattern",
            "named": true
          },
          {
            "type": "object_pattern",
            "named": true
          }
        ]
      }
    },
    "children": {
      "multiple": true,
      "required": false,
      "types": [
        {
          "type": "initializer",
          "named": true
        },
        {
          "type": "type",
          "named": true
        }
      ]
    }
  },
  {
    "type": "rest_parameter",
    "named": true,
    "fields": {},
    "children": {
      "multiple": true,
      "required": true,
      "types": [
        {
          "type": "identifier",
          "named": true
        },
        {
          "type": "type",
          "named": true
        }
      ]
    }
  },
  {
    "type": "rest_pattern",
    "named": true,
    "fields": {},
    "children": {
      "multiple": false,
      "required": true,
      "types": [
        {
          "type": "identifier",
          "named": true
        }
      ]
    }
  },
  {
    "type": "return_statement",
    "named": true,
    "fields": {},
    "children": {
      "multiple": false,
      "required": false,
      "types": [
        {
          "type": "expression",
          "named": true
        }
      ]
    }
  },
  {
    "type": "shorthand_property_identifier",
    "named": true,
    "fields": {},
    "children": {
      "multiple": false,
      "required": false,
      "types": [
        {
          "type": "shorthand_property_identifier_pattern",
          "named": true
        }
      ]
    }
  },
  {
    "type": "shorthand_property_identifier_pattern",
    "named": true,
    "fields": {},
    "children": {
      "multiple": false,
      "required": false,
      "types": [
        {
          "type": "shorthand_property_identifier",
          "named": true
        }
      ]
    }
  },
  {
    "type": "spread_element",
    "named": true,
    "fields": {},
    "children": {
      "multiple": false,
      "required": true,
      "types": [
        {
          "type": "expression",
          "named": true
        }
      ]
    }
  },
  {
    "type": "statement_block",
    "named": true,
    "fields": {},
    "children": {
      "multiple": true,
      "required": false,
      "types": [
        {
          "type": "statement",
          "named": true
        }
      ]
    }
  },
  {
    "type": "string",
    "named": true,
    "fields": {},
    "children": {
      "multiple": true,
      "required": false,
      "types": [
        {
          "type": "escape_sequence",
          "named": true
        }
      ]
    }
  },
  {
    "type": "style_directive",
    "named": true,
    "fields": {},
    "children": {
      "multiple": false,
      "required": true,
      "types": [
        {
          "type": "string",
          "named": true
        }
      ]
    }
  },
  {
    "type": "style_element",
    "named": true,
    "fields": {},
    "children": {
      "multiple": true,
      "required": false,
      "types": [
        {
          "type": "jsx_attribute",
          "named": true
        },
        {
          "type": "jsx_expression",
          "named": true
        },
        {
          "type": "raw_text",
          "named": true
        }
      ]
    }
  },
  {
    "type": "subscript_expression",
    "named": true,
    "fields": {
      "index": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "expression",
            "named": true
          }
        ]
      },
      "object": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "expression",
            "named": true
          }
        ]
      }
    }
  },
  {
    "type": "switch_body",
    "named": true,
    "fields": {},
    "children": {
      "multiple": true,
      "required": false,
      "types": [
        {
          "type": "switch_case",
          "named": true
        },
        {
          "type": "switch_default",
          "named": true
        }
      ]
    }
  },
  {
    "type": "switch_case",
    "named": true,
    "fields": {
      "value": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "expression",
            "named": true
          }
        ]
      }
    },
    "children": {
      "multiple": true,
      "required": false,
      "types": [
        {
          "type": "statement",
          "named": true
        }
      ]
    }
  },
  {
    "type": "switch_default",
    "named": true,
    "fields": {},
    "children": {
      "multiple": true,
      "required": false,
      "types": [
        {
          "type": "statement",
          "named": true
        }
      ]
    }
  },
  {
    "type": "switch_statement",
    "named": true,
    "fields": {
      "body": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "switch_body",
            "named": true
          }
        ]
      },
      "value": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "parenthesized_expression",
            "named": true
          }
        ]
      }
    }
  },
  {
    "type": "template_string",
    "named": true,
    "fields": {},
    "children": {
      "multiple": true,
      "required": false,
      "types": [
        {
          "type": "template_substitution",
          "named": true
        }
      ]
    }
  },
  {
    "type": "template_substitution",
    "named": true,
    "fields": {},
    "children": {
      "multiple": false,
      "required": true,
      "types": [
        {
          "type": "expression",
          "named": true
        }
      ]
    }
  },
  {
    "type": "ternary_expression",
    "named": true,
    "fields": {
      "alternative": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "expression",
            "named": true
          }
        ]
      },
      "condition": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "expression",
            "named": true
          }
        ]
      },
      "consequence": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "expression",
            "named": true
          }
        ]
      }
    }
  },
  {
    "type": "throw_statement",
    "named": true,
    "fields": {},
    "children": {
      "multiple": false,
      "required": true,
      "types": [
        {
          "type": "expression",
          "named": true
        }
      ]
    }
  },
  {
    "type": "try_statement",
    "named": true,
    "fields": {
      "body": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "statement_block",
            "named": true
          }
        ]
      },
      "finalizer": {
        "multiple": false,
        "required": false,
        "types": [
          {
            "type": "finally_clause",
            "named": true
          }
        ]
      },
      "handler": {
        "multiple": false,
        "required": false,
        "types": [
          {
            "type": "catch_clause",
            "named": true
          }
        ]
      },
      "pending": {
        "multiple": false,
        "required": false,
        "types": [
          {
            "type": "pending_clause",
            "named": true
          }
        ]
      }
    }
  },
  {
    "type": "tuple_type",
    "named": true,
    "fields": {},
    "children": {
      "multiple": true,
      "required": true,
      "types": [
        {
          "type": "type",
          "named": true
        }
      ]
    }
  },
  {
    "type": "type",
    "named": true,
    "fields": {},
    "children": {
      "multiple": false,
      "required": true,
      "types": [
        {
          "type": "array_type",
          "named": true
        },
        {
          "type": "function_type",
          "named": true
        },
        {
          "type": "generic_type",
          "named": true
        },
        {
          "type": "identifier",
          "named": true
        },
        {
          "type": "intersection_type",
          "named": true
        },
        {
          "type": "literal_type",
          "named": true
        },
        {
          "type": "nested_type_identifier",
          "named": true
        },
        {
          "type": "object_type",
          "named": true
        },
        {
          "type": "parenthesized_type",
          "named": true
        },
        {
          "type": "predefined_type",
          "named": true
        },
        {
          "type": "tuple_type",
          "named": true
        },
        {
          "type": "type_identifier",
          "named": true
        },
        {
          "type": "union_type",
          "named": true
        }
      ]
    }
  },
  {
    "type": "type_arguments",
    "named": true,
    "fields": {},
    "children": {
      "multiple": true,
      "required": true,
      "types": [
        {
          "type": "type",
          "named": true
        }
      ]
    }
  },
  {
    "type": "type_identifier",
    "named": true,
    "fields": {},
    "children": {
      "multiple": false,
      "required": false,
      "types": [
        {
          "type": "type_identifier",
          "named": true
        }
      ]
    }
  },
  {
    "type": "type_parameter",
    "named": true,
    "fields": {},
    "children": {
      "multiple": true,
      "required": true,
      "types": [
        {
          "type": "identifier",
          "named": true
        },
        {
          "type": "type",
          "named": true
        }
      ]
    }
  },
  {
    "type": "type_parameters",
    "named": true,
    "fields": {},
    "children": {
      "multiple": true,
      "required": true,
      "types": [
        {
          "type": "type_parameter",
          "named": true
        }
      ]
    }
  },
  {
    "type": "unary_expression",
    "named": true,
    "fields": {
      "argument": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "expression",
            "named": true
          }
        ]
      },
      "operator": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "!",
            "named": false
          },
          {
            "type": "+",
            "named": false
          },
          {
            "type": "-",
            "named": false
          },
          {
            "type": "delete",
            "named": false
          },
          {
            "type": "typeof",
            "named": false
          },
          {
            "type": "void",
            "named": false
          },
          {
            "type": "~",
            "named": false
          }
        ]
      }
    }
  },
  {
    "type": "union_type",
    "named": true,
    "fields": {},
    "children": {
      "multiple": true,
      "required": true,
      "types": [
        {
          "type": "type",
          "named": true
        }
      ]
    }
  },
  {
    "type": "update_expression",
    "named": true,
    "fields": {
      "argument": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "expression",
            "named": true
          }
        ]
      },
      "operator": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "++",
            "named": false
          },
          {
            "type": "--",
            "named": false
          }
        ]
      }
    }
  },
  {
    "type": "variable_declaration",
    "named": true,
    "fields": {},
    "children": {
      "multiple": true,
      "required": true,
      "types": [
        {
          "type": "variable_declarator",
          "named": true
        }
      ]
    }
  },
  {
    "type": "variable_declarator",
    "named": true,
    "fields": {
      "name": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "array_pattern",
            "named": true
          },
          {
            "type": "identifier",
            "named": true
          },
          {
            "type": "lazy_array_pattern",
            "named": true
          },
          {
            "type": "lazy_object_pattern",
            "named": true
          },
          {
            "type": "object_pattern",
            "named": true
          }
        ]
      }
    },
    "children": {
      "multiple": true,
      "required": false,
      "types": [
        {
          "type": "initializer",
          "named": true
        },
        {
          "type": "type",
          "named": true
        }
      ]
    }
  },
  {
    "type": "while_statement",
    "named": true,
    "fields": {
      "body": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "statement",
            "named": true
          }
        ]
      },
      "condition": {
        "multiple": false,
        "required": true,
        "types": [
          {
            "type": "parenthesized_expression",
            "named": true
          }
        ]
      }
    }
  },
  {
    "type": "yield_expression",
    "named": true,
    "fields": {},
    "children": {
      "multiple": false,
      "required": false,
      "types": [
        {
          "type": "expression",
          "named": true
        }
      ]
    }
  },
  {
    "type": "!",
    "named": false
  },
  {
    "type": "!=",
    "named": false
  },
  {
    "type": "!==",
    "named": false
  },
  {
    "type": "\"",
    "named": false
  },
  {
    "type": "${",
    "named": false
  },
  {
    "type": "%",
    "named": false
  },
  {
    "type": "%=",
    "named": false
  },
  {
    "type": "&",
    "named": false
  },
  {
    "type": "&&",
    "named": false
  },
  {
    "type": "&&=",
    "named": false
  },
  {
    "type": "&=",
    "named": false
  },
  {
    "type": "'",
    "named": false
  },
  {
    "type": "(",
    "named": false
  },
  {
    "type": ")",
    "named": false
  },
  {
    "type": "*",
    "named": false
  },
  {
    "type": "**",
    "named": false
  },
  {
    "type": "**=",
    "named": false
  },
  {
    "type": "*=",
    "named": false
  },
  {
    "type": "+",
    "named": false
  },
  {
    "type": "++",
    "named": false
  },
  {
    "type": "+=",
    "named": false
  },
  {
    "type": ",",
    "named": false
  },
  {
    "type": "-",
    "named": false
  },
  {
    "type": "--",
    "named": false
  },
  {
    "type": "-=",
    "named": false
  },
  {
    "type": ".",
    "named": false
  },
  {
    "type": "...",
    "named": false
  },
  {
    "type": "/",
    "named": false
  },
  {
    "type": "/=",
    "named": false
  },
  {
    "type": "/>",
    "named": false
  },
  {
    "type": ":",
    "named": false
  },
  {
    "type": ";",
    "named": false
  },
  {
    "type": "<",
    "named": false
  },
  {
    "type": "</",
    "named": false
  },
  {
    "type": "</style>",
    "named": false
  },
  {
    "type": "<<",
    "named": false
  },
  {
    "type": "<<=",
    "named": false
  },
  {
    "type": "<=",
    "named": false
  },
  {
    "type": "<style",
    "named": false
  },
  {
    "type": "=",
    "named": false
  },
  {
    "type": "==",
    "named": false
  },
  {
    "type": "===",
    "named": false
  },
  {
    "type": "=>",
    "named": false
  },
  {
    "type": ">",
    "named": false
  },
  {
    "type": ">=",
    "named": false
  },
  {
    "type": ">>",
    "named": false
  },
  {
    "type": ">>=",
    "named": false
  },
  {
    "type": ">>>",
    "named": false
  },
  {
    "type": ">>>=",
    "named": false
  },
  {
    "type": "?",
    "named": false
  },
  {
    "type": "?.",
    "named": false
  },
  {
    "type": "??",
    "named": false
  },
  {
    "type": "??=",
    "named": false
  },
  {
    "type": "@",
    "named": false
  },
  {
    "type": "[",
    "named": false
  },
  {
    "type": "]",
    "named": false
  },
  {
    "type": "^",
    "named": false
  },
  {
    "type": "^=",
    "named": false
  },
  {
    "type": "`",
    "named": false
  },
  {
    "type": "abstract",
    "named": false
  },
  {
    "type": "any",
    "named": false
  },
  {
    "type": "arguments",
    "named": false
  },
  {
    "type": "as",
    "named": false
  },
  {
    "type": "async",
    "named": false
  },
  {
    "type": "await",
    "named": false
  },
  {
    "type": "boolean",
    "named": false
  },
  {
    "type": "break",
    "named": false
  },
  {
    "type": "case",
    "named": false
  },
  {
    "type": "catch",
    "named": false
  },
  {
    "type": "class",
    "named": false
  },
  {
    "type": "comment",
    "named": true,
    "extra": true
  },
  {
    "type": "component",
    "named": false
  },
  {
    "type": "const",
    "named": false
  },
  {
    "type": "continue",
    "named": false
  },
  {
    "type": "debugger",
    "named": false
  },
  {
    "type": "declare",
    "named": false
  },
  {
    "type": "default",
    "named": false
  },
  {
    "type": "delete",
    "named": false
  },
  {
    "type": "do",
    "named": false
  },
  {
    "type": "else",
    "named": false
  },
  {
    "type": "escape_sequence",
    "named": true
  },
  {
    "type": "export",
    "named": false
  },
  {
    "type": "extends",
    "named": false
  },
  {
    "type": "false",
    "named": true
  },
  {
    "type": "finally",
    "named": false
  },
  {
    "type": "for",
    "named": false
  },
  {
    "type": "fragment",
    "named": false
  },
  {
    "type": "from",
    "named": false
  },
  {
    "type": "function",
    "named": false
  },
  {
    "type": "get",
    "named": false
  },
  {
    "type": "hash_bang_line",
    "named": true
  },
  {
    "type": "html",
    "named": false
  },
  {
    "type": "identifier",
    "named": true
  },
  {
    "type": "if",
    "named": false
  },
  {
    "type": "implements",
    "named": false
  },
  {
    "type": "import",
    "named": false
  },
  {
    "type": "in",
    "named": false
  },
  {
    "type": "index",
    "named": false
  },
  {
    "type": "instanceof",
    "named": false
  },
  {
    "type": "jsx_text",
    "named": true
  },
  {
    "type": "key",
    "named": false
  },
  {
    "type": "let",
    "named": false
  },
  {
    "type": "module",
    "named": false
  },
  {
    "type": "never",
    "named": false
  },
  {
    "type": "new",
    "named": false
  },
  {
    "type": "null",
    "named": true
  },
  {
    "type": "number",
    "named": false
  },
  {
    "type": "number",
    "named": true
  },
  {
    "type": "object",
    "named": false
  },
  {
    "type": "of",
    "named": false
  },
  {
    "type": "override",
    "named": false
  },
  {
    "type": "pending",
    "named": false
  },
  {
    "type": "private_property_identifier",
    "named": true
  },
  {
    "type": "raw_text",
    "named": true
  },
  {
    "type": "readonly",
    "named": false
  },
  {
    "type": "ref",
    "named": false
  },
  {
    "type": "regex_flags",
    "named": true
  },
  {
    "type": "regex_pattern",
    "named": true
  },
  {
    "type": "return",
    "named": false
  },
  {
    "type": "set",
    "named": false
  },
  {
    "type": "static",
    "named": false
  },
  {
    "type": "string",
    "named": false
  },
  {
    "type": "style",
    "named": false
  },
  {
    "type": "super",
    "named": true
  },
  {
    "type": "switch",
    "named": false
  },
  {
    "type": "symbol",
    "named": false
  },
  {
    "type": "text",
    "named": false
  },
  {
    "type": "this",
    "named": true
  },
  {
    "type": "throw",
    "named": false
  },
  {
    "type": "track",
    "named": false
  },
  {
    "type": "true",
    "named": true
  },
  {
    "type": "try",
    "named": false
  },
  {
    "type": "type",
    "named": false
  },
  {
    "type": "typeof",
    "named": false
  },
  {
    "type": "undefined",
    "named": true
  },
  {
    "type": "unknown",
    "named": false
  },
  {
    "type": "untrack",
    "named": false
  },
  {
    "type": "var",
    "named": false
  },
  {
    "type": "void",
    "named": false
  },
  {
    "type": "while",
    "named": false
  },
  {
    "type": "yield",
    "named": false
  },
  {
    "type": "{",
    "named": false
  },
  {
    "type": "|",
    "named": false
  },
  {
    "type": "|=",
    "named": false
  },
  {
    "type": "||",
    "named": false
  },
  {
    "type": "||=",
    "named": false
  },
  {
    "type": "}",
    "named": false
  },
  {
    "type": "~",
    "named": false
  }
]

```

## /grammars/tree-sitter/src/scanner.c

```c path="/grammars/tree-sitter/src/scanner.c" 
#include <tree_sitter/parser.h>
#include <wctype.h>

enum TokenType {
  AUTOMATIC_SEMICOLON,
  TEMPLATE_CHARS,
  TERNARY_QMARK,
  JSX_TEXT,
};

void *tree_sitter_ripple_external_scanner_create() { return NULL; }
void tree_sitter_ripple_external_scanner_destroy(void *p) {}
void tree_sitter_ripple_external_scanner_reset(void *p) {}
unsigned tree_sitter_ripple_external_scanner_serialize(void *p, char *buffer) { return 0; }
void tree_sitter_ripple_external_scanner_deserialize(void *p, const char *b, unsigned n) {}

static void advance(TSLexer *lexer) { lexer->advance(lexer, false); }
static void skip(TSLexer *lexer) { lexer->advance(lexer, true); }

static bool scan_whitespace_and_comments(TSLexer *lexer) {
  for (;;) {
    while (iswspace(lexer->lookahead)) {
      skip(lexer);
    }

    if (lexer->lookahead == '/') {
      skip(lexer);

      if (lexer->lookahead == '/') {
        skip(lexer);
        while (lexer->lookahead != 0 && lexer->lookahead != '\n') {
          skip(lexer);
        }
      } else if (lexer->lookahead == '*') {
        skip(lexer);
        while (true) {
          if (lexer->lookahead == 0) return false;
          if (lexer->lookahead == '*') {
            skip(lexer);
            if (lexer->lookahead == '/') {
              skip(lexer);
              break;
            }
          } else {
            skip(lexer);
          }
        }
      } else {
        return false;
      }
    } else {
      return true;
    }
  }
}

static bool scan_automatic_semicolon(TSLexer *lexer) {
  lexer->result_symbol = AUTOMATIC_SEMICOLON;
  lexer->mark_end(lexer);

  for (;;) {
    if (lexer->lookahead == 0) return true;
    if (lexer->lookahead == '}') return true;
    if (lexer->is_at_included_range_start(lexer)) return true;
    if (lexer->lookahead == '\n') break;
    if (!iswspace(lexer->lookahead)) return false;
    skip(lexer);
  }

  skip(lexer);

  if (!scan_whitespace_and_comments(lexer)) return false;

  if (lexer->lookahead == ',') return false;
  if (lexer->lookahead == '.') return false;
  if (lexer->lookahead == ':') return false;
  if (lexer->lookahead == ';') return false;
  if (lexer->lookahead == '*') return false;
  if (lexer->lookahead == '%') return false;
  if (lexer->lookahead == '^') return false;
  if (lexer->lookahead == '+') return false;
  if (lexer->lookahead == '-') return false;
  if (lexer->lookahead == '/') return false;
  if (lexer->lookahead == '<') return false;
  if (lexer->lookahead == '=') return false;
  if (lexer->lookahead == '>') return false;
  if (lexer->lookahead == '|') return false;
  if (lexer->lookahead == '&') return false;
  if (lexer->lookahead == '?') return false;
  if (lexer->lookahead == '[') return false;
  if (lexer->lookahead == '(') return false;

  return true;
}

static bool scan_template_chars(TSLexer *lexer) {
  lexer->result_symbol = TEMPLATE_CHARS;
  for (bool has_content = false;; has_content = true) {
    lexer->mark_end(lexer);
    switch (lexer->lookahead) {
      case '`':
        return has_content;
      case '{{contextString}}#39;:
        advance(lexer);
        if (lexer->lookahead == '{') {
          return has_content;
        }
        break;
      case '\\':
        return has_content;
      case 0:
        return false;
      default:
        advance(lexer);
    }
  }
}

static bool scan_ternary_qmark(TSLexer *lexer) {
  for (;;) {
    if (!iswspace(lexer->lookahead)) break;
    skip(lexer);
  }

  if (lexer->lookahead == '?') {
    advance(lexer);

    if (lexer->lookahead != '?') {
      lexer->mark_end(lexer);
      lexer->result_symbol = TERNARY_QMARK;

      if (lexer->lookahead == '.') return false;

      return true;
    }
  }

  return false;
}

static bool scan_jsx_text(TSLexer *lexer) {
  lexer->result_symbol = JSX_TEXT;
  for (bool has_content = false;; has_content = true) {
    lexer->mark_end(lexer);
    switch (lexer->lookahead) {
      case '<':
      case '{':
      case 0:
        return has_content;
      default:
        advance(lexer);
    }
  }
}

bool tree_sitter_ripple_external_scanner_scan(void *payload, TSLexer *lexer,
                                                const bool *valid_symbols) {
  if (valid_symbols[TEMPLATE_CHARS]) {
    return scan_template_chars(lexer);
  }

  if (valid_symbols[AUTOMATIC_SEMICOLON]) {
    bool ret = scan_automatic_semicolon(lexer);
    if (!ret && !valid_symbols[TERNARY_QMARK] && lexer->lookahead == '?') {
      return false;
    }
    return ret;
  }

  if (valid_symbols[TERNARY_QMARK]) {
    return scan_ternary_qmark(lexer);
  }

  if (valid_symbols[JSX_TEXT]) {
    return scan_jsx_text(lexer);
  }

  return false;
}


```

## /grammars/tree-sitter/src/tree_sitter/alloc.h

```h path="/grammars/tree-sitter/src/tree_sitter/alloc.h" 
#ifndef TREE_SITTER_ALLOC_H_
#define TREE_SITTER_ALLOC_H_

#ifdef __cplusplus
extern "C" {
#endif

#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>

// Allow clients to override allocation functions
#ifdef TREE_SITTER_REUSE_ALLOCATOR

extern void *(*ts_current_malloc)(size_t size);
extern void *(*ts_current_calloc)(size_t count, size_t size);
extern void *(*ts_current_realloc)(void *ptr, size_t size);
extern void (*ts_current_free)(void *ptr);

#ifndef ts_malloc
#define ts_malloc  ts_current_malloc
#endif
#ifndef ts_calloc
#define ts_calloc  ts_current_calloc
#endif
#ifndef ts_realloc
#define ts_realloc ts_current_realloc
#endif
#ifndef ts_free
#define ts_free    ts_current_free
#endif

#else

#ifndef ts_malloc
#define ts_malloc  malloc
#endif
#ifndef ts_calloc
#define ts_calloc  calloc
#endif
#ifndef ts_realloc
#define ts_realloc realloc
#endif
#ifndef ts_free
#define ts_free    free
#endif

#endif

#ifdef __cplusplus
}
#endif

#endif // TREE_SITTER_ALLOC_H_

```

## /grammars/tree-sitter/src/tree_sitter/array.h

```h path="/grammars/tree-sitter/src/tree_sitter/array.h" 
#ifndef TREE_SITTER_ARRAY_H_
#define TREE_SITTER_ARRAY_H_

#ifdef __cplusplus
extern "C" {
#endif

#include "./alloc.h"

#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>

#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4101)
#elif defined(__GNUC__) || defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-variable"
#endif

#define Array(T)       \
  struct {             \
    T *contents;       \
    uint32_t size;     \
    uint32_t capacity; \
  }

/// Initialize an array.
#define array_init(self) \
  ((self)->size = 0, (self)->capacity = 0, (self)->contents = NULL)

/// Create an empty array.
#define array_new() \
  { NULL, 0, 0 }

/// Get a pointer to the element at a given `index` in the array.
#define array_get(self, _index) \
  (assert((uint32_t)(_index) < (self)->size), &(self)->contents[_index])

/// Get a pointer to the first element in the array.
#define array_front(self) array_get(self, 0)

/// Get a pointer to the last element in the array.
#define array_back(self) array_get(self, (self)->size - 1)

/// Clear the array, setting its size to zero. Note that this does not free any
/// memory allocated for the array's contents.
#define array_clear(self) ((self)->size = 0)

/// Reserve `new_capacity` elements of space in the array. If `new_capacity` is
/// less than the array's current capacity, this function has no effect.
#define array_reserve(self, new_capacity)        \
  ((self)->contents = _array__reserve(           \
    (void *)(self)->contents, &(self)->capacity, \
    array_elem_size(self), new_capacity)         \
  )

/// Free any memory allocated for this array. Note that this does not free any
/// memory allocated for the array's contents.
#define array_delete(self)                           \
  do {                                               \
    if ((self)->contents) ts_free((self)->contents); \
    (self)->contents = NULL;                         \
    (self)->size = 0;                                \
    (self)->capacity = 0;                            \
  } while (0)

/// Push a new `element` onto the end of the array.
#define array_push(self, element)                                 \
  do {                                                            \
    (self)->contents = _array__grow(                              \
      (void *)(self)->contents, (self)->size, &(self)->capacity,  \
      1, array_elem_size(self)                                    \
    );                                                            \
   (self)->contents[(self)->size++] = (element);                  \
  } while(0)

/// Increase the array's size by `count` elements.
/// New elements are zero-initialized.
#define array_grow_by(self, count)                                               \
  do {                                                                           \
    if ((count) == 0) break;                                                     \
    (self)->contents = _array__grow(                                             \
      (self)->contents, (self)->size, &(self)->capacity,                         \
      count, array_elem_size(self)                                               \
    );                                                                           \
    memset((self)->contents + (self)->size, 0, (count) * array_elem_size(self)); \
    (self)->size += (count);                                                     \
  } while (0)

/// Append all elements from one array to the end of another.
#define array_push_all(self, other) \
  array_extend((self), (other)->size, (other)->contents)

/// Append `count` elements to the end of the array, reading their values from the
/// `contents` pointer.
#define array_extend(self, count, other_contents)                 \
  (self)->contents = _array__splice(                              \
    (void*)(self)->contents, &(self)->size, &(self)->capacity,    \
    array_elem_size(self), (self)->size, 0, count, other_contents \
  )

/// Remove `old_count` elements from the array starting at the given `index`. At
/// the same index, insert `new_count` new elements, reading their values from the
/// `new_contents` pointer.
#define array_splice(self, _index, old_count, new_count, new_contents) \
  (self)->contents = _array__splice(                                   \
    (void *)(self)->contents, &(self)->size, &(self)->capacity,        \
    array_elem_size(self), _index, old_count, new_count, new_contents  \
  )

/// Insert one `element` into the array at the given `index`.
#define array_insert(self, _index, element)                     \
  (self)->contents = _array__splice(                            \
    (void *)(self)->contents, &(self)->size, &(self)->capacity, \
    array_elem_size(self), _index, 0, 1, &(element)             \
  )

/// Remove one element from the array at the given `index`.
#define array_erase(self, _index) \
  _array__erase((void *)(self)->contents, &(self)->size, array_elem_size(self), _index)

/// Pop the last element off the array, returning the element by value.
#define array_pop(self) ((self)->contents[--(self)->size])

/// Assign the contents of one array to another, reallocating if necessary.
#define array_assign(self, other)                                   \
  (self)->contents = _array__assign(                                \
    (void *)(self)->contents, &(self)->size, &(self)->capacity,     \
    (const void *)(other)->contents, (other)->size, array_elem_size(self) \
  )

/// Swap one array with another
#define array_swap(self, other)                                     \
  do {                                                              \
    void *_array_swap_tmp = (void *)(self)->contents;               \
    (self)->contents = (other)->contents;                           \
    (other)->contents = _array_swap_tmp;                            \
    _array__swap(&(self)->size, &(self)->capacity,                  \
                 &(other)->size, &(other)->capacity);               \
  } while (0)

/// Get the size of the array contents
#define array_elem_size(self) (sizeof *(self)->contents)

/// Search a sorted array for a given `needle` value, using the given `compare`
/// callback to determine the order.
///
/// If an existing element is found to be equal to `needle`, then the `index`
/// out-parameter is set to the existing value's index, and the `exists`
/// out-parameter is set to true. Otherwise, `index` is set to an index where
/// `needle` should be inserted in order to preserve the sorting, and `exists`
/// is set to false.
#define array_search_sorted_with(self, compare, needle, _index, _exists) \
  _array__search_sorted(self, 0, compare, , needle, _index, _exists)

/// Search a sorted array for a given `needle` value, using integer comparisons
/// of a given struct field (specified with a leading dot) to determine the order.
///
/// See also `array_search_sorted_with`.
#define array_search_sorted_by(self, field, needle, _index, _exists) \
  _array__search_sorted(self, 0, _compare_int, field, needle, _index, _exists)

/// Insert a given `value` into a sorted array, using the given `compare`
/// callback to determine the order.
#define array_insert_sorted_with(self, compare, value) \
  do { \
    unsigned _index, _exists; \
    array_search_sorted_with(self, compare, &(value), &_index, &_exists); \
    if (!_exists) array_insert(self, _index, value); \
  } while (0)

/// Insert a given `value` into a sorted array, using integer comparisons of
/// a given struct field (specified with a leading dot) to determine the order.
///
/// See also `array_search_sorted_by`.
#define array_insert_sorted_by(self, field, value) \
  do { \
    unsigned _index, _exists; \
    array_search_sorted_by(self, field, (value) field, &_index, &_exists); \
    if (!_exists) array_insert(self, _index, value); \
  } while (0)

// Private

// Pointers to individual `Array` fields (rather than the entire `Array` itself)
// are passed to the various `_array__*` functions below to address strict aliasing
// violations that arises when the _entire_ `Array` struct is passed as `Array(void)*`.
//
// The `Array` type itself was not altered as a solution in order to avoid breakage
// with existing consumers (in particular, parsers with external scanners).

/// This is not what you're looking for, see `array_erase`.
static inline void _array__erase(void* self_contents, uint32_t *size,
                                size_t element_size, uint32_t index) {
  assert(index < *size);
  char *contents = (char *)self_contents;
  memmove(contents + index * element_size, contents + (index + 1) * element_size,
          (*size - index - 1) * element_size);
  (*size)--;
}

/// This is not what you're looking for, see `array_reserve`.
static inline void *_array__reserve(void *contents, uint32_t *capacity,
                                  size_t element_size, uint32_t new_capacity) {
  void *new_contents = contents;
  if (new_capacity > *capacity) {
    if (contents) {
      new_contents = ts_realloc(contents, new_capacity * element_size);
    } else {
      new_contents = ts_malloc(new_capacity * element_size);
    }
    *capacity = new_capacity;
  }
  return new_contents;
}

/// This is not what you're looking for, see `array_assign`.
static inline void *_array__assign(void* self_contents, uint32_t *self_size, uint32_t *self_capacity,
                                 const void *other_contents, uint32_t other_size, size_t element_size) {
  void *new_contents = _array__reserve(self_contents, self_capacity, element_size, other_size);
  *self_size = other_size;
  memcpy(new_contents, other_contents, *self_size * element_size);
  return new_contents;
}

/// This is not what you're looking for, see `array_swap`.
static inline void _array__swap(uint32_t *self_size, uint32_t *self_capacity,
                               uint32_t *other_size, uint32_t *other_capacity) {
  uint32_t tmp_size = *self_size;
  uint32_t tmp_capacity = *self_capacity;
  *self_size = *other_size;
  *self_capacity = *other_capacity;
  *other_size = tmp_size;
  *other_capacity = tmp_capacity;
}

/// This is not what you're looking for, see `array_push` or `array_grow_by`.
static inline void *_array__grow(void *contents, uint32_t size, uint32_t *capacity,
                               uint32_t count, size_t element_size) {
  void *new_contents = contents;
  uint32_t new_size = size + count;
  if (new_size > *capacity) {
    uint32_t new_capacity = *capacity * 2;
    if (new_capacity < 8) new_capacity = 8;
    if (new_capacity < new_size) new_capacity = new_size;
    new_contents = _array__reserve(contents, capacity, element_size, new_capacity);
  }
  return new_contents;
}

/// This is not what you're looking for, see `array_splice`.
static inline void *_array__splice(void *self_contents, uint32_t *size, uint32_t *capacity,
                                 size_t element_size,
                                 uint32_t index, uint32_t old_count,
                                 uint32_t new_count, const void *elements) {
  uint32_t new_size = *size + new_count - old_count;
  uint32_t old_end = index + old_count;
  uint32_t new_end = index + new_count;
  assert(old_end <= *size);

  void *new_contents = _array__reserve(self_contents, capacity, element_size, new_size);

  char *contents = (char *)new_contents;
  if (*size > old_end) {
    memmove(
      contents + new_end * element_size,
      contents + old_end * element_size,
      (*size - old_end) * element_size
    );
  }
  if (new_count > 0) {
    if (elements) {
      memcpy(
        (contents + index * element_size),
        elements,
        new_count * element_size
      );
    } else {
      memset(
        (contents + index * element_size),
        0,
        new_count * element_size
      );
    }
  }
  *size += new_count - old_count;

  return new_contents;
}

/// A binary search routine, based on Rust's `std::slice::binary_search_by`.
/// This is not what you're looking for, see `array_search_sorted_with` or `array_search_sorted_by`.
#define _array__search_sorted(self, start, compare, suffix, needle, _index, _exists) \
  do { \
    *(_index) = start; \
    *(_exists) = false; \
    uint32_t size = (self)->size - *(_index); \
    if (size == 0) break; \
    int comparison; \
    while (size > 1) { \
      uint32_t half_size = size / 2; \
      uint32_t mid_index = *(_index) + half_size; \
      comparison = compare(&((self)->contents[mid_index] suffix), (needle)); \
      if (comparison <= 0) *(_index) = mid_index; \
      size -= half_size; \
    } \
    comparison = compare(&((self)->contents[*(_index)] suffix), (needle)); \
    if (comparison == 0) *(_exists) = true; \
    else if (comparison < 0) *(_index) += 1; \
  } while (0)

/// Helper macro for the `_sorted_by` routines below. This takes the left (existing)
/// parameter by reference in order to work with the generic sorting function above.
#define _compare_int(a, b) ((int)*(a) - (int)(b))

#ifdef _MSC_VER
#pragma warning(pop)
#elif defined(__GNUC__) || defined(__clang__)
#pragma GCC diagnostic pop
#endif

#ifdef __cplusplus
}
#endif

#endif  // TREE_SITTER_ARRAY_H_

```

## /grammars/tree-sitter/test/corpus/components.txt

==================
Component Declaration
==================

component Button(props: { text: string }) {
  <button>{props.text}</button>
}

---

(program
  (component_declaration
    name: (identifier)
    parameters: (formal_parameters
      (required_parameter
        pattern: (identifier)
        (type
          (object_type
            (property_signature
              name: (property_name
                (identifier))
              (type
                (predefined_type)))))))
    body: (component_body
      (component_statement
        (expression_statement
          (jsx_element
            open_tag: (jsx_opening_element
              name: (jsx_element_name
                (identifier)))
            children: (jsx_expression
              (component_statement
                (expression_statement
                  (member_expression
                    object: (identifier)
                    property: (identifier)))))
            close_tag: (jsx_closing_element
              name: (jsx_element_name
                (identifier)))))))))

==================
Export Component
==================

export component App() {
  <div>{'Hello World'}</div>
}

---

(program
  (export_statement
    (component_declaration
      name: (identifier)
      parameters: (formal_parameters)
      body: (component_body
        (component_statement
          (expression_statement
            (jsx_element
              open_tag: (jsx_opening_element
                name: (jsx_element_name
                  (identifier)))
              children: (jsx_expression
                (component_statement
                  (expression_statement
                    (string))))
              close_tag: (jsx_closing_element
                name: (jsx_element_name
                  (identifier))))))))))

==================
Fragment Declaration
==================

fragment ListItems(props: { items: Array<string> }) {
  for (const item of props.items) {
    <li>{item}</li>
  }
}

---

(program
  (fragment_declaration
    name: (identifier)
    parameters: (formal_parameters
      (required_parameter
        pattern: (identifier)
        (type
          (object_type
            (property_signature
              name: (property_name
                (identifier))
              (type
                (generic_type
                  (identifier)
                  (type_arguments
                    (type
                      (predefined_type))))))))))
    body: (component_body
      (component_statement
        (for_of_statement
          (identifier)
          right: (member_expression
            object: (identifier)
            property: (identifier))
          body: (statement_block
            (expression_statement
              (jsx_element
                open_tag: (jsx_opening_element
                  name: (jsx_element_name
                    (identifier)))
                children: (jsx_expression
                  (component_statement
                    (expression_statement
                      (identifier))))
                close_tag: (jsx_closing_element
                  name: (jsx_element_name
                    (identifier)))))))))))

==================
Children Prop
==================

component Card({ children }) {
  <div class="card">
    {children}
  </div>
}

---

(program
  (component_declaration
    name: (identifier)
    parameters: (formal_parameters
      (required_parameter
        pattern: (object_pattern
          (shorthand_property_identifier_pattern
            (shorthand_property_identifier)))))
    body: (component_body
      (component_statement
        (expression_statement
          (jsx_element
            open_tag: (jsx_opening_element
              name: (jsx_element_name
                (identifier))
              attribute: (jsx_attribute
                name: (identifier)
                value: (string)))
            children: (jsx_text)
            children: (jsx_expression
              (component_statement
                (expression_statement
                  (identifier))))
            children: (jsx_text)
            close_tag: (jsx_closing_element
              name: (jsx_element_name
                (identifier)))))))))


## /grammars/tree-sitter/test/corpus/main.txt



## /grammars/tree-sitter/test/corpus/reactivity.txt

==================
Ripple Server Module Import And Style Directive
==================

module server {
  export const data = () => null;
}
import { data as serverData } from server;
const element = <Child className={style 'button'} />;

---

(program
  (module_declaration
    name: (identifier)
    body: (module_body
      (export_statement
        (variable_declaration
          (variable_declarator
            name: (identifier)
            (initializer
              (arrow_function
                parameters: (formal_parameters)
                body: (null))))))))
  (import_statement
    (import_clause
      (named_imports
        (import_specifier
          name: (identifier)
          alias: (identifier))))
    (from_clause
      (identifier)))
  (variable_declaration
    (variable_declarator
      name: (identifier)
      (initializer
        (jsx_self_closing_element
          name: (jsx_non_namespaced_element_name
            (identifier))
          attribute: (jsx_attribute
            name: (identifier)
            value: (jsx_expression
              (style_directive
                (string)))))))))


## /grammars/tree-sitter/tree-sitter.json

```json path="/grammars/tree-sitter/tree-sitter.json" 
{
  "$schema": "https://tree-sitter.github.io/tree-sitter/assets/schemas/config.schema.json",
  "grammars": [
    {
      "name": "ripple",
      "camelcase": "Ripple",
      "title": "Ripple",
      "scope": "source.tsrx",
      "file-types": ["ripple"],
      "injection-regex": "^ripple{{contextString}}quot;,
      "class-name": "TreeSitterRipple"
    }
  ],
  "metadata": {
    "version": "0.1.0",
    "license": "MIT",
    "description": "Ripple grammar for tree-sitter",
    "authors": [
      {
        "name": "Ripple"
      }
    ],
    "links": {
      "repository": "https://github.com/trueadm/ripple/grammars/tree-sitter"
    }
  },
  "bindings": {
    "c": false,
    "go": false,
    "node": true,
    "python": false,
    "rust": true,
    "swift": false,
    "zig": false
  }
}

```

## /packages/adapter-bun/package.json

```json path="/packages/adapter-bun/package.json" 
{
  "name": "@ripple-ts/adapter-bun",
  "description": "Bun adapter for Ripple metaframework (Web Request/Response bridge)",
  "license": "MIT",
  "author": "Dominic Gannaway",
  "version": "0.3.61",
  "type": "module",
  "module": "src/index.js",
  "main": "src/index.js",
  "exports": {
    ".": {
      "types": "./types/index.d.ts",
      "import": "./src/index.js",
      "default": "./src/index.js"
    }
  },
  "scripts": {
    "test": "pnpm -w test --project adapter-bun"
  },
  "dependencies": {
    "@ripple-ts/adapter": "workspace:*"
  },
  "devDependencies": {
    "@types/bun": "catalog:default"
  },
  "homepage": "https://ripple-ts.com",
  "repository": {
    "type": "git",
    "url": "git+https://github.com/Ripple-TS/ripple.git",
    "directory": "packages/adapter-bun"
  },
  "peerDependencies": {
    "bun": "^1.0.0"
  },
  "bugs": {
    "url": "https://github.com/Ripple-TS/ripple/issues"
  }
}

```

## /packages/create-ripple/src/index.js

```js path="/packages/create-ripple/src/index.js" 
#!/usr/bin/env node
import '@ripple-ts/cli';

```


The content has been capped at 50000 tokens. The user could consider applying other filters to refine the result. The better and more specific the context, the better the LLM can follow instructions. If the context seems verbose, the user can refine the filter using uithub. Thank you for using https://uithub.com - Perfect LLM context for any GitHub repo.
Copied!