Copy disabled (too large)
Download .txt
Showing preview only (10,236K chars total). Download the full file to get everything.
Repository: Ripple-TS/ripple
Branch: main
Commit: 25396085c05a
Files: 733
Total size: 29.1 MB
Directory structure:
gitextract_7ext8lh9/
├── .changeset/
│ ├── README.md
│ ├── config.json
│ ├── large-snails-crash.md
│ └── tame-snails-sneeze.md
├── .cursor/
│ ├── environment.json
│ ├── install.sh
│ └── rules/
│ └── project.mdc
├── .editorconfig
├── .gitattributes
├── .github/
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug-report.yml
│ │ ├── config.yml
│ │ └── feature-request.yml
│ ├── agents/
│ │ └── ripple.agent.md
│ ├── copilot-instructions.md
│ └── workflows/
│ ├── ci.yml
│ ├── copilot-setup-steps.yml
│ ├── livecodes-post-comment.yml
│ ├── livecodes-preview.yml
│ ├── pkg.pr.new.yml
│ ├── provenance.yml
│ ├── release.yml
│ ├── rulesync.yml
│ ├── vsix-manual.yml
│ └── vsix.yml
├── .gitignore
├── .livecodes/
│ └── playground.json
├── .prettierignore
├── .prettierrc
├── .rulesync/
│ └── rules/
│ └── project.md
├── .vscode/
│ ├── launch.json
│ ├── settings.json
│ └── tasks.json
├── AGENTS.md
├── CLAUDE.md
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── GEMINI.md
├── LICENSE
├── README.md
├── assets/
│ └── Ripple.tmbundle/
│ ├── README.md
│ ├── Syntaxes/
│ │ └── ripple.tmLanguage
│ └── info.plist
├── grammars/
│ ├── textmate/
│ │ ├── info.plist
│ │ └── ripple.tmLanguage.json
│ └── tree-sitter/
│ ├── .gitignore
│ ├── Cargo.toml
│ ├── LICENSE
│ ├── README.md
│ ├── binding.gyp
│ ├── bindings/
│ │ └── node/
│ │ └── binding.cc
│ ├── grammar.js
│ ├── package.json
│ ├── queries/
│ │ ├── brackets.scm
│ │ ├── folds.scm
│ │ ├── highlights.scm
│ │ ├── indents.nvim.scm
│ │ ├── indents.scm
│ │ ├── indents.zed.scm
│ │ ├── injections.scm
│ │ ├── locals.scm
│ │ ├── outline.scm
│ │ └── textobjects.scm
│ ├── src/
│ │ ├── grammar.json
│ │ ├── node-types.json
│ │ ├── parser.c
│ │ ├── scanner.c
│ │ └── tree_sitter/
│ │ ├── alloc.h
│ │ ├── array.h
│ │ └── parser.h
│ ├── test/
│ │ └── corpus/
│ │ ├── components.txt
│ │ ├── control-flow.txt
│ │ ├── javascript.txt
│ │ ├── jsx.txt
│ │ ├── main.txt
│ │ └── reactivity.txt
│ └── tree-sitter.json
├── package.json
├── packages/
│ ├── adapter/
│ │ ├── CHANGELOG.md
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── index.js
│ │ │ └── rpc.js
│ │ ├── tests/
│ │ │ ├── index.test.js
│ │ │ └── types.test.js
│ │ ├── tsconfig.json
│ │ └── types/
│ │ ├── index.d.ts
│ │ └── rpc.d.ts
│ ├── adapter-bun/
│ │ ├── CHANGELOG.md
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── src/
│ │ │ └── index.js
│ │ ├── tests/
│ │ │ ├── serve.test.js
│ │ │ └── types.test.js
│ │ ├── tsconfig.json
│ │ └── types/
│ │ └── index.d.ts
│ ├── adapter-node/
│ │ ├── CHANGELOG.md
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── src/
│ │ │ └── index.js
│ │ ├── tests/
│ │ │ ├── serve.test.js
│ │ │ └── types.test.js
│ │ ├── tsconfig.json
│ │ └── types/
│ │ └── index.d.ts
│ ├── adapter-vercel/
│ │ ├── CHANGELOG.md
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── adapt.js
│ │ │ ├── bin/
│ │ │ │ └── adapt.js
│ │ │ └── index.js
│ │ ├── tests/
│ │ │ ├── adapt.test.js
│ │ │ └── types.test.js
│ │ ├── tsconfig.json
│ │ └── types/
│ │ └── index.d.ts
│ ├── cli/
│ │ ├── CHANGELOG.md
│ │ ├── LICENSE
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── commands/
│ │ │ │ └── create.js
│ │ │ ├── constants.js
│ │ │ ├── index.js
│ │ │ └── lib/
│ │ │ ├── is-folder-empty.js
│ │ │ ├── package-manager.js
│ │ │ ├── project-creator.js
│ │ │ ├── prompts.js
│ │ │ ├── templates.js
│ │ │ └── validation.js
│ │ ├── tests/
│ │ │ ├── integration/
│ │ │ │ ├── cli.test.js
│ │ │ │ └── project-creator.test.js
│ │ │ └── unit/
│ │ │ ├── prompts.test.js
│ │ │ ├── templates.test.js
│ │ │ └── validation.test.js
│ │ ├── tsconfig.json
│ │ ├── tsdown.config.js
│ │ └── vitest.config.js
│ ├── compat-react/
│ │ ├── CHANGELOG.md
│ │ ├── LICENSE
│ │ ├── package.json
│ │ ├── src/
│ │ │ └── index.js
│ │ ├── tests/
│ │ │ ├── client.d.ts
│ │ │ ├── index.test.ripple
│ │ │ └── setup.js
│ │ ├── tsconfig.json
│ │ └── types/
│ │ └── index.d.ts
│ ├── create-ripple/
│ │ ├── CHANGELOG.md
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── src/
│ │ │ └── index.js
│ │ ├── tsconfig.json
│ │ └── tsdown.config.js
│ ├── eslint-parser/
│ │ ├── .npmignore
│ │ ├── CHANGELOG.md
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── index.ts
│ │ │ └── loader.ts
│ │ ├── tsconfig.json
│ │ └── tsdown.config.js
│ ├── eslint-plugin/
│ │ ├── .npmignore
│ │ ├── CHANGELOG.md
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── index.ts
│ │ │ └── rules/
│ │ │ ├── control-flow-jsx.ts
│ │ │ ├── no-introspect-in-modules.ts
│ │ │ ├── no-module-scope-track.ts
│ │ │ ├── no-return-in-component.ts
│ │ │ ├── prefer-oninput.ts
│ │ │ ├── unbox-tracked-values.ts
│ │ │ └── valid-for-of-key.ts
│ │ ├── tests/
│ │ │ └── rules/
│ │ │ ├── control-flow-jsx.test.ts
│ │ │ ├── no-introspect-in-modules.test.ts
│ │ │ ├── no-module-scope-track.test.ts
│ │ │ ├── no-return-in-component.test.ts
│ │ │ ├── prefer-oninput.test.ts
│ │ │ ├── unbox-tracked-values.test.ts
│ │ │ └── valid-for-of-key.test.ts
│ │ ├── tsconfig.json
│ │ ├── tsdown.config.js
│ │ └── vitest.config.ts
│ ├── intellij-plugin/
│ │ ├── .gitignore
│ │ ├── README.md
│ │ ├── build.gradle.kts
│ │ ├── gradle/
│ │ │ └── wrapper/
│ │ │ ├── gradle-wrapper.jar
│ │ │ └── gradle-wrapper.properties
│ │ ├── gradle.properties
│ │ ├── gradlew
│ │ ├── gradlew.bat
│ │ ├── package.json
│ │ ├── settings.gradle.kts
│ │ └── src/
│ │ └── main/
│ │ ├── kotlin/
│ │ │ └── com/
│ │ │ └── ripple_ts/
│ │ │ └── intellij_plugin/
│ │ │ ├── RippleCommenter.kt
│ │ │ ├── RippleFileType.kt
│ │ │ ├── RippleIcons.kt
│ │ │ ├── RippleLanguage.kt
│ │ │ ├── RippleLanguageServer.kt
│ │ │ ├── RippleLspServerDescriptor.kt
│ │ │ ├── RippleLspServerSupportProvider.kt
│ │ │ └── RippleTextMateBundleProvider.kt
│ │ └── resources/
│ │ ├── META-INF/
│ │ │ ├── plugin.xml
│ │ │ └── ripple-lsp.xml
│ │ └── lsp-version.txt
│ ├── language-server/
│ │ ├── CHANGELOG.md
│ │ ├── LICENSE
│ │ ├── README.md
│ │ ├── bin/
│ │ │ └── language-server.js
│ │ ├── index.js
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── autoInsertPlugin.js
│ │ │ ├── compileErrorDiagnosticPlugin.js
│ │ │ ├── completionPlugin.js
│ │ │ ├── definitionPlugin.js
│ │ │ ├── documentHighlightPlugin.js
│ │ │ ├── hoverPlugin.js
│ │ │ ├── server.js
│ │ │ ├── typescriptDiagnosticPlugin.js
│ │ │ ├── typescriptService.js
│ │ │ └── utils.js
│ │ └── tsconfig.json
│ ├── nvim-plugin/
│ │ ├── LICENSE
│ │ ├── README.md
│ │ ├── lua/
│ │ │ └── ripple/
│ │ │ ├── init.lua
│ │ │ ├── lsp.lua
│ │ │ └── treesitter.lua
│ │ ├── package.json
│ │ ├── plugin/
│ │ │ └── ripple.lua
│ │ └── queries/
│ │ └── ripple/
│ │ ├── brackets.scm
│ │ ├── folds.scm
│ │ ├── highlights.scm
│ │ ├── indents.scm
│ │ ├── injections.scm
│ │ ├── locals.scm
│ │ ├── outline.scm
│ │ └── textobjects.scm
│ ├── prettier-plugin/
│ │ ├── CHANGELOG.md
│ │ ├── LICENSE
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── index.js
│ │ │ └── index.test.js
│ │ ├── tsconfig.json
│ │ └── vitest-extensions.d.ts
│ ├── ripple/
│ │ ├── CHANGELOG.md
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── shims/
│ │ │ └── rollup-estree-types.d.ts
│ │ ├── src/
│ │ │ ├── compiler/
│ │ │ │ ├── comment-utils.js
│ │ │ │ ├── errors.js
│ │ │ │ ├── identifier-utils.js
│ │ │ │ ├── index.d.ts
│ │ │ │ ├── index.js
│ │ │ │ ├── phases/
│ │ │ │ │ ├── 1-parse/
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ └── style.js
│ │ │ │ │ ├── 2-analyze/
│ │ │ │ │ │ ├── css-analyze.js
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ ├── prune.js
│ │ │ │ │ │ └── validation.js
│ │ │ │ │ └── 3-transform/
│ │ │ │ │ ├── client/
│ │ │ │ │ │ └── index.js
│ │ │ │ │ ├── segments.js
│ │ │ │ │ ├── server/
│ │ │ │ │ │ └── index.js
│ │ │ │ │ └── stylesheet.js
│ │ │ │ ├── scope.js
│ │ │ │ ├── source-map-utils.js
│ │ │ │ ├── types/
│ │ │ │ │ ├── acorn.d.ts
│ │ │ │ │ ├── estree-jsx.d.ts
│ │ │ │ │ ├── estree.d.ts
│ │ │ │ │ ├── import.d.ts
│ │ │ │ │ ├── index.d.ts
│ │ │ │ │ ├── parse.d.ts
│ │ │ │ │ └── rpc.d.ts
│ │ │ │ └── utils.js
│ │ │ ├── constants.js
│ │ │ ├── helpers.d.ts
│ │ │ ├── html-tree-validation.js
│ │ │ ├── jsx-runtime.d.ts
│ │ │ ├── jsx-runtime.js
│ │ │ ├── runtime/
│ │ │ │ ├── array.js
│ │ │ │ ├── create-subscriber.js
│ │ │ │ ├── date.js
│ │ │ │ ├── index-client.js
│ │ │ │ ├── index-server.js
│ │ │ │ ├── internal/
│ │ │ │ │ ├── client/
│ │ │ │ │ │ ├── bindings.js
│ │ │ │ │ │ ├── blocks.js
│ │ │ │ │ │ ├── compat.js
│ │ │ │ │ │ ├── composite.js
│ │ │ │ │ │ ├── constants.js
│ │ │ │ │ │ ├── context.js
│ │ │ │ │ │ ├── css.js
│ │ │ │ │ │ ├── events.js
│ │ │ │ │ │ ├── for.js
│ │ │ │ │ │ ├── head.js
│ │ │ │ │ │ ├── hmr.js
│ │ │ │ │ │ ├── html.js
│ │ │ │ │ │ ├── hydration.js
│ │ │ │ │ │ ├── if.js
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ ├── operations.js
│ │ │ │ │ │ ├── portal.js
│ │ │ │ │ │ ├── render.js
│ │ │ │ │ │ ├── rpc.js
│ │ │ │ │ │ ├── runtime.js
│ │ │ │ │ │ ├── script.js
│ │ │ │ │ │ ├── switch.js
│ │ │ │ │ │ ├── template.js
│ │ │ │ │ │ ├── try.js
│ │ │ │ │ │ ├── types.d.ts
│ │ │ │ │ │ └── utils.js
│ │ │ │ │ └── server/
│ │ │ │ │ ├── context.js
│ │ │ │ │ ├── css-registry.js
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── rpc.js
│ │ │ │ │ └── types.d.ts
│ │ │ │ ├── map.js
│ │ │ │ ├── media-query.js
│ │ │ │ ├── object.js
│ │ │ │ ├── proxy.js
│ │ │ │ ├── reactive-value.js
│ │ │ │ ├── set.js
│ │ │ │ ├── url-search-params.js
│ │ │ │ └── url.js
│ │ │ ├── server/
│ │ │ │ └── index.js
│ │ │ └── utils/
│ │ │ ├── ast.js
│ │ │ ├── builders.js
│ │ │ ├── escaping.js
│ │ │ ├── events.js
│ │ │ ├── hashing.js
│ │ │ ├── normalize_css_property_name.js
│ │ │ ├── patterns.js
│ │ │ └── sanitize_template_string.js
│ │ ├── tests/
│ │ │ ├── client/
│ │ │ │ ├── __snapshots__/
│ │ │ │ │ ├── computed-properties.test.ripple.snap
│ │ │ │ │ ├── for.test.ripple.snap
│ │ │ │ │ ├── html.test.ripple.snap
│ │ │ │ │ └── tracked-expression.test.ripple.snap
│ │ │ │ ├── _etc.test.ripple
│ │ │ │ ├── array/
│ │ │ │ │ ├── array.copy-within.test.ripple
│ │ │ │ │ ├── array.derived.test.ripple
│ │ │ │ │ ├── array.iteration.test.ripple
│ │ │ │ │ ├── array.mutations.test.ripple
│ │ │ │ │ ├── array.static.test.ripple
│ │ │ │ │ └── array.to-methods.test.ripple
│ │ │ │ ├── async-suspend.test.ripple
│ │ │ │ ├── basic/
│ │ │ │ │ ├── __snapshots__/
│ │ │ │ │ │ ├── basic.attributes.test.ripple.snap
│ │ │ │ │ │ ├── basic.rendering.test.ripple.snap
│ │ │ │ │ │ └── basic.text.test.ripple.snap
│ │ │ │ │ ├── basic.attributes.test.ripple
│ │ │ │ │ ├── basic.collections.test.ripple
│ │ │ │ │ ├── basic.components.test.ripple
│ │ │ │ │ ├── basic.errors.test.ripple
│ │ │ │ │ ├── basic.events.test.ripple
│ │ │ │ │ ├── basic.get-set.test.ripple
│ │ │ │ │ ├── basic.hmr.test.ripple
│ │ │ │ │ ├── basic.reactivity.test.ripple
│ │ │ │ │ ├── basic.rendering.test.ripple
│ │ │ │ │ ├── basic.styling.test.ripple
│ │ │ │ │ └── basic.utilities.test.ripple
│ │ │ │ ├── boundaries.test.ripple
│ │ │ │ ├── compiler/
│ │ │ │ │ ├── __snapshots__/
│ │ │ │ │ │ ├── compiler.assignments.test.ripple.snap
│ │ │ │ │ │ └── compiler.typescript.test.ripple.snap
│ │ │ │ │ ├── compiler.assignments.test.ripple
│ │ │ │ │ ├── compiler.attributes.test.ripple
│ │ │ │ │ ├── compiler.basic.test.ripple
│ │ │ │ │ ├── compiler.regex.test.ripple
│ │ │ │ │ ├── compiler.tracked-access.test.ripple
│ │ │ │ │ ├── compiler.try-in-function.test.ripple
│ │ │ │ │ └── compiler.typescript.test.ripple
│ │ │ │ ├── composite/
│ │ │ │ │ ├── __snapshots__/
│ │ │ │ │ │ └── composite.render.test.ripple.snap
│ │ │ │ │ ├── composite.dynamic-components.test.ripple
│ │ │ │ │ ├── composite.generics.test.ripple
│ │ │ │ │ ├── composite.props.test.ripple
│ │ │ │ │ ├── composite.reactivity.test.ripple
│ │ │ │ │ └── composite.render.test.ripple
│ │ │ │ ├── computed-properties.test.ripple
│ │ │ │ ├── context.test.ripple
│ │ │ │ ├── css/
│ │ │ │ │ ├── global-additional-cases.test.ripple
│ │ │ │ │ ├── global-advanced-selectors.test.ripple
│ │ │ │ │ ├── global-at-rules.test.ripple
│ │ │ │ │ ├── global-basic.test.ripple
│ │ │ │ │ ├── global-classes-ids.test.ripple
│ │ │ │ │ ├── global-combinators.test.ripple
│ │ │ │ │ ├── global-complex-nesting.test.ripple
│ │ │ │ │ ├── global-edge-cases.test.ripple
│ │ │ │ │ ├── global-keyframes.test.ripple
│ │ │ │ │ ├── global-nested.test.ripple
│ │ │ │ │ ├── global-pseudo.test.ripple
│ │ │ │ │ ├── global-scoping.test.ripple
│ │ │ │ │ └── style-identifier.test.ripple
│ │ │ │ ├── date.test.ripple
│ │ │ │ ├── dynamic-elements.test.ripple
│ │ │ │ ├── events.test.ripple
│ │ │ │ ├── for.test.ripple
│ │ │ │ ├── function-overload-import.ripple
│ │ │ │ ├── function-overload.test.ripple
│ │ │ │ ├── head.test.ripple
│ │ │ │ ├── html.test.ripple
│ │ │ │ ├── input-value.test.ripple
│ │ │ │ ├── map.test.ripple
│ │ │ │ ├── media-query.test.ripple
│ │ │ │ ├── object.test.ripple
│ │ │ │ ├── portal.test.ripple
│ │ │ │ ├── ref.test.ripple
│ │ │ │ ├── return.test.ripple
│ │ │ │ ├── set.test.ripple
│ │ │ │ ├── svg.test.ripple
│ │ │ │ ├── switch.test.ripple
│ │ │ │ ├── tracked-expression.test.ripple
│ │ │ │ ├── try.test.ripple
│ │ │ │ ├── tsconfig.json
│ │ │ │ ├── typescript-generics.test.ripple
│ │ │ │ ├── url/
│ │ │ │ │ ├── url.derived.test.ripple
│ │ │ │ │ ├── url.parsing.test.ripple
│ │ │ │ │ ├── url.partial-removal.test.ripple
│ │ │ │ │ ├── url.reactivity.test.ripple
│ │ │ │ │ └── url.serialization.test.ripple
│ │ │ │ └── url-search-params/
│ │ │ │ ├── url-search-params.derived.test.ripple
│ │ │ │ ├── url-search-params.initialization.test.ripple
│ │ │ │ ├── url-search-params.iteration.test.ripple
│ │ │ │ ├── url-search-params.mutation.test.ripple
│ │ │ │ ├── url-search-params.retrieval.test.ripple
│ │ │ │ ├── url-search-params.serialization.test.ripple
│ │ │ │ └── url-search-params.tracked-url.test.ripple
│ │ │ ├── client.d.ts
│ │ │ ├── common.d.ts
│ │ │ ├── hydration/
│ │ │ │ ├── basic.test.js
│ │ │ │ ├── build-components.js
│ │ │ │ ├── compiled/
│ │ │ │ │ ├── client/
│ │ │ │ │ │ ├── basic.js
│ │ │ │ │ │ ├── composite.js
│ │ │ │ │ │ ├── events.js
│ │ │ │ │ │ ├── for.js
│ │ │ │ │ │ ├── head.js
│ │ │ │ │ │ ├── hmr.js
│ │ │ │ │ │ ├── html-in-template.js
│ │ │ │ │ │ ├── html.js
│ │ │ │ │ │ ├── if-children.js
│ │ │ │ │ │ ├── if.js
│ │ │ │ │ │ ├── mixed-control-flow.js
│ │ │ │ │ │ ├── nested-control-flow.js
│ │ │ │ │ │ ├── portal.js
│ │ │ │ │ │ ├── reactivity.js
│ │ │ │ │ │ ├── return.js
│ │ │ │ │ │ ├── switch.js
│ │ │ │ │ │ └── try.js
│ │ │ │ │ └── server/
│ │ │ │ │ ├── basic.js
│ │ │ │ │ ├── composite.js
│ │ │ │ │ ├── events.js
│ │ │ │ │ ├── for.js
│ │ │ │ │ ├── head.js
│ │ │ │ │ ├── hmr.js
│ │ │ │ │ ├── html-in-template.js
│ │ │ │ │ ├── html.js
│ │ │ │ │ ├── if-children.js
│ │ │ │ │ ├── if.js
│ │ │ │ │ ├── mixed-control-flow.js
│ │ │ │ │ ├── nested-control-flow.js
│ │ │ │ │ ├── portal.js
│ │ │ │ │ ├── reactivity.js
│ │ │ │ │ ├── return.js
│ │ │ │ │ ├── switch.js
│ │ │ │ │ └── try.js
│ │ │ │ ├── components/
│ │ │ │ │ ├── basic.ripple
│ │ │ │ │ ├── composite.ripple
│ │ │ │ │ ├── events.ripple
│ │ │ │ │ ├── for.ripple
│ │ │ │ │ ├── head.ripple
│ │ │ │ │ ├── hmr.ripple
│ │ │ │ │ ├── html-in-template.ripple
│ │ │ │ │ ├── html.ripple
│ │ │ │ │ ├── if-children.ripple
│ │ │ │ │ ├── if.ripple
│ │ │ │ │ ├── mixed-control-flow.ripple
│ │ │ │ │ ├── nested-control-flow.ripple
│ │ │ │ │ ├── portal.ripple
│ │ │ │ │ ├── reactivity.ripple
│ │ │ │ │ ├── return.ripple
│ │ │ │ │ ├── switch.ripple
│ │ │ │ │ └── try.ripple
│ │ │ │ ├── composite.test.js
│ │ │ │ ├── events.test.js
│ │ │ │ ├── for.test.js
│ │ │ │ ├── head.test.js
│ │ │ │ ├── hmr.test.js
│ │ │ │ ├── html-in-template.test.js
│ │ │ │ ├── html.test.js
│ │ │ │ ├── if-children.test.js
│ │ │ │ ├── if.test.js
│ │ │ │ ├── mixed-control-flow.test.js
│ │ │ │ ├── nested-control-flow.test.js
│ │ │ │ ├── portal.test.js
│ │ │ │ ├── reactivity.test.js
│ │ │ │ ├── return.test.js
│ │ │ │ ├── switch.test.js
│ │ │ │ ├── try.test.js
│ │ │ │ └── tsconfig.json
│ │ │ ├── hydration.d.ts
│ │ │ ├── server/
│ │ │ │ ├── __snapshots__/
│ │ │ │ │ └── compiler.test.ripple.snap
│ │ │ │ ├── await.test.ripple
│ │ │ │ ├── basic.attributes.test.ripple
│ │ │ │ ├── basic.components.test.ripple
│ │ │ │ ├── basic.test.ripple
│ │ │ │ ├── compiler.test.ripple
│ │ │ │ ├── composite.props.test.ripple
│ │ │ │ ├── composite.test.ripple
│ │ │ │ ├── context.test.ripple
│ │ │ │ ├── dynamic-elements.test.ripple
│ │ │ │ ├── for.test.ripple
│ │ │ │ ├── head.test.ripple
│ │ │ │ ├── html-nesting-validation.test.ripple
│ │ │ │ ├── if.test.ripple
│ │ │ │ ├── return.test.ripple
│ │ │ │ ├── streaming-ssr.test.ripple
│ │ │ │ ├── style-identifier.test.ripple
│ │ │ │ ├── switch.test.ripple
│ │ │ │ ├── try.test.ripple
│ │ │ │ └── tsconfig.json
│ │ │ ├── server.d.ts
│ │ │ ├── setup-client.js
│ │ │ ├── setup-hydration.js
│ │ │ ├── setup-server.js
│ │ │ └── utils/
│ │ │ ├── escaping.test.js
│ │ │ ├── events.test.js
│ │ │ ├── normalize_css_property_name.test.js
│ │ │ ├── patterns.test.js
│ │ │ └── sanitize_template_string.test.js
│ │ ├── tsconfig.json
│ │ └── types/
│ │ ├── index.d.ts
│ │ └── server.d.ts
│ ├── rollup-plugin/
│ │ ├── CHANGELOG.md
│ │ ├── LICENSE
│ │ ├── index.js
│ │ ├── package.json
│ │ └── tsconfig.json
│ ├── sublime-text-plugin/
│ │ ├── .gitignore
│ │ ├── package.json
│ │ ├── scripts/
│ │ │ └── build.js
│ │ └── src/
│ │ ├── .python-version
│ │ ├── Ripple.sublime-settings
│ │ ├── dependencies.json
│ │ ├── language-server/
│ │ │ └── package.json
│ │ └── plugin.py
│ ├── tree-sitter/
│ │ └── build/
│ │ ├── Makefile
│ │ ├── Release/
│ │ │ ├── .deps/
│ │ │ │ └── Release/
│ │ │ │ ├── obj.target/
│ │ │ │ │ └── tree_sitter_ripple_binding/
│ │ │ │ │ ├── bindings/
│ │ │ │ │ │ └── node/
│ │ │ │ │ │ └── binding.o.d
│ │ │ │ │ └── src/
│ │ │ │ │ ├── parser.o.d
│ │ │ │ │ └── scanner.o.d
│ │ │ │ └── tree_sitter_ripple_binding.node.d
│ │ │ ├── obj.target/
│ │ │ │ └── tree_sitter_ripple_binding/
│ │ │ │ ├── bindings/
│ │ │ │ │ └── node/
│ │ │ │ │ └── binding.o
│ │ │ │ └── src/
│ │ │ │ ├── parser.o
│ │ │ │ └── scanner.o
│ │ │ └── tree_sitter_ripple_binding.node
│ │ ├── binding.Makefile
│ │ ├── config.gypi
│ │ ├── gyp-mac-tool
│ │ └── tree_sitter_ripple_binding.target.mk
│ ├── typescript-plugin/
│ │ ├── CHANGELOG.md
│ │ ├── LICENSE
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── index.js
│ │ │ ├── language.js
│ │ │ └── utils.js
│ │ ├── tsconfig.json
│ │ └── tsdown.config.js
│ ├── vite-plugin/
│ │ ├── CHANGELOG.md
│ │ ├── LICENSE
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── bin/
│ │ │ │ └── preview.js
│ │ │ ├── constants.js
│ │ │ ├── index.js
│ │ │ ├── load-config.js
│ │ │ ├── routes.js
│ │ │ └── server/
│ │ │ ├── middleware.js
│ │ │ ├── production.js
│ │ │ ├── render-route.js
│ │ │ ├── router.js
│ │ │ ├── server-route.js
│ │ │ └── virtual-entry.js
│ │ ├── tsconfig.json
│ │ └── types/
│ │ ├── index.d.ts
│ │ └── production.d.ts
│ ├── vscode-plugin/
│ │ ├── .gitignore
│ │ ├── .vscodeignore
│ │ ├── CHANGELOG.md
│ │ ├── LICENSE
│ │ ├── README.md
│ │ ├── language-configuration.json
│ │ ├── package.json
│ │ ├── scripts/
│ │ │ └── repack-vsix.js
│ │ ├── src/
│ │ │ ├── extension.js
│ │ │ └── server.js
│ │ ├── tsconfig.json
│ │ └── tsdown.config.js
│ └── zed-plugin/
│ ├── .gitignore
│ ├── Cargo.toml
│ ├── DEVELOPMENT.md
│ ├── LICENSE
│ ├── README.md
│ ├── extension.toml
│ ├── languages/
│ │ └── ripple/
│ │ ├── brackets.scm
│ │ ├── config.toml
│ │ ├── folds.scm
│ │ ├── highlights.scm
│ │ ├── indents.scm
│ │ ├── injections.scm
│ │ ├── locals.scm
│ │ ├── outline.scm
│ │ └── textobjects.scm
│ ├── package.json
│ └── src/
│ └── lib.rs
├── playground/
│ ├── CHANGELOG.md
│ ├── debug-mode.js
│ ├── demo.css
│ ├── eslint.config.js
│ ├── index.html
│ ├── package.json
│ ├── ssr-dev.js
│ ├── tsconfig.json
│ └── vite.config.js
├── pnpm-workspace.yaml
├── rulesync.jsonc
├── scripts/
│ ├── collect-external-deps.js
│ ├── copy-external-deps.js
│ ├── copy-tree-sitter-queries.js
│ ├── regenerate-textmate.js
│ ├── remove.js
│ └── transform-package.js
├── templates/
│ └── basic/
│ ├── .gitignore
│ ├── .prettierignore
│ ├── .prettierrc
│ ├── README.md
│ ├── eslint.config.js
│ ├── index.html
│ ├── package.json
│ ├── src/
│ │ ├── App.ripple
│ │ └── index.ts
│ ├── tsconfig.json
│ └── vite.config.js
├── tree-sitter
├── vitest.config.js
├── website/
│ ├── .vitepress/
│ │ ├── components/
│ │ │ ├── Code.vue
│ │ │ ├── LiveCodes.vue
│ │ │ ├── Playground.vue
│ │ │ └── PlaygroundProps.ts
│ │ ├── config.js
│ │ └── theme/
│ │ ├── index.js
│ │ └── styles.css
│ ├── docs/
│ │ ├── best-practices.md
│ │ ├── comparison.md
│ │ ├── examples.ts
│ │ ├── guide/
│ │ │ ├── application.md
│ │ │ ├── bindings.md
│ │ │ ├── components.md
│ │ │ ├── control-flow.md
│ │ │ ├── dom-refs.md
│ │ │ ├── events.md
│ │ │ ├── head-management.md
│ │ │ ├── reactivity.md
│ │ │ ├── state-management.md
│ │ │ ├── styling.md
│ │ │ └── syntax.md
│ │ ├── introduction.md
│ │ ├── libraries.md
│ │ ├── quick-start.md
│ │ └── troubleshooting.md
│ ├── package.json
│ ├── playground.md
│ ├── public/
│ │ ├── 404.html
│ │ ├── index.html
│ │ ├── llms.txt
│ │ ├── robots.txt
│ │ └── sitemap.xml
│ └── vercel.json
└── website-new/
├── CHANGELOG.md
├── api/
│ └── handler.js
├── docs/
│ ├── best-practices.md
│ ├── comparison.md
│ ├── examples.ts
│ ├── guide/
│ │ ├── application.md
│ │ ├── bindings.md
│ │ ├── components.md
│ │ ├── control-flow.md
│ │ ├── dom-refs.md
│ │ ├── events.md
│ │ ├── head-management.md
│ │ ├── reactivity.md
│ │ ├── state-management.md
│ │ ├── styling.md
│ │ └── syntax.md
│ ├── introduction.md
│ ├── libraries.md
│ ├── quick-start.md
│ └── troubleshooting.md
├── index.html
├── package.json
├── playground.md
├── public/
│ ├── 404.html
│ ├── llms.txt
│ ├── robots.txt
│ └── sitemap.xml
├── ripple.config.ts
├── src/
│ ├── components/
│ │ ├── actions.ripple
│ │ ├── content.ripple
│ │ ├── doc-badge.ripple
│ │ ├── doc-callout.ripple
│ │ ├── doc-code-block.ripple
│ │ ├── doc-heading.ripple
│ │ ├── docs-footer.ripple
│ │ ├── docs-header.ripple
│ │ ├── docs-layout.ripple
│ │ ├── editor.ripple
│ │ ├── header.ripple
│ │ ├── layout.ripple
│ │ └── sidebar.ripple
│ ├── lib/
│ │ └── markdown.js
│ ├── middlewares.ts
│ ├── pages/
│ │ ├── 404.ripple
│ │ ├── docs/
│ │ │ ├── best-practices.ripple
│ │ │ ├── comparison.ripple
│ │ │ ├── guide/
│ │ │ │ ├── application.ripple
│ │ │ │ ├── bindings.ripple
│ │ │ │ ├── components.ripple
│ │ │ │ ├── control-flow.ripple
│ │ │ │ ├── dom-refs.ripple
│ │ │ │ ├── events.ripple
│ │ │ │ ├── head-management.ripple
│ │ │ │ ├── reactivity.ripple
│ │ │ │ ├── state-management.ripple
│ │ │ │ ├── styling.ripple
│ │ │ │ └── syntax.ripple
│ │ │ ├── introduction.ripple
│ │ │ ├── libraries.ripple
│ │ │ ├── quick-start.ripple
│ │ │ └── troubleshooting.ripple
│ │ └── index.ripple
│ └── routes.ts
├── tsconfig.json
├── vercel.json
└── vite.config.ts
================================================
FILE CONTENTS
================================================
================================================
FILE: .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)
================================================
FILE: .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": [
[
"ripple",
"@ripple-ts/cli",
"@ripple-ts/compat-react",
"create-ripple",
"@ripple-ts/eslint-parser",
"@ripple-ts/eslint-plugin",
"@ripple-ts/language-server",
"@ripple-ts/prettier-plugin",
"@ripple-ts/adapter",
"@ripple-ts/adapter-node",
"@ripple-ts/adapter-bun",
"@ripple-ts/adapter-vercel",
"@ripple-ts/rollup-plugin",
"@ripple-ts/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"
]
}
================================================
FILE: .changeset/large-snails-crash.md
================================================
---
'@ripple-ts/cli': patch
'create-ripple': patch
'@ripple-ts/vite-plugin': patch
---
Upgrade to Vite 8
================================================
FILE: .changeset/tame-snails-sneeze.md
================================================
---
'@ripple-ts/vite-plugin': patch
---
Split the production subpath declarations into a dedicated type file so the exported types resolve cleanly without self-import workarounds.
================================================
FILE: .cursor/environment.json
================================================
{
"name": "ripple-monorepo",
"install": "bash .cursor/install.sh"
}
================================================
FILE: .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
================================================
FILE: .cursor/rules/project.mdc
================================================
---
description: Ripple project overview and development guidelines
globs: **/*
---
# Ripple Project Guide for AI Agents
Ripple is a TypeScript UI framework that combines the best parts of React, Solid,
and Svelte. Created by Dominic Gannaway ([@trueadm](https://github.com/trueadm)),
Ripple is designed to be JS/TS-first with its own `.ripple` file extension that
fully supports TypeScript.
## Documentation
For comprehensive Ripple syntax, components, reactivity, and API documentation,
see:
- **[website/public/llms.txt](website/public/llms.txt)** - Full LLM-optimized
documentation
- **[README.md](README.md)** - Project overview and quick start
- **[CONTRIBUTING.md](CONTRIBUTING.md)** - Contribution guidelines
## RuleSync
This project uses [RuleSync](https://github.com/dyoshikawa/rulesync) to maintain a
single source of truth for AI agent instructions. The canonical rules are in
`.rulesync/rules/`, which are automatically generated to tool-specific locations:
| Agent | Generated File |
| -------------- | --------------------------------- |
| Claude Code | `CLAUDE.md` |
| GitHub Copilot | `.github/copilot-instructions.md` |
| Cursor | `.cursor/rules/project.mdc` |
| Gemini CLI | `GEMINI.md` |
| AGENTS.md | `AGENTS.md` |
**To regenerate after editing `.rulesync/rules/`:**
```bash
pnpm rules:generate
```
This runs automatically on `pnpm install` via the `prepare` script.
## Project Structure
This is a pnpm monorepo. Key packages are marked with `*`.
```
packages/
├── ripple/* # Core framework
│ └── src/
│ ├── compiler/ # Compilation pipeline (see Compiler Architecture)
│ │ ├── phases/
│ │ │ ├── 1-parse/ # Acorn-based parser with RipplePlugin
│ │ │ ├── 2-analyze/ # Scope analysis, CSS pruning, validation
│ │ │ └── 3-transform/# Client/server code generation
│ │ ├── scope.js # Scope and binding management
│ │ ├── types/ # AST type definitions
│ │ └── utils.js # Compiler utilities
│ ├── runtime/ # Runtime library (see Runtime Architecture)
│ │ ├── internal/
│ │ │ ├── client/ # DOM operations, reactivity, events
│ │ │ └── server/ # SSR string generation
│ │ ├── index-client.js # Client entry (browser)
│ │ └── index-server.js # Server entry (SSR)
│ └── server/ # Server-side rendering utilities
├── language-server/* # LSP implementation via Volar framework
├── vscode-plugin/* # VS Code extension (uses language-server)
├── typescript-plugin/* # TypeScript language service plugin
├── eslint-plugin/* # ESLint rules for Ripple
├── eslint-parser/* # ESLint parser for .ripple files
├── prettier-plugin/* # Prettier formatting support
├── vite-plugin/* # Vite build integration
├── rollup-plugin/ # Rollup build integration
├── cli/* # CLI tool (@ripple-ts/cli)
├── create-ripple/ # Project scaffolding (npx create-ripple)
├── compat-react/* # React interoperability layer
├── tree-sitter/* # Tree-sitter grammar for syntax highlighting
├── intellij-plugin/ # IntelliJ/WebStorm support
├── nvim-plugin/ # Neovim support
├── sublime-text-plugin/ # Sublime Text support
├── zed-plugin/ # Zed editor support
└── textmate/ # TextMate grammar (shared by editors)
playground/ # Development playground
website/ # Documentation website
templates/ # Project templates (basic, etc.)
scripts/ # Build and maintenance scripts
```
## Compiler Architecture
The compiler transforms `.ripple` files through three phases:
```
Source Code (.ripple) → Parse → Analyze → Transform → Output (JS + CSS)
```
### Phase 1: Parse (`packages/ripple/src/compiler/phases/1-parse/`)
**Parser:** Acorn extended with `@sveltejs/acorn-typescript` and custom
`RipplePlugin`
**Ripple-specific syntax handled:**
- `component` keyword for component declarations
- JSX with special handling for `@` tracked expressions
- `#server` blocks for server-only code
- `#ripple[]` (RippleArray shorthand), `#ripple{}` (RippleObject shorthand),
`#ripple.map()` (RippleMap), `#ripple.set()` (RippleSet),` #ripple.array()`
(RippleArray), `#ripple.object()` (RippleObject), `#ripple.url()` (RippleURL),
`#ripple.urlSearchParams()` (RippleURLSearchParams), `#ripple.Date()`
(RippleDate), `#ripple.Context()` (RippleContext), `#ripple.mediaQuery()`
(MediaQuery) `#ripple.track()` (track()), `#ripple.trackSplit()` (trackSplit())
`#ripple.untrack()` (untrack()), `#ripple.effect()` (effect()),
- `#style` identifier for scoped CSS classes
**Output:** ESTree-compatible AST with Ripple extensions
### Phase 2: Analyze (`packages/ripple/src/compiler/phases/2-analyze/`)
| File | Purpose |
| ---------------- | ----------------------------------------------- |
| `index.js` | Main analysis orchestration |
| `css-analyze.js` | CSS selector analysis, `:global()` handling |
| `prune.js` | Remove unused CSS rules based on template usage |
| `validation.js` | HTML nesting validation |
**Key operations:**
- **Scope creation:** `scope.js` creates scope chains tracking bindings (import,
prop, let, const, function, component, for_pattern)
- **Reactivity analysis:** Marks tracked expressions, derives tracking metadata
- **CSS scoping:** Hash-based class names via `CSS_HASH_IDENTIFIER`
- **`#style` analysis:** Validates usage context, collects referenced classes,
cross-checks against standalone CSS selectors
- **Server block analysis:** Tracks exports from `#server` blocks
### Phase 3: Transform (`packages/ripple/src/compiler/phases/3-transform/`)
**Client transform** (`client/index.js`):
- Generates runtime calls: `_$_.render()`, `_$_.if()`, `_$_.for()`,
`_$_.switch()`, etc.
- Creates template strings for static HTML
- Sets up event delegation
- Injects CSS hash for scoped styles
**Server transform** (`server/index.js`):
- Generates string concatenation for SSR output
- Handles `#server` block code execution
- Registers CSS for hydration
- Wraps control flow blocks with hydration comment markers
### SSR vs Client Compilation
The same `.ripple` module produces different output depending on the compilation
mode, controlled by `options.mode` in the compiler:
```javascript
// compiler/index.js
const result =
options.mode === 'server'
? transform_server(filename, source, analysis, options?.minify_css ?? false)
: transform_client(
filename,
source,
analysis,
false,
options?.minify_css ?? false,
);
```
| Aspect | Client Transform | Server Transform |
| ---------------- | ------------------------------------------ | ---------------------------------------- |
| **Output** | Runtime calls (`_$_.render()`, `_$_.if()`) | String concatenation (`__output.push()`) |
| **Templates** | DOM template literals, `cloneNode()` | Escaped HTML strings |
| **Reactivity** | Block scheduling, dirty checking | Immediate execution, no scheduling |
| **Control flow** | Creates branch blocks, DOM diffing | Wraps with `<!--[-->`/`<!--]-->` markers |
| **Events** | Delegation setup (`_$_.delegate()`) | Omitted entirely |
| **CSS** | Injects hash for scoping | Registers CSS hash via `register_css()` |
**Vite plugin** compiles modules twice for SSR apps - once with `mode: 'client'`
and once with `mode: 'server'`.
### Key AST Node Types (`packages/ripple/src/compiler/types/`)
| Node Type | Description |
| ------------------------ | -------------------------------------------------------- |
| `Component` | Component declaration with `id`, `params`, `body`, `css` |
| `Element` | HTML/SVG element with `id`, `attributes`, `children` |
| `Text` | Text node wrapping an expression |
| `ServerBlock` | `#server { ... }` block with exports tracking |
| `TrackedExpression` | `@expression` tracked reactive value |
| `RippleArrayExpression` | `#[...]` tracked array literal |
| `RippleObjectExpression` | `#{...}` tracked object literal |
| `Attribute` | Element attribute with `name`, `value`, `shorthand` |
| `RefAttribute` | `ref={...}` reference binding |
| `SpreadAttribute` | `{...props}` spread |
| `StyleIdentifier` | `#style` compile-time identifier for scoped CSS classes |
| `CSS.StyleSheet` | Parsed CSS with `hash` for scoping |
## Runtime Architecture
### Client Runtime (`packages/ripple/src/runtime/internal/client/`)
| Module | Responsibility |
| --------------- | ------------------------------------------------------------------------------- |
| `runtime.js` | Core reactivity: `tracked()`, `derived()`, `get()`, `set()`, block scheduling |
| `blocks.js` | Block creation: `render()`, `branch()`, `effect()`, `root()`, `destroy_block()` |
| `render.js` | DOM operations: `set_text()`, `set_class()`, `set_style()`, `set_attribute()` |
| `template.js` | Template instantiation: `template()`, `append()`, `assign_nodes()` |
| `operations.js` | DOM traversal: `child()`, `sibling()`, `create_text()` |
| `events.js` | Event handling: `event()`, `delegate()`, event propagation |
| `hydration.js` | SSR hydration: `hydrating`, `hydrate_node`, `hydrate_next()` |
| `bindings.js` | Two-way bindings for form elements |
| `context.js` | Context API implementation |
### Control Flow Blocks
| Block | File | Purpose |
| -------------- | -------------- | ------------------------------------------------------- |
| `if_block` | `if.js` | Conditional rendering with branch switching |
| `for_block` | `for.js` | List rendering with reconciliation (ref-based or keyed) |
| `switch_block` | `switch.js` | Multi-branch rendering |
| `try_block` | `try.js` | Error boundaries + async suspense |
| `composite` | `composite.js` | Dynamic component rendering (`<@Component />`) |
| `portal` | `portal.js` | Render children to different DOM location |
### Reactivity System
**Core concepts:**
- `tracked(value, block)` - Creates a tracked reactive value (`Tracked<V>`)
- `derived(fn, block)` - Creates a computed/derived value
- `get(tracked)` - Reads value, registers dependency
- `set(tracked, value)` - Updates value, schedules updates
**Implementation details:**
- Dependencies tracked via linked list structure: `{ c, t, n }` (consumer,
tracked, next)
- Dirty checking with clock-based versioning
- Block flags in `constants.js`: `ROOT_BLOCK`, `RENDER_BLOCK`, `EFFECT_BLOCK`,
`BRANCH_BLOCK`, etc.
### Reactive Collections (`packages/ripple/src/runtime/`)
| Collection | File | Description |
| -------------- | ----------- | ------------------------------------------- |
| `RippleArray` | `array.js` | Fully reactive array with all Array methods |
| `RippleObject` | `object.js` | Shallow reactive object |
| `RippleMap` | `map.js` | Reactive Map |
| `RippleSet` | `set.js` | Reactive Set |
| `RippleDate` | `date.js` | Reactive Date |
### Server Runtime (`packages/ripple/src/runtime/internal/server/`)
- String-based output via `Output` class (concatenates `head` and `body`)
- Simplified reactivity (no block scheduling, immediate execution)
- CSS registration for hydration markers
- Escape utilities for safe HTML output
### Hydration Mechanism
Hydration allows the client to "adopt" server-rendered HTML without re-rendering,
using comment markers to identify dynamic regions.
**Comment Markers (inserted by server transform):**
| Marker | Constant | Purpose |
| ----------- | ----------------- | -------------------------------------------- |
| `<!--[-->` | `HYDRATION_START` | Opens a dynamic block (if, for, switch, try) |
| `<!--]-->` | `HYDRATION_END` | Closes a dynamic block |
| `<!--[!-->` | `HYDRATION_ELSE` | Marks else/fallback branch boundary |
**Server-side generation:**
```javascript
// Server transform wraps control flow with markers
__output.push('<!--[-->'); // HYDRATION_START
// ... render content ...
__output.push('<!--]-->'); // HYDRATION_END
```
**Client-side hydration
(`packages/ripple/src/runtime/internal/client/hydration.js`):**
```javascript
export let hydrating = false; // True during hydration phase
export let hydrate_node = null; // Current DOM node being hydrated
```
**Key hydration functions:**
| Function | Purpose |
| ------------------------ | --------------------------------- |
| `set_hydrating(value)` | Enable/disable hydration mode |
| `set_hydrate_node(node)` | Set the current node pointer |
| `hydrate_next()` | Advance to next sibling node |
| `pop(node)` | Reset hydrate_node after mounting |
**Hydration flow:**
1. Server renders HTML with `<!--[-->` / `<!--]-->` markers around dynamic blocks
2. Client receives HTML, `hydrating = true` is set
3. Runtime walks DOM using `hydrate_node`, matching structure to component tree
4. Instead of creating elements, runtime "claims" existing DOM nodes
5. Comment markers guide block boundary detection
6. After hydration completes, `hydrating` is set back to `false`
## Language Server (`packages/language-server/src/`)
Built on **Volar framework** with TypeScript integration.
| Plugin | File | Purpose |
| -------------- | --------------------------------- | --------------------------------- |
| Completion | `completionPlugin.js` | Auto-completion for Ripple syntax |
| Definition | `definitionPlugin.js` | Go-to-definition |
| Hover | `hoverPlugin.js` | Hover information |
| Diagnostics | `compileErrorDiagnosticPlugin.js` | Compile-time error diagnostics |
| TS Diagnostics | `typescriptDiagnosticPlugin.js` | TypeScript diagnostic filtering |
| Auto-insert | `autoInsertPlugin.js` | Auto-insert completions |
| Highlight | `documentHighlightPlugin.js` | Document highlights |
**Integration:** Uses `@ripple-ts/typescript-plugin` for TypeScript language
service.
## Editor Plugins
All editor plugins use `@ripple-ts/language-server` internally:
| Editor | Package | Notes |
| ----------------- | ---------------------- | -------------------------------- |
| VS Code | `vscode-plugin/` | Primary development target |
| IntelliJ/WebStorm | `intellij-plugin/` | TextMate syntax + LSP via LSP4IJ |
| Neovim | `nvim-plugin/` | Tree-sitter + LSP |
| Sublime Text | `sublime-text-plugin/` | LSP package |
| Zed | `zed-plugin/` | Tree-sitter queries |
**Tree-sitter queries:** Located in `packages/tree-sitter/queries/`, copied to
nvim/zed plugins via `pnpm copy-tree-sitter-queries`.
## Validating Changes
**CRITICAL: Use pnpm for all package management. Do NOT use npm or yarn.**
### Changesets
For user-facing changes, add a changeset before committing:
```bash
pnpm changeset
```
This creates a markdown file in `.changeset/` describing the change. Select
affected packages and semver bump type (patch/minor/major). The file is committed
with your changes.
**Add a changeset for:** bug fixes, new features, breaking changes, API changes.
**Skip changesets for:** docs-only, internal refactoring, tests, CI/tooling.
### Required Validation Steps
After making changes, run these commands:
```bash
# Install dependencies (if needed)
pnpm install
# Format code with Prettier
pnpm format
# Check formatting without changes
pnpm format:check
# Run all tests
pnpm test
# Run specific test project
pnpm test --project ripple-client
pnpm test --project ripple-server
pnpm test --project eslint-plugin
pnpm test --project prettier-plugin
```
### Test Projects (from `vitest.config.js`)
| Project | Tests | Environment |
| ------------------ | ----------------------------------------------- | ----------- |
| `ripple-client` | `packages/ripple/tests/client/**/*.test.ripple` | jsdom |
| `ripple-server` | `packages/ripple/tests/server/**/*.test.ripple` | node |
| `ripple-hydration` | `packages/ripple/tests/hydration/**/*.test.js` | jsdom |
| `eslint-plugin` | `packages/eslint-plugin/tests/**/*.test.ts` | jsdom |
| `eslint-parser` | `packages/eslint-parser/tests/**/*.test.ts` | jsdom |
| `prettier-plugin` | `packages/prettier-plugin/src/*.test.js` | jsdom |
| `cli` | `packages/cli/tests/**/*.test.js` | jsdom |
| `compat-react` | `packages/compat-react/tests/**/*.test.ripple` | jsdom |
### Test Architecture
**Ripple test files (`.test.ripple`):**
Test files are valid Ripple modules that export a default test component. The Vite
plugin transforms them before Vitest runs:
```ripple
// Example: packages/ripple/tests/client/reactivity.test.ripple
import { describe, it, expect } from 'vitest';
component default() {
describe('tracked', () => {
it('updates when value changes', async () => {
let count = #ripple.track(0);
// test implementation
});
});
}
```
**Setup files (`packages/ripple/tests/`):**
| File | Purpose |
| ----------------- | ----------------------------------------------- |
| `setup-client.js` | Client test setup: DOM utilities, flush helpers |
| `setup-server.js` | Server test setup: Output class, render helpers |
**Hydration tests (`packages/ripple/tests/hydration/`):**
Hydration tests verify client/server output consistency:
1. Server compiles and renders to HTML string with hydration markers
2. Client receives pre-rendered HTML, sets `hydrating = true`
3. Client walks DOM, claiming existing nodes instead of creating new ones
4. Tests verify final DOM matches expected state
```javascript
// Typical hydration test pattern
const server_html = render_server(Component); // With <!--[--> markers
container.innerHTML = server_html;
hydrate(Component, container); // Claims existing nodes
expect(container.innerHTML).toBe(expected);
```
### Development Playground
```bash
cd playground
pnpm dev # Start dev server (Vite)
pnpm lint # Lint playground code
```
## Code Conventions
### Package Manager
**pnpm is required** (`engines` in package.json enforces this). Do NOT use npm or
yarn.
### Language & Types
- **Internal code:** JavaScript (`.js`) with JSDoc type annotations — NOT
TypeScript
- **Type definitions:** TypeScript `.d.ts` files in `types/` directories for
public API
- **JSDoc imports:** Use `@import` syntax at top of file:
```javascript
/** @import { Block, Tracked, Derived } from '#client' */
/** @import * as AST from 'estree' */
```
- **JSDoc annotations:** Use `@param`, `@returns`, `@type` for all functions:
```javascript
/**
* @param {Block} block - The block to destroy
* @returns {void}
*/
export function destroy_block(block) { ... }
```
### Naming Conventions
| Context | Style | Examples |
| --------------- | ---------------------- | ------------------------------------------ |
| Variables | `snake_case` | `active_block`, `is_mutating_allowed` |
| Functions | `snake_case` | `create_scopes`, `set_active_block` |
| Constants | `SCREAMING_SNAKE_CASE` | `ROOT_BLOCK`, `FLUSH_MICROTASK`, `DERIVED` |
| Files | `kebab-case` | `css-analyze.js`, `source-map-utils.js` |
| Component files | `PascalCase` | `Button.ripple`, `TodoList.ripple` |
| Classes | `PascalCase` | `Scope`, `RippleArray`, `Output` |
| Type parameters | Single uppercase | `V` in `Tracked<V>`, `T` in generics |
### Hot Path Optimizations
In performance-critical runtime code, short property names are used to minimize
bundle size:
```javascript
// Block structure uses short names
block.p; // parent
block.t; // teardown function
block.d; // dependencies
block.f; // flags
block.s; // state
block.c; // context
```
### General Guidelines
1. **Consistency:** Look for similar implementations before adding new code
2. **No abbreviations** in variable names (except hot path optimizations above)
3. **Prefer `const`** over `let` when value won't be reassigned
4. **Use `var`** only in specific runtime hot paths for performance
5. **Comments:** Add comments for complex logic, not obvious code
## Tips for Working with the Codebase
### Compiler work
- Parser changes go in `phases/1-parse/`, modify `RipplePlugin` for new syntax
- Scope-related changes in `scope.js` - track bindings with appropriate `kind`
- CSS changes: `css-analyze.js` for parsing, `prune.js` for dead code elimination
- Code generation: separate files for `client/` and `server/` transforms
### Runtime work
- Reactivity: `runtime.js` is the core, understand
`tracked()`/`derived()`/`get()`/`set()`
- New control flow: add to both client (`internal/client/`) and may need server
support
- DOM operations: `render.js` for attribute/text updates, `operations.js` for
traversal
- Events: delegation in `events.js`, check `DELEGATED_EVENTS` constant
### Editor plugins
- Language server plugins in `packages/language-server/src/`
- VS Code extension entry: `packages/vscode-plugin/src/extension.js`
- TypeScript plugin: `packages/typescript-plugin/src/` for IDE integration
### Prettier plugin
The Prettier plugin (`packages/prettier-plugin/src/index.js`) formats `.ripple`
files using **AST-based formatting**, not string manipulation.
#### Architecture
The plugin exports three objects required by Prettier:
| Export | Purpose |
| ----------- | ------------------------------------------------------------------ |
| `languages` | Declares `.ripple` extension and parser name |
| `parsers` | Uses Ripple's compiler (`parse()`) to create ESTree-compatible AST |
| `printers` | Contains `print`, `embed`, and `getVisitorKeys` functions |
**AST-based approach:**
- Parser produces ESTree AST with Ripple extensions (Component, Element,
TrackedExpression, etc.)
- Printer recursively walks AST nodes via `printRippleNode()` switch statement
- Uses Prettier's `doc.builders` API (`concat`, `join`, `group`, `indent`, `line`,
`hardline`, `softline`, `ifBreak`)
#### Comment handling
Comments are attached to AST nodes and printed via three mechanisms:
| Comment Type | Property | Handling |
| ----------------- | ----------------------- | ----------------------------------------- |
| Leading comments | `node.leadingComments` | Printed before node content |
| Trailing comments | `node.trailingComments` | Inline via `lineSuffix()` or on next line |
| Inner comments | `node.innerComments` | Printed inside empty blocks/elements |
Element-level comment helpers:
- `getElementLeadingComments(node)` - extracts comments for JSX elements
- `createElementLevelCommentParts(comments)` - formats with proper spacing
#### Options
Prettier options are accessed from the `options` parameter:
| Option | Helper function | Usage |
| ------------------------ | ----------------------- | ------------------------------------ |
| `singleQuote` | `formatStringLiteral()` | Quote style for string literals |
| `jsxSingleQuote` | — | Quote style for JSX attribute values |
| `semi` | `semi()` | Semicolon insertion |
| `trailingComma` | `shouldPrintComma()` | Trailing commas in arrays/objects |
| `useTabs` / `tabWidth` | `createIndent()` | Indentation style |
| `singleAttributePerLine` | — | JSX attribute line breaking |
| `bracketSameLine` | — | JSX closing bracket position |
#### Context passing via `args`
The `args` parameter passes context for conditional formatting:
```javascript
// Examples of context flags
{
isInAttribute: true;
} // Compact object formatting in attributes
{
isInArray: true;
} // Array element context
{
allowInlineObject: true;
} // Allow single-line objects
{
isConditionalTest: true;
} // Binary/logical in conditional test
{
suppressLeadingComments: true;
} // Skip comment printing
```
#### Adding new node types
When encountering `/* Unknown: NodeType */` in formatter output:
1. **Identify the missing node type** from the comment (e.g., `TSDeclareFunction`)
2. **Add a case** in the `printRippleNode` switch statement:
```javascript
case 'TSDeclareFunction':
nodeContent = printTSDeclareFunction(node, path, options, print);
break;
```
3. **Implement the print function** following existing patterns (see
`printFunctionDeclaration` as reference)
4. **Add a test** in `packages/prettier-plugin/src/index.test.js`
#### Common patterns
- Use `path.call(print, 'childNode')` to recursively print child nodes
- Use `concat([...])` to join parts, `group()` for line breaking
- Check `node.typeParameters`, `node.returnType` for TypeScript annotations
- All functions use JSDoc type annotations with proper types (no `any`/`unknown`)
### Testing
- Client tests: create `.test.ripple` files in `packages/ripple/tests/client/`
- Server tests: create `.test.ripple` files in `packages/ripple/tests/server/`
- Use `setup-client.js` / `setup-server.js` for test environment setup
================================================
FILE: .editorconfig
================================================
root = true
[*]
charset = utf-8
end_of_line = lf
indent_size = 2
indent_style = tab
insert_final_newline = true
trim_trailing_whitespace = true
================================================
FILE: .gitattributes
================================================
grammars/tree-sitter/src/parser.c -linguist-detectable
================================================
FILE: .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
================================================
FILE: .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"
================================================
FILE: .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
================================================
FILE: .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: `#ripple.track`, `#ripple.array`, `#ripple.map`, etc.
- 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
let count = #ripple.track(0); // tracked value
let doubled = #ripple.track(() => @count * 2); // derived value
```
### Validation Commands
```bash
pnpm test # Run all tests
pnpm format # Format code
pnpm format:check # Check formatting
```
================================================
FILE: .github/copilot-instructions.md
================================================
# Ripple Project Guide for AI Agents
Ripple is a TypeScript UI framework that combines the best parts of React, Solid,
and Svelte. Created by Dominic Gannaway ([@trueadm](https://github.com/trueadm)),
Ripple is designed to be JS/TS-first with its own `.ripple` file extension that
fully supports TypeScript.
## Documentation
For comprehensive Ripple syntax, components, reactivity, and API documentation,
see:
- **[website/public/llms.txt](website/public/llms.txt)** - Full LLM-optimized
documentation
- **[README.md](README.md)** - Project overview and quick start
- **[CONTRIBUTING.md](CONTRIBUTING.md)** - Contribution guidelines
## RuleSync
This project uses [RuleSync](https://github.com/dyoshikawa/rulesync) to maintain a
single source of truth for AI agent instructions. The canonical rules are in
`.rulesync/rules/`, which are automatically generated to tool-specific locations:
| Agent | Generated File |
| -------------- | --------------------------------- |
| Claude Code | `CLAUDE.md` |
| GitHub Copilot | `.github/copilot-instructions.md` |
| Cursor | `.cursor/rules/project.mdc` |
| Gemini CLI | `GEMINI.md` |
| AGENTS.md | `AGENTS.md` |
**To regenerate after editing `.rulesync/rules/`:**
```bash
pnpm rules:generate
```
This runs automatically on `pnpm install` via the `prepare` script.
## Project Structure
This is a pnpm monorepo. Key packages are marked with `*`.
```
packages/
├── ripple/* # Core framework
│ └── src/
│ ├── compiler/ # Compilation pipeline (see Compiler Architecture)
│ │ ├── phases/
│ │ │ ├── 1-parse/ # Acorn-based parser with RipplePlugin
│ │ │ ├── 2-analyze/ # Scope analysis, CSS pruning, validation
│ │ │ └── 3-transform/# Client/server code generation
│ │ ├── scope.js # Scope and binding management
│ │ ├── types/ # AST type definitions
│ │ └── utils.js # Compiler utilities
│ ├── runtime/ # Runtime library (see Runtime Architecture)
│ │ ├── internal/
│ │ │ ├── client/ # DOM operations, reactivity, events
│ │ │ └── server/ # SSR string generation
│ │ ├── index-client.js # Client entry (browser)
│ │ └── index-server.js # Server entry (SSR)
│ └── server/ # Server-side rendering utilities
├── language-server/* # LSP implementation via Volar framework
├── vscode-plugin/* # VS Code extension (uses language-server)
├── typescript-plugin/* # TypeScript language service plugin
├── eslint-plugin/* # ESLint rules for Ripple
├── eslint-parser/* # ESLint parser for .ripple files
├── prettier-plugin/* # Prettier formatting support
├── vite-plugin/* # Vite build integration
├── rollup-plugin/ # Rollup build integration
├── cli/* # CLI tool (@ripple-ts/cli)
├── create-ripple/ # Project scaffolding (npx create-ripple)
├── compat-react/* # React interoperability layer
├── tree-sitter/* # Tree-sitter grammar for syntax highlighting
├── intellij-plugin/ # IntelliJ/WebStorm support
├── nvim-plugin/ # Neovim support
├── sublime-text-plugin/ # Sublime Text support
├── zed-plugin/ # Zed editor support
└── textmate/ # TextMate grammar (shared by editors)
playground/ # Development playground
website/ # Documentation website
templates/ # Project templates (basic, etc.)
scripts/ # Build and maintenance scripts
```
## Compiler Architecture
The compiler transforms `.ripple` files through three phases:
```
Source Code (.ripple) → Parse → Analyze → Transform → Output (JS + CSS)
```
### Phase 1: Parse (`packages/ripple/src/compiler/phases/1-parse/`)
**Parser:** Acorn extended with `@sveltejs/acorn-typescript` and custom
`RipplePlugin`
**Ripple-specific syntax handled:**
- `component` keyword for component declarations
- JSX with special handling for `@` tracked expressions
- `#server` blocks for server-only code
- `#ripple[]` (RippleArray shorthand), `#ripple{}` (RippleObject shorthand),
`#ripple.map()` (RippleMap), `#ripple.set()` (RippleSet),` #ripple.array()`
(RippleArray), `#ripple.object()` (RippleObject), `#ripple.url()` (RippleURL),
`#ripple.urlSearchParams()` (RippleURLSearchParams), `#ripple.Date()`
(RippleDate), `#ripple.Context()` (RippleContext), `#ripple.mediaQuery()`
(MediaQuery) `#ripple.track()` (track()), `#ripple.trackSplit()` (trackSplit())
`#ripple.untrack()` (untrack()), `#ripple.effect()` (effect()),
- `#style` identifier for scoped CSS classes
**Output:** ESTree-compatible AST with Ripple extensions
### Phase 2: Analyze (`packages/ripple/src/compiler/phases/2-analyze/`)
| File | Purpose |
| ---------------- | ----------------------------------------------- |
| `index.js` | Main analysis orchestration |
| `css-analyze.js` | CSS selector analysis, `:global()` handling |
| `prune.js` | Remove unused CSS rules based on template usage |
| `validation.js` | HTML nesting validation |
**Key operations:**
- **Scope creation:** `scope.js` creates scope chains tracking bindings (import,
prop, let, const, function, component, for_pattern)
- **Reactivity analysis:** Marks tracked expressions, derives tracking metadata
- **CSS scoping:** Hash-based class names via `CSS_HASH_IDENTIFIER`
- **`#style` analysis:** Validates usage context, collects referenced classes,
cross-checks against standalone CSS selectors
- **Server block analysis:** Tracks exports from `#server` blocks
### Phase 3: Transform (`packages/ripple/src/compiler/phases/3-transform/`)
**Client transform** (`client/index.js`):
- Generates runtime calls: `_$_.render()`, `_$_.if()`, `_$_.for()`,
`_$_.switch()`, etc.
- Creates template strings for static HTML
- Sets up event delegation
- Injects CSS hash for scoped styles
**Server transform** (`server/index.js`):
- Generates string concatenation for SSR output
- Handles `#server` block code execution
- Registers CSS for hydration
- Wraps control flow blocks with hydration comment markers
### SSR vs Client Compilation
The same `.ripple` module produces different output depending on the compilation
mode, controlled by `options.mode` in the compiler:
```javascript
// compiler/index.js
const result =
options.mode === 'server'
? transform_server(filename, source, analysis, options?.minify_css ?? false)
: transform_client(
filename,
source,
analysis,
false,
options?.minify_css ?? false,
);
```
| Aspect | Client Transform | Server Transform |
| ---------------- | ------------------------------------------ | ---------------------------------------- |
| **Output** | Runtime calls (`_$_.render()`, `_$_.if()`) | String concatenation (`__output.push()`) |
| **Templates** | DOM template literals, `cloneNode()` | Escaped HTML strings |
| **Reactivity** | Block scheduling, dirty checking | Immediate execution, no scheduling |
| **Control flow** | Creates branch blocks, DOM diffing | Wraps with `<!--[-->`/`<!--]-->` markers |
| **Events** | Delegation setup (`_$_.delegate()`) | Omitted entirely |
| **CSS** | Injects hash for scoping | Registers CSS hash via `register_css()` |
**Vite plugin** compiles modules twice for SSR apps - once with `mode: 'client'`
and once with `mode: 'server'`.
### Key AST Node Types (`packages/ripple/src/compiler/types/`)
| Node Type | Description |
| ------------------------ | -------------------------------------------------------- |
| `Component` | Component declaration with `id`, `params`, `body`, `css` |
| `Element` | HTML/SVG element with `id`, `attributes`, `children` |
| `Text` | Text node wrapping an expression |
| `ServerBlock` | `#server { ... }` block with exports tracking |
| `TrackedExpression` | `@expression` tracked reactive value |
| `RippleArrayExpression` | `#[...]` tracked array literal |
| `RippleObjectExpression` | `#{...}` tracked object literal |
| `Attribute` | Element attribute with `name`, `value`, `shorthand` |
| `RefAttribute` | `ref={...}` reference binding |
| `SpreadAttribute` | `{...props}` spread |
| `StyleIdentifier` | `#style` compile-time identifier for scoped CSS classes |
| `CSS.StyleSheet` | Parsed CSS with `hash` for scoping |
## Runtime Architecture
### Client Runtime (`packages/ripple/src/runtime/internal/client/`)
| Module | Responsibility |
| --------------- | ------------------------------------------------------------------------------- |
| `runtime.js` | Core reactivity: `tracked()`, `derived()`, `get()`, `set()`, block scheduling |
| `blocks.js` | Block creation: `render()`, `branch()`, `effect()`, `root()`, `destroy_block()` |
| `render.js` | DOM operations: `set_text()`, `set_class()`, `set_style()`, `set_attribute()` |
| `template.js` | Template instantiation: `template()`, `append()`, `assign_nodes()` |
| `operations.js` | DOM traversal: `child()`, `sibling()`, `create_text()` |
| `events.js` | Event handling: `event()`, `delegate()`, event propagation |
| `hydration.js` | SSR hydration: `hydrating`, `hydrate_node`, `hydrate_next()` |
| `bindings.js` | Two-way bindings for form elements |
| `context.js` | Context API implementation |
### Control Flow Blocks
| Block | File | Purpose |
| -------------- | -------------- | ------------------------------------------------------- |
| `if_block` | `if.js` | Conditional rendering with branch switching |
| `for_block` | `for.js` | List rendering with reconciliation (ref-based or keyed) |
| `switch_block` | `switch.js` | Multi-branch rendering |
| `try_block` | `try.js` | Error boundaries + async suspense |
| `composite` | `composite.js` | Dynamic component rendering (`<@Component />`) |
| `portal` | `portal.js` | Render children to different DOM location |
### Reactivity System
**Core concepts:**
- `tracked(value, block)` - Creates a tracked reactive value (`Tracked<V>`)
- `derived(fn, block)` - Creates a computed/derived value
- `get(tracked)` - Reads value, registers dependency
- `set(tracked, value)` - Updates value, schedules updates
**Implementation details:**
- Dependencies tracked via linked list structure: `{ c, t, n }` (consumer,
tracked, next)
- Dirty checking with clock-based versioning
- Block flags in `constants.js`: `ROOT_BLOCK`, `RENDER_BLOCK`, `EFFECT_BLOCK`,
`BRANCH_BLOCK`, etc.
### Reactive Collections (`packages/ripple/src/runtime/`)
| Collection | File | Description |
| -------------- | ----------- | ------------------------------------------- |
| `RippleArray` | `array.js` | Fully reactive array with all Array methods |
| `RippleObject` | `object.js` | Shallow reactive object |
| `RippleMap` | `map.js` | Reactive Map |
| `RippleSet` | `set.js` | Reactive Set |
| `RippleDate` | `date.js` | Reactive Date |
### Server Runtime (`packages/ripple/src/runtime/internal/server/`)
- String-based output via `Output` class (concatenates `head` and `body`)
- Simplified reactivity (no block scheduling, immediate execution)
- CSS registration for hydration markers
- Escape utilities for safe HTML output
### Hydration Mechanism
Hydration allows the client to "adopt" server-rendered HTML without re-rendering,
using comment markers to identify dynamic regions.
**Comment Markers (inserted by server transform):**
| Marker | Constant | Purpose |
| ----------- | ----------------- | -------------------------------------------- |
| `<!--[-->` | `HYDRATION_START` | Opens a dynamic block (if, for, switch, try) |
| `<!--]-->` | `HYDRATION_END` | Closes a dynamic block |
| `<!--[!-->` | `HYDRATION_ELSE` | Marks else/fallback branch boundary |
**Server-side generation:**
```javascript
// Server transform wraps control flow with markers
__output.push('<!--[-->'); // HYDRATION_START
// ... render content ...
__output.push('<!--]-->'); // HYDRATION_END
```
**Client-side hydration
(`packages/ripple/src/runtime/internal/client/hydration.js`):**
```javascript
export let hydrating = false; // True during hydration phase
export let hydrate_node = null; // Current DOM node being hydrated
```
**Key hydration functions:**
| Function | Purpose |
| ------------------------ | --------------------------------- |
| `set_hydrating(value)` | Enable/disable hydration mode |
| `set_hydrate_node(node)` | Set the current node pointer |
| `hydrate_next()` | Advance to next sibling node |
| `pop(node)` | Reset hydrate_node after mounting |
**Hydration flow:**
1. Server renders HTML with `<!--[-->` / `<!--]-->` markers around dynamic blocks
2. Client receives HTML, `hydrating = true` is set
3. Runtime walks DOM using `hydrate_node`, matching structure to component tree
4. Instead of creating elements, runtime "claims" existing DOM nodes
5. Comment markers guide block boundary detection
6. After hydration completes, `hydrating` is set back to `false`
## Language Server (`packages/language-server/src/`)
Built on **Volar framework** with TypeScript integration.
| Plugin | File | Purpose |
| -------------- | --------------------------------- | --------------------------------- |
| Completion | `completionPlugin.js` | Auto-completion for Ripple syntax |
| Definition | `definitionPlugin.js` | Go-to-definition |
| Hover | `hoverPlugin.js` | Hover information |
| Diagnostics | `compileErrorDiagnosticPlugin.js` | Compile-time error diagnostics |
| TS Diagnostics | `typescriptDiagnosticPlugin.js` | TypeScript diagnostic filtering |
| Auto-insert | `autoInsertPlugin.js` | Auto-insert completions |
| Highlight | `documentHighlightPlugin.js` | Document highlights |
**Integration:** Uses `@ripple-ts/typescript-plugin` for TypeScript language
service.
## Editor Plugins
All editor plugins use `@ripple-ts/language-server` internally:
| Editor | Package | Notes |
| ----------------- | ---------------------- | -------------------------------- |
| VS Code | `vscode-plugin/` | Primary development target |
| IntelliJ/WebStorm | `intellij-plugin/` | TextMate syntax + LSP via LSP4IJ |
| Neovim | `nvim-plugin/` | Tree-sitter + LSP |
| Sublime Text | `sublime-text-plugin/` | LSP package |
| Zed | `zed-plugin/` | Tree-sitter queries |
**Tree-sitter queries:** Located in `packages/tree-sitter/queries/`, copied to
nvim/zed plugins via `pnpm copy-tree-sitter-queries`.
## Validating Changes
**CRITICAL: Use pnpm for all package management. Do NOT use npm or yarn.**
### Changesets
For user-facing changes, add a changeset before committing:
```bash
pnpm changeset
```
This creates a markdown file in `.changeset/` describing the change. Select
affected packages and semver bump type (patch/minor/major). The file is committed
with your changes.
**Add a changeset for:** bug fixes, new features, breaking changes, API changes.
**Skip changesets for:** docs-only, internal refactoring, tests, CI/tooling.
### Required Validation Steps
After making changes, run these commands:
```bash
# Install dependencies (if needed)
pnpm install
# Format code with Prettier
pnpm format
# Check formatting without changes
pnpm format:check
# Run all tests
pnpm test
# Run specific test project
pnpm test --project ripple-client
pnpm test --project ripple-server
pnpm test --project eslint-plugin
pnpm test --project prettier-plugin
```
### Test Projects (from `vitest.config.js`)
| Project | Tests | Environment |
| ------------------ | ----------------------------------------------- | ----------- |
| `ripple-client` | `packages/ripple/tests/client/**/*.test.ripple` | jsdom |
| `ripple-server` | `packages/ripple/tests/server/**/*.test.ripple` | node |
| `ripple-hydration` | `packages/ripple/tests/hydration/**/*.test.js` | jsdom |
| `eslint-plugin` | `packages/eslint-plugin/tests/**/*.test.ts` | jsdom |
| `eslint-parser` | `packages/eslint-parser/tests/**/*.test.ts` | jsdom |
| `prettier-plugin` | `packages/prettier-plugin/src/*.test.js` | jsdom |
| `cli` | `packages/cli/tests/**/*.test.js` | jsdom |
| `compat-react` | `packages/compat-react/tests/**/*.test.ripple` | jsdom |
### Test Architecture
**Ripple test files (`.test.ripple`):**
Test files are valid Ripple modules that export a default test component. The Vite
plugin transforms them before Vitest runs:
```ripple
// Example: packages/ripple/tests/client/reactivity.test.ripple
import { describe, it, expect } from 'vitest';
component default() {
describe('tracked', () => {
it('updates when value changes', async () => {
let count = #ripple.track(0);
// test implementation
});
});
}
```
**Setup files (`packages/ripple/tests/`):**
| File | Purpose |
| ----------------- | ----------------------------------------------- |
| `setup-client.js` | Client test setup: DOM utilities, flush helpers |
| `setup-server.js` | Server test setup: Output class, render helpers |
**Hydration tests (`packages/ripple/tests/hydration/`):**
Hydration tests verify client/server output consistency:
1. Server compiles and renders to HTML string with hydration markers
2. Client receives pre-rendered HTML, sets `hydrating = true`
3. Client walks DOM, claiming existing nodes instead of creating new ones
4. Tests verify final DOM matches expected state
```javascript
// Typical hydration test pattern
const server_html = render_server(Component); // With <!--[--> markers
container.innerHTML = server_html;
hydrate(Component, container); // Claims existing nodes
expect(container.innerHTML).toBe(expected);
```
### Development Playground
```bash
cd playground
pnpm dev # Start dev server (Vite)
pnpm lint # Lint playground code
```
## Code Conventions
### Package Manager
**pnpm is required** (`engines` in package.json enforces this). Do NOT use npm or
yarn.
### Language & Types
- **Internal code:** JavaScript (`.js`) with JSDoc type annotations — NOT
TypeScript
- **Type definitions:** TypeScript `.d.ts` files in `types/` directories for
public API
- **JSDoc imports:** Use `@import` syntax at top of file:
```javascript
/** @import { Block, Tracked, Derived } from '#client' */
/** @import * as AST from 'estree' */
```
- **JSDoc annotations:** Use `@param`, `@returns`, `@type` for all functions:
```javascript
/**
* @param {Block} block - The block to destroy
* @returns {void}
*/
export function destroy_block(block) { ... }
```
### Naming Conventions
| Context | Style | Examples |
| --------------- | ---------------------- | ------------------------------------------ |
| Variables | `snake_case` | `active_block`, `is_mutating_allowed` |
| Functions | `snake_case` | `create_scopes`, `set_active_block` |
| Constants | `SCREAMING_SNAKE_CASE` | `ROOT_BLOCK`, `FLUSH_MICROTASK`, `DERIVED` |
| Files | `kebab-case` | `css-analyze.js`, `source-map-utils.js` |
| Component files | `PascalCase` | `Button.ripple`, `TodoList.ripple` |
| Classes | `PascalCase` | `Scope`, `RippleArray`, `Output` |
| Type parameters | Single uppercase | `V` in `Tracked<V>`, `T` in generics |
### Hot Path Optimizations
In performance-critical runtime code, short property names are used to minimize
bundle size:
```javascript
// Block structure uses short names
block.p; // parent
block.t; // teardown function
block.d; // dependencies
block.f; // flags
block.s; // state
block.c; // context
```
### General Guidelines
1. **Consistency:** Look for similar implementations before adding new code
2. **No abbreviations** in variable names (except hot path optimizations above)
3. **Prefer `const`** over `let` when value won't be reassigned
4. **Use `var`** only in specific runtime hot paths for performance
5. **Comments:** Add comments for complex logic, not obvious code
## Tips for Working with the Codebase
### Compiler work
- Parser changes go in `phases/1-parse/`, modify `RipplePlugin` for new syntax
- Scope-related changes in `scope.js` - track bindings with appropriate `kind`
- CSS changes: `css-analyze.js` for parsing, `prune.js` for dead code elimination
- Code generation: separate files for `client/` and `server/` transforms
### Runtime work
- Reactivity: `runtime.js` is the core, understand
`tracked()`/`derived()`/`get()`/`set()`
- New control flow: add to both client (`internal/client/`) and may need server
support
- DOM operations: `render.js` for attribute/text updates, `operations.js` for
traversal
- Events: delegation in `events.js`, check `DELEGATED_EVENTS` constant
### Editor plugins
- Language server plugins in `packages/language-server/src/`
- VS Code extension entry: `packages/vscode-plugin/src/extension.js`
- TypeScript plugin: `packages/typescript-plugin/src/` for IDE integration
### Prettier plugin
The Prettier plugin (`packages/prettier-plugin/src/index.js`) formats `.ripple`
files using **AST-based formatting**, not string manipulation.
#### Architecture
The plugin exports three objects required by Prettier:
| Export | Purpose |
| ----------- | ------------------------------------------------------------------ |
| `languages` | Declares `.ripple` extension and parser name |
| `parsers` | Uses Ripple's compiler (`parse()`) to create ESTree-compatible AST |
| `printers` | Contains `print`, `embed`, and `getVisitorKeys` functions |
**AST-based approach:**
- Parser produces ESTree AST with Ripple extensions (Component, Element,
TrackedExpression, etc.)
- Printer recursively walks AST nodes via `printRippleNode()` switch statement
- Uses Prettier's `doc.builders` API (`concat`, `join`, `group`, `indent`, `line`,
`hardline`, `softline`, `ifBreak`)
#### Comment handling
Comments are attached to AST nodes and printed via three mechanisms:
| Comment Type | Property | Handling |
| ----------------- | ----------------------- | ----------------------------------------- |
| Leading comments | `node.leadingComments` | Printed before node content |
| Trailing comments | `node.trailingComments` | Inline via `lineSuffix()` or on next line |
| Inner comments | `node.innerComments` | Printed inside empty blocks/elements |
Element-level comment helpers:
- `getElementLeadingComments(node)` - extracts comments for JSX elements
- `createElementLevelCommentParts(comments)` - formats with proper spacing
#### Options
Prettier options are accessed from the `options` parameter:
| Option | Helper function | Usage |
| ------------------------ | ----------------------- | ------------------------------------ |
| `singleQuote` | `formatStringLiteral()` | Quote style for string literals |
| `jsxSingleQuote` | — | Quote style for JSX attribute values |
| `semi` | `semi()` | Semicolon insertion |
| `trailingComma` | `shouldPrintComma()` | Trailing commas in arrays/objects |
| `useTabs` / `tabWidth` | `createIndent()` | Indentation style |
| `singleAttributePerLine` | — | JSX attribute line breaking |
| `bracketSameLine` | — | JSX closing bracket position |
#### Context passing via `args`
The `args` parameter passes context for conditional formatting:
```javascript
// Examples of context flags
{
isInAttribute: true;
} // Compact object formatting in attributes
{
isInArray: true;
} // Array element context
{
allowInlineObject: true;
} // Allow single-line objects
{
isConditionalTest: true;
} // Binary/logical in conditional test
{
suppressLeadingComments: true;
} // Skip comment printing
```
#### Adding new node types
When encountering `/* Unknown: NodeType */` in formatter output:
1. **Identify the missing node type** from the comment (e.g., `TSDeclareFunction`)
2. **Add a case** in the `printRippleNode` switch statement:
```javascript
case 'TSDeclareFunction':
nodeContent = printTSDeclareFunction(node, path, options, print);
break;
```
3. **Implement the print function** following existing patterns (see
`printFunctionDeclaration` as reference)
4. **Add a test** in `packages/prettier-plugin/src/index.test.js`
#### Common patterns
- Use `path.call(print, 'childNode')` to recursively print child nodes
- Use `concat([...])` to join parts, `group()` for line breaking
- Check `node.typeParameters`, `node.returnType` for TypeScript annotations
- All functions use JSDoc type annotations with proper types (no `any`/`unknown`)
### Testing
- Client tests: create `.test.ripple` files in `packages/ripple/tests/client/`
- Server tests: create `.test.ripple` files in `packages/ripple/tests/server/`
- Use `setup-client.js` / `setup-server.js` for test environment setup
================================================
FILE: .github/workflows/ci.yml
================================================
name: CI
on:
push:
branches: [main, develop]
tags: ["!**"]
paths:
- "packages/**"
- "package.json"
- "pnpm-lock.yaml"
- "pnpm-workspace.yaml"
- "vitest.config.js"
pull_request:
branches: [main, develop]
tags: ["!**"]
paths:
- "packages/**"
- "package.json"
- "pnpm-lock.yaml"
- "pnpm-workspace.yaml"
- "vitest.config.js"
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [20, 22, 24]
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install pnpm
uses: pnpm/action-setup@v4
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
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@v4
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@v4
- name: Install pnpm
uses: pnpm/action-setup@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: "pnpm"
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Check formatting
run: pnpm format:check
================================================
FILE: .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@v4
- name: Install pnpm
uses: pnpm/action-setup@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "20"
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
================================================
FILE: .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 }}
================================================
FILE: .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@v3
- name: Build and generate
uses: live-codes/preview-in-livecodes@v1
================================================
FILE: .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:
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.collaborator-approved }}
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.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@v4
- name: Install pnpm
uses: pnpm/action-setup@v4
- name: Setup Node.js
uses: actions/setup-node@v4
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'
================================================
FILE: .github/workflows/provenance.yml
================================================
on:
push:
branches: [main, develop]
tags: ["!**"]
paths: ["packages/**"]
pull_request:
branches: ["main"]
permissions:
contents: read
name: Check for NPM Provenance Downgrade
jobs:
check-provenance:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Check provenance downgrades
uses: danielroe/provenance-action@main
id: check
with:
fail-on-provenance-change: true # optional, default: false
# lockfile: pnpm-lock.yaml # optional, auto-detects
# base-ref: origin/main # optional, default: origin/main
# fail-on-downgrade: true # optional, default: true
- name: Print result
run: "echo 'Downgraded: ${{ steps.check.outputs.downgraded }}'"
================================================
FILE: .github/workflows/release.yml
================================================
name: Release
on:
push:
branches:
- main
concurrency:
group: ${{ github.workflow }}
permissions: {}
jobs:
release:
if: github.repository == 'Ripple-TS/ripple'
permissions:
contents: write
id-token: write
pull-requests: write
name: Release
runs-on: ubuntu-latest
steps:
- name: Checkout Repo
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Install pnpm
uses: pnpm/action-setup@v4
- 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: Create Release Pull Request or Publish to npm
id: changesets
uses: changesets/action@v1
with:
version: pnpm changeset:version
publish: pnpm changeset:publish
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_CONFIG_PROVENANCE: true
================================================
FILE: .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@v4
- name: Install pnpm
uses: pnpm/action-setup@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: pnpm
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Check RuleSync is up to date
run: pnpm rules:check
================================================
FILE: .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@v4
- name: Install pnpm
uses: pnpm/action-setup@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 24
cache: "pnpm"
- name: Install deps w/ yarn
working-directory: ./packages/vscode-plugin
run: yarn install
- name: Build VSIX
working-directory: ./packages/vscode-plugin
run: pnpx @vscode/vsce package
- name: Upload VSIX
uses: actions/upload-artifact@v4
with:
name: vscode-plugin VSIX
path: ./packages/vscode-plugin/*.vsix
publish-vsm:
runs-on: ubuntu-latest
needs: build
steps:
- name: Download VSIX
uses: actions/download-artifact@v5
with:
name: vscode-plugin VSIX
- name: Install pnpm
uses: pnpm/action-setup@v4
- name: Publish to VSM
run: pnpx -- @vscode/vsce publish -i *.vsix
env:
VSCE_PAT: ${{ secrets.VSM_TOKEN }}
publish-ovsx:
runs-on: ubuntu-latest
needs: build
steps:
- name: Download VSIX
uses: actions/download-artifact@v5
with:
name: vscode-plugin VSIX
- name: Install pnpm
uses: pnpm/action-setup@v4
- name: Publish to OVSX
run: pnpx ovsx publish *.vsix
env:
OVSX_PAT: ${{ secrets.OVSX_TOKEN }}
================================================
FILE: .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@v4
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@v4
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: 24.x
cache: "pnpm"
- name: Install deps w/ pnpm
working-directory: ./packages/vscode-plugin
run: pnpm install
- name: Build VSIX
working-directory: ./packages/vscode-plugin
run: pnpm run build-and-package
- name: Upload VSIX
uses: actions/upload-artifact@v4
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@v5
with:
name: vscode-plugin VSIX
- name: Install pnpm
uses: pnpm/action-setup@v4
- name: Publish to VSM
run: pnpx -- @vscode/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@v5
with:
name: vscode-plugin VSIX
- name: Install pnpm
uses: pnpm/action-setup@v4
- name: Publish to OVSX
run: pnpx ovsx publish *.vsix
env:
OVSX_PAT: ${{ secrets.OVSX_TOKEN }}
================================================
FILE: .gitignore
================================================
# Dependency directories
node_modules/
# IDE related
.idea
# Test coverage
coverage
*.lcov
packages/vscode-plugin/*.vsix
playground/src
website/.vitepress/dist/
website/.vitepress/cache/
# 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
# Chrome Debugger
.chrome-debug-profile/
tmp
dist
debug
# Temporary folders
tmp/
temp/
================================================
FILE: .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\"\n\nexport default component App() {\n <div class=\"container\">\n let count = #ripple.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 }"
}
}
}
================================================
FILE: .prettierignore
================================================
# pnpm files - can have formatting differences between environments
pnpm-lock.yaml
pnpm-workspace.yaml
# RuleSync generated files
CLAUDE.md
GEMINI.md
AGENTS.md
.github/copilot-instructions.md
.cursor/
# Changesets
.changeset/
# Build outputs
**/dist/
**/build/
# Compiled test files (generated by build scripts)
packages/ripple/tests/hydration/compiled/
# Dependencies
**/node_modules/
# Editor/IDE generated files
**/.cache/
**/coverage/
# Generated test files
packages/ripple/tests/hydration/compiled/
================================================
FILE: .prettierrc
================================================
{
"useTabs": true,
"tabWidth": 2,
"singleQuote": true,
"jsxSingleQuote": false,
"printWidth": 100,
"plugins": ["@ripple-ts/prettier-plugin"],
"overrides": [
{
"files": ["*.ripple"],
"options": {
"bracketSameLine": false,
"parser": "ripple"
}
},
{
"files": ["**/*.md"],
"options": {
"useTabs": false,
"printWidth": 82,
"proseWrap": "always"
}
},
{
"files": ["**/*.json"],
"options": {
"useTabs": false
}
},
{
"files": ["**/*.yml", "**/*.yaml"],
"options": {
"singleQuote": false
}
}
]
}
================================================
FILE: .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 UI framework that combines the best parts of React, Solid,
and Svelte. Created by Dominic Gannaway ([@trueadm](https://github.com/trueadm)),
Ripple is designed to be JS/TS-first with its own `.ripple` file extension that
fully supports TypeScript.
## Documentation
For comprehensive Ripple syntax, components, reactivity, and API documentation,
see:
- **[website/public/llms.txt](website/public/llms.txt)** - Full LLM-optimized
documentation
- **[README.md](README.md)** - Project overview and quick start
- **[CONTRIBUTING.md](CONTRIBUTING.md)** - Contribution guidelines
## RuleSync
This project uses [RuleSync](https://github.com/dyoshikawa/rulesync) to maintain a
single source of truth for AI agent instructions. The canonical rules are in
`.rulesync/rules/`, which are automatically generated to tool-specific locations:
| Agent | Generated File |
| -------------- | --------------------------------- |
| Claude Code | `CLAUDE.md` |
| GitHub Copilot | `.github/copilot-instructions.md` |
| Cursor | `.cursor/rules/project.mdc` |
| Gemini CLI | `GEMINI.md` |
| AGENTS.md | `AGENTS.md` |
**To regenerate after editing `.rulesync/rules/`:**
```bash
pnpm rules:generate
```
This runs automatically on `pnpm install` via the `prepare` script.
## Project Structure
This is a pnpm monorepo. Key packages are marked with `*`.
```
packages/
├── ripple/* # Core framework
│ └── src/
│ ├── compiler/ # Compilation pipeline (see Compiler Architecture)
│ │ ├── phases/
│ │ │ ├── 1-parse/ # Acorn-based parser with RipplePlugin
│ │ │ ├── 2-analyze/ # Scope analysis, CSS pruning, validation
│ │ │ └── 3-transform/# Client/server code generation
│ │ ├── scope.js # Scope and binding management
│ │ ├── types/ # AST type definitions
│ │ └── utils.js # Compiler utilities
│ ├── runtime/ # Runtime library (see Runtime Architecture)
│ │ ├── internal/
│ │ │ ├── client/ # DOM operations, reactivity, events
│ │ │ └── server/ # SSR string generation
│ │ ├── index-client.js # Client entry (browser)
│ │ └── index-server.js # Server entry (SSR)
│ └── server/ # Server-side rendering utilities
├── language-server/* # LSP implementation via Volar framework
├── vscode-plugin/* # VS Code extension (uses language-server)
├── typescript-plugin/* # TypeScript language service plugin
├── eslint-plugin/* # ESLint rules for Ripple
├── eslint-parser/* # ESLint parser for .ripple files
├── prettier-plugin/* # Prettier formatting support
├── vite-plugin/* # Vite build integration
├── rollup-plugin/ # Rollup build integration
├── cli/* # CLI tool (@ripple-ts/cli)
├── create-ripple/ # Project scaffolding (npx create-ripple)
├── compat-react/* # React interoperability layer
├── tree-sitter/* # Tree-sitter grammar for syntax highlighting
├── intellij-plugin/ # IntelliJ/WebStorm support
├── nvim-plugin/ # Neovim support
├── sublime-text-plugin/ # Sublime Text support
├── zed-plugin/ # Zed editor support
└── textmate/ # TextMate grammar (shared by editors)
playground/ # Development playground
website/ # Documentation website
templates/ # Project templates (basic, etc.)
scripts/ # Build and maintenance scripts
```
## Compiler Architecture
The compiler transforms `.ripple` files through three phases:
```
Source Code (.ripple) → Parse → Analyze → Transform → Output (JS + CSS)
```
### Phase 1: Parse (`packages/ripple/src/compiler/phases/1-parse/`)
**Parser:** Acorn extended with `@sveltejs/acorn-typescript` and custom
`RipplePlugin`
**Ripple-specific syntax handled:**
- `component` keyword for component declarations
- JSX with special handling for `@` tracked expressions
- `#server` blocks for server-only code
- `#ripple[]` (RippleArray shorthand), `#ripple{}` (RippleObject shorthand),
`#ripple.map()` (RippleMap), `#ripple.set()` (RippleSet),` #ripple.array()`
(RippleArray), `#ripple.object()` (RippleObject), `#ripple.url()` (RippleURL),
`#ripple.urlSearchParams()` (RippleURLSearchParams), `#ripple.Date()`
(RippleDate), `#ripple.Context()` (RippleContext), `#ripple.mediaQuery()`
(MediaQuery) `#ripple.track()` (track()), `#ripple.trackSplit()` (trackSplit())
`#ripple.untrack()` (untrack()), `#ripple.effect()` (effect()),
- `#style` identifier for scoped CSS classes
**Output:** ESTree-compatible AST with Ripple extensions
### Phase 2: Analyze (`packages/ripple/src/compiler/phases/2-analyze/`)
| File | Purpose |
| ---------------- | ----------------------------------------------- |
| `index.js` | Main analysis orchestration |
| `css-analyze.js` | CSS selector analysis, `:global()` handling |
| `prune.js` | Remove unused CSS rules based on template usage |
| `validation.js` | HTML nesting validation |
**Key operations:**
- **Scope creation:** `scope.js` creates scope chains tracking bindings (import,
prop, let, const, function, component, for_pattern)
- **Reactivity analysis:** Marks tracked expressions, derives tracking metadata
- **CSS scoping:** Hash-based class names via `CSS_HASH_IDENTIFIER`
- **`#style` analysis:** Validates usage context, collects referenced classes,
cross-checks against standalone CSS selectors
- **Server block analysis:** Tracks exports from `#server` blocks
### Phase 3: Transform (`packages/ripple/src/compiler/phases/3-transform/`)
**Client transform** (`client/index.js`):
- Generates runtime calls: `_$_.render()`, `_$_.if()`, `_$_.for()`,
`_$_.switch()`, etc.
- Creates template strings for static HTML
- Sets up event delegation
- Injects CSS hash for scoped styles
**Server transform** (`server/index.js`):
- Generates string concatenation for SSR output
- Handles `#server` block code execution
- Registers CSS for hydration
- Wraps control flow blocks with hydration comment markers
### SSR vs Client Compilation
The same `.ripple` module produces different output depending on the compilation
mode, controlled by `options.mode` in the compiler:
```javascript
// compiler/index.js
const result =
options.mode === 'server'
? transform_server(filename, source, analysis, options?.minify_css ?? false)
: transform_client(
filename,
source,
analysis,
false,
options?.minify_css ?? false,
);
```
| Aspect | Client Transform | Server Transform |
| ---------------- | ------------------------------------------ | ---------------------------------------- |
| **Output** | Runtime calls (`_$_.render()`, `_$_.if()`) | String concatenation (`__output.push()`) |
| **Templates** | DOM template literals, `cloneNode()` | Escaped HTML strings |
| **Reactivity** | Block scheduling, dirty checking | Immediate execution, no scheduling |
| **Control flow** | Creates branch blocks, DOM diffing | Wraps with `<!--[-->`/`<!--]-->` markers |
| **Events** | Delegation setup (`_$_.delegate()`) | Omitted entirely |
| **CSS** | Injects hash for scoping | Registers CSS hash via `register_css()` |
**Vite plugin** compiles modules twice for SSR apps - once with `mode: 'client'`
and once with `mode: 'server'`.
### Key AST Node Types (`packages/ripple/src/compiler/types/`)
| Node Type | Description |
| ------------------------ | -------------------------------------------------------- |
| `Component` | Component declaration with `id`, `params`, `body`, `css` |
| `Element` | HTML/SVG element with `id`, `attributes`, `children` |
| `Text` | Text node wrapping an expression |
| `ServerBlock` | `#server { ... }` block with exports tracking |
| `TrackedExpression` | `@expression` tracked reactive value |
| `RippleArrayExpression` | `#[...]` tracked array literal |
| `RippleObjectExpression` | `#{...}` tracked object literal |
| `Attribute` | Element attribute with `name`, `value`, `shorthand` |
| `RefAttribute` | `ref={...}` reference binding |
| `SpreadAttribute` | `{...props}` spread |
| `StyleIdentifier` | `#style` compile-time identifier for scoped CSS classes |
| `CSS.StyleSheet` | Parsed CSS with `hash` for scoping |
## Runtime Architecture
### Client Runtime (`packages/ripple/src/runtime/internal/client/`)
| Module | Responsibility |
| --------------- | ------------------------------------------------------------------------------- |
| `runtime.js` | Core reactivity: `tracked()`, `derived()`, `get()`, `set()`, block scheduling |
| `blocks.js` | Block creation: `render()`, `branch()`, `effect()`, `root()`, `destroy_block()` |
| `render.js` | DOM operations: `set_text()`, `set_class()`, `set_style()`, `set_attribute()` |
| `template.js` | Template instantiation: `template()`, `append()`, `assign_nodes()` |
| `operations.js` | DOM traversal: `child()`, `sibling()`, `create_text()` |
| `events.js` | Event handling: `event()`, `delegate()`, event propagation |
| `hydration.js` | SSR hydration: `hydrating`, `hydrate_node`, `hydrate_next()` |
| `bindings.js` | Two-way bindings for form elements |
| `context.js` | Context API implementation |
### Control Flow Blocks
| Block | File | Purpose |
| -------------- | -------------- | ------------------------------------------------------- |
| `if_block` | `if.js` | Conditional rendering with branch switching |
| `for_block` | `for.js` | List rendering with reconciliation (ref-based or keyed) |
| `switch_block` | `switch.js` | Multi-branch rendering |
| `try_block` | `try.js` | Error boundaries + async suspense |
| `composite` | `composite.js` | Dynamic component rendering (`<@Component />`) |
| `portal` | `portal.js` | Render children to different DOM location |
### Reactivity System
**Core concepts:**
- `tracked(value, block)` - Creates a tracked reactive value (`Tracked<V>`)
- `derived(fn, block)` - Creates a computed/derived value
- `get(tracked)` - Reads value, registers dependency
- `set(tracked, value)` - Updates value, schedules updates
**Implementation details:**
- Dependencies tracked via linked list structure: `{ c, t, n }` (consumer,
tracked, next)
- Dirty checking with clock-based versioning
- Block flags in `constants.js`: `ROOT_BLOCK`, `RENDER_BLOCK`, `EFFECT_BLOCK`,
`BRANCH_BLOCK`, etc.
### Reactive Collections (`packages/ripple/src/runtime/`)
| Collection | File | Description |
| -------------- | ----------- | ------------------------------------------- |
| `RippleArray` | `array.js` | Fully reactive array with all Array methods |
| `RippleObject` | `object.js` | Shallow reactive object |
| `RippleMap` | `map.js` | Reactive Map |
| `RippleSet` | `set.js` | Reactive Set |
| `RippleDate` | `date.js` | Reactive Date |
### Server Runtime (`packages/ripple/src/runtime/internal/server/`)
- String-based output via `Output` class (concatenates `head` and `body`)
- Simplified reactivity (no block scheduling, immediate execution)
- CSS registration for hydration markers
- Escape utilities for safe HTML output
### Hydration Mechanism
Hydration allows the client to "adopt" server-rendered HTML without re-rendering,
using comment markers to identify dynamic regions.
**Comment Markers (inserted by server transform):**
| Marker | Constant | Purpose |
| ----------- | ----------------- | -------------------------------------------- |
| `<!--[-->` | `HYDRATION_START` | Opens a dynamic block (if, for, switch, try) |
| `<!--]-->` | `HYDRATION_END` | Closes a dynamic block |
| `<!--[!-->` | `HYDRATION_ELSE` | Marks else/fallback branch boundary |
**Server-side generation:**
```javascript
// Server transform wraps control flow with markers
__output.push('<!--[-->'); // HYDRATION_START
// ... render content ...
__output.push('<!--]-->'); // HYDRATION_END
```
**Client-side hydration
(`packages/ripple/src/runtime/internal/client/hydration.js`):**
```javascript
export let hydrating = false; // True during hydration phase
export let hydrate_node = null; // Current DOM node being hydrated
```
**Key hydration functions:**
| Function | Purpose |
| ------------------------ | --------------------------------- |
| `set_hydrating(value)` | Enable/disable hydration mode |
| `set_hydrate_node(node)` | Set the current node pointer |
| `hydrate_next()` | Advance to next sibling node |
| `pop(node)` | Reset hydrate_node after mounting |
**Hydration flow:**
1. Server renders HTML with `<!--[-->` / `<!--]-->` markers around dynamic blocks
2. Client receives HTML, `hydrating = true` is set
3. Runtime walks DOM using `hydrate_node`, matching structure to component tree
4. Instead of creating elements, runtime "claims" existing DOM nodes
5. Comment markers guide block boundary detection
6. After hydration completes, `hydrating` is set back to `false`
## Language Server (`packages/language-server/src/`)
Built on **Volar framework** with TypeScript integration.
| Plugin | File | Purpose |
| -------------- | --------------------------------- | --------------------------------- |
| Completion | `completionPlugin.js` | Auto-completion for Ripple syntax |
| Definition | `definitionPlugin.js` | Go-to-definition |
| Hover | `hoverPlugin.js` | Hover information |
| Diagnostics | `compileErrorDiagnosticPlugin.js` | Compile-time error diagnostics |
| TS Diagnostics | `typescriptDiagnosticPlugin.js` | TypeScript diagnostic filtering |
| Auto-insert | `autoInsertPlugin.js` | Auto-insert completions |
| Highlight | `documentHighlightPlugin.js` | Document highlights |
**Integration:** Uses `@ripple-ts/typescript-plugin` for TypeScript language
service.
## Editor Plugins
All editor plugins use `@ripple-ts/language-server` internally:
| Editor | Package | Notes |
| ----------------- | ---------------------- | -------------------------------- |
| VS Code | `vscode-plugin/` | Primary development target |
| IntelliJ/WebStorm | `intellij-plugin/` | TextMate syntax + LSP via LSP4IJ |
| Neovim | `nvim-plugin/` | Tree-sitter + LSP |
| Sublime Text | `sublime-text-plugin/` | LSP package |
| Zed | `zed-plugin/` | Tree-sitter queries |
**Tree-sitter queries:** Located in `packages/tree-sitter/queries/`, copied to
nvim/zed plugins via `pnpm copy-tree-sitter-queries`.
## Validating Changes
**CRITICAL: Use pnpm for all package management. Do NOT use npm or yarn.**
### Changesets
For user-facing changes, add a changeset before committing:
```bash
pnpm changeset
```
This creates a markdown file in `.changeset/` describing the change. Select
affected packages and semver bump type (patch/minor/major). The file is committed
with your changes.
**Add a changeset for:** bug fixes, new features, breaking changes, API changes.
**Skip changesets for:** docs-only, internal refactoring, tests, CI/tooling.
### Required Validation Steps
After making changes, run these commands:
```bash
# Install dependencies (if needed)
pnpm install
# Format code with Prettier
pnpm format
# Check formatting without changes
pnpm format:check
# Run all tests
pnpm test
# Run specific test project
pnpm test --project ripple-client
pnpm test --project ripple-server
pnpm test --project eslint-plugin
pnpm test --project prettier-plugin
```
### Test Projects (from `vitest.config.js`)
| Project | Tests | Environment |
| ------------------ | ----------------------------------------------- | ----------- |
| `ripple-client` | `packages/ripple/tests/client/**/*.test.ripple` | jsdom |
| `ripple-server` | `packages/ripple/tests/server/**/*.test.ripple` | node |
| `ripple-hydration` | `packages/ripple/tests/hydration/**/*.test.js` | jsdom |
| `eslint-plugin` | `packages/eslint-plugin/tests/**/*.test.ts` | jsdom |
| `eslint-parser` | `packages/eslint-parser/tests/**/*.test.ts` | jsdom |
| `prettier-plugin` | `packages/prettier-plugin/src/*.test.js` | jsdom |
| `cli` | `packages/cli/tests/**/*.test.js` | jsdom |
| `compat-react` | `packages/compat-react/tests/**/*.test.ripple` | jsdom |
### Test Architecture
**Ripple test files (`.test.ripple`):**
Test files are valid Ripple modules that export a default test component. The Vite
plugin transforms them before Vitest runs:
```ripple
// Example: packages/ripple/tests/client/reactivity.test.ripple
import { describe, it, expect } from 'vitest';
component default() {
describe('tracked', () => {
it('updates when value changes', async () => {
let count = #ripple.track(0);
// test implementation
});
});
}
```
**Setup files (`packages/ripple/tests/`):**
| File | Purpose |
| ----------------- | ----------------------------------------------- |
| `setup-client.js` | Client test setup: DOM utilities, flush helpers |
| `setup-server.js` | Server test setup: Output class, render helpers |
**Hydration tests (`packages/ripple/tests/hydration/`):**
Hydration tests verify client/server output consistency:
1. Server compiles and renders to HTML string with hydration markers
2. Client receives pre-rendered HTML, sets `hydrating = true`
3. Client walks DOM, claiming existing nodes instead of creating new ones
4. Tests verify final DOM matches expected state
```javascript
// Typical hydration test pattern
const server_html = render_server(Component); // With <!--[--> markers
container.innerHTML = server_html;
hydrate(Component, container); // Claims existing nodes
expect(container.innerHTML).toBe(expected);
```
### Development Playground
```bash
cd playground
pnpm dev # Start dev server (Vite)
pnpm lint # Lint playground code
```
## Code Conventions
### Package Manager
**pnpm is required** (`engines` in package.json enforces this). Do NOT use npm or
yarn.
### Language & Types
- **Internal code:** JavaScript (`.js`) with JSDoc type annotations — NOT
TypeScript
- **Type definitions:** TypeScript `.d.ts` files in `types/` directories for
public API
- **JSDoc imports:** Use `@import` syntax at top of file:
```javascript
/** @import { Block, Tracked, Derived } from '#client' */
/** @import * as AST from 'estree' */
```
- **JSDoc annotations:** Use `@param`, `@returns`, `@type` for all functions:
```javascript
/**
* @param {Block} block - The block to destroy
* @returns {void}
*/
export function destroy_block(block) { ... }
```
### Naming Conventions
| Context | Style | Examples |
| --------------- | ---------------------- | ------------------------------------------ |
| Variables | `snake_case` | `active_block`, `is_mutating_allowed` |
| Functions | `snake_case` | `create_scopes`, `set_active_block` |
| Constants | `SCREAMING_SNAKE_CASE` | `ROOT_BLOCK`, `FLUSH_MICROTASK`, `DERIVED` |
| Files | `kebab-case` | `css-analyze.js`, `source-map-utils.js` |
| Component files | `PascalCase` | `Button.ripple`, `TodoList.ripple` |
| Classes | `PascalCase` | `Scope`, `RippleArray`, `Output` |
| Type parameters | Single uppercase | `V` in `Tracked<V>`, `T` in generics |
### Hot Path Optimizations
In performance-critical runtime code, short property names are used to minimize
bundle size:
```javascript
// Block structure uses short names
block.p; // parent
block.t; // teardown function
block.d; // dependencies
block.f; // flags
block.s; // state
block.c; // context
```
### General Guidelines
1. **Consistency:** Look for similar implementations before adding new code
2. **No abbreviations** in variable names (except hot path optimizations above)
3. **Prefer `const`** over `let` when value won't be reassigned
4. **Use `var`** only in specific runtime hot paths for performance
5. **Comments:** Add comments for complex logic, not obvious code
## Tips for Working with the Codebase
### Compiler work
- Parser changes go in `phases/1-parse/`, modify `RipplePlugin` for new syntax
- Scope-related changes in `scope.js` - track bindings with appropriate `kind`
- CSS changes: `css-analyze.js` for parsing, `prune.js` for dead code elimination
- Code generation: separate files for `client/` and `server/` transforms
### Runtime work
- Reactivity: `runtime.js` is the core, understand
`tracked()`/`derived()`/`get()`/`set()`
- New control flow: add to both client (`internal/client/`) and may need server
support
- DOM operations: `render.js` for attribute/text updates, `operations.js` for
traversal
- Events: delegation in `events.js`, check `DELEGATED_EVENTS` constant
### Editor plugins
- Language server plugins in `packages/language-server/src/`
- VS Code extension entry: `packages/vscode-plugin/src/extension.js`
- TypeScript plugin: `packages/typescript-plugin/src/` for IDE integration
### Prettier plugin
The Prettier plugin (`packages/prettier-plugin/src/index.js`) formats `.ripple`
files using **AST-based formatting**, not string manipulation.
#### Architecture
The plugin exports three objects required by Prettier:
| Export | Purpose |
| ----------- | ------------------------------------------------------------------ |
| `languages` | Declares `.ripple` extension and parser name |
| `parsers` | Uses Ripple's compiler (`parse()`) to create ESTree-compatible AST |
| `printers` | Contains `print`, `embed`, and `getVisitorKeys` functions |
**AST-based approach:**
- Parser produces ESTree AST with Ripple extensions (Component, Element,
TrackedExpression, etc.)
- Printer recursively walks AST nodes via `printRippleNode()` switch statement
- Uses Prettier's `doc.builders` API (`concat`, `join`, `group`, `indent`, `line`,
`hardline`, `softline`, `ifBreak`)
#### Comment handling
Comments are attached to AST nodes and printed via three mechanisms:
| Comment Type | Property | Handling |
| ----------------- | ----------------------- | ----------------------------------------- |
| Leading comments | `node.leadingComments` | Printed before node content |
| Trailing comments | `node.trailingComments` | Inline via `lineSuffix()` or on next line |
| Inner comments | `node.innerComments` | Printed inside empty blocks/elements |
Element-level comment helpers:
- `getElementLeadingComments(node)` - extracts comments for JSX elements
- `createElementLevelCommentParts(comments)` - formats with proper spacing
#### Options
Prettier options are accessed from the `options` parameter:
| Option | Helper function | Usage |
| ------------------------ | ----------------------- | ------------------------------------ |
| `singleQuote` | `formatStringLiteral()` | Quote style for string literals |
| `jsxSingleQuote` | — | Quote style for JSX attribute values |
| `semi` | `semi()` | Semicolon insertion |
| `trailingComma` | `shouldPrintComma()` | Trailing commas in arrays/objects |
| `useTabs` / `tabWidth` | `createIndent()` | Indentation style |
| `singleAttributePerLine` | — | JSX attribute line breaking |
| `bracketSameLine` | — | JSX closing bracket position |
#### Context passing via `args`
The `args` parameter passes context for conditional formatting:
```javascript
// Examples of context flags
{
isInAttribute: true;
} // Compact object formatting in attributes
{
isInArray: true;
} // Array element context
{
allowInlineObject: true;
} // Allow single-line objects
{
isConditionalTest: true;
} // Binary/logical in conditional test
{
suppressLeadingComments: true;
} // Skip comment printing
```
#### Adding new node types
When encountering `/* Unknown: NodeType */` in formatter output:
1. **Identify the missing node type** from the comment (e.g., `TSDeclareFunction`)
2. **Add a case** in the `printRippleNode` switch statement:
```javascript
case 'TSDeclareFunction':
nodeContent = printTSDeclareFunction(node, path, options, print);
break;
```
3. **Implement the print function** following existing patterns (see
`printFunctionDeclaration` as reference)
4. **Add a test** in `packages/prettier-plugin/src/index.test.js`
#### Common patterns
- Use `path.call(print, 'childNode')` to recursively print child nodes
- Use `concat([...])` to join parts, `group()` for line breaking
- Check `node.typeParameters`, `node.returnType` for TypeScript annotations
- All functions use JSDoc type annotations with proper types (no `any`/`unknown`)
### Testing
- Client tests: create `.test.ripple` files in `packages/ripple/tests/client/`
- Server tests: create `.test.ripple` files in `packages/ripple/tests/server/`
- Use `setup-client.js` / `setup-server.js` for test environment setup
================================================
FILE: .vscode/launch.json
================================================
{
"version": "0.2.1",
"configurations": [
{
"name": "VSCode Extension",
"type": "extensionHost",
"request": "launch",
"autoAttachChildProcesses": true,
"args": [
"--disable-extension=ripple-ts.ripple-ts-vscode-plugin",
"--extensionDevelopmentPath=${workspaceFolder}/packages/vscode-plugin/",
"${workspaceFolder}/playground"
],
"outFiles": ["${workspaceFolder}/packages/vscode-plugin/src/**/*.js"],
"sourceMaps": false,
"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": ""
}
]
}
================================================
FILE: .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,
"prettier.requireConfig": true,
"js/ts.implicitProjectConfig.checkJs": true,
"typescript.preferences.preferTypeOnlyAutoImports": true,
"typescript.preferences.useAliasesForRenames": false,
"javascript.preferences.importModuleSpecifierEnding": "js",
"[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"
}
}
================================================
FILE: .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"
}
]
}
================================================
FILE: 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 UI framework that combines the best parts of React, Solid,
and Svelte. Created by Dominic Gannaway ([@trueadm](https://github.com/trueadm)),
Ripple is designed to be JS/TS-first with its own `.ripple` file extension that
fully supports TypeScript.
## Documentation
For comprehensive Ripple syntax, components, reactivity, and API documentation,
see:
- **[website/public/llms.txt](website/public/llms.txt)** - Full LLM-optimized
documentation
- **[README.md](README.md)** - Project overview and quick start
- **[CONTRIBUTING.md](CONTRIBUTING.md)** - Contribution guidelines
## RuleSync
This project uses [RuleSync](https://github.com/dyoshikawa/rulesync) to maintain a
single source of truth for AI agent instructions. The canonical rules are in
`.rulesync/rules/`, which are automatically generated to tool-specific locations:
| Agent | Generated File |
| -------------- | --------------------------------- |
| Claude Code | `CLAUDE.md` |
| GitHub Copilot | `.github/copilot-instructions.md` |
| Cursor | `.cursor/rules/project.mdc` |
| Gemini CLI | `GEMINI.md` |
| AGENTS.md | `AGENTS.md` |
**To regenerate after editing `.rulesync/rules/`:**
```bash
pnpm rules:generate
```
This runs automatically on `pnpm install` via the `prepare` script.
## Project Structure
This is a pnpm monorepo. Key packages are marked with `*`.
```
packages/
├── ripple/* # Core framework
│ └── src/
│ ├── compiler/ # Compilation pipeline (see Compiler Architecture)
│ │ ├── phases/
│ │ │ ├── 1-parse/ # Acorn-based parser with RipplePlugin
│ │ │ ├── 2-analyze/ # Scope analysis, CSS pruning, validation
│ │ │ └── 3-transform/# Client/server code generation
│ │ ├── scope.js # Scope and binding management
│ │ ├── types/ # AST type definitions
│ │ └── utils.js # Compiler utilities
│ ├── runtime/ # Runtime library (see Runtime Architecture)
│ │ ├── internal/
│ │ │ ├── client/ # DOM operations, reactivity, events
│ │ │ └── server/ # SSR string generation
│ │ ├── index-client.js # Client entry (browser)
│ │ └── index-server.js # Server entry (SSR)
│ └── server/ # Server-side rendering utilities
├── language-server/* # LSP implementation via Volar framework
├── vscode-plugin/* # VS Code extension (uses language-server)
├── typescript-plugin/* # TypeScript language service plugin
├── eslint-plugin/* # ESLint rules for Ripple
├── eslint-parser/* # ESLint parser for .ripple files
├── prettier-plugin/* # Prettier formatting support
├── vite-plugin/* # Vite build integration
├── rollup-plugin/ # Rollup build integration
├── cli/* # CLI tool (@ripple-ts/cli)
├── create-ripple/ # Project scaffolding (npx create-ripple)
├── compat-react/* # React interoperability layer
├── tree-sitter/* # Tree-sitter grammar for syntax highlighting
├── intellij-plugin/ # IntelliJ/WebStorm support
├── nvim-plugin/ # Neovim support
├── sublime-text-plugin/ # Sublime Text support
├── zed-plugin/ # Zed editor support
└── textmate/ # TextMate grammar (shared by editors)
playground/ # Development playground
website/ # Documentation website
templates/ # Project templates (basic, etc.)
scripts/ # Build and maintenance scripts
```
## Compiler Architecture
The compiler transforms `.ripple` files through three phases:
```
Source Code (.ripple) → Parse → Analyze → Transform → Output (JS + CSS)
```
### Phase 1: Parse (`packages/ripple/src/compiler/phases/1-parse/`)
**Parser:** Acorn extended with `@sveltejs/acorn-typescript` and custom
`RipplePlugin`
**Ripple-specific syntax handled:**
- `component` keyword for component declarations
- JSX with special handling for `@` tracked expressions
- `#server` blocks for server-only code
- `#ripple[]` (RippleArray shorthand), `#ripple{}` (RippleObject shorthand),
`#ripple.map()` (RippleMap), `#ripple.set()` (RippleSet),` #ripple.array()`
(RippleArray), `#ripple.object()` (RippleObject), `#ripple.url()` (RippleURL),
`#ripple.urlSearchParams()` (RippleURLSearchParams), `#ripple.Date()`
(RippleDate), `#ripple.Context()` (RippleContext), `#ripple.mediaQuery()`
(MediaQuery) `#ripple.track()` (track()), `#ripple.trackSplit()` (trackSplit())
`#ripple.untrack()` (untrack()), `#ripple.effect()` (effect()),
- `#style` identifier for scoped CSS classes
**Output:** ESTree-compatible AST with Ripple extensions
### Phase 2: Analyze (`packages/ripple/src/compiler/phases/2-analyze/`)
| File | Purpose |
| ---------------- | ----------------------------------------------- |
| `index.js` | Main analysis orchestration |
| `css-analyze.js` | CSS selector analysis, `:global()` handling |
| `prune.js` | Remove unused CSS rules based on template usage |
| `validation.js` | HTML nesting validation |
**Key operations:**
- **Scope creation:** `scope.js` creates scope chains tracking bindings (import,
prop, let, const, function, component, for_pattern)
- **Reactivity analysis:** Marks tracked expressions, derives tracking metadata
- **CSS scoping:** Hash-based class names via `CSS_HASH_IDENTIFIER`
- **`#style` analysis:** Validates usage context, collects referenced classes,
cross-checks against standalone CSS selectors
- **Server block analysis:** Tracks exports from `#server` blocks
### Phase 3: Transform (`packages/ripple/src/compiler/phases/3-transform/`)
**Client transform** (`client/index.js`):
- Generates runtime calls: `_$_.render()`, `_$_.if()`, `_$_.for()`,
`_$_.switch()`, etc.
- Creates template strings for static HTML
- Sets up event delegation
- Injects CSS hash for scoped styles
**Server transform** (`server/index.js`):
- Generates string concatenation for SSR output
- Handles `#server` block code execution
- Registers CSS for hydration
- Wraps control flow blocks with hydration comment markers
### SSR vs Client Compilation
The same `.ripple` module produces different output depending on the compilation
mode, controlled by `options.mode` in the compiler:
```javascript
// compiler/index.js
const result =
options.mode === 'server'
? transform_server(filename, source, analysis, options?.minify_css ?? false)
: transform_client(
filename,
source,
analysis,
false,
options?.minify_css ?? false,
);
```
| Aspect | Client Transform | Server Transform |
| ---------------- | ------------------------------------------ | ---------------------------------------- |
| **Output** | Runtime calls (`_$_.render()`, `_$_.if()`) | String concatenation (`__output.push()`) |
| **Templates** | DOM template literals, `cloneNode()` | Escaped HTML strings |
| **Reactivity** | Block scheduling, dirty checking | Immediate execution, no scheduling |
| **Control flow** | Creates branch blocks, DOM diffing | Wraps with `<!--[-->`/`<!--]-->` markers |
| **Events** | Delegation setup (`_$_.delegate()`) | Omitted entirely |
| **CSS** | Injects hash for scoping | Registers CSS hash via `register_css()` |
**Vite plugin** compiles modules twice for SSR apps - once with `mode: 'client'`
and once with `mode: 'server'`.
### Key AST Node Types (`packages/ripple/src/compiler/types/`)
| Node Type | Description |
| ------------------------ | -------------------------------------------------------- |
| `Component` | Component declaration with `id`, `params`, `body`, `css` |
| `Element` | HTML/SVG element with `id`, `attributes`, `children` |
| `Text` | Text node wrapping an expression |
| `ServerBlock` | `#server { ... }` block with exports tracking |
| `TrackedExpression` | `@expression` tracked reactive value |
| `RippleArrayExpression` | `#[...]` tracked array literal |
| `RippleObjectExpression` | `#{...}` tracked object literal |
| `Attribute` | Element attribute with `name`, `value`, `shorthand` |
| `RefAttribute` | `ref={...}` reference binding |
| `SpreadAttribute` | `{...props}` spread |
| `StyleIdentifier` | `#style` compile-time identifier for scoped CSS classes |
| `CSS.StyleSheet` | Parsed CSS with `hash` for scoping |
## Runtime Architecture
### Client Runtime (`packages/ripple/src/runtime/internal/client/`)
| Module | Responsibility |
| --------------- | ------------------------------------------------------------------------------- |
| `runtime.js` | Core reactivity: `tracked()`, `derived()`, `get()`, `set()`, block scheduling |
| `blocks.js` | Block creation: `render()`, `branch()`, `effect()`, `root()`, `destroy_block()` |
| `render.js` | DOM operations: `set_text()`, `set_class()`, `set_style()`, `set_attribute()` |
| `template.js` | Template instantiation: `template()`, `append()`, `assign_nodes()` |
| `operations.js` | DOM traversal: `child()`, `sibling()`, `create_text()` |
| `events.js` | Event handling: `event()`, `delegate()`, event propagation |
| `hydration.js` | SSR hydration: `hydrating`, `hydrate_node`, `hydrate_next()` |
| `bindings.js` | Two-way bindings for form elements |
| `context.js` | Context API implementation |
### Control Flow Blocks
| Block | File | Purpose |
| -------------- | -------------- | ------------------------------------------------------- |
| `if_block` | `if.js` | Conditional rendering with branch switching |
| `for_block` | `for.js` | List rendering with reconciliation (ref-based or keyed) |
| `switch_block` | `switch.js` | Multi-branch rendering |
| `try_block` | `try.js` | Error boundaries + async suspense |
| `composite` | `composite.js` | Dynamic component rendering (`<@Component />`) |
| `portal` | `portal.js` | Render children to different DOM location |
### Reactivity System
**Core concepts:**
- `tracked(value, block)` - Creates a tracked reactive value (`Tracked<V>`)
- `derived(fn, block)` - Creates a computed/derived value
- `get(tracked)` - Reads value, registers dependency
- `set(tracked, value)` - Updates value, schedules updates
**Implementation details:**
- Dependencies tracked via linked list structure: `{ c, t, n }` (consumer,
tracked, next)
- Dirty checking with clock-based versioning
- Block flags in `constants.js`: `ROOT_BLOCK`, `RENDER_BLOCK`, `EFFECT_BLOCK`,
`BRANCH_BLOCK`, etc.
### Reactive Collections (`packages/ripple/src/runtime/`)
| Collection | File | Description |
| -------------- | ----------- | ------------------------------------------- |
| `RippleArray` | `array.js` | Fully reactive array with all Array methods |
| `RippleObject` | `object.js` | Shallow reactive object |
| `RippleMap` | `map.js` | Reactive Map |
| `RippleSet` | `set.js` | Reactive Set |
| `RippleDate` | `date.js` | Reactive Date |
### Server Runtime (`packages/ripple/src/runtime/internal/server/`)
- String-based output via `Output` class (concatenates `head` and `body`)
- Simplified reactivity (no block scheduling, immediate execution)
- CSS registration for hydration markers
- Escape utilities for safe HTML output
### Hydration Mechanism
Hydration allows the client to "adopt" server-rendered HTML without re-rendering,
using comment markers to identify dynamic regions.
**Comment Markers (inserted by server transform):**
| Marker | Constant | Purpose |
| ----------- | ----------------- | -------------------------------------------- |
| `<!--[-->` | `HYDRATION_START` | Opens a dynamic block (if, for, switch, try) |
| `<!--]-->` | `HYDRATION_END` | Closes a dynamic block |
| `<!--[!-->` | `HYDRATION_ELSE` | Marks else/fallback branch boundary |
**Server-side generation:**
```javascript
// Server transform wraps control flow with markers
__output.push('<!--[-->'); // HYDRATION_START
// ... render content ...
__output.push('<!--]-->'); // HYDRATION_END
```
**Client-side hydration
(`packages/ripple/src/runtime/internal/client/hydration.js`):**
```javascript
export let hydrating = false; // True during hydration phase
export let hydrate_node = null; // Current DOM node being hydrated
```
**Key hydration functions:**
| Function | Purpose |
| ------------------------ | --------------------------------- |
| `set_hydrating(value)` | Enable/disable hydration mode |
| `set_hydrate_node(node)` | Set the current node pointer |
| `hydrate_next()` | Advance to next sibling node |
| `pop(node)` | Reset hydrate_node after mounting |
**Hydration flow:**
1. Server renders HTML with `<!--[-->` / `<!--]-->` markers around dynamic blocks
2. Client receives HTML, `hydrating = true` is set
3. Runtime walks DOM using `hydrate_node`, matching structure to component tree
4. Instead of creating elements, runtime "claims" existing DOM nodes
5. Comment markers guide block boundary detection
6. After hydration completes, `hydrating` is set back to `false`
## Language Server (`packages/language-server/src/`)
Built on **Volar framework** with TypeScript integration.
| Plugin | File | Purpose |
| -------------- | --------------------------------- | --------------------------------- |
| Completion | `completionPlugin.js` | Auto-completion for Ripple syntax |
| Definition | `definitionPlugin.js` | Go-to-definition |
| Hover | `hoverPlugin.js` | Hover information |
| Diagnostics | `compileErrorDiagnosticPlugin.js` | Compile-time error diagnostics |
| TS Diagnostics | `typescriptDiagnosticPlugin.js` | TypeScript diagnostic filtering |
| Auto-insert | `autoInsertPlugin.js` | Auto-insert completions |
| Highlight | `documentHighlightPlugin.js` | Document highlights |
**Integration:** Uses `@ripple-ts/typescript-plugin` for TypeScript language
service.
## Editor Plugins
All editor plugins use `@ripple-ts/language-server` internally:
| Editor | Package | Notes |
| ----------------- | ---------------------- | -------------------------------- |
| VS Code | `vscode-plugin/` | Primary development target |
| IntelliJ/WebStorm | `intellij-plugin/` | TextMate syntax + LSP via LSP4IJ |
| Neovim | `nvim-plugin/` | Tree-sitter + LSP |
| Sublime Text | `sublime-text-plugin/` | LSP package |
| Zed | `zed-plugin/` | Tree-sitter queries |
**Tree-sitter queries:** Located in `packages/tree-sitter/queries/`, copied to
nvim/zed plugins via `pnpm copy-tree-sitter-queries`.
## Validating Changes
**CRITICAL: Use pnpm for all package management. Do NOT use npm or yarn.**
### Changesets
For user-facing changes, add a changeset before committing:
```bash
pnpm changeset
```
This creates a markdown file in `.changeset/` describing the change. Select
affected packages and semver bump type (patch/minor/major). The file is committed
with your changes.
**Add a changeset for:** bug fixes, new features, breaking changes, API changes.
**Skip changesets for:** docs-only, internal refactoring, tests, CI/tooling.
### Required Validation Steps
After making changes, run these commands:
```bash
# Install dependencies (if needed)
pnpm install
# Format code with Prettier
pnpm format
# Check formatting without changes
pnpm format:check
# Run all tests
pnpm test
# Run specific test project
pnpm test --project ripple-client
pnpm test --project ripple-server
pnpm test --project eslint-plugin
pnpm test --project prettier-plugin
```
### Test Projects (from `vitest.config.js`)
| Project | Tests | Environment |
| ------------------ | ----------------------------------------------- | ----------- |
| `ripple-client` | `packages/ripple/tests/client/**/*.test.ripple` | jsdom |
| `ripple-server` | `packages/ripple/tests/server/**/*.test.ripple` | node |
| `ripple-hydration` | `packages/ripple/tests/hydration/**/*.test.js` | jsdom |
| `eslint-plugin` | `packages/eslint-plugin/tests/**/*.test.ts` | jsdom |
| `eslint-parser` | `packages/eslint-parser/tests/**/*.test.ts` | jsdom |
| `prettier-plugin` | `packages/prettier-plugin/src/*.test.js` | jsdom |
| `cli` | `packages/cli/tests/**/*.test.js` | jsdom |
| `compat-react` | `packages/compat-react/tests/**/*.test.ripple` | jsdom |
### Test Architecture
**Ripple test files (`.test.ripple`):**
Test files are valid Ripple modules that export a default test component. The Vite
plugin transforms them before Vitest runs:
```ripple
// Example: packages/ripple/tests/client/reactivity.test.ripple
import { describe, it, expect } from 'vitest';
component default() {
describe('tracked', () => {
it('updates when value changes', async () => {
let count = #ripple.track(0);
// test implementation
});
});
}
```
**Setup files (`packages/ripple/tests/`):**
| File | Purpose |
| ----------------- | ----------------------------------------------- |
| `setup-client.js` | Client test setup: DOM utilities, flush helpers |
| `setup-server.js` | Server test setup: Output class, render helpers |
**Hydration tests (`packages/ripple/tests/hydration/`):**
Hydration tests verify client/server output consistency:
1. Server compiles and renders to HTML string with hydration markers
2. Client receives pre-rendered HTML, sets `hydrating = true`
3. Client walks DOM, claiming existing nodes instead of creating new ones
4. Tests verify final DOM matches expected state
```javascript
// Typical hydration test pattern
const server_html = render_server(Component); // With <!--[--> markers
container.innerHTML = server_html;
hydrate(Component, container); // Claims existing nodes
expect(container.innerHTML).toBe(expected);
```
### Development Playground
```bash
cd playground
pnpm dev # Start dev server (Vite)
pnpm lint # Lint playground code
```
## Code Conventions
### Package Manager
**pnpm is required** (`engines` in package.json enforces this). Do NOT use npm or
yarn.
### Language & Types
- **Internal code:** JavaScript (`.js`) with JSDoc type annotations — NOT
TypeScript
- **Type definitions:** TypeScript `.d.ts` files in `types/` directories for
public API
- **JSDoc imports:** Use `@import` syntax at top of file:
```javascript
/** @import { Block, Tracked, Derived } from '#client' */
/** @import * as AST from 'estree' */
```
- **JSDoc annotations:** Use `@param`, `@returns`, `@type` for all functions:
```javascript
/**
* @param {Block} block - The block to destroy
* @returns {void}
*/
export function destroy_block(block) { ... }
```
### Naming Conventions
| Context | Style | Examples |
| --------------- | ---------------------- | ------------------------------------------ |
| Variables | `snake_case` | `active_block`, `is_mutating_allowed` |
| Functions | `snake_case` | `create_scopes`, `set_active_block` |
| Constants | `SCREAMING_SNAKE_CASE` | `ROOT_BLOCK`, `FLUSH_MICROTASK`, `DERIVED` |
| Files | `kebab-case` | `css-analyze.js`, `source-map-utils.js` |
| Component files | `PascalCase` | `Button.ripple`, `TodoList.ripple` |
| Classes | `PascalCase` | `Scope`, `RippleArray`, `Output` |
| Type parameters | Single uppercase | `V` in `Tracked<V>`, `T` in generics |
### Hot Path Optimizations
In performance-critical runtime code, short property names are used to minimize
bundle size:
```javascript
// Block structure uses short names
block.p; // parent
block.t; // teardown function
block.d; // dependencies
block.f; // flags
block.s; // state
block.c; // context
```
### General Guidelines
1. **Consistency:** Look for similar implementations before adding new code
2. **No abbreviations** in variable names (except hot path optimizations above)
3. **Prefer `const`** over `let` when value won't be reassigned
4. **Use `var`** only in specific runtime hot paths for performance
5. **Comments:** Add comments for complex logic, not obvious code
## Tips for Working with the Codebase
### Compiler work
- Parser changes go in `phases/1-parse/`, modify `RipplePlugin` for new syntax
- Scope-related changes in `scope.js` - track bindings with appropriate `kind`
- CSS changes: `css-analyze.js` for parsing, `prune.js` for dead code elimination
- Code generation: separate files for `client/` and `server/` transforms
### Runtime work
- Reactivity: `runtime.js` is the core, understand
`tracked()`/`derived()`/`get()`/`set()`
- New control flow: add to both client (`internal/client/`) and may need server
support
- DOM operations: `render.js` for attribute/text updates, `operations.js` for
traversal
- Events: delegation in `events.js`, check `DELEGATED_EVENTS` constant
### Editor plugins
- Language server plugins in `packages/language-server/src/`
- VS Code extension entry: `packages/vscode-plugin/src/extension.js`
- TypeScript plugin: `packages/typescript-plugin/src/` for IDE integration
### Prettier plugin
The Prettier plugin (`packages/prettier-plugin/src/index.js`) formats `.ripple`
files using **AST-based formatting**, not string manipulation.
#### Architecture
The plugin exports three objects required by Prettier:
| Export | Purpose |
| ----------- | ------------------------------------------------------------------ |
| `languages` | Declares `.ripple` extension and parser name |
| `parsers` | Uses Ripple's compiler (`parse()`) to create ESTree-compatible AST |
| `printers` | Contains `print`, `embed`, and `getVisitorKeys` functions |
**AST-based approach:**
- Parser produces ESTree AST with Ripple extensions (Component, Element,
TrackedExpression, etc.)
- Printer recursively walks AST nodes via `printRippleNode()` switch statement
- Uses Prettier's `doc.builders` API (`concat`, `join`, `group`, `indent`, `line`,
`hardline`, `softline`, `ifBreak`)
#### Comment handling
Comments are attached to AST nodes and printed via three mechanisms:
| Comment Type | Property | Handling |
| ----------------- | ----------------------- | ----------------------------------------- |
| Leading comments | `node.leadingComments` | Printed before node content |
| Trailing comments | `node.trailingComments` | Inline via `lineSuffix()` or on next line |
| Inner comments | `node.innerComments` | Printed inside empty blocks/elements |
Element-level comment helpers:
- `getElementLeadingComments(node)` - extracts comments for JSX elements
- `createElementLevelCommentParts(comments)` - formats with proper spacing
#### Options
Prettier options are accessed from the `options` parameter:
| Option | Helper function | Usage |
| ------------------------ | ----------------------- | ------------------------------------ |
| `singleQuote` | `formatStringLiteral()` | Quote style for string literals |
| `jsxSingleQuote` | — | Quote style for JSX attribute values |
| `semi` | `semi()` | Semicolon insertion |
| `trailingComma` | `shouldPrintComma()` | Trailing commas in arrays/objects |
| `useTabs` / `tabWidth` | `createIndent()` | Indentation style |
| `singleAttributePerLine` | — | JSX attribute line breaking |
| `bracketSameLine` | — | JSX closing bracket position |
#### Context passing via `args`
The `args` parameter passes context for conditional formatting:
```javascript
// Examples of context flags
{
isInAttribute: true;
} // Compact object formatting in attributes
{
isInArray: true;
} // Array element context
{
allowInlineObject: true;
} // Allow single-line objects
{
isConditionalTest: true;
} // Binary/logical in conditional test
{
suppressLeadingComments: true;
} // Skip comment printing
```
#### Adding new node types
When encountering `/* Unknown: NodeType */` in formatter output:
1. **Identify the missing node type** from the comment (e.g., `TSDeclareFunction`)
2. **Add a case** in the `printRippleNode` switch statement:
```javascript
case 'TSDeclareFunction':
nodeContent = printTSDeclareFunction(node, path, options, print);
break;
```
3. **Implement the print function** following existing patterns (see
`printFunctionDeclaration` as reference)
4. **Add a test** in `packages/prettier-plugin/src/index.test.js`
#### Common patterns
- Use `path.call(print, 'childNode')` to recursively print child nodes
- Use `concat([...])` to join parts, `group()` for line breaking
- Check `node.typeParameters`, `node.returnType` for TypeScript annotations
- All functions use JSDoc type annotations with proper types (no `any`/`unknown`)
### Testing
- Client tests: create `.test.ripple` files in `packages/ripple/tests/client/`
- Server tests: create `.test.ripple` files in `packages/ripple/tests/server/`
- Use `setup-client.js` / `setup-server.js` for test environment setup
================================================
FILE: CLAUDE.md
================================================
# Ripple Project Guide for AI Agents
Ripple is a TypeScript UI framework that combines the best parts of React, Solid,
and Svelte. Created by Dominic Gannaway ([@trueadm](https://github.com/trueadm)),
Ripple is designed to be JS/TS-first with its own `.ripple` file extension that
fully supports TypeScript.
## Documentation
For comprehensive Ripple syntax, components, reactivity, and API documentation,
see:
- **[website/public/llms.txt](website/public/llms.txt)** - Full LLM-optimized
documentation
- **[README.md](README.md)** - Project overview and quick start
- **[CONTRIBUTING.md](CONTRIBUTING.md)** - Contribution guidelines
## RuleSync
This project uses [RuleSync](https://github.com/dyoshikawa/rulesync) to maintain a
single source of truth for AI agent instructions. The canonical rules are in
`.rulesync/rules/`, which are automatically generated to tool-specific locations:
| Agent | Generated File |
| -------------- | --------------------------------- |
| Claude Code | `CLAUDE.md` |
| GitHub Copilot | `.github/copilot-instructions.md` |
| Cursor | `.cursor/rules/project.mdc` |
| Gemini CLI | `GEMINI.md` |
| AGENTS.md | `AGENTS.md` |
**To regenerate after editing `.rulesync/rules/`:**
```bash
pnpm rules:generate
```
This runs automatically on `pnpm install` via the `prepare` script.
## Project Structure
This is a pnpm monorepo. Key packages are marked with `*`.
```
packages/
├── ripple/* # Core framework
│ └── src/
│ ├── compiler/ # Compilation pipeline (see Compiler Architecture)
│ │ ├── phases/
│ │ │ ├── 1-parse/ # Acorn-based parser with RipplePlugin
│ │ │ ├── 2-analyze/ # Scope analysis, CSS pruning, validation
│ │ │ └── 3-transform/# Client/server code generation
│ │ ├── scope.js # Scope and binding management
│ │ ├── types/ # AST type definitions
│ │ └── utils.js # Compiler utilities
│ ├── runtime/ # Runtime library (see Runtime Architecture)
│ │ ├── internal/
│ │ │ ├── client/ # DOM operations, reactivity, events
│ │ │ └── server/ # SSR string generation
│ │ ├── index-client.js # Client entry (browser)
│ │ └── index-server.js # Server entry (SSR)
│ └── server/ # Server-side rendering utilities
├── language-server/* # LSP implementation via Volar framework
├── vscode-plugin/* # VS Code extension (uses language-server)
├── typescript-plugin/* # TypeScript language service plugin
├── eslint-plugin/* # ESLint rules for Ripple
├── eslint-parser/* # ESLint parser for .ripple files
├── prettier-plugin/* # Prettier formatting support
├── vite-plugin/* # Vite build integration
├── rollup-plugin/ # Rollup build integration
├── cli/* # CLI tool (@ripple-ts/cli)
├── create-ripple/ # Project scaffolding (npx create-ripple)
├── compat-react/* # React interoperability layer
├── tree-sitter/* # Tree-sitter grammar for syntax highlighting
├── intellij-plugin/ # IntelliJ/WebStorm support
├── nvim-plugin/ # Neovim support
├── sublime-text-plugin/ # Sublime Text support
├── zed-plugin/ # Zed editor support
└── textmate/ # TextMate grammar (shared by editors)
playground/ # Development playground
website/ # Documentation website
templates/ # Project templates (basic, etc.)
scripts/ # Build and maintenance scripts
```
## Compiler Architecture
The compiler transforms `.ripple` files through three phases:
```
Source Code (.ripple) → Parse → Analyze → Transform → Output (JS + CSS)
```
### Phase 1: Parse (`packages/ripple/src/compiler/phases/1-parse/`)
**Parser:** Acorn extended with `@sveltejs/acorn-typescript` and custom
`RipplePlugin`
**Ripple-specific syntax handled:**
- `component` keyword for component declarations
- JSX with special handling for `@` tracked expressions
- `#server` blocks for server-only code
- `#ripple[]` (RippleArray shorthand), `#ripple{}` (RippleObject shorthand),
`#ripple.map()` (RippleMap), `#ripple.set()` (RippleSet),` #ripple.array()`
(RippleArray), `#ripple.object()` (RippleObject), `#ripple.url()` (RippleURL),
`#ripple.urlSearchParams()` (RippleURLSearchParams), `#ripple.Date()`
(RippleDate), `#ripple.Context()` (RippleContext), `#ripple.mediaQuery()`
(MediaQuery) `#ripple.track()` (track()), `#ripple.trackSplit()` (trackSplit())
`#ripple.untrack()` (untrack()), `#ripple.effect()` (effect()),
- `#style` identifier for scoped CSS classes
**Output:** ESTree-compatible AST with Ripple extensions
### Phase 2: Analyze (`packages/ripple/src/compiler/phases/2-analyze/`)
| File | Purpose |
| ---------------- | ----------------------------------------------- |
| `index.js` | Main analysis orchestration |
| `css-analyze.js` | CSS selector analysis, `:global()` handling |
| `prune.js` | Remove unused CSS rules based on template usage |
| `validation.js` | HTML nesting validation |
**Key operations:**
- **Scope creation:** `scope.js` creates scope chains tracking bindings (import,
prop, let, const, function, component, for_pattern)
- **Reactivity analysis:** Marks tracked expressions, derives tracking metadata
- **CSS scoping:** Hash-based class names via `CSS_HASH_IDENTIFIER`
- **`#style` analysis:** Validates usage context, collects referenced classes,
cross-checks against standalone CSS selectors
- **Server block analysis:** Tracks exports from `#server` blocks
### Phase 3: Transform (`packages/ripple/src/compiler/phases/3-transform/`)
**Client transform** (`client/index.js`):
- Generates runtime calls: `_$_.render()`, `_$_.if()`, `_$_.for()`,
`_$_.switch()`, etc.
- Creates template strings for static HTML
- Sets up event delegation
- Injects CSS hash for scoped styles
**Server transform** (`server/index.js`):
- Generates string concatenation for SSR output
- Handles `#server` block code execution
- Registers CSS for hydration
- Wraps control flow blocks with hydration comment markers
### SSR vs Client Compilation
The same `.ripple` module produces different output depending on the compilation
mode, controlled by `options.mode` in the compiler:
```javascript
// compiler/index.js
const result =
options.mode === 'server'
? transform_server(filename, source, analysis, options?.minify_css ?? false)
: transform_client(
filename,
source,
analysis,
false,
options?.minify_css ?? false,
);
```
| Aspect | Client Transform | Server Transform |
| ---------------- | ------------------------------------------ | ---------------------------------------- |
| **Output** | Runtime calls (`_$_.render()`, `_$_.if()`) | String concatenation (`__output.push()`) |
| **Templates** | DOM template literals, `cloneNode()` | Escaped HTML strings |
| **Reactivity** | Block scheduling, dirty checking | Immediate execution, no scheduling |
| **Control flow** | Creates branch blocks, DOM diffing | Wraps with `<!--[-->`/`<!--]-->` markers |
| **Events** | Delegation setup (`_$_.delegate()`) | Omitted entirely |
| **CSS** | Injects hash for scoping | Registers CSS hash via `register_css()` |
**Vite plugin** compiles modules twice for SSR apps - once with `mode: 'client'`
and once with `mode: 'server'`.
### Key AST Node Types (`packages/ripple/src/compiler/types/`)
| Node Type | Description |
| ------------------------ | -------------------------------------------------------- |
| `Component` | Component declaration with `id`, `params`, `body`, `css` |
| `Element` | HTML/SVG element with `id`, `attributes`, `children` |
| `Text` | Text node wrapping an expression |
| `ServerBlock` | `#server { ... }` block with exports tracking |
| `TrackedExpression` | `@expression` tracked reactive value |
| `RippleArrayExpression` | `#[...]` tracked array literal |
| `RippleObjectExpression` | `#{...}` tracked object literal |
| `Attribute` | Element attribute with `name`, `value`, `shorthand` |
| `RefAttribute` | `ref={...}` reference binding |
| `SpreadAttribute` | `{...props}` spread |
| `StyleIdentifier` | `#style` compile-time identifier for scoped CSS classes |
| `CSS.StyleSheet` | Parsed CSS with `hash` for scoping |
## Runtime Architecture
### Client Runtime (`packages/ripple/src/runtime/internal/client/`)
| Module | Responsibility |
| --------------- | ------------------------------------------------------------------------------- |
| `runtime.js` | Core reactivity: `tracked()`, `derived()`, `get()`, `set()`, block scheduling |
| `blocks.js` | Block creation: `render()`, `branch()`, `effect()`, `root()`, `destroy_block()` |
| `render.js` | DOM operations: `set_text()`, `set_class()`, `set_style()`, `set_attribute()` |
| `template.js` | Template instantiation: `template()`, `append()`, `assign_nodes()` |
| `operations.js` | DOM traversal: `child()`, `sibling()`, `create_text()` |
| `events.js` | Event handling: `event()`, `delegate()`, event propagation |
| `hydration.js` | SSR hydration: `hydrating`, `hydrate_node`, `hydrate_next()` |
| `bindings.js` | Two-way bindings for form elements |
| `context.js` | Context API implementation |
### Control Flow Blocks
| Block | File | Purpose |
| -------------- | -------------- | ------------------------------------------------------- |
| `if_block` | `if.js` | Conditional rendering with branch switching |
| `for_block` | `for.js` | List rendering with reconciliation (ref-based or keyed) |
| `switch_block` | `switch.js` | Multi-branch rendering |
| `try_block` | `try.js` | Error boundaries + async suspense |
| `composite` | `composite.js` | Dynamic component rendering (`<@Component />`) |
| `portal` | `portal.js` | Render children to different DOM location |
### Reactivity System
**Core concepts:**
- `tracked(value, block)` - Creates a tracked reactive value (`Tracked<V>`)
- `derived(fn, block)` - Creates a computed/derived value
- `get(tracked)` - Reads value, registers dependency
- `set(tracked, value)` - Updates value, schedules updates
**Implementation details:**
- Dependencies tracked via linked list structure: `{ c, t, n }` (consumer,
tracked, next)
- Dirty checking with clock-based versioning
- Block flags in `constants.js`: `ROOT_BLOCK`, `RENDER_BLOCK`, `EFFECT_BLOCK`,
`BRANCH_BLOCK`, etc.
### Reactive Collections (`packages/ripple/src/runtime/`)
| Collection | File | Description |
| -------------- | ----------- | ------------------------------------------- |
| `RippleArray` | `array.js` | Fully reactive array with all Array methods |
| `RippleObject` | `object.js` | Shallow reactive object |
| `RippleMap` | `map.js` | Reactive Map |
| `RippleSet` | `set.js` | Reactive Set |
| `RippleDate` | `date.js` | Reactive Date |
### Server Runtime (`packages/ripple/src/runtime/internal/server/`)
- String-based output via `Output` class (concatenates `head` and `body`)
- Simplified reactivity (no block scheduling, immediate execution)
- CSS registration for hydration markers
- Escape utilities for safe HTML output
### Hydration Mechanism
Hydration allows the client to "adopt" server-rendered HTML without re-rendering,
using comment markers to identify dynamic regions.
**Comment Markers (inserted by server transform):**
| Marker | Constant | Purpose |
| ----------- | ----------------- | -------------------------------------------- |
| `<!--[-->` | `HYDRATION_START` | Opens a dynamic block (if, for, switch, try) |
| `<!--]-->` | `HYDRATION_END` | Closes a dynamic block |
| `<!--[!-->` | `HYDRATION_ELSE` | Marks else/fallback branch boundary |
**Server-side generation:**
```javascript
// Server transform wraps control flow with markers
__output.push('<!--[-->'); // HYDRATION_START
// ... render content ...
__output.push('<!--]-->'); // HYDRATION_END
```
**Client-side hydration
(`packages/ripple/src/runtime/internal/client/hydration.js`):**
```javascript
export let hydrating = false; // True during hydration phase
export let hydrate_node = null; // Current DOM node being hydrated
```
**Key hydration functions:**
| Function | Purpose |
| ------------------------ | --------------------------------- |
| `set_hydrating(value)` | Enable/disable hydration mode |
| `set_hydrate_node(node)` | Set the current node pointer |
| `hydrate_next()` | Advance to next sibling node |
| `pop(node)` | Reset hydrate_node after mounting |
**Hydration flow:**
1. Server renders HTML with `<!--[-->` / `<!--]-->` markers around dynamic blocks
2. Client receives HTML, `hydrating = true` is set
3. Runtime walks DOM using `hydrate_node`, matching structure to component tree
4. Instead of creating elements, runtime "claims" existing DOM nodes
5. Comment markers guide block boundary detection
6. After hydration completes, `hydrating` is set back to `false`
## Language Server (`packages/language-server/src/`)
Built on **Volar framework** with TypeScript integration.
| Plugin | File | Purpose |
| -------------- | --------------------------------- | --------------------------------- |
| Completion | `completionPlugin.js` | Auto-completion for Ripple syntax |
| Definition | `definitionPlugin.js` | Go-to-definition |
| Hover | `hoverPlugin.js` | Hover information |
| Diagnostics | `compileErrorDiagnosticPlugin.js` | Compile-time error diagnostics |
| TS Diagnostics | `typescriptDiagnosticPlugin.js` | TypeScript diagnostic filtering |
| Auto-insert | `autoInsertPlugin.js` | Auto-insert completions |
| Highlight | `documentHighlightPlugin.js` | Document highlights |
**Integration:** Uses `@ripple-ts/typescript-plugin` for TypeScript language
service.
## Editor Plugins
All editor plugins use `@ripple-ts/language-server` internally:
| Editor | Package | Notes |
| ----------------- | ---------------------- | -------------------------------- |
| VS Code | `vscode-plugin/` | Primary development target |
| IntelliJ/WebStorm | `intellij-plugin/` | TextMate syntax + LSP via LSP4IJ |
| Neovim | `nvim-plugin/` | Tree-sitter + LSP |
| Sublime Text | `sublime-text-plugin/` | LSP package |
| Zed | `zed-plugin/` | Tree-sitter queries |
**Tree-sitter queries:** Located in `packages/tree-sitter/queries/`, copied to
nvim/zed plugins via `pnpm copy-tree-sitter-queries`.
## Validating Changes
**CRITICAL: Use pnpm for all package management. Do NOT use npm or yarn.**
### Changesets
For user-facing changes, add a changeset before committing:
```bash
pnpm changeset
```
This creates a markdown file in `.changeset/` describing the change. Select
affected packages and semver bump type (patch/minor/major). The file is committed
with your changes.
**Add a changeset for:** bug fixes, new features, breaking changes, API changes.
**Skip changesets for:** docs-only, internal refactoring, tests, CI/tooling.
### Required Validation Steps
After making changes, run these commands:
```bash
# Install dependencies (if needed)
pnpm install
# Format code with Prettier
pnpm format
# Check formatting without changes
pnpm format:check
# Run all tests
pnpm test
# Run specific test project
pnpm test --project ripple-client
pnpm test --project ripple-server
pnpm test --project eslint-plugin
pnpm test --project prettier-plugin
```
### Test Projects (from `vitest.config.js`)
| Project | Tests | Environment |
| ------------------ | ----------------------------------------------- | ----------- |
| `ripple-client` | `packages/ripple/tests/client/**/*.test.ripple` | jsdom |
| `ripple-server` | `packages/ripple/tests/server/**/*.test.ripple` | node |
| `ripple-hydration` | `packages/ripple/tests/hydration/**/*.test.js` | jsdom |
| `eslint-plugin` | `packages/eslint-plugin/tests/**/*.test.ts` | jsdom |
| `eslint-parser` | `packages/eslint-parser/tests/**/*.test.ts` | jsdom |
| `prettier-plugin` | `packages/prettier-plugin/src/*.test.js` | jsdom |
| `cli` | `packages/cli/tests/**/*.test.js` | jsdom |
| `compat-react` | `packages/compat-react/tests/**/*.test.ripple` | jsdom |
### Test Architecture
**Ripple test files (`.test.ripple`):**
Test files are valid Ripple modules that export a default test component. The Vite
plugin transforms them before Vitest runs:
```ripple
// Example: packages/ripple/tests/client/reactivity.test.ripple
import { describe, it, expect } from 'vitest';
component default() {
describe('tracked', () => {
it('updates when value changes', async () => {
let count = #ripple.track(0);
// test implementation
});
});
}
```
**Setup files (`packages/ripple/tests/`):**
| File | Purpose |
| ----------------- | ----------------------------------------------- |
| `setup-client.js` | Client test setup: DOM utilities, flush helpers |
| `setup-server.js` | Server test setup: Output class, render helpers |
**Hydration tests (`packages/ripple/tests/hydration/`):**
Hydration tests verify client/server output consistency:
1. Server compiles and renders to HTML string with hydration markers
2. Client receives pre-rendered HTML, sets `hydrating = true`
3. Client walks DOM, claiming existing nodes instead of creating new ones
4. Tests verify final DOM matches expected state
```javascript
// Typical hydration test pattern
const server_html = render_server(Component); // With <!--[--> markers
container.innerHTML = server_html;
hydrate(Component, container); // Claims existing nodes
expect(container.innerHTML).toBe(expected);
```
### Development Playground
```bash
cd playground
pnpm dev # Start dev server (Vite)
pnpm lint # Lint playground code
```
## Code Conventions
### Package Manager
**pnpm is required** (`engines` in package.json enforces this). Do NOT use npm or
yarn.
### Language & Types
- **Internal code:** JavaScript (`.js`) with JSDoc type annotations — NOT
TypeScript
- **Type definitions:** TypeScript `.d.ts` files in `types/` directories for
public API
- **JSDoc imports:** Use `@import` syntax at top of file:
```javascript
/** @import { Block, Tracked, Derived } from '#client' */
/** @import * as AST from 'estree' */
```
- **JSDoc annotations:** Use `@param`, `@returns`, `@type` for all functions:
```javascript
/**
* @param {Block} block - The block to destroy
* @returns {void}
*/
export function destroy_block(block) { ... }
```
### Naming Conventions
| Context | Style | Examples |
| --------------- | ---------------------- | ------------------------------------------ |
| Variables | `snake_case` | `active_block`, `is_mutating_allowed` |
| Functions | `snake_case` | `create_scopes`, `set_active_block` |
| Constants | `SCREAMING_SNAKE_CASE` | `ROOT_BLOCK`, `FLUSH_MICROTASK`, `DERIVED` |
| Files | `kebab-case` | `css-analyze.js`, `source-map-utils.js` |
| Component files | `PascalCase` | `Button.ripple`, `TodoList.ripple` |
| Classes | `PascalCase` | `Scope`, `RippleArray`, `Output` |
| Type parameters | Single uppercase | `V` in `Tracked<V>`, `T` in generics |
### Hot Path Optimizations
In performance-critical runtime code, short property names are used to minimize
bundle size:
```javascript
// Block structure uses short names
block.p; // parent
block.t; // teardown function
block.d; // dependencies
block.f; // flags
block.s; // state
block.c; // context
```
### General Guidelines
1. **Consistency:** Look for similar implementations before adding new code
2. **No abbreviations** in variable names (except hot path optimizations above)
3. **Prefer `const`** over `let` when value won't be reassigned
4. **Use `var`** only in specific runtime hot paths for performance
5. **Comments:** Add comments for complex logic, not obvious code
## Tips for Working with the Codebase
### Compiler work
- Parser changes go in `phases/1-parse/`, modify `RipplePlugin` for new syntax
- Scope-related changes in `scope.js` - track bindings with appropriate `kind`
- CSS changes: `css-analyze.js` for parsing, `prune.js` for dead code elimination
- Code generation: separate files for `client/` and `server/` transforms
### Runtime work
- Reactivity: `runtime.js` is the core, understand
`tracked()`/`derived()`/`get()`/`set()`
- New control flow: add to both client (`internal/client/`) and may need server
support
- DOM operations: `render.js` for attribute/text updates, `operations.js` for
traversal
- Events: delegation in `events.js`, check `DELEGATED_EVENTS` constant
### Editor plugins
- Language server plugins in `packages/language-server/src/`
- VS Code extension entry: `packages/vscode-plugin/src/extension.js`
- TypeScript plugin: `packages/typescript-plugin/src/` for IDE integration
### Prettier plugin
The Prettier plugin (`packages/prettier-plugin/src/index.js`) formats `.ripple`
files using **AST-based formatting**, not string manipulation.
#### Architecture
The plugin exports three objects required by Prettier:
| Export | Purpose |
| ----------- | ------------------------------------------------------------------ |
| `languages` | Declares `.ripple` extension and parser name |
| `parsers` | Uses Ripple's compiler (`parse()`) to create ESTree-compatible AST |
| `printers` | Contains `print`, `embed`, and `getVisitorKeys` functions |
**AST-based approach:**
- Parser produces ESTree AST with Ripple extensions (Component, Element,
TrackedExpression, etc.)
- Printer recursively walks AST nodes via `printRippleNode()` switch statement
- Uses Prettier's `doc.builders` API (`concat`, `join`, `group`, `indent`, `line`,
`hardline`, `softline`, `ifBreak`)
#### Comment handling
Comments are attached to AST nodes and printed via three mechanisms:
| Comment Type | Property | Handling |
| ----------------- | ----------------------- | ----------------------------------------- |
| Leading comments | `node.leadingComments` | Printed before node content |
| Trailing comments | `node.trailingComments` | Inline via `lineSuffix()` or on next line |
| Inner comments | `node.innerComments` | Printed inside empty blocks/elements |
Element-level comment helpers:
- `getElementLeadingComments(node)` - extracts comments for JSX elements
- `createElementLevelCommentParts(comments)` - formats with proper spacing
#### Options
Prettier options are accessed from the `options` parameter:
| Option | Helper function | Usage |
| ------------------------ | ----------------------- | ------------------------------------ |
| `singleQuote` | `formatStringLiteral()` | Quote style for string literals |
| `jsxSingleQuote` | — | Quote style for JSX attribute values |
| `semi` | `semi()` | Semicolon insertion |
| `trailingComma` | `shouldPrintComma()` | Trailing commas in arrays/objects |
| `useTabs` / `tabWidth` | `createIndent()` | Indentation style |
| `singleAttributePerLine` | — | JSX attribute line breaking |
| `bracketSameLine` | — | JSX closing bracket position |
#### Context passing via `args`
The `args` parameter passes context for conditional formatting:
```javascript
// Examples of context flags
{
isInAttribute: true;
} // Compact object formatting in attributes
{
isInArray: true;
} // Array element context
{
allowInlineObject: true;
} // Allow single-line objects
{
isConditionalTest: true;
} // Binary/logical in conditional test
{
suppressLeadingComments: true;
} // Skip comment printing
```
#### Adding new node types
When encountering `/* Unknown: NodeType */` in formatter output:
1. **Identify the missing node type** from the comment (e.g., `TSDeclareFunction`)
2. **Add a case** in the `printRippleNode` switch statement:
```javascript
case 'TSDeclareFunction':
nodeContent = printTSDeclareFunction(node, path, options, print);
break;
```
3. **Implement the print function** following existing patterns (see
`printFunctionDeclaration` as reference)
4. **Add a test** in `packages/prettier-plugin/src/index.test.js`
#### Common patterns
- Use `path.call(print, 'childNode')` to recursively print child nodes
- Use `concat([...])` to join parts, `group()` for line breaking
- Check `node.typeParameters`, `node.returnType` for TypeScript annotations
- All functions use JSDoc type annotations with proper types (no `any`/`unknown`)
### Testing
- Client tests: create `.test.ripple` files in `packages/ripple/tests/client/`
- Server tests: create `.test.ripple` files in `packages/ripple/tests/server/`
- Use `setup-client.js` / `setup-server.js` for test environment setup
================================================
FILE: 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!
================================================
FILE: 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.
================================================
FILE: 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 UI framework that combines the best parts of React, Solid,
and Svelte. Created by Dominic Gannaway ([@trueadm](https://github.com/trueadm)),
Ripple is designed to be JS/TS-first with its own `.ripple` file extension that
fully supports TypeScript.
## Documentation
For comprehensive Ripple syntax, components, reactivity, and API documentation,
see:
- **[website/public/llms.txt](website/public/llms.txt)** - Full LLM-optimized
documentation
- **[README.md](README.md)** - Project overview and quick start
- **[CONTRIBUTING.md](CONTRIBUTING.md)** - Contribution guidelines
## RuleSync
This project uses [RuleSync](https://github.com/dyoshikawa/rulesync) to maintain a
single source of truth for AI agent instructions. The canonical rules are in
`.rulesync/rules/`, which are automatically generated to tool-specific locations:
| Agent | Generated File |
| -------------- | --------------------------------- |
| Claude Code | `CLAUDE.md` |
| GitHub Copilot | `.github/copilot-instructions.md` |
| Cursor | `.cursor/rules/project.mdc` |
| Gemini CLI | `GEMINI.md` |
| AGENTS.md | `AGENTS.md` |
**To regenerate after editing `.rulesync/rules/`:**
```bash
pnpm rules:generate
```
This runs automatically on `pnpm install` via the `prepare` script.
## Project Structure
This is a pnpm monorepo. Key packages are marked with `*`.
```
packages/
├── ripple/* # Core framework
│ └── src/
│ ├── compiler/ # Compilation pipeline (see Compiler Architecture)
│ │ ├── phases/
│ │ │ ├── 1-parse/ # Acorn-based parser with RipplePlugin
│ │ │ ├── 2-analyze/ # Scope analysis, CSS pruning, validation
│ │ │ └── 3-transform/# Client/server code generation
│ │ ├── scope.js # Scope and binding management
│ │ ├── types/ # AST type definitions
│ │ └── utils.js # Compiler utilities
│ ├── runtime/ # Runtime library (see Runtime Architecture)
│ │ ├── internal/
│ │ │ ├── client/ # DOM operations, reactivity, events
│ │ │ └── server/ # SSR string generation
│ │ ├── index-client.js # Client entry (browser)
│ │ └── index-server.js # Server entry (SSR)
│ └── server/ # Server-side rendering utilities
├── language-server/* # LSP implementation via Volar framework
├── vscode-plugin/* # VS Code extension (uses language-server)
├── typescript-plugin/* # TypeScript language service plugin
├── eslint-plugin/* # ESLint rules for Ripple
├── eslint-parser/* # ESLint parser for .ripple files
├── prettier-plugin/* # Prettier formatting support
├── vite-plugin/* # Vite build integration
├── rollup-plugin/ # Rollup build integration
├── cli/* # CLI tool (@ripple-ts/cli)
├── create-ripple/ # Project scaffolding (npx create-ripple)
├── compat-react/* # React interoperability layer
├── tree-sitter/* # Tree-sitter grammar for syntax highlighting
├── intellij-plugin/ # IntelliJ/WebStorm support
├── nvim-plugin/ # Neovim support
├── sublime-text-plugin/ # Sublime Text support
├── zed-plugin/ # Zed editor support
└── textmate/ # TextMate grammar (shared by editors)
playground/ # Development playground
website/ # Documentation website
templates/ # Project templates (basic, etc.)
scripts/ # Build and maintenance scripts
```
## Compiler Architecture
The compiler transforms `.ripple` files through three phases:
```
Source Code (.ripple) → Parse → Analyze → Transform → Output (JS + CSS)
```
### Phase 1: Parse (`packages/ripple/src/compiler/phases/1-parse/`)
**Parser:** Acorn extended with `@sveltejs/acorn-typescript` and custom
`RipplePlugin`
**Ripple-specific syntax handled:**
- `component` keyword for component declarations
- JSX with special handling for `@` tracked expressions
- `#server` blocks for server-only code
- `#ripple[]` (RippleArray shorthand), `#ripple{}` (RippleObject shorthand),
`#ripple.map()` (RippleMap), `#ripple.set()` (RippleSet),` #ripple.array()`
(RippleArray), `#ripple.object()` (RippleObject), `#ripple.url()` (RippleURL),
`#ripple.urlSearchParams()` (RippleURLSearchParams), `#ripple.Date()`
(RippleDate), `#ripple.Context()` (RippleContext), `#ripple.mediaQuery()`
(MediaQuery) `#ripple.track()` (track()), `#ripple.trackSplit()` (trackSplit())
`#ripple.untrack()` (untrack()), `#ripple.effect()` (effect()),
- `#style` identifier for scoped CSS classes
**Output:** ESTree-compatible AST with Ripple extensions
### Phase 2: Analyze (`packages/ripple/src/compiler/phases/2-analyze/`)
| File | Purpose |
| ---------------- | ----------------------------------------------- |
| `index.js` | Main analysis orchestration |
| `css-analyze.js` | CSS selector analysis, `:global()` handling |
| `prune.js` | Remove unused CSS rules based on template usage |
| `validation.js` | HTML nesting validation |
**Key operations:**
- **Scope creation:** `scope.js` creates scope chains tracking bindings (import,
prop, let, const, function, component, for_pattern)
- **Reactivity analysis:** Marks tracked expressions, derives tracking metadata
- **CSS scoping:** Hash-based class names via `CSS_HASH_IDENTIFIER`
- **`#style` analysis:** Validates usage context, collects referenced classes,
cross-checks against standalone CSS selectors
- **Server block analysis:** Tracks exports from `#server` blocks
### Phase 3: Transform (`packages/ripple/src/compiler/phases/3-transform/`)
**Client transform** (`client/index.js`):
- Generates runtime calls: `_$_.render()`, `_$_.if()`, `_$_.for()`,
`_$_.switch()`, etc.
- Creates template strings for static HTML
- Sets up event delegation
- Injects CSS hash for scoped styles
**Server transform** (`server/index.js`):
- Generates string concatenation for SSR output
- Handles `#server` block code execution
- Registers CSS for hydration
- Wraps control flow blocks with hydration comment markers
### SSR vs Client Compilation
The same `.ripple` module produces different output depending on the compilation
mode, controlled by `options.mode` in the compiler:
```javascript
// compiler/index.js
const result =
options.mode === 'server'
? transform_server(filename, source, analysis, options?.minify_css ?? false)
: transform_client(
filename,
source,
analysis,
false,
options?.minify_css ?? false,
);
```
| Aspect | Client Transform | Server Transform |
| ---------------- | ------------------------------------------ | ---------------------------------------- |
| **Output** | Runtime calls (`_$_.render()`, `_$_.if()`) | String concatenation (`__output.push()`) |
| **Templates** | DOM template literals, `cloneNode()` | Escaped HTML strings |
| **Reactivity** | Block scheduling, dirty checking | Immediate execution, no scheduling |
| **Control flow** | Creates branch blocks, DOM diffing | Wraps with `<!--[-->`/`<!--]-->` markers |
| **Events** | Delegation setup (`_$_.delegate()`) | Omitted entirely |
| **CSS** | Injects hash for scoping | Registers CSS hash via `register_css()` |
**Vite plugin** compiles modules twice for SSR apps - once with `mode: 'client'`
and once with `mode: 'server'`.
### Key AST Node Types (`packages/ripple/src/compiler/types/`)
| Node Type | Description |
| ------------------------ | -------------------------------------------------------- |
| `Component` | Component declaration with `id`, `params`, `body`, `css` |
| `Element` | HTML/SVG element with `id`, `attributes`, `children` |
| `Text` | Text node wrapping an expression |
| `ServerBlock` | `#server { ... }` block with exports tracking |
| `TrackedExpression` | `@expression` tracked reactive value |
| `RippleArrayExpression` | `#[...]` tracked array literal |
| `RippleObjectExpression` | `#{...}` tracked object literal |
| `Attribute` | Element attribute with `name`, `value`, `shorthand` |
| `RefAttribute` | `ref={...}` reference binding |
| `SpreadAttribute` | `{...props}` spread |
| `StyleIdentifier` | `#style` compile-time identifier for scoped CSS classes |
| `CSS.StyleSheet` | Parsed CSS with `hash` for scoping |
## Runtime Architecture
### Client Runtime (`packages/ripple/src/runtime/internal/client/`)
| Module | Responsibility |
| --------------- | ------------------------------------------------------------------------------- |
| `runtime.js` | Core reactivity: `tracked()`, `derived()`, `get()`, `set()`, block scheduling |
| `blocks.js` | Block creation: `render()`, `branch()`, `effect()`, `root()`, `destroy_block()` |
| `render.js` | DOM operations: `set_text()`, `set_class()`, `set_style()`, `set_attribute()` |
| `template.js` | Template instantiation: `template()`, `append()`, `assign_nodes()` |
| `operations.js` | DOM traversal: `child()`, `sibling()`, `create_text()` |
| `events.js` | Event handling: `event()`, `delegate()`, event propagation |
| `hydration.js` | SSR hydration: `hydrating`, `hydrate_node`, `hydrate_next()` |
| `bindings.js` | Two-way bindings for form elements |
| `context.js` | Context API implementation |
### Control Flow Blocks
| Block | File | Purpose |
| -------------- | -------------- | ------------------------------------------------------- |
| `if_block` | `if.js` | Conditional rendering with branch switching |
| `for_block` | `for.js` | List rendering with reconciliation (ref-based or keyed) |
| `switch_block` | `switch.js` | Multi-branch rendering |
| `try_block` | `try.js` | Error boundaries + async suspense |
| `composite` | `composite.js` | Dynamic component rendering (`<@Component />`) |
| `portal` | `portal.js` | Render children to different DOM location |
### Reactivity System
**Core concepts:**
- `tracked(value, block)` - Creates a tracked reactive value (`Tracked<V>`)
- `derived(fn, block)` - Creates a computed/derived value
- `get(tracked)` - Reads value, registers dependency
- `set(tracked, value)` - Updates value, schedules updates
**Implementation details:**
- Dependencies tracked via linked list structure: `{ c, t, n }` (consumer,
tracked, next)
- Dirty checking with clock-based versioning
- Block flags in `constants.js`: `ROOT_BLOCK`, `RENDER_BLOCK`, `EFFECT_BLOCK`,
`BRANCH_BLOCK`, etc.
### Reactive Collections (`packages/ripple/src/runtime/`)
| Collection | File | Description |
| -------------- | ----------- | ------------------------------------------- |
| `RippleArray` | `array.js` | Fully reactive array with all Array methods |
| `RippleObject` | `object.js` | Shallow reactive object |
| `RippleMap` | `map.js` | Reactive Map |
| `RippleSet` | `set.js` | Reactive Set |
| `RippleDate` | `date.js` | Reactive Date |
### Server Runtime (`packages/ripple/src/runtime/internal/server/`)
- String-based output via `Output` class (concatenates `head` and `body`)
- Simplified reactivity (no block scheduling, immediate execution)
- CSS registration for hydration markers
- Escape utilities for safe HTML output
### Hydration Mechanism
Hydration allows the client to "adopt" server-rendered HTML without re-rendering,
using comment markers to identify dynamic regions.
**Comment Markers (inserted by server transform):**
| Marker | Constant | Purpose |
| ----------- | ----------------- | -------------------------------------------- |
| `<!--[-->` | `HYDRATION_START` | Opens a dynamic block (if, for, switch, try) |
| `<!--]-->` | `HYDRATION_END` | Closes a dynamic block |
| `<!--[!-->` | `HYDRATION_ELSE` | Marks else/fallback branch boundary |
**Server-side generation:**
```javascript
// Server transform wraps control flow with markers
__output.push('<!--[-->'); // HYDRATION_START
// ... render content ...
__output.push('<!--]-->'); // HYDRATION_END
```
**Client-side hydration
(`packages/ripple/src/runtime/internal/client/hydration.js`):**
```javascript
export let hydrating = false; // True during hydration phase
export let hydrate_node = null; // Current DOM node being hydrated
```
**Key hydration functions:**
| Function | Purpose |
| ------------------------ | --------------------------------- |
| `set_hydrating(value)` | Enable/disable hydration mode |
| `set_hydrate_node(node)` | Set the current node pointer |
| `hydrate_next()` | Advance to next sibling node |
| `pop(node)` | Rese
gitextract_7ext8lh9/
├── .changeset/
│ ├── README.md
│ ├── config.json
│ ├── large-snails-crash.md
│ └── tame-snails-sneeze.md
├── .cursor/
│ ├── environment.json
│ ├── install.sh
│ └── rules/
│ └── project.mdc
├── .editorconfig
├── .gitattributes
├── .github/
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug-report.yml
│ │ ├── config.yml
│ │ └── feature-request.yml
│ ├── agents/
│ │ └── ripple.agent.md
│ ├── copilot-instructions.md
│ └── workflows/
│ ├── ci.yml
│ ├── copilot-setup-steps.yml
│ ├── livecodes-post-comment.yml
│ ├── livecodes-preview.yml
│ ├── pkg.pr.new.yml
│ ├── provenance.yml
│ ├── release.yml
│ ├── rulesync.yml
│ ├── vsix-manual.yml
│ └── vsix.yml
├── .gitignore
├── .livecodes/
│ └── playground.json
├── .prettierignore
├── .prettierrc
├── .rulesync/
│ └── rules/
│ └── project.md
├── .vscode/
│ ├── launch.json
│ ├── settings.json
│ └── tasks.json
├── AGENTS.md
├── CLAUDE.md
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── GEMINI.md
├── LICENSE
├── README.md
├── assets/
│ └── Ripple.tmbundle/
│ ├── README.md
│ ├── Syntaxes/
│ │ └── ripple.tmLanguage
│ └── info.plist
├── grammars/
│ ├── textmate/
│ │ ├── info.plist
│ │ └── ripple.tmLanguage.json
│ └── tree-sitter/
│ ├── .gitignore
│ ├── Cargo.toml
│ ├── LICENSE
│ ├── README.md
│ ├── binding.gyp
│ ├── bindings/
│ │ └── node/
│ │ └── binding.cc
│ ├── grammar.js
│ ├── package.json
│ ├── queries/
│ │ ├── brackets.scm
│ │ ├── folds.scm
│ │ ├── highlights.scm
│ │ ├── indents.nvim.scm
│ │ ├── indents.scm
│ │ ├── indents.zed.scm
│ │ ├── injections.scm
│ │ ├── locals.scm
│ │ ├── outline.scm
│ │ └── textobjects.scm
│ ├── src/
│ │ ├── grammar.json
│ │ ├── node-types.json
│ │ ├── parser.c
│ │ ├── scanner.c
│ │ └── tree_sitter/
│ │ ├── alloc.h
│ │ ├── array.h
│ │ └── parser.h
│ ├── test/
│ │ └── corpus/
│ │ ├── components.txt
│ │ ├── control-flow.txt
│ │ ├── javascript.txt
│ │ ├── jsx.txt
│ │ ├── main.txt
│ │ └── reactivity.txt
│ └── tree-sitter.json
├── package.json
├── packages/
│ ├── adapter/
│ │ ├── CHANGELOG.md
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── index.js
│ │ │ └── rpc.js
│ │ ├── tests/
│ │ │ ├── index.test.js
│ │ │ └── types.test.js
│ │ ├── tsconfig.json
│ │ └── types/
│ │ ├── index.d.ts
│ │ └── rpc.d.ts
│ ├── adapter-bun/
│ │ ├── CHANGELOG.md
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── src/
│ │ │ └── index.js
│ │ ├── tests/
│ │ │ ├── serve.test.js
│ │ │ └── types.test.js
│ │ ├── tsconfig.json
│ │ └── types/
│ │ └── index.d.ts
│ ├── adapter-node/
│ │ ├── CHANGELOG.md
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── src/
│ │ │ └── index.js
│ │ ├── tests/
│ │ │ ├── serve.test.js
│ │ │ └── types.test.js
│ │ ├── tsconfig.json
│ │ └── types/
│ │ └── index.d.ts
│ ├── adapter-vercel/
│ │ ├── CHANGELOG.md
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── adapt.js
│ │ │ ├── bin/
│ │ │ │ └── adapt.js
│ │ │ └── index.js
│ │ ├── tests/
│ │ │ ├── adapt.test.js
│ │ │ └── types.test.js
│ │ ├── tsconfig.json
│ │ └── types/
│ │ └── index.d.ts
│ ├── cli/
│ │ ├── CHANGELOG.md
│ │ ├── LICENSE
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── commands/
│ │ │ │ └── create.js
│ │ │ ├── constants.js
│ │ │ ├── index.js
│ │ │ └── lib/
│ │ │ ├── is-folder-empty.js
│ │ │ ├── package-manager.js
│ │ │ ├── project-creator.js
│ │ │ ├── prompts.js
│ │ │ ├── templates.js
│ │ │ └── validation.js
│ │ ├── tests/
│ │ │ ├── integration/
│ │ │ │ ├── cli.test.js
│ │ │ │ └── project-creator.test.js
│ │ │ └── unit/
│ │ │ ├── prompts.test.js
│ │ │ ├── templates.test.js
│ │ │ └── validation.test.js
│ │ ├── tsconfig.json
│ │ ├── tsdown.config.js
│ │ └── vitest.config.js
│ ├── compat-react/
│ │ ├── CHANGELOG.md
│ │ ├── LICENSE
│ │ ├── package.json
│ │ ├── src/
│ │ │ └── index.js
│ │ ├── tests/
│ │ │ ├── client.d.ts
│ │ │ ├── index.test.ripple
│ │ │ └── setup.js
│ │ ├── tsconfig.json
│ │ └── types/
│ │ └── index.d.ts
│ ├── create-ripple/
│ │ ├── CHANGELOG.md
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── src/
│ │ │ └── index.js
│ │ ├── tsconfig.json
│ │ └── tsdown.config.js
│ ├── eslint-parser/
│ │ ├── .npmignore
│ │ ├── CHANGELOG.md
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── index.ts
│ │ │ └── loader.ts
│ │ ├── tsconfig.json
│ │ └── tsdown.config.js
│ ├── eslint-plugin/
│ │ ├── .npmignore
│ │ ├── CHANGELOG.md
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── index.ts
│ │ │ └── rules/
│ │ │ ├── control-flow-jsx.ts
│ │ │ ├── no-introspect-in-modules.ts
│ │ │ ├── no-module-scope-track.ts
│ │ │ ├── no-return-in-component.ts
│ │ │ ├── prefer-oninput.ts
│ │ │ ├── unbox-tracked-values.ts
│ │ │ └── valid-for-of-key.ts
│ │ ├── tests/
│ │ │ └── rules/
│ │ │ ├── control-flow-jsx.test.ts
│ │ │ ├── no-introspect-in-modules.test.ts
│ │ │ ├── no-module-scope-track.test.ts
│ │ │ ├── no-return-in-component.test.ts
│ │ │ ├── prefer-oninput.test.ts
│ │ │ ├── unbox-tracked-values.test.ts
│ │ │ └── valid-for-of-key.test.ts
│ │ ├── tsconfig.json
│ │ ├── tsdown.config.js
│ │ └── vitest.config.ts
│ ├── intellij-plugin/
│ │ ├── .gitignore
│ │ ├── README.md
│ │ ├── build.gradle.kts
│ │ ├── gradle/
│ │ │ └── wrapper/
│ │ │ ├── gradle-wrapper.jar
│ │ │ └── gradle-wrapper.properties
│ │ ├── gradle.properties
│ │ ├── gradlew
│ │ ├── gradlew.bat
│ │ ├── package.json
│ │ ├── settings.gradle.kts
│ │ └── src/
│ │ └── main/
│ │ ├── kotlin/
│ │ │ └── com/
│ │ │ └── ripple_ts/
│ │ │ └── intellij_plugin/
│ │ │ ├── RippleCommenter.kt
│ │ │ ├── RippleFileType.kt
│ │ │ ├── RippleIcons.kt
│ │ │ ├── RippleLanguage.kt
│ │ │ ├── RippleLanguageServer.kt
│ │ │ ├── RippleLspServerDescriptor.kt
│ │ │ ├── RippleLspServerSupportProvider.kt
│ │ │ └── RippleTextMateBundleProvider.kt
│ │ └── resources/
│ │ ├── META-INF/
│ │ │ ├── plugin.xml
│ │ │ └── ripple-lsp.xml
│ │ └── lsp-version.txt
│ ├── language-server/
│ │ ├── CHANGELOG.md
│ │ ├── LICENSE
│ │ ├── README.md
│ │ ├── bin/
│ │ │ └── language-server.js
│ │ ├── index.js
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── autoInsertPlugin.js
│ │ │ ├── compileErrorDiagnosticPlugin.js
│ │ │ ├── completionPlugin.js
│ │ │ ├── definitionPlugin.js
│ │ │ ├── documentHighlightPlugin.js
│ │ │ ├── hoverPlugin.js
│ │ │ ├── server.js
│ │ │ ├── typescriptDiagnosticPlugin.js
│ │ │ ├── typescriptService.js
│ │ │ └── utils.js
│ │ └── tsconfig.json
│ ├── nvim-plugin/
│ │ ├── LICENSE
│ │ ├── README.md
│ │ ├── lua/
│ │ │ └── ripple/
│ │ │ ├── init.lua
│ │ │ ├── lsp.lua
│ │ │ └── treesitter.lua
│ │ ├── package.json
│ │ ├── plugin/
│ │ │ └── ripple.lua
│ │ └── queries/
│ │ └── ripple/
│ │ ├── brackets.scm
│ │ ├── folds.scm
│ │ ├── highlights.scm
│ │ ├── indents.scm
│ │ ├── injections.scm
│ │ ├── locals.scm
│ │ ├── outline.scm
│ │ └── textobjects.scm
│ ├── prettier-plugin/
│ │ ├── CHANGELOG.md
│ │ ├── LICENSE
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── index.js
│ │ │ └── index.test.js
│ │ ├── tsconfig.json
│ │ └── vitest-extensions.d.ts
│ ├── ripple/
│ │ ├── CHANGELOG.md
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── shims/
│ │ │ └── rollup-estree-types.d.ts
│ │ ├── src/
│ │ │ ├── compiler/
│ │ │ │ ├── comment-utils.js
│ │ │ │ ├── errors.js
│ │ │ │ ├── identifier-utils.js
│ │ │ │ ├── index.d.ts
│ │ │ │ ├── index.js
│ │ │ │ ├── phases/
│ │ │ │ │ ├── 1-parse/
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ └── style.js
│ │ │ │ │ ├── 2-analyze/
│ │ │ │ │ │ ├── css-analyze.js
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ ├── prune.js
│ │ │ │ │ │ └── validation.js
│ │ │ │ │ └── 3-transform/
│ │ │ │ │ ├── client/
│ │ │ │ │ │ └── index.js
│ │ │ │ │ ├── segments.js
│ │ │ │ │ ├── server/
│ │ │ │ │ │ └── index.js
│ │ │ │ │ └── stylesheet.js
│ │ │ │ ├── scope.js
│ │ │ │ ├── source-map-utils.js
│ │ │ │ ├── types/
│ │ │ │ │ ├── acorn.d.ts
│ │ │ │ │ ├── estree-jsx.d.ts
│ │ │ │ │ ├── estree.d.ts
│ │ │ │ │ ├── import.d.ts
│ │ │ │ │ ├── index.d.ts
│ │ │ │ │ ├── parse.d.ts
│ │ │ │ │ └── rpc.d.ts
│ │ │ │ └── utils.js
│ │ │ ├── constants.js
│ │ │ ├── helpers.d.ts
│ │ │ ├── html-tree-validation.js
│ │ │ ├── jsx-runtime.d.ts
│ │ │ ├── jsx-runtime.js
│ │ │ ├── runtime/
│ │ │ │ ├── array.js
│ │ │ │ ├── create-subscriber.js
│ │ │ │ ├── date.js
│ │ │ │ ├── index-client.js
│ │ │ │ ├── index-server.js
│ │ │ │ ├── internal/
│ │ │ │ │ ├── client/
│ │ │ │ │ │ ├── bindings.js
│ │ │ │ │ │ ├── blocks.js
│ │ │ │ │ │ ├── compat.js
│ │ │ │ │ │ ├── composite.js
│ │ │ │ │ │ ├── constants.js
│ │ │ │ │ │ ├── context.js
│ │ │ │ │ │ ├── css.js
│ │ │ │ │ │ ├── events.js
│ │ │ │ │ │ ├── for.js
│ │ │ │ │ │ ├── head.js
│ │ │ │ │ │ ├── hmr.js
│ │ │ │ │ │ ├── html.js
│ │ │ │ │ │ ├── hydration.js
│ │ │ │ │ │ ├── if.js
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ ├── operations.js
│ │ │ │ │ │ ├── portal.js
│ │ │ │ │ │ ├── render.js
│ │ │ │ │ │ ├── rpc.js
│ │ │ │ │ │ ├── runtime.js
│ │ │ │ │ │ ├── script.js
│ │ │ │ │ │ ├── switch.js
│ │ │ │ │ │ ├── template.js
│ │ │ │ │ │ ├── try.js
│ │ │ │ │ │ ├── types.d.ts
│ │ │ │ │ │ └── utils.js
│ │ │ │ │ └── server/
│ │ │ │ │ ├── context.js
│ │ │ │ │ ├── css-registry.js
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── rpc.js
│ │ │ │ │ └── types.d.ts
│ │ │ │ ├── map.js
│ │ │ │ ├── media-query.js
│ │ │ │ ├── object.js
│ │ │ │ ├── proxy.js
│ │ │ │ ├── reactive-value.js
│ │ │ │ ├── set.js
│ │ │ │ ├── url-search-params.js
│ │ │ │ └── url.js
│ │ │ ├── server/
│ │ │ │ └── index.js
│ │ │ └── utils/
│ │ │ ├── ast.js
│ │ │ ├── builders.js
│ │ │ ├── escaping.js
│ │ │ ├── events.js
│ │ │ ├── hashing.js
│ │ │ ├── normalize_css_property_name.js
│ │ │ ├── patterns.js
│ │ │ └── sanitize_template_string.js
│ │ ├── tests/
│ │ │ ├── client/
│ │ │ │ ├── __snapshots__/
│ │ │ │ │ ├── computed-properties.test.ripple.snap
│ │ │ │ │ ├── for.test.ripple.snap
│ │ │ │ │ ├── html.test.ripple.snap
│ │ │ │ │ └── tracked-expression.test.ripple.snap
│ │ │ │ ├── _etc.test.ripple
│ │ │ │ ├── array/
│ │ │ │ │ ├── array.copy-within.test.ripple
│ │ │ │ │ ├── array.derived.test.ripple
│ │ │ │ │ ├── array.iteration.test.ripple
│ │ │ │ │ ├── array.mutations.test.ripple
│ │ │ │ │ ├── array.static.test.ripple
│ │ │ │ │ └── array.to-methods.test.ripple
│ │ │ │ ├── async-suspend.test.ripple
│ │ │ │ ├── basic/
│ │ │ │ │ ├── __snapshots__/
│ │ │ │ │ │ ├── basic.attributes.test.ripple.snap
│ │ │ │ │ │ ├── basic.rendering.test.ripple.snap
│ │ │ │ │ │ └── basic.text.test.ripple.snap
│ │ │ │ │ ├── basic.attributes.test.ripple
│ │ │ │ │ ├── basic.collections.test.ripple
│ │ │ │ │ ├── basic.components.test.ripple
│ │ │ │ │ ├── basic.errors.test.ripple
│ │ │ │ │ ├── basic.events.test.ripple
│ │ │ │ │ ├── basic.get-set.test.ripple
│ │ │ │ │ ├── basic.hmr.test.ripple
│ │ │ │ │ ├── basic.reactivity.test.ripple
│ │ │ │ │ ├── basic.rendering.test.ripple
│ │ │ │ │ ├── basic.styling.test.ripple
│ │ │ │ │ └── basic.utilities.test.ripple
│ │ │ │ ├── boundaries.test.ripple
│ │ │ │ ├── compiler/
│ │ │ │ │ ├── __snapshots__/
│ │ │ │ │ │ ├── compiler.assignments.test.ripple.snap
│ │ │ │ │ │ └── compiler.typescript.test.ripple.snap
│ │ │ │ │ ├── compiler.assignments.test.ripple
│ │ │ │ │ ├── compiler.attributes.test.ripple
│ │ │ │ │ ├── compiler.basic.test.ripple
│ │ │ │ │ ├── compiler.regex.test.ripple
│ │ │ │ │ ├── compiler.tracked-access.test.ripple
│ │ │ │ │ ├── compiler.try-in-function.test.ripple
│ │ │ │ │ └── compiler.typescript.test.ripple
│ │ │ │ ├── composite/
│ │ │ │ │ ├── __snapshots__/
│ │ │ │ │ │ └── composite.render.test.ripple.snap
│ │ │ │ │ ├── composite.dynamic-components.test.ripple
│ │ │ │ │ ├── composite.generics.test.ripple
│ │ │ │ │ ├── composite.props.test.ripple
│ │ │ │ │ ├── composite.reactivity.test.ripple
│ │ │ │ │ └── composite.render.test.ripple
│ │ │ │ ├── computed-properties.test.ripple
│ │ │ │ ├── context.test.ripple
│ │ │ │ ├── css/
│ │ │ │ │ ├── global-additional-cases.test.ripple
│ │ │ │ │ ├── global-advanced-selectors.test.ripple
│ │ │ │ │ ├── global-at-rules.test.ripple
│ │ │ │ │ ├── global-basic.test.ripple
│ │ │ │ │ ├── global-classes-ids.test.ripple
│ │ │ │ │ ├── global-combinators.test.ripple
│ │ │ │ │ ├── global-complex-nesting.test.ripple
│ │ │ │ │ ├── global-edge-cases.test.ripple
│ │ │ │ │ ├── global-keyframes.test.ripple
│ │ │ │ │ ├── global-nested.test.ripple
│ │ │ │ │ ├── global-pseudo.test.ripple
│ │ │ │ │ ├── global-scoping.test.ripple
│ │ │ │ │ └── style-identifier.test.ripple
│ │ │ │ ├── date.test.ripple
│ │ │ │ ├── dynamic-elements.test.ripple
│ │ │ │ ├── events.test.ripple
│ │ │ │ ├── for.test.ripple
│ │ │ │ ├── function-overload-import.ripple
│ │ │ │ ├── function-overload.test.ripple
│ │ │ │ ├── head.test.ripple
│ │ │ │ ├── html.test.ripple
│ │ │ │ ├── input-value.test.ripple
│ │ │ │ ├── map.test.ripple
│ │ │ │ ├── media-query.test.ripple
│ │ │ │ ├── object.test.ripple
│ │ │ │ ├── portal.test.ripple
│ │ │ │ ├── ref.test.ripple
│ │ │ │ ├── return.test.ripple
│ │ │ │ ├── set.test.ripple
│ │ │ │ ├── svg.test.ripple
│ │ │ │ ├── switch.test.ripple
│ │ │ │ ├── tracked-expression.test.ripple
│ │ │ │ ├── try.test.ripple
│ │ │ │ ├── tsconfig.json
│ │ │ │ ├── typescript-generics.test.ripple
│ │ │ │ ├── url/
│ │ │ │ │ ├── url.derived.test.ripple
│ │ │ │ │ ├── url.parsing.test.ripple
│ │ │ │ │ ├── url.partial-removal.test.ripple
│ │ │ │ │ ├── url.reactivity.test.ripple
│ │ │ │ │ └── url.serialization.test.ripple
│ │ │ │ └── url-search-params/
│ │ │ │ ├── url-search-params.derived.test.ripple
│ │ │ │ ├── url-search-params.initialization.test.ripple
│ │ │ │ ├── url-search-params.iteration.test.ripple
│ │ │ │ ├── url-search-params.mutation.test.ripple
│ │ │ │ ├── url-search-params.retrieval.test.ripple
│ │ │ │ ├── url-search-params.serialization.test.ripple
│ │ │ │ └── url-search-params.tracked-url.test.ripple
│ │ │ ├── client.d.ts
│ │ │ ├── common.d.ts
│ │ │ ├── hydration/
│ │ │ │ ├── basic.test.js
│ │ │ │ ├── build-components.js
│ │ │ │ ├── compiled/
│ │ │ │ │ ├── client/
│ │ │ │ │ │ ├── basic.js
│ │ │ │ │ │ ├── composite.js
│ │ │ │ │ │ ├── events.js
│ │ │ │ │ │ ├── for.js
│ │ │ │ │ │ ├── head.js
│ │ │ │ │ │ ├── hmr.js
│ │ │ │ │ │ ├── html-in-template.js
│ │ │ │ │ │ ├── html.js
│ │ │ │ │ │ ├── if-children.js
│ │ │ │ │ │ ├── if.js
│ │ │ │ │ │ ├── mixed-control-flow.js
│ │ │ │ │ │ ├── nested-control-flow.js
│ │ │ │ │ │ ├── portal.js
│ │ │ │ │ │ ├── reactivity.js
│ │ │ │ │ │ ├── return.js
│ │ │ │ │ │ ├── switch.js
│ │ │ │ │ │ └── try.js
│ │ │ │ │ └── server/
│ │ │ │ │ ├── basic.js
│ │ │ │ │ ├── composite.js
│ │ │ │ │ ├── events.js
│ │ │ │ │ ├── for.js
│ │ │ │ │ ├── head.js
│ │ │ │ │ ├── hmr.js
│ │ │ │ │ ├── html-in-template.js
│ │ │ │ │ ├── html.js
│ │ │ │ │ ├── if-children.js
│ │ │ │ │ ├── if.js
│ │ │ │ │ ├── mixed-control-flow.js
│ │ │ │ │ ├── nested-control-flow.js
│ │ │ │ │ ├── portal.js
│ │ │ │ │ ├── reactivity.js
│ │ │ │ │ ├── return.js
│ │ │ │ │ ├── switch.js
│ │ │ │ │ └── try.js
│ │ │ │ ├── components/
│ │ │ │ │ ├── basic.ripple
│ │ │ │ │ ├── composite.ripple
│ │ │ │ │ ├── events.ripple
│ │ │ │ │ ├── for.ripple
│ │ │ │ │ ├── head.ripple
│ │ │ │ │ ├── hmr.ripple
│ │ │ │ │ ├── html-in-template.ripple
│ │ │ │ │ ├── html.ripple
│ │ │ │ │ ├── if-children.ripple
│ │ │ │ │ ├── if.ripple
│ │ │ │ │ ├── mixed-control-flow.ripple
│ │ │ │ │ ├── nested-control-flow.ripple
│ │ │ │ │ ├── portal.ripple
│ │ │ │ │ ├── reactivity.ripple
│ │ │ │ │ ├── return.ripple
│ │ │ │ │ ├── switch.ripple
│ │ │ │ │ └── try.ripple
│ │ │ │ ├── composite.test.js
│ │ │ │ ├── events.test.js
│ │ │ │ ├── for.test.js
│ │ │ │ ├── head.test.js
│ │ │ │ ├── hmr.test.js
│ │ │ │ ├── html-in-template.test.js
│ │ │ │ ├── html.test.js
│ │ │ │ ├── if-children.test.js
│ │ │ │ ├── if.test.js
│ │ │ │ ├── mixed-control-flow.test.js
│ │ │ │ ├── nested-control-flow.test.js
│ │ │ │ ├── portal.test.js
│ │ │ │ ├── reactivity.test.js
│ │ │ │ ├── return.test.js
│ │ │ │ ├── switch.test.js
│ │ │ │ ├── try.test.js
│ │ │ │ └── tsconfig.json
│ │ │ ├── hydration.d.ts
│ │ │ ├── server/
│ │ │ │ ├── __snapshots__/
│ │ │ │ │ └── compiler.test.ripple.snap
│ │ │ │ ├── await.test.ripple
│ │ │ │ ├── basic.attributes.test.ripple
│ │ │ │ ├── basic.components.test.ripple
│ │ │ │ ├── basic.test.ripple
│ │ │ │ ├── compiler.test.ripple
│ │ │ │ ├── composite.props.test.ripple
│ │ │ │ ├── composite.test.ripple
│ │ │ │ ├── context.test.ripple
│ │ │ │ ├── dynamic-elements.test.ripple
│ │ │ │ ├── for.test.ripple
│ │ │ │ ├── head.test.ripple
│ │ │ │ ├── html-nesting-validation.test.ripple
│ │ │ │ ├── if.test.ripple
│ │ │ │ ├── return.test.ripple
│ │ │ │ ├── streaming-ssr.test.ripple
│ │ │ │ ├── style-identifier.test.ripple
│ │ │ │ ├── switch.test.ripple
│ │ │ │ ├── try.test.ripple
│ │ │ │ └── tsconfig.json
│ │ │ ├── server.d.ts
│ │ │ ├── setup-client.js
│ │ │ ├── setup-hydration.js
│ │ │ ├── setup-server.js
│ │ │ └── utils/
│ │ │ ├── escaping.test.js
│ │ │ ├── events.test.js
│ │ │ ├── normalize_css_property_name.test.js
│ │ │ ├── patterns.test.js
│ │ │ └── sanitize_template_string.test.js
│ │ ├── tsconfig.json
│ │ └── types/
│ │ ├── index.d.ts
│ │ └── server.d.ts
│ ├── rollup-plugin/
│ │ ├── CHANGELOG.md
│ │ ├── LICENSE
│ │ ├── index.js
│ │ ├── package.json
│ │ └── tsconfig.json
│ ├── sublime-text-plugin/
│ │ ├── .gitignore
│ │ ├── package.json
│ │ ├── scripts/
│ │ │ └── build.js
│ │ └── src/
│ │ ├── .python-version
│ │ ├── Ripple.sublime-settings
│ │ ├── dependencies.json
│ │ ├── language-server/
│ │ │ └── package.json
│ │ └── plugin.py
│ ├── tree-sitter/
│ │ └── build/
│ │ ├── Makefile
│ │ ├── Release/
│ │ │ ├── .deps/
│ │ │ │ └── Release/
│ │ │ │ ├── obj.target/
│ │ │ │ │ └── tree_sitter_ripple_binding/
│ │ │ │ │ ├── bindings/
│ │ │ │ │ │ └── node/
│ │ │ │ │ │ └── binding.o.d
│ │ │ │ │ └── src/
│ │ │ │ │ ├── parser.o.d
│ │ │ │ │ └── scanner.o.d
│ │ │ │ └── tree_sitter_ripple_binding.node.d
│ │ │ ├── obj.target/
│ │ │ │ └── tree_sitter_ripple_binding/
│ │ │ │ ├── bindings/
│ │ │ │ │ └── node/
│ │ │ │ │ └── binding.o
│ │ │ │ └── src/
│ │ │ │ ├── parser.o
│ │ │ │ └── scanner.o
│ │ │ └── tree_sitter_ripple_binding.node
│ │ ├── binding.Makefile
│ │ ├── config.gypi
│ │ ├── gyp-mac-tool
│ │ └── tree_sitter_ripple_binding.target.mk
│ ├── typescript-plugin/
│ │ ├── CHANGELOG.md
│ │ ├── LICENSE
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── index.js
│ │ │ ├── language.js
│ │ │ └── utils.js
│ │ ├── tsconfig.json
│ │ └── tsdown.config.js
│ ├── vite-plugin/
│ │ ├── CHANGELOG.md
│ │ ├── LICENSE
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── bin/
│ │ │ │ └── preview.js
│ │ │ ├── constants.js
│ │ │ ├── index.js
│ │ │ ├── load-config.js
│ │ │ ├── routes.js
│ │ │ └── server/
│ │ │ ├── middleware.js
│ │ │ ├── production.js
│ │ │ ├── render-route.js
│ │ │ ├── router.js
│ │ │ ├── server-route.js
│ │ │ └── virtual-entry.js
│ │ ├── tsconfig.json
│ │ └── types/
│ │ ├── index.d.ts
│ │ └── production.d.ts
│ ├── vscode-plugin/
│ │ ├── .gitignore
│ │ ├── .vscodeignore
│ │ ├── CHANGELOG.md
│ │ ├── LICENSE
│ │ ├── README.md
│ │ ├── language-configuration.json
│ │ ├── package.json
│ │ ├── scripts/
│ │ │ └── repack-vsix.js
│ │ ├── src/
│ │ │ ├── extension.js
│ │ │ └── server.js
│ │ ├── tsconfig.json
│ │ └── tsdown.config.js
│ └── zed-plugin/
│ ├── .gitignore
│ ├── Cargo.toml
│ ├── DEVELOPMENT.md
│ ├── LICENSE
│ ├── README.md
│ ├── extension.toml
│ ├── languages/
│ │ └── ripple/
│ │ ├── brackets.scm
│ │ ├── config.toml
│ │ ├── folds.scm
│ │ ├── highlights.scm
│ │ ├── indents.scm
│ │ ├── injections.scm
│ │ ├── locals.scm
│ │ ├── outline.scm
│ │ └── textobjects.scm
│ ├── package.json
│ └── src/
│ └── lib.rs
├── playground/
│ ├── CHANGELOG.md
│ ├── debug-mode.js
│ ├── demo.css
│ ├── eslint.config.js
│ ├── index.html
│ ├── package.json
│ ├── ssr-dev.js
│ ├── tsconfig.json
│ └── vite.config.js
├── pnpm-workspace.yaml
├── rulesync.jsonc
├── scripts/
│ ├── collect-external-deps.js
│ ├── copy-external-deps.js
│ ├── copy-tree-sitter-queries.js
│ ├── regenerate-textmate.js
│ ├── remove.js
│ └── transform-package.js
├── templates/
│ └── basic/
│ ├── .gitignore
│ ├── .prettierignore
│ ├── .prettierrc
│ ├── README.md
│ ├── eslint.config.js
│ ├── index.html
│ ├── package.json
│ ├── src/
│ │ ├── App.ripple
│ │ └── index.ts
│ ├── tsconfig.json
│ └── vite.config.js
├── tree-sitter
├── vitest.config.js
├── website/
│ ├── .vitepress/
│ │ ├── components/
│ │ │ ├── Code.vue
│ │ │ ├── LiveCodes.vue
│ │ │ ├── Playground.vue
│ │ │ └── PlaygroundProps.ts
│ │ ├── config.js
│ │ └── theme/
│ │ ├── index.js
│ │ └── styles.css
│ ├── docs/
│ │ ├── best-practices.md
│ │ ├── comparison.md
│ │ ├── examples.ts
│ │ ├── guide/
│ │ │ ├── application.md
│ │ │ ├── bindings.md
│ │ │ ├── components.md
│ │ │ ├── control-flow.md
│ │ │ ├── dom-refs.md
│ │ │ ├── events.md
│ │ │ ├── head-management.md
│ │ │ ├── reactivity.md
│ │ │ ├── state-management.md
│ │ │ ├── styling.md
│ │ │ └── syntax.md
│ │ ├── introduction.md
│ │ ├── libraries.md
│ │ ├── quick-start.md
│ │ └── troubleshooting.md
│ ├── package.json
│ ├── playground.md
│ ├── public/
│ │ ├── 404.html
│ │ ├── index.html
│ │ ├── llms.txt
│ │ ├── robots.txt
│ │ └── sitemap.xml
│ └── vercel.json
└── website-new/
├── CHANGELOG.md
├── api/
│ └── handler.js
├── docs/
│ ├── best-practices.md
│ ├── comparison.md
│ ├── examples.ts
│ ├── guide/
│ │ ├── application.md
│ │ ├── bindings.md
│ │ ├── components.md
│ │ ├── control-flow.md
│ │ ├── dom-refs.md
│ │ ├── events.md
│ │ ├── head-management.md
│ │ ├── reactivity.md
│ │ ├── state-management.md
│ │ ├── styling.md
│ │ └── syntax.md
│ ├── introduction.md
│ ├── libraries.md
│ ├── quick-start.md
│ └── troubleshooting.md
├── index.html
├── package.json
├── playground.md
├── public/
│ ├── 404.html
│ ├── llms.txt
│ ├── robots.txt
│ └── sitemap.xml
├── ripple.config.ts
├── src/
│ ├── components/
│ │ ├── actions.ripple
│ │ ├── content.ripple
│ │ ├── doc-badge.ripple
│ │ ├── doc-callout.ripple
│ │ ├── doc-code-block.ripple
│ │ ├── doc-heading.ripple
│ │ ├── docs-footer.ripple
│ │ ├── docs-header.ripple
│ │ ├── docs-layout.ripple
│ │ ├── editor.ripple
│ │ ├── header.ripple
│ │ ├── layout.ripple
│ │ └── sidebar.ripple
│ ├── lib/
│ │ └── markdown.js
│ ├── middlewares.ts
│ ├── pages/
│ │ ├── 404.ripple
│ │ ├── docs/
│ │ │ ├── best-practices.ripple
│ │ │ ├── comparison.ripple
│ │ │ ├── guide/
│ │ │ │ ├── application.ripple
│ │ │ │ ├── bindings.ripple
│ │ │ │ ├── components.ripple
│ │ │ │ ├── control-flow.ripple
│ │ │ │ ├── dom-refs.ripple
│ │ │ │ ├── events.ripple
│ │ │ │ ├── head-management.ripple
│ │ │ │ ├── reactivity.ripple
│ │ │ │ ├── state-management.ripple
│ │ │ │ ├── styling.ripple
│ │ │ │ └── syntax.ripple
│ │ │ ├── introduction.ripple
│ │ │ ├── libraries.ripple
│ │ │ ├── quick-start.ripple
│ │ │ └── troubleshooting.ripple
│ │ └── index.ripple
│ └── routes.ts
├── tsconfig.json
├── vercel.json
└── vite.config.ts
SYMBOL INDEX (2064 symbols across 206 files)
FILE: grammars/tree-sitter/bindings/node/binding.cc
type TSLanguage (line 3) | struct TSLanguage
function Init (line 7) | Napi::Object Init(Napi::Env env, Napi::Object exports) {
FILE: grammars/tree-sitter/grammar.js
constant PREC (line 1) | const PREC = {
function commaSep (line 1118) | function commaSep(rule) {
function commaSep1 (line 1122) | function commaSep1(rule) {
FILE: grammars/tree-sitter/src/parser.c
type ts_symbol_identifiers (line 22) | enum ts_symbol_identifiers {
type ts_field_identifiers (line 2235) | enum ts_field_identifiers {
function ts_lex (line 6117) | static bool ts_lex(TSLexer *lexer, TSStateId state) {
function ts_lex_keywords (line 7576) | static bool ts_lex_keywords(TSLexer *lexer, TSStateId state) {
type ts_external_scanner_symbol_identifiers (line 153745) | enum ts_external_scanner_symbol_identifiers {
function TS_PUBLIC (line 153801) | TS_PUBLIC const TSLanguage *tree_sitter_ripple(void) {
FILE: grammars/tree-sitter/src/scanner.c
type TokenType (line 4) | enum TokenType {
function tree_sitter_ripple_external_scanner_destroy (line 12) | void tree_sitter_ripple_external_scanner_destroy(void *p) {}
function tree_sitter_ripple_external_scanner_reset (line 13) | void tree_sitter_ripple_external_scanner_reset(void *p) {}
function tree_sitter_ripple_external_scanner_serialize (line 14) | unsigned tree_sitter_ripple_external_scanner_serialize(void *p, char *bu...
function tree_sitter_ripple_external_scanner_deserialize (line 15) | void tree_sitter_ripple_external_scanner_deserialize(void *p, const char...
function advance (line 17) | static void advance(TSLexer *lexer) { lexer->advance(lexer, false); }
function skip (line 18) | static void skip(TSLexer *lexer) { lexer->advance(lexer, true); }
function scan_whitespace_and_comments (line 20) | static bool scan_whitespace_and_comments(TSLexer *lexer) {
function scan_automatic_semicolon (line 57) | static bool scan_automatic_semicolon(TSLexer *lexer) {
function scan_template_chars (line 96) | static bool scan_template_chars(TSLexer *lexer) {
function scan_ternary_qmark (line 119) | static bool scan_ternary_qmark(TSLexer *lexer) {
function scan_jsx_text (line 141) | static bool scan_jsx_text(TSLexer *lexer) {
function tree_sitter_ripple_external_scanner_scan (line 156) | bool tree_sitter_ripple_external_scanner_scan(void *payload, TSLexer *le...
FILE: grammars/tree-sitter/src/tree_sitter/array.h
function _array__erase (line 197) | static inline void _array__erase(void* self_contents, uint32_t *size,
function _array__swap (line 231) | static inline void _array__swap(uint32_t *self_size, uint32_t *self_capa...
FILE: grammars/tree-sitter/src/tree_sitter/parser.h
type TSStateId (line 17) | typedef uint16_t TSStateId;
type TSSymbol (line 18) | typedef uint16_t TSSymbol;
type TSFieldId (line 19) | typedef uint16_t TSFieldId;
type TSLanguage (line 20) | typedef struct TSLanguage TSLanguage;
type TSLanguageMetadata (line 21) | typedef struct TSLanguageMetadata {
type TSFieldMapEntry (line 28) | typedef struct {
type TSMapSlice (line 35) | typedef struct {
type TSSymbolMetadata (line 40) | typedef struct {
type TSLexer (line 46) | typedef struct TSLexer TSLexer;
type TSLexer (line 48) | struct TSLexer {
type TSParseActionType (line 59) | typedef enum {
type TSParseAction (line 66) | typedef union {
type TSLexMode (line 83) | typedef struct {
type TSLexerMode (line 88) | typedef struct {
type TSParseActionEntry (line 94) | typedef union {
type TSCharacterRange (line 102) | typedef struct {
type TSLanguage (line 107) | struct TSLanguage {
function set_contains (line 154) | static inline bool set_contains(const TSCharacterRange *ranges, uint32_t...
FILE: packages/adapter-bun/src/index.js
method hash (line 33) | hash(str) {
method createAsyncContext (line 38) | createAsyncContext() {
function serve (line 65) | function serve(fetch_handler, options = {}) {
function serveStatic (line 139) | function serveStatic(dir, options = {}) {
FILE: packages/adapter-bun/tests/serve.test.js
function mock_bun_file (line 23) | function mock_bun_file(file_path) {
function ensure_bun_file_mock (line 52) | function ensure_bun_file_mock() {
function create_bun_mock (line 95) | function create_bun_mock() {
function with_cwd (line 125) | async function with_cwd(cwd, run) {
FILE: packages/adapter-bun/types/index.d.ts
type ServeOptions (line 18) | type ServeOptions = AdapterCoreOptions & {
type ServeStaticOptions (line 23) | type ServeStaticOptions = BaseServeStaticOptions;
FILE: packages/adapter-node/src/index.js
method hash (line 36) | hash(str) {
method createAsyncContext (line 39) | createAsyncContext() {
function first_header_value (line 52) | function first_header_value(value) {
function normalize_forwarded_value (line 62) | function normalize_forwarded_value(value) {
function node_request_to_web_request (line 73) | function node_request_to_web_request(node_request, signal, trust_proxy =...
function web_response_to_node_response (line 126) | function web_response_to_node_response(web_response, node_response, requ...
function run_node_middleware (line 171) | function run_node_middleware(middleware, node_request, node_response) {
function serve (line 198) | function serve(fetch_handler, options = {}) {
function resolve_static_file_path (line 301) | function resolve_static_file_path(base_dir, pathname) {
function create_static_handler (line 314) | function create_static_handler(dir, options = {}) {
function serveStatic (line 383) | function serveStatic(dir, options = {}) {
FILE: packages/adapter-node/tests/serve.test.js
function with_server (line 14) | async function with_server(fetch_handler, run, options = {}) {
function with_cwd (line 45) | async function with_cwd(cwd, run) {
function send_node_request (line 64) | function send_node_request(url, options = {}) {
method middleware (line 185) | middleware(req, res, next) {
method middleware (line 208) | middleware(req, res, next) {
FILE: packages/adapter-node/types/index.d.ts
type ServeOptions (line 17) | type ServeOptions = AdapterCoreOptions & {
type ServeStaticOptions (line 28) | type ServeStaticOptions = BaseServeStaticOptions;
type StaticMiddleware (line 30) | type StaticMiddleware = (
FILE: packages/adapter-vercel/src/adapt.js
constant VERCEL_OUTPUT_DIR (line 42) | const VERCEL_OUTPUT_DIR = '.vercel/output';
function get_default_runtime (line 49) | function get_default_runtime() {
function write (line 74) | function write(file_path, data) {
function copy_dir (line 85) | function copy_dir(src, dest) {
function trace_and_copy_dependencies (line 115) | async function trace_and_copy_dependencies(entry, func_dir, project_root) {
function generate_handler_source (line 174) | function generate_handler_source(server_entry_relative) {
function generate_vercel_config (line 206) | function generate_vercel_config(options) {
function adapt (line 301) | async function adapt(options = {}) {
FILE: packages/adapter-vercel/src/bin/adapt.js
function parse_args (line 21) | function parse_args(argv) {
FILE: packages/adapter-vercel/tests/adapt.test.js
function create_build_output (line 37) | function create_build_output(root, options = {}) {
FILE: packages/adapter-vercel/types/index.d.ts
type ServerlessConfig (line 40) | interface ServerlessConfig {
type ISRConfig (line 67) | interface ISRConfig {
type ImagesConfig (line 92) | interface ImagesConfig {
type ImageFormat (line 103) | type ImageFormat = 'image/avif' | 'image/webp';
type RemotePattern (line 105) | interface RemotePattern {
type VercelHeader (line 115) | interface VercelHeader {
type VercelRedirect (line 123) | interface VercelRedirect {
type VercelRewrite (line 132) | interface VercelRewrite {
type VercelRoute (line 140) | interface VercelRoute {
type VercelConfig (line 152) | interface VercelConfig {
type AdaptOptions (line 167) | interface AdaptOptions {
FILE: packages/adapter/src/index.js
constant DEFAULT_HOSTNAME (line 1) | const DEFAULT_HOSTNAME = 'localhost';
constant DEFAULT_PORT (line 2) | const DEFAULT_PORT = 3000;
constant DEFAULT_STATIC_PREFIX (line 3) | const DEFAULT_STATIC_PREFIX = '/';
constant DEFAULT_STATIC_MAX_AGE (line 4) | const DEFAULT_STATIC_MAX_AGE = 86400;
constant MIME_TYPES (line 10) | const MIME_TYPES = {
function internal_server_error_response (line 42) | function internal_server_error_response() {
function run_next_middleware (line 61) | async function run_next_middleware(middleware, request, server, next_han...
function is_hashed_asset (line 86) | function is_hashed_asset(pathname) {
function get_static_cache_control (line 96) | function get_static_cache_control(
function get_mime_type (line 112) | function get_mime_type(pathname) {
FILE: packages/adapter/src/rpc.js
constant RPC_PATH_PREFIX (line 22) | const RPC_PATH_PREFIX = '/_$_ripple_rpc_$_/';
function derive_origin (line 29) | function derive_origin(request, trust_proxy) {
function has_scheme (line 58) | function has_scheme(url) {
function patch_global_fetch (line 63) | function patch_global_fetch(async_context) {
function build_rpc_lookup (line 155) | function build_rpc_lookup(rpc_modules, hash_fn) {
function is_rpc_request (line 175) | function is_rpc_request(pathname) {
function handle_rpc_request (line 180) | async function handle_rpc_request(request, options) {
FILE: packages/adapter/types/index.d.ts
type FetchHandler (line 1) | type FetchHandler<Platform = any, ResultValue = Response> = (
type AdapterCoreOptions (line 9) | type AdapterCoreOptions = {
type ServeStaticOptions (line 25) | type ServeStaticOptions = {
type ServeStaticDirectoryOptions (line 31) | type ServeStaticDirectoryOptions = ServeStaticOptions & {
type NextMiddleware (line 35) | type NextMiddleware<RequestValue = Request, Server = any, ResultValue = ...
type ServeResult (line 41) | type ServeResult<Server = any> = {
type ServeFunction (line 46) | type ServeFunction<
constant DEFAULT_HOSTNAME (line 52) | const DEFAULT_HOSTNAME: 'localhost';
constant DEFAULT_PORT (line 53) | const DEFAULT_PORT: 3000;
constant DEFAULT_STATIC_PREFIX (line 54) | const DEFAULT_STATIC_PREFIX: '/';
constant DEFAULT_STATIC_MAX_AGE (line 55) | const DEFAULT_STATIC_MAX_AGE: 86400;
constant MIME_TYPES (line 56) | const MIME_TYPES: Readonly<Record<string, string>>;
FILE: packages/adapter/types/rpc.d.ts
type AsyncContext (line 5) | type AsyncContext<T = any> = {
type RuntimePrimitives (line 18) | type RuntimePrimitives = {
type RpcEntry (line 42) | type RpcEntry = {
type HandleRpcOptions (line 50) | type HandleRpcOptions = {
type PatchedFetchHandle (line 70) | type PatchedFetchHandle = {
type RipplePatchedFetch (line 110) | type RipplePatchedFetch = typeof globalThis.fetch & {
FILE: packages/cli/src/commands/create.js
function createCommand (line 28) | async function createCommand(projectName, options) {
function showNextSteps (line 130) | function showNextSteps(projectPath, packageManager) {
function getInstallCommand (line 160) | function getInstallCommand(packageManager) {
function getDevCommand (line 175) | function getDevCommand(packageManager) {
FILE: packages/cli/src/constants.js
constant TEMPLATES (line 4) | const TEMPLATES = [
constant GITHUB_REPO (line 15) | const GITHUB_REPO = 'Ripple-TS/ripple';
constant GITHUB_BRANCH (line 16) | const GITHUB_BRANCH = 'main';
constant GITHUB_TEMPLATES_DIRECTORY (line 17) | const GITHUB_TEMPLATES_DIRECTORY = 'templates';
FILE: packages/cli/src/lib/is-folder-empty.js
function isFolderEmpty (line 19) | function isFolderEmpty(root, name) {
FILE: packages/cli/src/lib/package-manager.js
function getCurrentPackageManager (line 7) | function getCurrentPackageManager() {
FILE: packages/cli/src/lib/project-creator.js
function createProject (line 24) | async function createProject({
function updatePackageJson (line 159) | function updatePackageJson(projectPath, projectName, packageManager, sty...
function configureStyling (line 212) | function configureStyling(projectPath, stylingFramework) {
function updateDependencyVersions (line 261) | function updateDependencyVersions(packageJson) {
function updateScripts (line 295) | function updateScripts(packageJson) {
function getPackageManagerVersion (line 312) | function getPackageManagerVersion(packageManager) {
FILE: packages/cli/src/lib/prompts.js
function promptProjectName (line 13) | async function promptProjectName(defaultName = 'my-ripple-app') {
function promptTemplate (line 37) | async function promptTemplate() {
function promptPackageManager (line 66) | async function promptPackageManager(defaultPackageManager) {
function promptTypeScript (line 94) | async function promptTypeScript() {
function promptGitInit (line 114) | async function promptGitInit() {
function promptStylingFramework (line 130) | async function promptStylingFramework() {
FILE: packages/cli/src/lib/templates.js
function getTemplate (line 17) | function getTemplate(templateName) {
function getTemplateNames (line 25) | function getTemplateNames() {
function getTemplateChoices (line 33) | function getTemplateChoices() {
function validateTemplate (line 46) | function validateTemplate(templateName) {
function downloadTemplate (line 57) | async function downloadTemplate(templateName) {
function getLocalTemplatePath (line 89) | function getLocalTemplatePath(templateName) {
function isLocalDevelopment (line 100) | function isLocalDevelopment() {
FILE: packages/cli/src/lib/validation.js
function validateProjectName (line 12) | function validateProjectName(inputName) {
function sanitizeDirectoryName (line 116) | function sanitizeDirectoryName(name) {
function validateDirectoryPath (line 129) | function validateDirectoryPath(path) {
FILE: packages/cli/tests/integration/cli.test.js
constant CLI_PATH (line 13) | const CLI_PATH = join(__dirname, '../../src/index.js');
FILE: packages/cli/tests/unit/templates.test.js
function normalizePath (line 128) | function normalizePath(path) {
FILE: packages/compat-react/src/index.js
function map_portals (line 47) | function map_portals(portals) {
function is_inside_try_pending (line 57) | function is_inside_try_pending(block) {
function createReactCompat (line 69) | function createReactCompat() {
function get_block_from_dom (line 180) | function get_block_from_dom(node) {
function Ripple (line 198) | function Ripple({ component, props }) {
function RippleRoot (line 286) | function RippleRoot({ children }) {
FILE: packages/compat-react/tests/client.d.ts
type HTMLElement (line 5) | interface HTMLElement {
FILE: packages/compat-react/types/index.d.ts
type Tsx (line 3) | type Tsx = {
FILE: packages/eslint-parser/src/index.ts
type ParseResult (line 5) | interface ParseResult {
function normalizeRippleAstForEslint (line 19) | function normalizeRippleAstForEslint(ast: any): void {
function ensureNodeProperties (line 51) | function ensureNodeProperties(node: any, code: string): void {
function parseForESLint (line 117) | function parseForESLint(code: string, options?: Linter.ParserOptions): P...
function parse (line 163) | function parse(code: string, options?: Linter.ParserOptions): Program {
function requireRippleCompiler (line 172) | function requireRippleCompiler(): any {
FILE: packages/eslint-parser/src/loader.ts
function initializeParser (line 12) | async function initializeParser() {
function getRippleCompiler (line 36) | function getRippleCompiler() {
FILE: packages/eslint-plugin/src/index.ts
function createConfig (line 48) | function createConfig(name: string, files: string[], parser: any) {
FILE: packages/eslint-plugin/src/rules/control-flow-jsx.ts
method create (line 20) | create(context) {
FILE: packages/eslint-plugin/src/rules/no-introspect-in-modules.ts
method create (line 17) | create(context) {
FILE: packages/eslint-plugin/src/rules/no-module-scope-track.ts
method create (line 17) | create(context) {
FILE: packages/eslint-plugin/src/rules/no-return-in-component.ts
method create (line 16) | create(context) {
FILE: packages/eslint-plugin/src/rules/prefer-oninput.ts
method create (line 19) | create(context) {
FILE: packages/eslint-plugin/src/rules/unbox-tracked-values.ts
method create (line 16) | create(context) {
FILE: packages/eslint-plugin/src/rules/valid-for-of-key.ts
method create (line 17) | create(context) {
function findVariable (line 107) | function findVariable(scope: Scope.Scope, name: string) {
FILE: packages/language-server/src/autoInsertPlugin.js
constant VOID_ELEMENTS (line 11) | const VOID_ELEMENTS = new Set([
function createAutoInsertPlugin (line 35) | function createAutoInsertPlugin() {
FILE: packages/language-server/src/compileErrorDiagnosticPlugin.js
function createCompileErrorDiagnosticPlugin (line 17) | function createCompileErrorDiagnosticPlugin() {
function parseCompilationErrorWithDocument (line 71) | function parseCompilationErrorWithDocument(error, virtualCode, sourceMap...
function get_error_range_from_source (line 128) | function get_error_range_from_source(error, document) {
function get_end_offset_from_error (line 141) | function get_end_offset_from_error(error, start_offset) {
function get_start_offset_from_error (line 154) | function get_start_offset_from_error(error) {
FILE: packages/language-server/src/completionPlugin.js
constant TRACKED_COLLECTION_SNIPPETS (line 12) | const TRACKED_COLLECTION_SNIPPETS = [
function findRippleImport (line 92) | function findRippleImport(text) {
function generateImportEdit (line 122) | function generateImportEdit(documentText, importName) {
constant RIPPLE_SNIPPETS (line 172) | const RIPPLE_SNIPPETS = [
constant RIPPLE_NAMESPACE_SNIPPETS (line 339) | const RIPPLE_NAMESPACE_SNIPPETS = [
constant RIPPLE_IMPORTS (line 505) | const RIPPLE_IMPORTS = [
function get_ripple_namespace_match (line 552) | function get_ripple_namespace_match(line) {
function create_ripple_namespace_completion_items (line 561) | function create_ripple_namespace_completion_items(namespace_match, posit...
function createCompletionPlugin (line 583) | function createCompletionPlugin() {
FILE: packages/language-server/src/definitionPlugin.js
function createDefinitionPlugin (line 24) | function createDefinitionPlugin() {
FILE: packages/language-server/src/documentHighlightPlugin.js
function createDocumentHighlightPlugin (line 12) | function createDocumentHighlightPlugin() {
FILE: packages/language-server/src/hoverPlugin.js
function createHoverPlugin (line 21) | function createHoverPlugin() {
FILE: packages/language-server/src/server.js
function createRippleLanguageServer (line 25) | function createRippleLanguageServer() {
FILE: packages/language-server/src/typescriptDiagnosticPlugin.js
function process (line 19) | function process(diagnostic, items) {
function processDiagnostics (line 31) | function processDiagnostics(document, context, diagnostics) {
function createTypeScriptDiagnosticFilterPlugin (line 96) | function createTypeScriptDiagnosticFilterPlugin() {
FILE: packages/language-server/src/typescriptService.js
function createTypeScriptServices (line 40) | function createTypeScriptServices(ts) {
FILE: packages/language-server/src/utils.js
constant IMPORT_EXPORT_REGEX (line 15) | const IMPORT_EXPORT_REGEX = {
constant IDENTIFIER_OBFUSCATION_PREFIX (line 32) | let IDENTIFIER_OBFUSCATION_PREFIX;
function escapeRegExp (line 50) | function escapeRegExp(source) {
function deobfuscateIdentifiers (line 59) | function deobfuscateIdentifiers(text) {
function concatMarkdownContents (line 67) | function concatMarkdownContents(...contents) {
function getVirtualCode (line 83) | function getVirtualCode(document, context) {
function isInsideImportOrExport (line 106) | function isInsideImportOrExport(type, text, start) {
function isInsideImport (line 140) | function isInsideImport(text, start) {
function isInsideExport (line 149) | function isInsideExport(text, start) {
FILE: packages/prettier-plugin/src/index.js
method parse (line 97) | parse(text, _options) {
method locStart (line 105) | locStart(node) {
method locEnd (line 113) | locEnd(node) {
method print (line 129) | print(path, options, print, args) {
method embed (line 144) | embed(path) {
method getVisitorKeys (line 194) | getVisitorKeys(node) {
function formatStringLiteral (line 226) | function formatStringLiteral(value, options) {
function semi (line 247) | function semi(options) {
function wasOriginallySingleLine (line 256) | function wasOriginallySingleLine(node) {
function isSingleLineObjectExpression (line 269) | function isSingleLineObjectExpression(node) {
function hasComment (line 278) | function hasComment(node) {
function getFunctionParameters (line 286) | function getFunctionParameters(node) {
function iterateFunctionParametersPath (line 304) | function iterateFunctionParametersPath(path, iteratee) {
constant PRECEDENCE (line 318) | const PRECEDENCE = {
function getPrecedence (line 350) | function getPrecedence(operator) {
function binaryExpressionNeedsParens (line 360) | function binaryExpressionNeedsParens(node, parent) {
function createSkip (line 405) | function createSkip(characters) {
function isCharNewLine (line 444) | function isCharNewLine(character) {
function isCharSpace (line 455) | function isCharSpace(character) {
function skipInlineComment (line 465) | function skipInlineComment(text, startIndex) {
function skipNewline (line 488) | function skipNewline(text, startIndex, options) {
function skipTrailingComment (line 520) | function skipTrailingComment(text, startIndex) {
function isRegExpLiteral (line 537) | function isRegExpLiteral(node) {
function isCommentFollowedBySameLineParen (line 547) | function isCommentFollowedBySameLineParen(comment, options) {
function hasNewline (line 575) | function hasNewline(text, startIndex, options) {
function isNextLineEmpty (line 587) | function isNextLineEmpty(node, options) {
function hasRestParameter (line 614) | function hasRestParameter(node) {
function shouldPrintComma (line 628) | function shouldPrintComma(options, level = 'all') {
function uses_long_tracked_syntax (line 648) | function uses_long_tracked_syntax(node, options, kind) {
function canAttachLeadingCommentToPreviousElement (line 675) | function canAttachLeadingCommentToPreviousElement(comment, previousNode,...
function buildInlineArrayCommentDoc (line 705) | function buildInlineArrayCommentDoc(comments) {
function printKey (line 737) | function printKey(node, path, options, print) {
function printRippleNode (line 774) | function printRippleNode(node, path, options, print, args) {
function printImportDeclaration (line 2353) | function printImportDeclaration(node, path, options, _print) {
function printExportNamedDeclaration (line 2437) | function printExportNamedDeclaration(node, path, options, print) {
function printComponent (line 2484) | function printComponent(
function printVariableDeclaration (line 2643) | function printVariableDeclaration(node, path, options, print) {
function printFunctionExpression (line 2673) | function printFunctionExpression(node, path, options, print) {
function printArrowFunction (line 2733) | function printArrowFunction(node, path, options, print) {
function printExportDefaultDeclaration (line 2805) | function printExportDefaultDeclaration(node, path, options, print) {
function shouldHugTheOnlyFunctionParameter (line 2818) | function shouldHugTheOnlyFunctionParameter(node) {
function printFunctionParameters (line 2844) | function printFunctionParameters(path, options, print) {
function isSpreadLike (line 2897) | function isSpreadLike(node) {
function isBlockLikeFunction (line 2906) | function isBlockLikeFunction(node) {
function shouldHugLastArgument (line 2925) | function shouldHugLastArgument(args, argumentBreakFlags) {
function shouldHugArrowFunctions (line 2966) | function shouldHugArrowFunctions(args) {
function printCallArguments (line 2996) | function printCallArguments(path, options, print) {
function printTSDeclareFunction (line 3209) | function printTSDeclareFunction(node, path, options, print) {
function printFunctionDeclaration (line 3269) | function printFunctionDeclaration(node, path, options, print) {
function extractAndPrintLeadingComments (line 3318) | function extractAndPrintLeadingComments(node) {
function printIfStatement (line 3365) | function printIfStatement(node, path, options, print) {
function printForInStatement (line 3424) | function printForInStatement(node, path, options, print) {
function printForOfStatement (line 3446) | function printForOfStatement(node, path, options, print) {
function printForStatement (line 3479) | function printForStatement(node, path, options, print) {
function printWhileStatement (line 3517) | function printWhileStatement(node, path, options, print) {
function printDoWhileStatement (line 3546) | function printDoWhileStatement(node, path, options, print) {
function printObjectExpression (line 3584) | function printObjectExpression(node, path, options, print, args) {
function printClassDeclaration (line 3747) | function printClassDeclaration(node, path, options, print) {
function printTryStatement (line 3787) | function printTryStatement(node, path, options, print) {
function printClassBody (line 3838) | function printClassBody(node, path, options, print) {
function printPropertyDefinition (line 3871) | function printPropertyDefinition(node, path, options, print) {
function printMethodDefinition (line 3924) | function printMethodDefinition(node, path, options, print) {
function printMemberExpression (line 4025) | function printMemberExpression(node, path, options, print) {
function printUnaryExpression (line 4070) | function printUnaryExpression(node, path, options, print) {
function printYieldExpression (line 4110) | function printYieldExpression(node, path, options, print) {
function printNewExpression (line 4135) | function printNewExpression(node, path, options, print) {
function printTemplateLiteral (line 4182) | function printTemplateLiteral(node, path, options, print) {
function printTaggedTemplateExpression (line 4228) | function printTaggedTemplateExpression(node, path, options, print) {
function printThrowStatement (line 4244) | function printThrowStatement(node, path, options, print) {
function printTSInterfaceDeclaration (line 4261) | function printTSInterfaceDeclaration(node, path, options, print) {
function printTSInterfaceBody (line 4292) | function printTSInterfaceBody(node, path, options, print) {
function printTSTypeAliasDeclaration (line 4313) | function printTSTypeAliasDeclaration(node, path, options, print) {
function printTSEnumDeclaration (line 4338) | function printTSEnumDeclaration(node, path, options, print) {
function printTSEnumMember (line 4388) | function printTSEnumMember(node, path, options, print) {
function printTSTypeParameterDeclaration (line 4417) | function printTSTypeParameterDeclaration(node, path, options, print) {
function printTSTypeParameter (line 4444) | function printTSTypeParameter(node, path, options, print) {
function printTSTypeParameterInstantiation (line 4470) | function printTSTypeParameterInstantiation(node, path, options, print) {
function printSwitchStatement (line 4519) | function printSwitchStatement(node, path, options, print) {
function printSwitchCase (line 4564) | function printSwitchCase(node, path, options, print) {
function printBreakStatement (line 4638) | function printBreakStatement(node, path, options, print) {
function printContinueStatement (line 4658) | function printContinueStatement(node, path, options, print) {
function printDebuggerStatement (line 4677) | function printDebuggerStatement(node, path, options) {
function printSequenceExpression (line 4689) | function printSequenceExpression(node, path, options, print) {
function getBlankLinesBetweenPositions (line 4708) | function getBlankLinesBetweenPositions(current_pos, next_pos) {
function getBlankLinesBetweenNodes (line 4723) | function getBlankLinesBetweenNodes(currentNode, nextNode) {
function shouldAddBlankLine (line 4744) | function shouldAddBlankLine(currentNode, nextNode) {
function printObjectPattern (line 4794) | function printObjectPattern(node, path, options, print) {
function printArrayPattern (line 4873) | function printArrayPattern(node, path, options, print) {
function printProperty (line 4900) | function printProperty(node, path, options, print) {
function printVariableDeclarator (line 5013) | function printVariableDeclarator(node, path, options, print) {
function printAssignmentPattern (line 5133) | function printAssignmentPattern(node, path, options, print) {
function printTSTypeLiteral (line 5146) | function printTSTypeLiteral(node, path, options, print) {
function printTSPropertySignature (line 5179) | function printTSPropertySignature(node, path, options, print) {
function printTSMethodSignature (line 5204) | function printTSMethodSignature(node, path, options, print) {
function printTSTypeReference (line 5254) | function printTSTypeReference(node, path, options, print) {
function printTSTupleType (line 5291) | function printTSTupleType(node, path, options, print) {
function printTSIndexSignature (line 5311) | function printTSIndexSignature(node, path, options, print) {
function printTSConstructorType (line 5342) | function printTSConstructorType(node, path, options, print) {
function printTSConditionalType (line 5373) | function printTSConditionalType(node, path, options, print) {
function printTSMappedType (line 5394) | function printTSMappedType(node, path, options, print) {
function printTSQualifiedName (line 5444) | function printTSQualifiedName(node, path, options, print) {
function printTSIndexedAccessType (line 5455) | function printTSIndexedAccessType(node, path, options, print) {
function shouldInlineSingleChild (line 5465) | function shouldInlineSingleChild(parentNode, firstChild, childDoc) {
function getElementLeadingComments (line 5504) | function getElementLeadingComments(node) {
function createElementLevelCommentParts (line 5517) | function createElementLevelCommentParts(comments) {
function createElementLevelCommentPartsTrimmed (line 5553) | function createElementLevelCommentPartsTrimmed(comments) {
function printTsxCompat (line 5569) | function printTsxCompat(node, path, options, print) {
function printJSXElement (line 5650) | function printJSXElement(node, path, options, print) {
function printJSXFragment (line 5786) | function printJSXFragment(node, path, options, print) {
function printJSXAttribute (line 5839) | function printJSXAttribute(attr, path, options, print) {
function printJSXMemberExpression (line 5870) | function printJSXMemberExpression(node) {
function printMemberExpressionSimple (line 5887) | function printMemberExpressionSimple(node, options, computed = false) {
function printElement (line 5929) | function printElement(element, path, options, print) {
function printAttribute (line 6329) | function printAttribute(node, path, options, print) {
FILE: packages/prettier-plugin/src/index.test.js
method toBeWithNewline (line 10) | toBeWithNewline(received, expected) {
FILE: packages/prettier-plugin/vitest-extensions.d.ts
type Assertion (line 4) | interface Assertion<T = any> {
type AsymmetricMatchersContaining (line 8) | interface AsymmetricMatchersContaining {
FILE: packages/ripple/src/compiler/comment-utils.js
function is_ts_pragma (line 10) | function is_ts_pragma(comment) {
function is_triple_slash_directive (line 23) | function is_triple_slash_directive(comment) {
function is_jsdoc_ts_annotation (line 38) | function is_jsdoc_ts_annotation(comment) {
function should_preserve_comment (line 66) | function should_preserve_comment(comment) {
function format_comment (line 77) | function format_comment(comment) {
FILE: packages/ripple/src/compiler/errors.js
function error (line 15) | function error(message, filename, node, errors, comments) {
function is_ripple_error_suppress_comment (line 56) | function is_ripple_error_suppress_comment(comment) {
function is_ripple_error_suppressed (line 65) | function is_ripple_error_suppressed(node, comments) {
FILE: packages/ripple/src/compiler/identifier-utils.js
constant IDENTIFIER_OBFUSCATION_PREFIX (line 1) | const IDENTIFIER_OBFUSCATION_PREFIX = '_$_';
constant RIPPLE_NAMESPACE_IDENTIFIER (line 2) | const RIPPLE_NAMESPACE_IDENTIFIER =
constant STYLE_IDENTIFIER (line 4) | const STYLE_IDENTIFIER = IDENTIFIER_OBFUSCATION_PREFIX + encode_utf16_ch...
constant SERVER_IDENTIFIER (line 5) | const SERVER_IDENTIFIER =
constant CSS_HASH_IDENTIFIER (line 11) | const CSS_HASH_IDENTIFIER = IDENTIFIER_OBFUSCATION_PREFIX + 'hash';
constant DECODE_UTF16_REGEX (line 13) | const DECODE_UTF16_REGEX = /_u([0-9a-fA-F]{4})_/g;
function encode_utf16_char (line 19) | function encode_utf16_char(char) {
function find_next_uppercase (line 29) | function find_next_uppercase(name, start) {
function decode_utf16_string (line 42) | function decode_utf16_string(encoded) {
function obfuscate_identifier (line 50) | function obfuscate_identifier(name) {
function is_identifier_obfuscated (line 75) | function is_identifier_obfuscated(name) {
function deobfuscate_identifier (line 83) | function deobfuscate_identifier(name) {
FILE: packages/ripple/src/compiler/index.d.ts
type CompileResult (line 15) | interface CompileResult {
type DefinitionLocation (line 27) | interface DefinitionLocation {
type PluginActionOverrides (line 33) | interface PluginActionOverrides {
type CustomMappingData (line 60) | interface CustomMappingData extends PluginActionOverrides {
type MappingData (line 65) | interface MappingData extends VolarCodeInformation {
type CodeMapping (line 69) | interface CodeMapping extends Omit<VolarMapping<MappingData>, 'generated...
type VolarMappingsResult (line 74) | interface VolarMappingsResult {
type RippleCompileError (line 81) | interface RippleCompileError extends Error {
type SharedCompileOptions (line 94) | interface SharedCompileOptions {
type CompileOptions (line 98) | interface CompileOptions extends SharedCompileOptions {
type ParseOptions (line 103) | interface ParseOptions {
type AnalyzeOptions (line 109) | interface AnalyzeOptions extends ParseOptions, Pick<CompileOptions, 'mod...
type VolarCompileOptions (line 114) | interface VolarCompileOptions
FILE: packages/ripple/src/compiler/index.js
function parse (line 14) | function parse(source) {
function compile (line 25) | function compile(source, filename, options = {}) {
function compile_to_volar_mappings (line 59) | function compile_to_volar_mappings(source, filename, options = {}) {
FILE: packages/ripple/src/compiler/phases/1-parse/index.js
constant BINDING_TYPES (line 30) | const BINDING_TYPES = {
function DestructuringErrors (line 43) | function DestructuringErrors() {
function set_tracked_name (line 59) | function set_tracked_name(node, name) {
function convert_from_jsx (line 70) | function convert_from_jsx(node) {
function skipWhitespace (line 99) | function skipWhitespace(parser) {
function isWhitespaceTextNode (line 132) | function isWhitespaceTextNode(node) {
function RipplePlugin (line 154) | function RipplePlugin(config) {
function get_comment_handlers (line 2562) | function get_comment_handlers(source, comments, index = 0) {
function parse (line 3150) | function parse(source, filename, options) {
FILE: packages/ripple/src/compiler/phases/1-parse/style.js
constant REGEX_MATCHER (line 5) | const REGEX_MATCHER = /^[~^$*|]?=/;
constant REGEX_ATTRIBUTE_FLAGS (line 6) | const REGEX_ATTRIBUTE_FLAGS = /^[a-zA-Z]+/;
constant REGEX_COMMENT_CLOSE (line 7) | const REGEX_COMMENT_CLOSE = /\*\//;
constant REGEX_HTML_COMMENT_CLOSE (line 8) | const REGEX_HTML_COMMENT_CLOSE = /-->/;
constant REGEX_PERCENTAGE (line 9) | const REGEX_PERCENTAGE = /^\d+(\.\d+)?%/;
constant REGEX_COMBINATOR (line 10) | const REGEX_COMBINATOR = /^(\+|~|>|\|\|)/;
constant REGEX_VALID_IDENTIFIER_CHAR (line 11) | const REGEX_VALID_IDENTIFIER_CHAR = /[a-zA-Z0-9_-]/;
constant REGEX_LEADING_HYPHEN_OR_DIGIT (line 12) | const REGEX_LEADING_HYPHEN_OR_DIGIT = /-?\d/;
constant REGEX_WHITESPACE_OR_COLON (line 13) | const REGEX_WHITESPACE_OR_COLON = /[\s:]/;
constant REGEX_NTH_OF (line 14) | const REGEX_NTH_OF =
class Parser (line 19) | class Parser {
method constructor (line 26) | constructor(template, loose) {
method match (line 37) | match(str) {
method eat (line 52) | eat(str, required = false, required_in_loose = true) {
method match_regex (line 69) | match_regex(pattern) {
method read (line 80) | read(pattern) {
method allow_whitespace (line 86) | allow_whitespace() {
method read_until (line 93) | read_until(pattern) {
function parse_style (line 117) | function parse_style(content, options) {
function allow_comment_or_whitespace (line 131) | function allow_comment_or_whitespace(parser) {
function read_body (line 152) | function read_body(parser) {
function read_at_rule (line 173) | function read_at_rule(parser) {
function read_rule (line 206) | function read_rule(parser) {
function read_block (line 227) | function read_block(parser) {
function read_block_item (line 261) | function read_block_item(parser) {
function read_declaration (line 280) | function read_declaration(parser) {
function read_value (line 314) | function read_value(parser) {
function read_selector_list (line 355) | function read_selector_list(parser, inside_pseudo_class = false) {
function read_combinator (line 390) | function read_combinator(parser) {
function read_selector (line 426) | function read_selector(parser, inside_pseudo_class = false) {
function read_attribute_value (line 637) | function read_attribute_value(parser) {
function read_identifier (line 669) | function read_identifier(parser) {
FILE: packages/ripple/src/compiler/phases/2-analyze/css-analyze.js
function is_global_block_selector (line 9) | function is_global_block_selector(simple_selector) {
function is_global (line 21) | function is_global(relative_selector) {
function analyze_css (line 41) | function analyze_css(css) {
FILE: packages/ripple/src/compiler/phases/2-analyze/index.js
function mark_control_flow_has_template (line 45) | function mark_control_flow_has_template(path) {
function visit_function (line 75) | function visit_function(node, context) {
function mark_as_tracked (line 94) | function mark_as_tracked(path) {
function get_return_keyword_node (line 116) | function get_return_keyword_node(node) {
function error_return_keyword (line 136) | function error_return_keyword(node, context, message) {
function unwrap_template_expression (line 152) | function unwrap_template_expression(expression) {
function is_children_template_expression (line 184) | function is_children_template_expression(expression, state) {
method _ (line 222) | _(node, { state, next, path }) {
method Program (line 234) | Program(_, context) {
method ServerBlock (line 238) | ServerBlock(node, context) {
method Identifier (line 257) | Identifier(node, context) {
method MemberExpression (line 348) | MemberExpression(node, context) {
method CallExpression (line 517) | CallExpression(node, context) {
method NewExpression (line 546) | NewExpression(node, context) {
method VariableDeclaration (line 582) | VariableDeclaration(node, context) {
method StyleIdentifier (line 635) | StyleIdentifier(node, context) {
method ServerIdentifier (line 656) | ServerIdentifier(node, context) {
method ArrowFunctionExpression (line 672) | ArrowFunctionExpression(node, context) {
method FunctionExpression (line 675) | FunctionExpression(node, context) {
method FunctionDeclaration (line 678) | FunctionDeclaration(node, context) {
method Component (line 682) | Component(node, context) {
method ForStatement (line 784) | ForStatement(node, context) {
method SwitchStatement (line 798) | SwitchStatement(node, context) {
method ForOfStatement (line 831) | ForOfStatement(node, context) {
method ExportNamedDeclaration (line 904) | ExportNamedDeclaration(node, context) {
method TSTypeReference (line 1009) | TSTypeReference(node, context) {
method IfStatement (line 1021) | IfStatement(node, context) {
method ReturnStatement (line 1087) | ReturnStatement(node, context) {
method TryStatement (line 1137) | TryStatement(node, context) {
method ForInStatement (line 1193) | ForInStatement(node, context) {
method WhileStatement (line 1207) | WhileStatement(node, context) {
method DoWhileStatement (line 1219) | DoWhileStatement(node, context) {
method JSXElement (line 1231) | JSXElement(node, context) {
method TsxCompat (line 1245) | TsxCompat(_, context) {
method Element (line 1250) | Element(node, context) {
method Text (line 1513) | Text(node, context) {
method AwaitExpression (line 1534) | AwaitExpression(node, context) {
function analyze (line 1585) | function analyze(ast, filename, options = {}) {
FILE: packages/ripple/src/compiler/phases/2-analyze/prune.js
constant FORWARD (line 10) | const FORWARD = 0;
constant BACKWARD (line 12) | const BACKWARD = 1;
function create_descendant_combinator (line 29) | function create_descendant_combinator(start, end) {
function is_standalone_class_selector (line 38) | function is_standalone_class_selector(relative_selector, selector) {
function create_nesting_selector (line 47) | function create_nesting_selector(start, end) {
function create_any_selector (line 63) | function create_any_selector(start, end) {
function get_relative_selectors (line 128) | function get_relative_selectors(node) {
function truncate (line 170) | function truncate(node) {
function apply_selector (line 204) | function apply_selector(relative_selectors, rule, element, direction) {
function get_ancestor_elements (line 255) | function get_ancestor_elements(node, adjacent_only) {
function get_descendant_elements (line 281) | function get_descendant_elements(node, adjacent_only) {
function can_render_dynamic_content (line 334) | function can_render_dynamic_content(element, check_classes = false) {
function get_possible_element_siblings (line 369) | function get_possible_element_siblings(node, direction, adjacent_only) {
function apply_combinator (line 432) | function apply_combinator(relative_selector, rest_selectors, rule, node,...
function get_element_parent (line 547) | function get_element_parent(node) {
function is_unscoped_pseudo_class (line 572) | function is_unscoped_pseudo_class(selector) {
function is_global_simple (line 595) | function is_global_simple(relative_selector) {
function is_global (line 616) | function is_global(selector, rule) {
function is_text_attribute (line 661) | function is_text_attribute(attribute) {
function test_attribute (line 672) | function test_attribute(operator, expected_value, case_insensitive, valu...
function attribute_matches (line 703) | function attribute_matches(node, name, expected_value, operator, case_in...
function is_outer_global (line 728) | function is_outer_global(relative_selector) {
function relative_selector_might_apply_to_node (line 752) | function relative_selector_might_apply_to_node(relative_selector, rule, ...
function unquote (line 1005) | function unquote(str) {
function get_parent_rules (line 1019) | function get_parent_rules(rule) {
function rule_has_animation (line 1036) | function rule_has_animation(rule) {
function prune_css (line 1058) | function prune_css(css, element, styleClasses, topScopedClasses) {
FILE: packages/ripple/src/compiler/phases/2-analyze/validation.js
function get_element_tag (line 125) | function get_element_tag(element) {
function validate_nesting (line 134) | function validate_nesting(element, context, errors) {
FILE: packages/ripple/src/compiler/phases/3-transform/client/index.js
function visit_function (line 85) | function visit_function(node, context) {
function visit_head_element (line 138) | function visit_head_element(node, index, context) {
function apply_updates (line 189) | function apply_updates(init, update, state) {
function visit_title_element (line 321) | function visit_title_element(node, context) {
function set_hidden_import_from_ripple (line 351) | function set_hidden_import_from_ripple(name, context, is_obfuscated = fa...
function slice_loc_info (line 368) | function slice_loc_info(loc_info, start_offset = 0, length) {
function build_ripple_namespace_member (line 395) | function build_ripple_namespace_member(property_name, source_name, loc_i...
function ripple_namespace_requires_block (line 411) | function ripple_namespace_requires_block(name) {
function SetContextForOutsideComponent (line 425) | function SetContextForOutsideComponent(context, more_state = {}) {
function SetStateForOutsideComponent (line 437) | function SetStateForOutsideComponent(state, more_state = {}) {
method _ (line 449) | _(node, { next, state, path }) {
method Identifier (line 465) | Identifier(node, context) {
method ServerIdentifier (line 543) | ServerIdentifier(node, context) {
method StyleIdentifier (line 549) | StyleIdentifier(node, context) {
method ImportDeclaration (line 584) | ImportDeclaration(node, context) {
method TSNonNullExpression (line 622) | TSNonNullExpression(node, context) {
method CallExpression (line 629) | CallExpression(node, context) {
method TSTypeAliasDeclaration (line 809) | TSTypeAliasDeclaration(_, context) {
method TSInterfaceDeclaration (line 816) | TSInterfaceDeclaration(_, context) {
method TSMappedType (line 823) | TSMappedType(_, context) {
method NewExpression (line 830) | NewExpression(node, context) {
method RippleArrayExpression (line 865) | RippleArrayExpression(node, context) {
method RippleObjectExpression (line 893) | RippleObjectExpression(node, context) {
method TrackedExpression (line 929) | TrackedExpression(node, context) {
method MemberExpression (line 945) | MemberExpression(node, context) {
method PropertyDefinition (line 1021) | PropertyDefinition(node, context) {
method VariableDeclaration (line 1028) | VariableDeclaration(node, context) {
method VariableDeclarator (line 1038) | VariableDeclarator(node, context) {
method FunctionDeclaration (line 1114) | FunctionDeclaration(node, context) {
method ArrowFunctionExpression (line 1120) | ArrowFunctionExpression(node, context) {
method FunctionExpression (line 1126) | FunctionExpression(node, context) {
method JSXText (line 1130) | JSXText(node, context) {
method JSXIdentifier (line 1137) | JSXIdentifier(node, context) {
method JSXExpressionContainer (line 1144) | JSXExpressionContainer(node, context) {
method JSXEmptyExpression (line 1151) | JSXEmptyExpression(node, context) {
method JSXFragment (line 1162) | JSXFragment(node, context) {
method JSXElement (line 1214) | JSXElement(node, context) {
method TsxCompat (line 1269) | TsxCompat(node, context) {
method Element (line 1309) | Element(node, context) {
method Component (line 1947) | Component(node, context) {
method AssignmentExpression (line 2107) | AssignmentExpression(node, context) {
method UpdateExpression (line 2167) | UpdateExpression(node, context) {
method ForOfStatement (line 2224) | ForOfStatement(node, context) {
method SwitchStatement (line 2278) | SwitchStatement(node, context) {
method IfStatement (line 2356) | IfStatement(node, context) {
method ReturnStatement (line 2500) | ReturnStatement(node, context) {
method TSAsExpression (line 2518) | TSAsExpression(node, context) {
method TSInstantiationExpression (line 2525) | TSInstantiationExpression(node, context) {
method ExportNamedDeclaration (line 2537) | ExportNamedDeclaration(node, context) {
method TSDeclareFunction (line 2566) | TSDeclareFunction(node, context) {
method TryStatement (line 2577) | TryStatement(node, context) {
method AwaitExpression (line 2625) | AwaitExpression(node, context) {
method BinaryExpression (line 2651) | BinaryExpression(node, context) {
method TemplateLiteral (line 2659) | TemplateLiteral(node, context) {
method BlockStatement (line 2681) | BlockStatement(node, context) {
method ServerBlock (line 2692) | ServerBlock(node, context) {
method ScriptContent (line 2759) | ScriptContent(node, context) {
method Program (line 2763) | Program(node, context) {
function join_template (line 2782) | function join_template(items) {
function transform_ts_child (line 2830) | function transform_ts_child(node, context) {
function is_template_or_control_flow (line 3256) | function is_template_or_control_flow(node) {
function build_return_guard (line 3275) | function build_return_guard(flags) {
function collect_returns_from_children (line 3293) | function collect_returns_from_children(children) {
function element_has_dynamic_content (line 3328) | function element_has_dynamic_content(element) {
function transform_template_element (line 3395) | function transform_template_element(node, state, visit, child_namespace,...
function transform_children (line 3474) | function transform_children(children, context) {
function consequent_has_break (line 4039) | function consequent_has_break(consequent) {
function transform_body (line 4054) | function transform_body(body, { visit, state }) {
function create_tsx_with_typescript_support (line 4096) | function create_tsx_with_typescript_support(comments) {
function transform_client (line 5034) | function transform_client(filename, source, analysis, to_ts, minify_css,...
FILE: packages/ripple/src/compiler/phases/3-transform/segments.js
constant LABEL_TO_COMPONENT_REPLACE_REGEX (line 55) | const LABEL_TO_COMPONENT_REPLACE_REGEX = /(function|\((property|method)\...
function replace_label_to_component (line 61) | function replace_label_to_component(content) {
function get_style_region_id (line 73) | function get_style_region_id(hash, fallback) {
function visit_source_ast (line 87) | function visit_source_ast(ast, src_line_offsets, { regions, css_element_...
function extract_classes (line 141) | function extract_classes(node, src_to_gen_map, gen_line_offsets, src_lin...
function convert_source_map_to_mappings (line 291) | function convert_source_map_to_mappings(
FILE: packages/ripple/src/compiler/phases/3-transform/server/index.js
function is_template_or_control_flow (line 49) | function is_template_or_control_flow(node) {
function build_return_guard (line 67) | function build_return_guard(flags) {
function collect_returns_from_children (line 81) | function collect_returns_from_children(children) {
function transform_children (line 108) | function transform_children(children, context) {
function transform_body (line 280) | function transform_body(body, context) {
method Identifier (line 306) | Identifier(node, context) {
method Component (line 325) | Component(node, context) {
method CallExpression (line 451) | CallExpression(node, context) {
method NewExpression (line 522) | NewExpression(node, context) {
method PropertyDefinition (line 531) | PropertyDefinition(node, context) {
method FunctionDeclaration (line 538) | FunctionDeclaration(node, context) {
method FunctionExpression (line 553) | FunctionExpression(node, context) {
method BlockStatement (line 568) | BlockStatement(node, context) {
method ArrowFunctionExpression (line 579) | ArrowFunctionExpression(node, context) {
method TSAsExpression (line 593) | TSAsExpression(node, context) {
method TSInstantiationExpression (line 600) | TSInstantiationExpression(node, context) {
method TSTypeAliasDeclaration (line 608) | TSTypeAliasDeclaration(_, context) {
method TSInterfaceDeclaration (line 615) | TSInterfaceDeclaration(_, context) {
method ExportNamedDeclaration (line 622) | ExportNamedDeclaration(node, context) {
method VariableDeclaration (line 725) | VariableDeclaration(node, context) {
method Element (line 735) | Element(node, context) {
method SwitchStatement (line 1152) | SwitchStatement(node, context) {
method ForOfStatement (line 1196) | ForOfStatement(node, context) {
method IfStatement (line 1231) | IfStatement(node, context) {
method ReturnStatement (line 1282) | ReturnStatement(node, context) {
method AssignmentExpression (line 1293) | AssignmentExpression(node, context) {
method UpdateExpression (line 1346) | UpdateExpression(node, context) {
method ServerIdentifier (line 1383) | ServerIdentifier(node, context) {
method StyleIdentifier (line 1387) | StyleIdentifier(node, context) {
method ImportDeclaration (line 1391) | ImportDeclaration(node, context) {
method TryStatement (line 1423) | TryStatement(node, context) {
method AwaitExpression (line 1548) | AwaitExpression(node, context) {
method TrackedExpression (line 1562) | TrackedExpression(node, context) {
method RippleObjectExpression (line 1566) | RippleObjectExpression(node, context) {
method RippleArrayExpression (line 1574) | RippleArrayExpression(node, context) {
method MemberExpression (line 1583) | MemberExpression(node, context) {
method Text (line 1602) | Text(node, { visit, state }) {
method Html (line 1623) | Html(node, { visit, state }) {
method ScriptContent (line 1674) | ScriptContent(node, context) {
method ServerBlock (line 1680) | ServerBlock(node, context) {
method Program (line 1733) | Program(node, context) {
function transform_server (line 1760) | function transform_server(filename, source, analysis, minify_css, dev = ...
FILE: packages/ripple/src/compiler/phases/3-transform/stylesheet.js
function remove_css_prefix (line 35) | function remove_css_prefix(name) {
function remove_preceding_whitespace (line 44) | function remove_preceding_whitespace(end, state) {
function is_used (line 51) | function is_used(rule) {
function is_in_global_block (line 58) | function is_in_global_block(path) {
function is_in_global_pseudo (line 67) | function is_in_global_pseudo(path) {
function has_global_in_middle (line 108) | function has_global_in_middle(rule) {
function remove_global_pseudo_class (line 126) | function remove_global_pseudo_class(selector, combinator, state) {
function escape_comment_close (line 145) | function escape_comment_close(node, code) {
function append_hash (line 172) | function append_hash(state, index) {
function is_empty (line 180) | function is_empty(rule, is_in_global_block) {
method Atrule (line 217) | Atrule(node, { state, next, path }) {
method Declaration (line 237) | Declaration(node, { state }) {
method Rule (line 271) | Rule(node, { state, next, visit, path }) {
method SelectorList (line 312) | SelectorList(node, { state, next, path }) {
method ComplexSelector (line 397) | ComplexSelector(node, context) {
method PseudoClassSelector (line 511) | PseudoClassSelector(node, context) {
function render_stylesheets (line 524) | function render_stylesheets(stylesheets, minify = false) {
FILE: packages/ripple/src/compiler/scope.js
function create_scopes (line 29) | function create_scopes(ast, root, parent, error_options) {
class Scope (line 249) | class Scope {
method constructor (line 310) | constructor(...params) {
method declare (line 322) | declare(node, kind, declaration_kind, initial = null) {
method child (line 376) | child(porous = false) {
method generate (line 383) | generate(preferred_name) {
method get (line 409) | get(name) {
method get_bindings (line 416) | get_bindings(node) {
method owner (line 427) | owner(name) {
method reference (line 434) | reference(node, path) {
class ScopeRoot (line 456) | class ScopeRoot {
method unique (line 463) | unique(preferred_name) {
FILE: packages/ripple/src/compiler/source-map-utils.js
function build_src_to_gen_map (line 88) | function build_src_to_gen_map(
function maybe_get_generated_position (line 219) | function maybe_get_generated_position(src_line, src_column, src_to_gen_m...
function get_generated_position (line 238) | function get_generated_position(src_line, src_column, src_to_gen_map) {
function loc_to_offset (line 256) | function loc_to_offset(line, column, line_offsets) {
function build_line_offsets (line 270) | function build_line_offsets(text) {
function maybe_get_mapping_from_node (line 289) | function maybe_get_mapping_from_node(
function get_mapping_from_node (line 336) | function get_mapping_from_node(
FILE: packages/ripple/src/compiler/types/index.d.ts
type NameSpace (line 11) | type NameSpace = keyof typeof NAMESPACE_URI;
type BaseNodeMetaData (line 12) | interface BaseNodeMetaData {
type FunctionMetaData (line 48) | interface FunctionMetaData extends BaseNodeMetaData {
type AcornTSNode (line 57) | type AcornTSNode<T> = Omit<T, 'parent' | 'loc' | 'range' | 'expression'>...
type FunctionLikeTS (line 68) | interface FunctionLikeTS {
type FunctionDeclaration (line 76) | interface FunctionDeclaration extends FunctionLikeTS {
type FunctionExpression (line 79) | interface FunctionExpression extends FunctionLikeTS {
type ArrowFunctionExpression (line 82) | interface ArrowFunctionExpression extends FunctionLikeTS {
type NewExpression (line 86) | interface NewExpression {
type Accessibility (line 92) | type Accessibility = 'public' | 'protected' | 'private';
type MethodDefinition (line 93) | interface MethodDefinition {
type PropertyDefinition (line 98) | interface PropertyDefinition {
type ClassDeclaration (line 104) | interface ClassDeclaration {
type ClassExpression (line 110) | interface ClassExpression {
type Identifier (line 116) | interface Identifier extends AST.TrackedNode {
type MemberExpression (line 128) | interface MemberExpression extends AST.TrackedNode {}
type SimpleLiteral (line 132) | interface SimpleLiteral extends AST.LiteralTrackedNode {}
type RegExpLiteral (line 133) | interface RegExpLiteral extends AST.LiteralTrackedNode {}
type BigIntLiteral (line 134) | interface BigIntLiteral extends AST.LiteralTrackedNode {}
type TrackedNode (line 136) | interface TrackedNode {
type LiteralTrackedNode (line 140) | interface LiteralTrackedNode extends AST.TrackedNode {
type NodeMap (line 145) | interface NodeMap {
type ExpressionMap (line 163) | interface ExpressionMap {
type ParenthesizedExpression (line 176) | interface ParenthesizedExpression extends AST.BaseNode {
type Comment (line 184) | interface Comment {
type ObjectExpression (line 191) | interface ObjectExpression {
type CommentWithLocation (line 200) | type CommentWithLocation = AST.Comment & NodeWithLocation;
type TryStatement (line 202) | interface TryStatement {
type ForOfStatement (line 206) | interface ForOfStatement {
type ServerIdentifier (line 211) | interface ServerIdentifier extends AST.BaseExpression {
type StyleIdentifier (line 215) | interface StyleIdentifier extends AST.BaseExpression {
type ImportDeclaration (line 219) | interface ImportDeclaration {
type ImportSpecifier (line 222) | interface ImportSpecifier {
type ExportNamedDeclaration (line 225) | interface ExportNamedDeclaration {
type BaseNodeWithoutComments (line 229) | interface BaseNodeWithoutComments {
type BaseNode (line 238) | interface BaseNode {
type NodeWithLocation (line 256) | interface NodeWithLocation {
type NodeWithMaybeComments (line 262) | interface NodeWithMaybeComments {
type Component (line 271) | interface Component extends AST.BaseNode {
type TsxCompat (line 287) | interface TsxCompat extends AST.BaseNode {
type Html (line 298) | interface Html extends AST.BaseNode {
type Element (line 303) | interface Element extends AST.BaseNode {
type TextNode (line 336) | interface TextNode extends AST.BaseExpression {
type ServerBlockStatement (line 342) | interface ServerBlockStatement extends Omit<BlockStatement, 'body'> {
type ServerBlock (line 346) | interface ServerBlock extends AST.BaseNode {
type ScriptContent (line 354) | interface ScriptContent extends Omit<AST.Element, 'type'> {
type RippleArrayExpression (line 362) | interface RippleArrayExpression extends Omit<AST.ArrayExpression, 'type'> {
type TrackedExpression (line 367) | interface TrackedExpression extends AST.BaseExpression {
type RippleObjectExpression (line 372) | interface RippleObjectExpression extends Omit<AST.ObjectExpression, 'typ...
type Attribute (line 380) | interface Attribute extends AST.BaseNode {
type RefAttribute (line 391) | interface RefAttribute extends AST.BaseNode {
type SpreadAttribute (line 397) | interface SpreadAttribute extends AST.BaseNode {
type RippleDeclaration (line 407) | type RippleDeclaration = AST.Declaration | Component | AST.TSDeclareFunc...
type RippleExportNamedDeclaration (line 412) | interface RippleExportNamedDeclaration extends Omit<AST.ExportNamedDecla...
type RippleProgram (line 419) | interface RippleProgram extends Omit<Program, 'body'> {
type RippleMethodDefinition (line 423) | interface RippleMethodDefinition extends Omit<AST.MethodDefinition, 'val...
type RippleProperty (line 427) | interface RippleProperty extends Omit<AST.Property, 'value'> {
type RippleAttribute (line 431) | type RippleAttribute = AST.Attribute | AST.SpreadAttribute | AST.RefAttr...
type RippleStatement (line 433) | type RippleStatement = AST.Statement | TSESTree.Statement;
type NodeWithChildren (line 435) | type NodeWithChildren = AST.Element | AST.TsxCompat;
type BaseNode (line 438) | interface BaseNode extends AST.NodeWithMaybeComments {
type StyleSheet (line 444) | interface StyleSheet extends BaseNode {
type Atrule (line 451) | interface Atrule extends BaseNode {
type Rule (line 458) | interface Rule extends BaseNode {
type SelectorList (line 472) | interface SelectorList extends BaseNode {
type ComplexSelector (line 483) | interface ComplexSelector extends BaseNode {
type RelativeSelector (line 499) | interface RelativeSelector extends BaseNode {
type TypeSelector (line 517) | interface TypeSelector extends BaseNode {
type IdSelector (line 522) | interface IdSelector extends BaseNode {
type ClassSelector (line 527) | interface ClassSelector extends BaseNode {
type AttributeSelector (line 532) | interface AttributeSelector extends BaseNode {
type PseudoElementSelector (line 540) | interface PseudoElementSelector extends BaseNode {
type PseudoClassSelector (line 545) | interface PseudoClassSelector extends BaseNode {
type Percentage (line 551) | interface Percentage extends BaseNode {
type NestingSelector (line 556) | interface NestingSelector extends BaseNode {
type Nth (line 561) | interface Nth extends BaseNode {
type SimpleSelector (line 566) | type SimpleSelector =
type Combinator (line 577) | interface Combinator extends BaseNode {
type Block (line 582) | interface Block extends BaseNode {
type Declaration (line 587) | interface Declaration extends BaseNode {
type Node (line 594) | type Node =
type JSXAttribute (line 609) | interface JSXAttribute {
type JSXIdentifier (line 613) | interface JSXIdentifier {
type JSXEmptyExpression (line 620) | interface JSXEmptyExpression {
type JSXOpeningFragment (line 625) | interface JSXOpeningFragment {
type JSXElement (line 629) | interface JSXElement {
type JSXExpressionContainer (line 635) | interface JSXExpressionContainer {
type JSXMemberExpression (line 639) | interface JSXMemberExpression {
type RippleJSXOpeningElement (line 643) | interface RippleJSXOpeningElement extends Omit<JSXOpeningElement, 'name'> {
type RippleJSXClosingElement (line 647) | interface RippleJSXClosingElement extends Omit<JSXClosingElement, 'name'> {
type ExpressionMap (line 651) | interface ExpressionMap {
type TSNodeMap (line 659) | interface TSNodeMap {
type TypeNode (line 729) | type TypeNode = TSNodeMap[keyof TSNodeMap];
type NodeMap (line 732) | interface NodeMap extends TSNodeMap {
type EntityName (line 736) | type EntityName = AST.Identifier | AST.ThisExpression | TSQualifiedName;
type Parameter (line 737) | type Parameter =
type TypeElement (line 744) | type TypeElement =
type TSPropertySignature (line 750) | type TSPropertySignature = TSPropertySignatureComputedName | TSPropertyS...
type PropertyNameComputed (line 751) | type PropertyNameComputed = AST.Expression;
type PropertyNameNonComputed (line 752) | type PropertyNameNonComputed = AST.Identifier | NumberLiteral | StringLi...
type TSAnyKeyword (line 756) | interface TSAnyKeyword extends AcornTSNode<TSESTree.TSAnyKeyword> {}
type TSArrayType (line 757) | interface TSArrayType extends Omit<AcornTSNode<TSESTree.TSArrayType>, 'e...
type TSAsExpression (line 760) | interface TSAsExpression extends Omit<AcornTSNode<TSESTree.TSAsExpressio...
type TSBigIntKeyword (line 765) | interface TSBigIntKeyword extends AcornTSNode<TSESTree.TSBigIntKeyword> {}
type TSBooleanKeyword (line 766) | interface TSBooleanKeyword extends AcornTSNode<TSESTree.TSBooleanKeyword...
type TSCallSignatureDeclaration (line 767) | interface TSCallSignatureDeclaration extends Omit<
type TSConditionalType (line 775) | interface TSConditionalType extends Omit<
type TSConstructorType (line 784) | interface TSConstructorType extends Omit<
type TSConstructSignatureDeclaration (line 792) | interface TSConstructSignatureDeclaration extends Omit<
type TSDeclareFunction (line 800) | interface TSDeclareFunction extends Omit<
type TSEnumDeclaration (line 809) | interface TSEnumDeclaration extends Omit<
type TSEnumMember (line 816) | interface TSEnumMember extends Omit<AcornTSNode<TSESTree.TSEnumMember>, ...
type TSExportAssignment (line 820) | interface TSExportAssignment extends Omit<
type TSExternalModuleReference (line 826) | interface TSExternalModuleReference extends Omit<
type TSFunctionType (line 832) | interface TSFunctionType extends Omit<
type TSImportEqualsDeclaration (line 840) | interface TSImportEqualsDeclaration extends AcornTSNode<TSESTree.TSImpor...
type TSImportType (line 841) | interface TSImportType extends Omit<
type TSIndexedAccessType (line 850) | interface TSIndexedAccessType extends Omit<
type TSIndexSignature (line 857) | interface TSIndexSignature extends Omit<
type TSInferType (line 864) | interface TSInferType extends Omit<AcornTSNode<TSESTree.TSInferType>, 't...
type TSInstantiationExpression (line 867) | interface TSInstantiationExpression extends Omit<
type TSInterfaceBody (line 874) | interface TSInterfaceBody extends Omit<AcornTSNode<TSESTree.TSInterfaceB...
type TSInterfaceDeclaration (line 877) | interface TSInterfaceDeclaration extends Omit<
type TSIntersectionType (line 886) | interface TSIntersectionType extends Omit<AcornTSNode<TSESTree.TSInterse...
type TSIntrinsicKeyword (line 889) | interface TSIntrinsicKeyword extends AcornTSNode<TSESTree.TSIntrinsicKey...
type TSLiteralType (line 890) | interface TSLiteralType extends Omit<AcornTSNode<TSESTree.TSLiteralType>...
type TSMappedType (line 893) | interface TSMappedType extends Omit<
type TSMethodSignature (line 901) | interface TSMethodSignature extends Omit<
type TSModuleBlock (line 911) | interface TSModuleBlock extends Omit<AcornTSNode<TSESTree.TSModuleBlock>...
type TSModuleDeclaration (line 914) | interface TSModuleDeclaration extends Omit<
type TSNamedTupleMember (line 921) | interface TSNamedTupleMember extends Omit<
type TSNamespaceExportDeclaration (line 928) | interface TSNamespaceExportDeclaration extends Omit<
type TSNeverKeyword (line 934) | interface TSNeverKeyword extends AcornTSNode<TSESTree.TSNeverKeyword> {}
type TSNonNullExpression (line 935) | interface TSNonNullExpression extends AcornTSNode<TSESTree.TSNonNullExpr...
type TSNullKeyword (line 938) | interface TSNullKeyword extends AcornTSNode<TSESTree.TSNullKeyword> {}
type TSNumberKeyword (line 939) | interface TSNumberKeyword extends AcornTSNode<TSESTree.TSNumberKeyword> {}
type TSObjectKeyword (line 940) | interface TSObjectKeyword extends AcornTSNode<TSESTree.TSObjectKeyword> {}
type TSOptionalType (line 941) | interface TSOptionalType extends Omit<AcornTSNode<TSESTree.TSOptionalTyp...
type TSParameterProperty (line 944) | interface TSParameterProperty extends AcornTSNode<TSESTree.TSParameterPr...
type TSPropertySignatureComputedName (line 945) | interface TSPropertySignatureComputedName extends Omit<
type TSPropertySignatureNonComputedName (line 952) | interface TSPropertySignatureNonComputedName extends Omit<
type TSQualifiedName (line 959) | interface TSQualifiedName extends Omit<AcornTSNode<TSESTree.TSQualifiedN...
type TSRestType (line 963) | interface TSRestType extends Omit<AcornTSNode<TSESTree.TSRestType>, 'typ...
type TSSatisfiesExpression (line 966) | interface TSSatisfiesExpression extends Omit<
type TSStringKeyword (line 973) | interface TSStringKeyword extends AcornTSNode<TSESTree.TSStringKeyword> {}
type TSSymbolKeyword (line 974) | interface TSSymbolKeyword extends AcornTSNode<TSESTree.TSSymbolKeyword> {}
type TSThisType (line 975) | interface TSThisType extends AcornTSNode<TSESTree.TSThisType> {}
type TSTupleType (line 976) | interface TSTupleType extends Omit<AcornTSNode<TSESTree.TSTupleType>, 'e...
type TSTypeAliasDeclaration (line 979) | interface TSTypeAliasDeclaration extends Omit<
type TSTypeAnnotation (line 987) | interface TSTypeAnnotation extends Omit<
type TSTypeAssertion (line 993) | interface TSTypeAssertion extends AcornTSNode<TSESTree.TSTypeAssertion> {
type TSTypeLiteral (line 996) | interface TSTypeLiteral extends Omit<AcornTSNode<TSESTree.TSTypeLiteral>...
type TSTypeOperator (line 999) | interface TSTypeOperator extends Omit<AcornTSNode<TSESTree.TSTypeOperato...
type TSTypeParameter (line 1002) | interface TSTypeParameter extends Omit<
type TSTypeParameterDeclaration (line 1010) | interface TSTypeParameterDeclaration extends Omit<
type TSTypeParameterInstantiation (line 1019) | interface TSTypeParameterInstantiation extends Omit<
type TSTypePredicate (line 1025) | interface TSTypePredicate extends AcornTSNode<TSESTree.TSTypePredicate> {}
type TSTypeQuery (line 1026) | interface TSTypeQuery extends Omit<
type TSTypeReference (line 1033) | interface TSTypeReference extends Omit<
type TSUndefinedKeyword (line 1040) | interface TSUndefinedKeyword extends AcornTSNode<TSESTree.TSUndefinedKey...
type TSUnionType (line 1041) | interface TSUnionType extends Omit<AcornTSNode<TSESTree.TSUnionType>, 't...
type TSInterfaceHeritage (line 1045) | interface TSInterfaceHeritage extends Omit<
type TSExpressionWithTypeArguments (line 1054) | interface TSExpressionWithTypeArguments extends Omit<TSInterfaceHeritage...
type TSClassImplements (line 1058) | interface TSClassImplements extends AcornTSNode<TSESTree.TSClassImplemen...
type TSUnknownKeyword (line 1059) | interface TSUnknownKeyword extends AcornTSNode<TSESTree.TSUnknownKeyword...
type TSVoidKeyword (line 1060) | interface TSVoidKeyword extends AcornTSNode<TSESTree.TSVoidKeyword> {}
type NumberLiteral (line 1061) | interface NumberLiteral extends AcornTSNode<TSESTree.NumberLiteral> {}
type StringLiteral (line 1062) | interface StringLiteral extends AcornTSNode<TSESTree.StringLiteral> {}
type TSParenthesizedType (line 1065) | interface TSParenthesizedType extends AST.BaseNode {
type ExpressionMap (line 1070) | interface ExpressionMap {
type ParseError (line 1082) | interface ParseError {
type ParseResult (line 1091) | interface ParseResult {
type AnalysisResult (line 1096) | interface AnalysisResult {
type RipplePluginConfig (line 1111) | interface RipplePluginConfig {
type DeclarationKind (line 1118) | type DeclarationKind =
type BindingKind (line 1133) | type BindingKind =
type Binding (line 1144) | interface Binding {
type ScopeRoot (line 1187) | interface ScopeRoot {
type ScopeConstructorInterface (line 1194) | interface ScopeConstructorInterface {
type ScopeConstructorParameters (line 1206) | type ScopeConstructorParameters = [
type ScopeInterface (line 1216) | interface ScopeInterface {
type BaseStateMetaData (line 1263) | interface BaseStateMetaData {
type BaseState (line 1268) | interface BaseState {
type AnalysisState (line 1282) | interface AnalysisState extends BaseState {
type TransformServerState (line 1300) | interface TransformServerState extends BaseState {
type UpdateList (line 1316) | type UpdateList = Array<
type TransformClientState (line 1329) | interface TransformClientState extends BaseState {
type NodeOf (line 1350) | type NodeOf<T extends string, X> = X extends { type: T } ? X : never;
type SpecializedVisitors (line 1352) | type SpecializedVisitors<T extends AST.Node | AST.CSS.Node, U> = {
type VisitFn (line 1356) | type VisitFn<V> = (node: V) => void;
type CatchAllVisitor (line 1358) | type CatchAllVisitor<T, U, V> = (
type Visitor (line 1364) | type Visitor<T, U, V> = (node: T, context: Context<V, U>) => V | void;
type Visitors (line 1366) | type Visitors<T extends AST.Node | AST.CSS.Node, U> = T['type'] extends '_'
type Context (line 1372) | interface Context<T, U> extends Omit<
type TransformClientContext (line 1386) | type TransformClientContext = Context<AST.Node, TransformClientState>;
type TransformServerContext (line 1387) | type TransformServerContext = Context<AST.Node, TransformServerState>;
type AnalysisContext (line 1388) | type AnalysisContext = Context<AST.Node, AnalysisState>;
type CommonContext (line 1389) | type CommonContext = TransformClientContext | TransformServerContext | A...
type VisitorClientContext (line 1390) | type VisitorClientContext = TransformClientContext & { root?: boolean };
type DelegatedEventResult (line 1395) | interface DelegatedEventResult {
type TopScopedClasses (line 1399) | type TopScopedClasses = Map<
type StyleClasses (line 1408) | type StyleClasses = Map<string, AST.MemberExpression['property']>;
FILE: packages/ripple/src/compiler/types/parse.d.ts
type ForInit (line 21) | type ForInit = boolean | 'await';
type ReadToken (line 25) | type ReadToken = Parse.Parser['readToken'];
class Position (line 28) | class Position implements AST.Position {
type Parser (line 36) | interface Parser {
type ESRapTSOptions (line 70) | interface ESRapTSOptions {
type DestructuringErrors (line 79) | interface DestructuringErrors {
type BindingType (line 91) | interface BindingType {
type BranchID (line 111) | interface BranchID {
type RegExpValidationState (line 127) | interface RegExpValidationState {
type Options (line 185) | interface Options extends Omit<acorn.Options, 'onComment' | 'ecmaVersion...
type CommentMetaData (line 206) | interface CommentMetaData {
type TokContext (line 215) | interface TokContext {
type TokenType (line 225) | interface TokenType {
type TokContexts (line 241) | interface TokContexts {
type TokTypes (line 267) | interface TokTypes {
type AcornTypeScriptTokTypes (line 357) | interface AcornTypeScriptTokTypes {
type TokenType (line 374) | enum: TokenType & { label: 'enum' }
type TokenType (line 378) | interface: TokenType & { label: 'interface' }
type AcornTypeScriptTokContexts (line 402) | interface AcornTypeScriptTokContexts {
type AcornTypeScriptExtensions (line 414) | interface AcornTypeScriptExtensions {
type Scope (line 419) | interface Scope {
type Exports (line 426) | type Exports = Record<string, boolean>;
type Parser (line 435) | interface Parser {
type ParserConstructor (line 1720) | interface ParserConstructor {
FILE: packages/ripple/src/compiler/types/rpc.d.ts
type RpcModules (line 1) | type RpcModules = Map<string, [string, string]>;
FILE: packages/ripple/src/compiler/utils.js
constant VOID_ELEMENT_NAMES (line 12) | const VOID_ELEMENT_NAMES = [
function is_void_element (line 40) | function is_void_element(name) {
constant RESERVED_WORDS (line 44) | const RESERVED_WORDS = [
function is_reserved (line 100) | function is_reserved(word) {
constant DOM_BOOLEAN_ATTRIBUTES (line 107) | const DOM_BOOLEAN_ATTRIBUTES = [
function is_boolean_attribute (line 144) | function is_boolean_attribute(name) {
constant DOM_PROPERTIES (line 148) | const DOM_PROPERTIES = [
constant RIPPLE_NAMESPACE_CALL_NAME (line 167) | const RIPPLE_NAMESPACE_CALL_NAME = {
function is_dom_property (line 186) | function is_dom_property(name) {
function is_delegated_event (line 197) | function is_delegated_event(event_name, handler, context) {
function is_top_level_await (line 217) | function is_top_level_await(context) {
function is_inside_component (line 243) | function is_inside_component(context, includes_functions = false) {
function is_component_level_function (line 268) | function is_component_level_function(context) {
function is_ripple_track_call (line 297) | function is_ripple_track_call(callee, context) {
function is_inside_call_expression (line 317) | function is_inside_call_expression(context) {
function is_value_static (line 345) | function is_value_static(node) {
function is_ripple_import (line 368) | function is_ripple_import(callee, context) {
function is_declared_function_within_component (line 404) | function is_declared_function_within_component(node, context) {
function visit_assignment_expression (line 441) | function visit_assignment_expression(node, context, build_assignment) {
function build_assignment (line 513) | function build_assignment(operator, left, right, context) {
constant ATTR_REGEX (line 545) | const ATTR_REGEX = /[&"<]/g;
constant CONTENT_REGEX (line 546) | const CONTENT_REGEX = /[&<]/g;
function escape_html (line 554) | function escape_html(value, is_attr = false) {
function is_element_dom_element (line 578) | function is_element_dom_element(node) {
function is_element_dynamic (line 593) | function is_element_dynamic(node) {
function is_id_dynamic (line 601) | function is_id_dynamic(node) {
function normalize_children (line 628) | function normalize_children(children, context) {
function normalize_child (line 664) | function normalize_child(node, normalized, context) {
function get_parent_block_node (line 685) | function get_parent_block_node(context) {
function build_getter (line 716) | function build_getter(node, context) {
function determine_namespace_for_children (line 744) | function determine_namespace_for_children(element_name, current_namespac...
function index_to_key (line 765) | function index_to_key(index) {
function is_binding_function (line 784) | function is_binding_function(binding, scope, visited = new Set()) {
function is_inside_try_block (line 820) | function is_inside_try_block(try_parent_stmt, context) {
function is_inside_left_side_assignment (line 843) | function is_inside_left_side_assignment(node) {
function flatten_switch_consequent (line 921) | function flatten_switch_consequent(consequent) {
function get_ripple_namespace_call_name (line 938) | function get_ripple_namespace_call_name(name) {
FILE: packages/ripple/src/constants.js
constant TEMPLATE_FRAGMENT (line 1) | const TEMPLATE_FRAGMENT = 1;
constant TEMPLATE_USE_IMPORT_NODE (line 2) | const TEMPLATE_USE_IMPORT_NODE = 1 << 1;
constant IS_CONTROLLED (line 3) | const IS_CONTROLLED = 1 << 2;
constant IS_INDEXED (line 4) | const IS_INDEXED = 1 << 3;
constant TEMPLATE_SVG_NAMESPACE (line 5) | const TEMPLATE_SVG_NAMESPACE = 1 << 5;
constant TEMPLATE_MATHML_NAMESPACE (line 6) | const TEMPLATE_MATHML_NAMESPACE = 1 << 6;
constant HYDRATION_START (line 8) | const HYDRATION_START = '[';
constant HYDRATION_END (line 9) | const HYDRATION_END = ']';
constant HYDRATION_ERROR (line 10) | const HYDRATION_ERROR = {};
constant BLOCK_OPEN (line 12) | const BLOCK_OPEN = `<!--${HYDRATION_START}-->`;
constant BLOCK_CLOSE (line 13) | const BLOCK_CLOSE = `<!--${HYDRATION_END}-->`;
constant EMPTY_COMMENT (line 14) | const EMPTY_COMMENT = `<!---->`;
constant ELEMENT_NODE (line 16) | const ELEMENT_NODE = 1;
constant TEXT_NODE (line 17) | const TEXT_NODE = 3;
constant COMMENT_NODE (line 18) | const COMMENT_NODE = 8;
constant DOCUMENT_FRAGMENT_NODE (line 19) | const DOCUMENT_FRAGMENT_NODE = 11;
FILE: packages/ripple/src/helpers.d.ts
type RequireAllOrNone (line 1) | type RequireAllOrNone<T, K extends keyof T> =
type RequiredPresent (line 5) | type RequiredPresent<T, K extends keyof T> = Omit<T, K> & Required<Pick<...
type Nullable (line 7) | type Nullable<T> = T | null;
type Nullish (line 9) | type Nullish<T> = T | null | undefined;
FILE: packages/ripple/src/html-tree-validation.js
function is_tag_valid_with_ancestor (line 117) | function is_tag_valid_with_ancestor(child_tag, ancestors, child_loc, anc...
function is_tag_valid_with_parent (line 157) | function is_tag_valid_with_parent(child_tag, parent_tag, child_loc, pare...
FILE: packages/ripple/src/jsx-runtime.d.ts
type ComponentType (line 10) | type ComponentType<P = {}> = (props: P) => void;
type ClassValue (line 44) | type ClassValue = string | import('clsx').ClassArray | import('clsx').Cl...
type HTMLAttributes (line 47) | interface HTMLAttributes {
type SVGAttributes (line 133) | interface SVGAttributes {
type SVGAnimationAttributes (line 287) | interface SVGAnimationAttributes {
type SVGGradientAttributes (line 311) | interface SVGGradientAttributes extends SVGAttributes {
type SVGFilterAttributes (line 320) | interface SVGFilterAttributes {
type SVGTransferFunctionAttributes (line 330) | interface SVGTransferFunctionAttributes {
type SVGTextAttributes (line 341) | interface SVGTextAttributes {
type Element (line 355) | type Element = void;
type IntrinsicElements (line 357) | interface IntrinsicElements {
type ElementChildrenAttribute (line 1043) | interface ElementChildrenAttribute {
FILE: packages/ripple/src/jsx-runtime.js
function jsx (line 15) | function jsx(type, props, key) {
function jsxs (line 34) | function jsxs(type, props, key) {
function Fragment (line 43) | function Fragment(props) {
FILE: packages/ripple/src/runtime/array.js
function RippleArray (line 11) | function RippleArray(...elements) {
function ripple_array (line 57) | function ripple_array(block, ...elements) {
FILE: packages/ripple/src/runtime/create-subscriber.js
function createSubscriber (line 6) | function createSubscriber(start) {
FILE: packages/ripple/src/runtime/date.js
class RippleDate (line 6) | class RippleDate extends Date {
method constructor (line 14) | constructor(...params) {
method #init (line 23) | #init() {
function ripple_date (line 79) | function ripple_date(block, ...params) {
FILE: packages/ripple/src/runtime/index-client.js
function mount (line 30) | function mount(component, options) {
function hydrate (line 62) | function hydrate(component, options) {
FILE: packages/ripple/src/runtime/index-server.js
function noop (line 7) | function noop() {}
function MediaQuery (line 27) | function MediaQuery(query, matches = false) {
function createSubscriber (line 38) | function createSubscriber(_) {
function Portal (line 67) | function Portal(output, __) {
FILE: packages/ripple/src/runtime/internal/client/bindings.js
function not_tracked_type_error (line 19) | function not_tracked_type_error(name) {
function not_set_function_type_error (line 27) | function not_set_function_type_error(name) {
function get_bind_get_set (line 39) | function get_bind_get_set(name, maybe_tracked, set_func) {
class ResizeObserverSingleton (line 66) | class ResizeObserverSingleton {
method constructor (line 80) | constructor(options) {
method observe (line 88) | observe(element, listener) {
method #getObserver (line 106) | #getObserver() {
function to_number (line 138) | function to_number(value) {
function is_numberlike_input (line 145) | function is_numberlike_input(input) {
function get_option_value (line 151) | function get_option_value(option) {
function select_option (line 162) | function select_option(select, value, mounting = false) {
function bindValue (line 200) | function bindValue(maybe_tracked, set_func = undefined) {
function bindChecked (line 310) | function bindChecked(maybe_tracked, set_func = undefined) {
function bindIndeterminate (line 332) | function bindIndeterminate(maybe_tracked, set_func = undefined) {
function bindGroup (line 354) | function bindGroup(maybe_tracked, set_func = undefined) {
function bind_element_size (line 403) | function bind_element_size(maybe_tracked, type, set_func = undefined) {
function bindClientWidth (line 425) | function bindClientWidth(maybe_tracked, set_func = undefined) {
function bindClientHeight (line 434) | function bindClientHeight(maybe_tracked, set_func = undefined) {
function bindOffsetWidth (line 443) | function bindOffsetWidth(maybe_tracked, set_func = undefined) {
function bindOffsetHeight (line 452) | function bindOffsetHeight(maybe_tracked, set_func = undefined) {
function bind_element_rect (line 461) | function bind_element_rect(maybe_tracked, type, set_func = undefined) {
function bindContentRect (line 490) | function bindContentRect(maybe_tracked, set_func = undefined) {
function bindContentBoxSize (line 499) | function bindContentBoxSize(maybe_tracked, set_func = undefined) {
function bindBorderBoxSize (line 508) | function bindBorderBoxSize(maybe_tracked, set_func = undefined) {
function bindDevicePixelContentBoxSize (line 517) | function bindDevicePixelContentBoxSize(maybe_tracked, set_func = undefin...
function bind_content_editable (line 527) | function bind_content_editable(maybe_tracked, property, set_func = undef...
function bindInnerHTML (line 560) | function bindInnerHTML(maybe_tracked, set_func = undefined) {
function bindInnerText (line 569) | function bindInnerText(maybe_tracked, set_func = undefined) {
function bindTextContent (line 578) | function bindTextContent(maybe_tracked, set_func = undefined) {
function bindFiles (line 587) | function bindFiles(maybe_tracked, set_func = undefined) {
function bindNode (line 613) | function bindNode(maybe_tracked, set_func = undefined) {
FILE: packages/ripple/src/runtime/internal/client/blocks.js
function user_effect (line 34) | function user_effect(fn) {
function effect (line 59) | function effect(fn) {
function render (line 68) | function render(fn, state, flags = 0) {
function render_spread (line 77) | function render_spread(element, fn, flags = 0) {
function branch (line 86) | function branch(fn, flags = 0, state = null) {
function async (line 93) | function async(fn) {
function ref (line 116) | function ref(element, get_fn) {
function root (line 145) | function root(fn, compat) {
function create_try_block (line 175) | function create_try_block(fn, state) {
function push_block (line 183) | function push_block(block, parent_block) {
function block (line 201) | function block(flags, fn, state = null, co) {
function destroy_block_children (line 240) | function destroy_block_children(parent, remove_dom = false) {
function destroy_non_branch_children (line 257) | function destroy_non_branch_children(parent, remove_dom = false) {
function unlink_block (line 280) | function unlink_block(block) {
function pause_block (line 297) | function pause_block(block) {
function resume_block (line 317) | function resume_block(block) {
function is_destroyed (line 340) | function is_destroyed(target_block) {
function remove_block_dom (line 362) | function remove_block_dom(node, end) {
function move_block (line 380) | function move_block(block, target) {
function destroy_block (line 415) | function destroy_block(block, remove_dom = true) {
FILE: packages/ripple/src/runtime/internal/client/compat.js
function get_compat_from_root (line 10) | function get_compat_from_root(kind) {
function tsx_compat (line 32) | function tsx_compat(kind, node, children_fn) {
FILE: packages/ripple/src/runtime/internal/client/composite.js
function composite (line 16) | function composite(get_component, node, props) {
FILE: packages/ripple/src/runtime/internal/client/constants.js
constant TRACKED_ARRAY (line 25) | const TRACKED_ARRAY = Symbol();
constant TRACKED_OBJECT (line 27) | const TRACKED_OBJECT = Symbol();
constant HMR (line 30) | const HMR = Symbol();
constant ARRAY_SET_INDEX_AT (line 33) | const ARRAY_SET_INDEX_AT = Symbol();
constant MAX_ARRAY_LENGTH (line 34) | const MAX_ARRAY_LENGTH = 2 ** 32 - 1;
constant DEFAULT_NAMESPACE (line 35) | const DEFAULT_NAMESPACE = 'html';
constant NAMESPACE_URI (line 36) | const NAMESPACE_URI = {
FILE: packages/ripple/src/runtime/internal/client/context.js
class Context (line 8) | class Context {
method constructor (line 12) | constructor(initial_value) {
method get (line 17) | get() {
method set (line 44) | set(value) {
function context (line 66) | function context(initial_value) {
FILE: packages/ripple/src/runtime/internal/client/css.js
function remove_ssr_css (line 3) | function remove_ssr_css() {
function remove_styles (line 11) | function remove_styles() {
function remove (line 24) | function remove() {
function remove_when_css_loaded (line 32) | function remove_when_css_loaded(callback) {
FILE: packages/ripple/src/runtime/internal/client/events.js
function get_event_options (line 35) | function get_event_options(options) {
function on (line 60) | function on(element, type, handler, options = {}) {
function handle_event_propagation (line 87) | function handle_event_propagation(event) {
function create_event (line 222) | function create_event(event_name, dom, handler, options) {
function event (line 321) | function event(event_name, dom, handler) {
function render_event (line 343) | function render_event(event_name, dom, get_handler) {
function delegate (line 371) | function delegate(events) {
function handle_root_events (line 382) | function handle_root_events(target) {
FILE: packages/ripple/src/runtime/internal/client/for.js
function create_item (line 21) | function create_item(anchor, value, index, render_fn, is_indexed, is_key...
function move (line 65) | function move(block, anchor) {
function collection_to_array (line 89) | function collection_to_array(collection) {
function for_block (line 109) | function for_block(node, get_collection, render_fn, flags) {
function for_block_keyed (line 156) | function for_block_keyed(node, get_collection, render_fn, flags, get_key) {
function reconcile_fast_clear (line 206) | function reconcile_fast_clear(anchor, block, array) {
function update_index (line 221) | function update_index(block, index) {
function update_value (line 230) | function update_value(block, value) {
function reconcile_by_key (line 246) | function reconcile_by_key(anchor, block, b, render_fn, is_controlled, is...
function reconcile_by_ref (line 521) | function reconcile_by_ref(anchor, block, b, render_fn, is_controlled, is...
function lis_algorithm (line 776) | function lis_algorithm(arr) {
FILE: packages/ripple/src/runtime/internal/client/head.js
function head (line 13) | function head(hash, render_fn) {
FILE: packages/ripple/src/runtime/internal/client/hmr.js
function hmr (line 33) | function hmr(fn) {
FILE: packages/ripple/src/runtime/internal/client/html.js
function html (line 17) | function html(node, get_html, svg = false, mathml = false) {
FILE: packages/ripple/src/runtime/internal/client/hydration.js
function set_hydrating (line 17) | function set_hydrating(value) {
function set_hydrate_node (line 25) | function set_hydrate_node(node, mounting = false) {
function hydrate_next (line 32) | function hydrate_next() {
function hydrate_advance (line 36) | function hydrate_advance() {
function next (line 40) | function next(n = 1) {
function pop (line 53) | function pop(node) {
function skip_to_hydration_end (line 64) | function skip_to_hydration_end() {
FILE: packages/ripple/src/runtime/internal/client/if.js
function if_block (line 12) | function if_block(node, fn) {
FILE: packages/ripple/src/runtime/internal/client/operations.js
function init_operations (line 18) | function init_operations() {
function get_first_child (line 46) | function get_first_child(node) {
function get_last_child (line 55) | function get_last_child(node) {
function first_child (line 65) | function first_child(node, is_text) {
function first_child_frag (line 92) | function first_child_frag(node, is_text) {
function get_next_sibling (line 111) | function get_next_sibling(node) {
function next_sibling (line 121) | function next_sibling(node, is_text) {
function create_text (line 155) | function create_text(value = '') {
FILE: packages/ripple/src/runtime/internal/client/portal.js
function Portal (line 21) | function Portal(_, props) {
FILE: packages/ripple/src/runtime/internal/client/render.js
function set_text (line 22) | function set_text(text, value) {
function get_setters (line 38) | function get_setters(element) {
function set_style (line 70) | function set_style(element, value, prev = {}) {
function set_attribute (line 87) | function set_attribute(element, attribute, value) {
function apply_styles (line 102) | function apply_styles(element, new_styles, prev) {
function set_attribute_helper (line 132) | function set_attribute_helper(element, key, value, remove_listeners, pre...
function set_class (line 160) | function set_class(dom, value, hash, is_html = true) {
function set_value (line 188) | function set_value(element, value) {
function set_checked (line 210) | function set_checked(element, checked) {
function set_selected (line 230) | function set_selected(element, selected) {
function apply_element_spread (line 247) | function apply_element_spread(element, fn) {
FILE: packages/ripple/src/runtime/internal/client/rpc.js
function rpc (line 7) | async function rpc(hash, args) {
FILE: packages/ripple/src/runtime/internal/client/runtime.js
constant FLUSH_MICROTASK (line 42) | const FLUSH_MICROTASK = 0;
constant FLUSH_SYNC (line 43) | const FLUSH_SYNC = 1;
function increment_clock (line 84) | function increment_clock() {
function set_active_block (line 91) | function set_active_block(block) {
function set_active_reaction (line 98) | function set_active_reaction(reaction) {
function set_active_component (line 105) | function set_active_component(component) {
function set_tracking (line 112) | function set_tracking(value) {
function run_teardown (line 119) | function run_teardown(block) {
function with_block (line 146) | function with_block(block, fn) {
function update_derived (line 162) | function update_derived(computed) {
function destroy_computed_children (line 178) | function destroy_computed_children(computed) {
function run_derived (line 192) | function run_derived(computed) {
function handle_error (line 229) | function handle_error(error, block) {
function run_block (line 248) | function run_block(block) {
function tracked (line 300) | function tracked(v, block, get, set) {
function derived (line 329) | function derived(fn, block, get, set) {
function track (line 365) | function track(v, get, set, b) {
function track_split (line 385) | function track_split(v, l, b) {
function create_dependency (line 435) | function create_dependency(tracked) {
function is_tracking_dirty (line 458) | function is_tracking_dirty(tracking) {
function is_block_dirty (line 481) | function is_block_dirty(block) {
function async_computed (line 500) | function async_computed(fn, block) {
function trigger_track_get (line 571) | function trigger_track_get(fn, v) {
function capture_deferred (line 585) | function capture_deferred(fn) {
function flush_updates (line 607) | function flush_updates(root_block) {
function flush_queued_root_blocks (line 678) | function flush_queued_root_blocks(root_blocks) {
function tick (line 687) | async function tick() {
function flush_microtasks (line 694) | function flush_microtasks() {
function queue_microtask (line 723) | function queue_microtask(fn) {
function schedule_update (line 736) | function schedule_update(block) {
function register_dependency (line 758) | function register_dependency(tracked) {
function get_derived (line 787) | function get_derived(computed) {
function get (line 803) | function get(tracked) {
function get_tracked (line 817) | function get_tracked(tracked) {
function public_set (line 838) | function public_set(tracked, value) {
function set (line 846) | function set(tracked, value) {
function untrack (line 882) | function untrack(fn) {
function flush_sync (line 900) | function flush_sync(fn) {
function spread_props (line 933) | function spread_props(fn) {
function proxy_props (line 941) | function proxy_props(fn) {
function computed_property (line 1045) | function computed_property(fn) {
function call_property (line 1061) | function call_property(obj, property, chain_obj, chain_prop, ...args) {
function get_property (line 1081) | function get_property(obj, property, chain = false) {
function set_property (line 1098) | function set_property(obj, property, value) {
function update (line 1108) | function update(tracked, d = 1) {
function increment (line 1119) | function increment(tracked) {
function decrement (line 1127) | function decrement(tracked) {
function update_pre (line 1136) | function update_pre(tracked, d = 1) {
function update_property (line 1149) | function update_property(obj, property, d = 1) {
function update_pre_property (line 1163) | function update_pre_property(obj, property, d = 1) {
function with_scope (line 1177) | function with_scope(block, fn) {
function scope (line 1190) | function scope() {
function safe_scope (line 1198) | function safe_scope(err = 'Cannot access outside of a component context') {
function create_component_ctx (line 1206) | function create_component_ctx() {
function push_component (line 1218) | function push_component() {
function pop_component (line 1226) | function pop_component() {
function with_ns (line 1256) | function with_ns(namespace, fn) {
function ref_prop (line 1269) | function ref_prop() {
function fallback (line 1279) | function fallback(value, fallback) {
function exclude_from_object (line 1288) | function exclude_from_object(obj, exclude_keys) {
function maybe_tracked (line 1314) | async function maybe_tracked(v) {
FILE: packages/ripple/src/runtime/internal/client/script.js
function script (line 6) | function script(node, content) {
FILE: packages/ripple/src/runtime/internal/client/switch.js
function move (line 15) | function move(block, anchor) {
function switch_block (line 37) | function switch_block(anchor, fn) {
FILE: packages/ripple/src/runtime/internal/client/template.js
function assign_nodes (line 18) | function assign_nodes(start, end) {
function create_fragment_from_html (line 39) | function create_fragment_from_html(
function template (line 62) | function template(content, flags, count = 1) {
function append (line 141) | function append(anchor, dom, skip_advance) {
function text (line 190) | function text(data = '') {
function from_namespace (line 206) | function from_namespace(content, ns = 'svg') {
FILE: packages/ripple/src/runtime/internal/client/try.js
function try_block (line 40) | function try_block(node, fn, catch_fn, pending_fn = null) {
function suspend (line 178) | function suspend() {
function exit (line 195) | function exit() {
function capture (line 205) | function capture() {
function aborted (line 224) | function aborted() {
function resume_context (line 236) | async function resume_context(promise) {
FILE: packages/ripple/src/runtime/internal/client/types.d.ts
type Component (line 3) | type Component = {
type Dependency (line 14) | type Dependency = {
type Tracked (line 20) | type Tracked<V = any> = {
type Derived (line 29) | type Derived = {
type Block (line 42) | type Block = {
type CompatApi (line 57) | type CompatApi = {
type CompatOptions (line 63) | type CompatOptions = {
type Element (line 68) | interface Element {
type Event (line 76) | interface Event {
type Text (line 80) | interface Text {
FILE: packages/ripple/src/runtime/internal/client/utils.js
function create_anchor (line 34) | function create_anchor() {
function is_ripple_object (line 45) | function is_ripple_object(v) {
function top_element_to_ns (line 55) | function top_element_to_ns(element, current_namespace) {
FILE: packages/ripple/src/runtime/internal/server/context.js
class Context (line 8) | class Context {
method constructor (line 12) | constructor(initial_value) {
method get (line 17) | get() {
method set (line 44) | set(value) {
function context (line 66) | function context(initial_value) {
FILE: packages/ripple/src/runtime/internal/server/css-registry.js
function register_component_css (line 15) | function register_component_css(hash, content) {
function get_css_for_hashes (line 26) | function get_css_for_hashes(hashes) {
FILE: packages/ripple/src/runtime/internal/server/index.js
function increment_clock (line 38) | function increment_clock() {
function create_dependency (line 46) | function create_dependency(tracked) {
function register_dependency (line 57) | function register_dependency(tracked) {
function is_tracking_dirty (line 86) | function is_tracking_dirty(tracking) {
function untrack (line 111) | function untrack(fn) {
function update_derived (line 127) | function update_derived(computed) {
function run_derived (line 143) | function run_derived(computed) {
class Output (line 178) | class Output {
method constructor (line 196) | constructor(parent, stream = null) {
method push (line 205) | push(str) {
method register_css (line 222) | register_css(hash) {
function render (line 228) | async function render(component) {
function renderToStream (line 259) | function renderToStream(component) {
function render_in_chunks (line 273) | async function render_in_chunks(component, stream, output) {
function push_component (line 297) | function push_component() {
function pop_component (line 308) | function pop_component() {
function print_nesting_error (line 334) | function print_nesting_error(message) {
function push_element (line 356) | function push_element(tag, filename, line, column) {
function pop_element (line 392) | function pop_element() {
function reset_element_state (line 405) | function reset_element_state() {
function async (line 414) | async function async(fn) {
function aborted (line 421) | function aborted() {
function get (line 430) | function get(tracked) {
function set (line 452) | function set(tracked, value) {
function update (line 467) | function update(tracked, d = 1) {
function update_pre (line 479) | function update_pre(tracked, d = 1) {
function set_property (line 492) | function set_property(obj, property, value) {
function get_property (line 503) | function get_property(obj, property, chain = false) {
function update_property (line 520) | function update_property(obj, property, d = 1) {
function update_pre_property (line 534) | function update_pre_property(obj, property, d = 1) {
function attr (line 549) | function attr(name, value, is_boolean = false) {
function get_styles (line 570) | function get_styles(styles) {
function spread_attrs (line 585) | function spread_attrs(attrs, css_hash) {
function tracked (line 616) | function tracked(v, get, set) {
function track (line 631) | function track(v, get, set) {
function track_split (line 658) | function track_split(v, l) {
function ripple_url (line 709) | function ripple_url(_, ...params) {
function ripple_url_search_params (line 718) | function ripple_url_search_params(_, ...params) {
function ripple_date (line 726) | function ripple_date(...params) {
function media_query (line 735) | function media_query(query, matches = false) {
function effect (line 744) | function effect(_fn) {
function ripple_array (line 753) | function ripple_array(...elements) {
function ripple_object (line 792) | function ripple_object(obj) {
FILE: packages/ripple/src/runtime/internal/server/rpc.js
function executeServerFunction (line 9) | async function executeServerFunction(fn, rpc_arguments_string) {
FILE: packages/ripple/src/runtime/internal/server/types.d.ts
type Component (line 3) | type Component = {
type Dependency (line 8) | type Dependency = {
type Derived (line 14) | type Derived = {
type Tracked (line 24) | type Tracked = {
FILE: packages/ripple/src/runtime/map.js
class RippleMap (line 13) | class RippleMap extends Map {
method constructor (line 24) | constructor(iterable) {
method #init (line 47) | #init() {
method get (line 65) | get(key) {
method has (line 83) | has(key) {
method set (line 106) | set(key, value) {
method delete (line 128) | delete(key) {
method clear (line 146) | clear() {
method keys (line 165) | keys() {
method #read_all (line 173) | #read_all() {
method size (line 182) | get size() {
method toJSON (line 189) | toJSON() {
function ripple_map (line 203) | function ripple_map(block, iterable) {
FILE: packages/ripple/src/runtime/media-query.js
function MediaQuery (line 14) | function MediaQuery(query, fallback) {
function media_query (line 52) | function media_query(block, query, fallback) {
FILE: packages/ripple/src/runtime/object.js
function RippleObject (line 11) | function RippleObject(obj) {
function ripple_object (line 27) | function ripple_object(block, obj) {
FILE: packages/ripple/src/runtime/proxy.js
function proxy (line 26) | function proxy(value, block) {
function array_proxy (line 282) | function array_proxy({ elements, block, from_static = false, use_array =...
function object_proxy (line 307) | function object_proxy(obj, block) {
function get_first_if_length (line 331) | function get_first_if_length(array) {
FILE: packages/ripple/src/runtime/reactive-value.js
function ReactiveValue (line 12) | function ReactiveValue(fn, start) {
FILE: packages/ripple/src/runtime/set.js
class RippleSet (line 17) | class RippleSet extends Set {
method constructor (line 28) | constructor(iterable) {
method #init (line 51) | #init() {
method add (line 110) | add(value) {
method delete (line 126) | delete(value) {
method has (line 148) | has(value) {
method clear (line 169) | clear() {
method size (line 188) | get size() {
method toJSON (line 195) | toJSON() {
function ripple_set (line 208) | function ripple_set(block, iterable) {
FILE: packages/ripple/src/runtime/url-search-params.js
constant REPLACE (line 4) | const REPLACE = Symbol();
class RippleURLSearchParams (line 6) | class RippleURLSearchParams extends URLSearchParams {
method #update_url (line 13) | #update_url() {
method [REPLACE] (line 27) | [REPLACE](params) {
method append (line 48) | append(name, value) {
method delete (line 59) | delete(name, value) {
method get (line 72) | get(name) {
method getAll (line 81) | getAll(name) {
method has (line 91) | has(name, value) {
method keys (line 96) | keys() {
method set (line 106) | set(name, value) {
method sort (line 117) | sort() {
method toString (line 123) | toString() {
method values (line 128) | values() {
method entries (line 133) | entries() {
method size (line 142) | get size() {
method [Symbol.iterator] (line 138) | [Symbol.iterator]() {
function ripple_url_search_params (line 153) | function ripple_url_search_params(block, ...params) {
FILE: packages/ripple/src/runtime/url.js
function get_current_url (line 7) | function get_current_url() {
class RippleURL (line 11) | class RippleURL extends URL {
method constructor (line 27) | constructor(url, base) {
method hash (line 36) | get hash() {
method hash (line 40) | set hash(value) {
method host (line 45) | get host() {
method host (line 51) | set host(value) {
method hostname (line 57) | get hostname() {
method hostname (line 61) | set hostname(value) {
method href (line 66) | get href() {
method href (line 78) | set href(value) {
method password (line 91) | get password() {
method password (line 95) | set password(value) {
method pathname (line 100) | get pathname() {
method pathname (line 104) | set pathname(value) {
method port (line 109) | get port() {
method port (line 113) | set port(value) {
method protocol (line 118) | get protocol() {
method protocol (line 122) | set protocol(value) {
method search (line 127) | get search() {
method search (line 131) | set search(value) {
method username (line 137) | get username() {
method username (line 141) | set username(value) {
method origin (line 146) | get origin() {
method searchParams (line 153) | get searchParams() {
method toString (line 157) | toString() {
method toJSON (line 161) | toJSON() {
function ripple_url (line 172) | function ripple_url(block, url, base) {
FILE: packages/ripple/src/utils/ast.js
function object (line 28) | function object(expression) {
function unwrap_pattern (line 46) | function unwrap_pattern(pattern, nodes = []) {
function extract_identifiers (line 93) | function extract_identifiers(pattern) {
function extract_paths (line 102) | function extract_paths(param) {
function _extract_paths (line 122) | function _extract_paths(assignments = [], param, expression, update_expr...
function build_fallback (line 259) | function build_fallback(expression, fallback) {
function build_assignment_value (line 268) | function build_assignment_value(operator, left, right) {
FILE: packages/ripple/src/utils/builders.js
function set_location (line 14) | function set_location(node, loc_info, is_deep_copy = false) {
function array (line 36) | function array(elements = []) {
function array_pattern (line 44) | function array_pattern(elements) {
function assignment_pattern (line 53) | function assignment_pattern(left, right) {
function arrow (line 62) | function arrow(params, body, async = false) {
function component (line 80) | function component(id, params, body) {
function assignment (line 98) | function assignment(operator, left, right) {
function async (line 107) | function async(func) {
function await_builder (line 115) | function await_builder(argument) {
function binary (line 125) | function binary(operator, left, right) {
function block (line 134) | function block(body, loc_info) {
function labeled (line 146) | function labeled(name, body) {
function call (line 155) | function call(callee, ...args) {
function maybe_call (line 188) | function maybe_call(callee, ...args) {
function unary (line 204) | function unary(operator, argument) {
function conditional (line 214) | function conditional(test, consequent, alternate) {
function logical (line 224) | function logical(operator, left, right) {
function declaration (line 233) | function declaration(kind, declarations) {
function declarator (line 247) | function declarator(pattern, init) {
function export_default (line 262) | function export_default(declaration) {
function export_builder (line 274) | function export_builder(
function function_declaration (line 298) | function function_declaration(id, params, body, async = false) {
function get (line 315) | function get(name, body) {
function id (line 326) | function id(name, loc_info) {
function private_id (line 343) | function private_id(name) {
function import_namespace (line 351) | function import_namespace(local) {
function init (line 364) | function init(name, value) {
function literal (line 373) | function literal(value, loc_info) {
function member (line 387) | function member(object, property, computed = false, optional = false, lo...
function ts_as (line 411) | function ts_as(expression, type_annotation, loc_info) {
function parenthesized (line 427) | function parenthesized(expression, loc_info) {
function ts_type_query (line 443) | function ts_type_query(expr_name, type_arguments = null, loc_info) {
function ts_type_parameter_instantiation (line 459) | function ts_type_parameter_instantiation(params, loc_info) {
function ts_type_reference (line 475) | function ts_type_reference(type_name, type_arguments = null, loc_info) {
function ts_literal_type (line 491) | function ts_literal_type(literal_node, loc_info) {
function ts_intersection_type (line 506) | function ts_intersection_type(types, loc_info) {
function ts_type_annotation (line 521) | function ts_type_annotation(type_annotation, loc_info) {
function ts_property_signature (line 537) | function ts_property_signature(key, type_annotation = null, loc_info) {
function ts_type_literal (line 559) | function ts_type_literal(members, loc_info) {
function ts_type_alias (line 575) | function ts_type_alias(id, type_annotation, loc_info) {
function member_id (line 592) | function member_id(path) {
function object (line 609) | function object(properties, loc_info) {
function object_pattern (line 620) | function object_pattern(properties) {
function prop (line 633) | function prop(kind, key, value, computed = false, shorthand = false) {
function prop_def (line 653) | function prop_def(key, value, computed = false, is_static = false) {
function quasi (line 669) | function quasi(cooked, tail = false) {
function rest (line 678) | function rest(argument) {
function sequence (line 686) | function sequence(expressions) {
function set (line 695) | function set(name, body) {
function spread (line 705) | function spread(argument) {
function stmt (line 713) | function stmt(expression) {
function template (line 723) | function template(elements, expressions, loc_info) {
function thunk (line 735) | function thunk(expression, async = false) {
function unthunk (line 746) | function unthunk(expression) {
function new_builder (line 770) | function new_builder(expression, loc_info, ...args) {
function update (line 790) | function update(operator, argument, prefix = false) {
function do_while (line 799) | function do_while(test, body) {
function let_builder (line 824) | function let_builder(pattern, init) {
function const_builder (line 833) | function const_builder(pattern, init) {
function var_builder (line 842) | function var_builder(pattern, init) {
function for_builder (line 854) | function for_builder(init, test, update, body) {
function for_of (line 866) | function for_of(left, right, body, await_flag = false, loc_info) {
function method (line 890) | function method(kind, key, params, body, computed = false, is_static = f...
function function_builder (line 911) | function function_builder(id, params, body, async = false, loc_info) {
function if_builder (line 933) | function if_builder(test, consequent, alternate, loc_info) {
function import_all (line 946) | function import_all(as, source, attributes = [], importKind = 'value') {
function imports (line 964) | function imports(parts, source, attributes = [], importKind = 'value') {
function return_builder (line 986) | function return_builder(argument = null, loc_info) {
function throw_error (line 996) | function throw_error(str) {
function try_builder (line 1011) | function try_builder(block, handler = null, finalizer = null, pending = ...
function catch_clause_builder (line 1028) | function catch_clause_builder(param, body, loc_info) {
function key (line 1046) | function key(name) {
function jsx_attribute (line 1057) | function jsx_attribute(name, value = null, shorthand = false, loc_info) {
function jsx_element (line 1075) | function jsx_element(node, attributes = [], children = []) {
function jsx_fragment (line 1103) | function jsx_fragment(children = [], attributes = []) {
function jsx_expression_container (line 1125) | function jsx_expression_container(expression, loc_info) {
function jsx_id (line 1140) | function jsx_id(name, loc_info) {
function jsx_member (line 1155) | function jsx_member(object, property) {
function jsx_spread_attribute (line 1169) | function jsx_spread_attribute(argument, loc_info) {
function jsx_text (line 1184) | function jsx_text(value, raw) {
function switch_builder (line 1199) | function switch_builder(discriminant, cases, loc_info) {
function switch_case (line 1216) | function switch_case(test = null, consequent = []) {
FILE: packages/ripple/src/utils/escaping.js
constant ATTR_REGEX (line 1) | const ATTR_REGEX = /[&"<]/g;
constant CONTENT_REGEX (line 2) | const CONTENT_REGEX = /[&<]/g;
function escape (line 9) | function escape(value, is_attr) {
FILE: packages/ripple/src/utils/events.js
constant NON_DELEGATED_EVENTS (line 3) | const NON_DELEGATED_EVENTS = new Set([
function is_non_delegated (line 63) | function is_non_delegated(event_name) {
function is_event_attribute (line 72) | function is_event_attribute(attr) {
function is_capture_event (line 81) | function is_capture_event(event_name) {
function get_original_event_name (line 95) | function get_original_event_name(name) {
function normalize_event_name (line 104) | function normalize_event_name(name) {
function extract_event_name (line 113) | function extract_event_name(name) {
function event_name_from_capture (line 127) | function event_name_from_capture(event_name) {
function get_attribute_event_name (line 137) | function get_attribute_event_name(name, handler) {
constant PASSIVE_EVENTS (line 145) | const PASSIVE_EVENTS = ['touchstart', 'touchmove', 'wheel', 'mousewheel'];
function is_passive_event (line 152) | function is_passive_event(name) {
FILE: packages/ripple/src/utils/hashing.js
function hash (line 8) | function hash(str) {
FILE: packages/ripple/src/utils/normalize_css_property_name.js
function normalize_css_property_name (line 11) | function normalize_css_property_name(str) {
FILE: packages/ripple/src/utils/sanitize_template_string.js
function sanitize_template_string (line 5) | function sanitize_template_string(str) {
FILE: packages/ripple/tests/common.d.ts
type TestAttributes (line 6) | type TestAttributes = Record<string, any>;
type TagNameMap (line 8) | type TagNameMap = HTMLElementTagNameMap & SVGElementTagNameMap;
type ParentNode (line 10) | interface ParentNode {
FILE: packages/ripple/tests/hydration.d.ts
type CustomMatchers (line 3) | interface CustomMatchers<R = unknown> {
type Assertion (line 12) | interface Assertion<T = any> extends CustomMatchers<T> {}
type AsymmetricMatchersContaining (line 13) | interface AsymmetricMatchersContaining extends CustomMatchers {}
FILE: packages/ripple/tests/hydration/build-components.js
function transformServerImports (line 27) | function transformServerImports(code) {
function buildComponents (line 43) | function buildComponents() {
function setup (line 77) | function setup() {
FILE: packages/ripple/tests/hydration/compiled/client/basic.js
function StaticText (line 30) | function StaticText(__anchor, _, __block) {
function MultipleElements (line 39) | function MultipleElements(__anchor, _, __block) {
function NestedElements (line 49) | function NestedElements(__anchor, _, __block) {
function WithAttributes (line 58) | function WithAttributes(__anchor, _, __block) {
function ChildComponent (line 68) | function ChildComponent(__anchor, _, __block) {
function ParentWithChild (line 77) | function ParentWithChild(__anchor, _, __block) {
function FirstSibling (line 93) | function FirstSibling(__anchor, _, __block) {
function SecondSibling (line 102) | function SecondSibling(__anchor, _, __block) {
function SiblingComponents (line 111) | function SiblingComponents(__anchor, _, __block) {
function Greeting (line 126) | function Greeting(__anchor, props, __block) {
function WithGreeting (line 145) | function WithGreeting(__anchor, _, __block) {
function ExpressionContent (line 156) | function ExpressionContent(__anchor, _, __block) {
function StaticHeader (line 189) | function StaticHeader(__anchor, _, __block) {
function StaticChildWithSiblings (line 199) | function StaticChildWithSiblings(__anchor, _, __block) {
function Header (line 231) | function Header(__anchor, _, __block) {
function Actions (line 241) | function Actions(__anchor, __props, __block) {
function Layout (line 270) | function Layout(__anchor, __props, __block) {
function Content (line 290) | function Content(__anchor, _, __block) {
function WebsiteIndex (line 299) | function WebsiteIndex(__anchor, _, __block) {
function LastChild (line 338) | function LastChild(__anchor, _, __block) {
function ComponentAsLastSibling (line 347) | function ComponentAsLastSibling(__anchor, _, __block) {
function InnerContent (line 365) | function InnerContent(__anchor, _, __block) {
function NestedComponentAsLastSibling (line 382) | function NestedComponentAsLastSibling(__anchor, _, __block) {
FILE: packages/ripple/tests/hydration/compiled/client/composite.js
function Layout (line 15) | function Layout(__anchor, __props, __block) {
function SingleChild (line 31) | function SingleChild(__anchor, _, __block) {
function MultiRootChild (line 40) | function MultiRootChild(__anchor, _, __block) {
function EmptyLayout (line 50) | function EmptyLayout(__anchor, _, __block) {
function LayoutWithSingleChild (line 61) | function LayoutWithSingleChild(__anchor, _, __block) {
function LayoutWithMultipleChildren (line 88) | function LayoutWithMultipleChildren(__anchor, _, __block) {
function LayoutWithMultiRootChild (line 115) | function LayoutWithMultiRootChild(__anchor, _, __block) {
FILE: packages/ripple/tests/hydration/compiled/client/events.js
function ClickCounter (line 12) | function ClickCounter(__anchor, _, __block) {
function IncrementDecrement (line 42) | function IncrementDecrement(__anchor, _, __block) {
function MultipleEvents (line 78) | function MultipleEvents(__anchor, _, __block) {
function MultiStateUpdate (line 134) | function MultiStateUpdate(__anchor, _, __block) {
function ToggleButton (line 190) | function ToggleButton(__anchor, _, __block) {
function ChildButton (line 218) | function ChildButton(__anchor, props, __block) {
function ParentWithChildButton (line 239) | function ParentWithChildButton(__anchor, _, __block) {
FILE: packages/ripple/tests/hydration/compiled/client/for.js
function StaticForLoop (line 67) | function StaticForLoop(__anchor, _, __block) {
function ForLoopWithIndex (line 99) | function ForLoopWithIndex(__anchor, _, __block) {
function KeyedForLoop (line 134) | function KeyedForLoop(__anchor, _, __block) {
function ReactiveForLoopAdd (line 175) | function ReactiveForLoopAdd(__anchor, _, __block) {
function ReactiveForLoopRemove (line 215) | function ReactiveForLoopRemove(__anchor, _, __block) {
function ForLoopInteractive (line 255) | function ForLoopInteractive(__anchor, _, __block) {
function NestedForLoop (line 304) | function NestedForLoop(__anchor, _, __block) {
function EmptyForLoop (line 359) | function EmptyForLoop(__anchor, _, __block) {
function ForLoopComplexObjects (line 391) | function ForLoopComplexObjects(__anchor, _, __block) {
function KeyedForLoopReorder (line 462) | function KeyedForLoopReorder(__anchor, _, __block) {
function KeyedForLoopUpdate (line 529) | function KeyedForLoopUpdate(__anchor, _, __block) {
function ForLoopMixedOperations (line 586) | function ForLoopMixedOperations(__anchor, _, __block) {
function ForLoopInsideIf (line 628) | function ForLoopInsideIf(__anchor, _, __block) {
function ForLoopEmptyToPopulated (line 686) | function ForLoopEmptyToPopulated(__anchor, _, __block) {
function ForLoopPopulatedToEmpty (line 726) | function ForLoopPopulatedToEmpty(__anchor, _, __block) {
function NestedForLoopReactive (line 766) | function NestedForLoopReactive(__anchor, _, __block) {
function ForLoopDeeplyNested (line 838) | function ForLoopDeeplyNested(__anchor, _, __block) {
function ForLoopIndexUpdate (line 974) | function ForLoopIndexUpdate(__anchor, _, __block) {
function KeyedForLoopWithIndex (line 1030) | function KeyedForLoopWithIndex(__anchor, _, __block) {
function ForLoopWithSiblings (line 1103) | function ForLoopWithSiblings(__anchor, _, __block) {
function ForLoopItemState (line 1148) | function ForLoopItemState(__anchor, _, __block) {
function TodoItem (line 1194) | function TodoItem(__anchor, props, __block) {
function ForLoopSingleItem (line 1249) | function ForLoopSingleItem(__anchor, _, __block) {
function ForLoopAddAtBeginning (line 1281) | function ForLoopAddAtBeginning(__anchor, _, __block) {
function ForLoopAddInMiddle (line 1323) | function ForLoopAddInMiddle(__anchor, _, __block) {
function ForLoopRemoveFromMiddle (line 1368) | function ForLoopRemoveFromMiddle(__anchor, _, __block) {
function ForLoopLargeList (line 1410) | function ForLoopLargeList(__anchor, _, __block) {
function ForLoopSwap (line 1446) | function ForLoopSwap(__anchor, _, __block) {
function ForLoopReverse (line 1491) | function ForLoopReverse(__anchor, _, __block) {
FILE: packages/ripple/tests/hydration/compiled/client/head.js
function StaticTitle (line 18) | function StaticTitle(__anchor, _, __block) {
function ReactiveTitle (line 31) | function ReactiveTitle(__anchor, _, __block) {
function MultipleHeadElements (line 61) | function MultipleHeadElements(__anchor, _, __block) {
function ReactiveMetaTags (line 78) | function ReactiveMetaTags(__anchor, _, __block) {
function TitleWithTemplate (line 106) | function TitleWithTemplate(__anchor, _, __block) {
function EmptyTitle (line 132) | function EmptyTitle(__anchor, _, __block) {
function ConditionalTitle (line 145) | function ConditionalTitle(__anchor, _, __block) {
function ComputedTitle (line 172) | function ComputedTitle(__anchor, _, __block) {
function MultipleHeadBlocks (line 203) | function MultipleHeadBlocks(__anchor, _, __block) {
function HeadWithStyle (line 222) | function HeadWithStyle(__anchor, _, __block) {
FILE: packages/ripple/tests/hydration/compiled/client/hmr.js
function Layout (line 10) | function Layout(__anchor, __props, __block) {
function Content (line 31) | function Content(__anchor, _, __block) {
function LayoutWithContent (line 59) | function LayoutWithContent(__anchor, _, __block) {
FILE: packages/ripple/tests/hydration/compiled/client/html-in-template.js
function SimpleTemplateHtml (line 9) | function SimpleTemplateHtml(__anchor, _, __block) {
function TemplateWithJSON (line 20) | function TemplateWithJSON(__anchor, _, __block) {
function TemplateAroundIfBlock (line 31) | function TemplateAroundIfBlock(__anchor, _, __block) {
FILE: packages/ripple/tests/hydration/compiled/client/html.js
function StaticHtml (line 91) | function StaticHtml(__anchor, _, __block) {
function DynamicHtml (line 111) | function DynamicHtml(__anchor, _, __block) {
function EmptyHtml (line 131) | function EmptyHtml(__anchor, _, __block) {
function ComplexHtml (line 151) | function ComplexHtml(__anchor, _, __block) {
function MultipleHtml (line 171) | function MultipleHtml(__anchor, _, __block) {
function HtmlWithReactivity (line 197) | function HtmlWithReactivity(__anchor, _, __block) {
function HtmlWrapper (line 216) | function HtmlWrapper(__anchor, __props, __block) {
function HtmlInChildren (line 236) | function HtmlInChildren(__anchor, _, __block) {
function HtmlInChildrenWithSiblings (line 272) | function HtmlInChildrenWithSiblings(__anchor, _, __block) {
function MultipleHtmlInChildren (line 312) | function MultipleHtmlInChildren(__anchor, _, __block) {
function HtmlWithComments (line 354) | function HtmlWithComments(__anchor, _, __block) {
function HtmlWithEmptyComment (line 374) | function HtmlWithEmptyComment(__anchor, _, __block) {
function HtmlWithCommentsInChildren (line 394) | function HtmlWithCommentsInChildren(__anchor, _, __block) {
function DocFooter (line 430) | function DocFooter(__anchor, _, __block) {
function DocLayout (line 439) | function DocLayout(__anchor, __props, __block) {
function HtmlWithServerData (line 603) | function HtmlWithServerData(__anchor, _, __block) {
function HtmlWithClientDefaults (line 646) | function HtmlWithClientDefaults(__anchor, _, __block) {
function HtmlWithUndefinedContent (line 682) | function HtmlWithUndefinedContent(__anchor, _, __block) {
function DynamicHeading (line 718) | function DynamicHeading(__anchor, __props, __block) {
function CodeBlock (line 769) | function CodeBlock(__anchor, __props, __block) {
function ContentWrapper (line 797) | function ContentWrapper(__anchor, __props, __block) {
function HtmlAfterSwitchInChildren (line 817) | function HtmlAfterSwitchInChildren(__anchor, _, __block) {
function NavItem (line 864) | function NavItem(__anchor, __props, __block) {
function SidebarSection (line 926) | function SidebarSection(__anchor, __props, __block) {
function SideNav (line 983) | function SideNav(__anchor, __props, __block) {
function PageHeader (line 1100) | function PageHeader(__anchor, _, __block) {
function LayoutWithSidebarAndMain (line 1109) | function LayoutWithSidebarAndMain(__anchor, _, __block) {
function ArticleWrapper (line 1163) | function ArticleWrapper(__anchor, __props, __block) {
function SimpleFooter (line 1183) | function SimpleFooter(__anchor, _, __block) {
function ArticleWithChildrenThenSibling (line 1192) | function ArticleWithChildrenThenSibling(__anchor, _, __block) {
function ArticleWithHtmlChildThenSibling (line 1253) | function ArticleWithHtmlChildThenSibling(__anchor, _, __block) {
function InlineArticleLayout (line 1311) | function InlineArticleLayout(__anchor, __props, __block) {
function InlineArticleWithHtmlChild (line 1356) | function InlineArticleWithHtmlChild(__anchor, _, __block) {
function HeaderStub (line 1392) | function HeaderStub(__anchor, _, __block) {
function SidebarStub (line 1401) | function SidebarStub(__anchor, _, __block) {
function FooterStub (line 1410) | function FooterStub(__anchor, _, __block) {
function DocsLayoutInner (line 1419) | function DocsLayoutInner(__anchor, __props, __block) {
function DocsLayoutWithData (line 1537) | function DocsLayoutWithData(__anchor, _, __block) {
function DocsLayoutWithoutData (line 1575) | function DocsLayoutWithoutData(__anchor, _, __block) {
function DocsLayoutExact (line 1611) | function DocsLayoutExact(__anchor, __props, __block) {
function DocsLayoutExactWithData (line 1866) | function DocsLayoutExactWithData(__anchor, _, __block) {
function DocsLayoutExactWithoutData (line 1910) | function DocsLayoutExactWithoutData(__anchor, _, __block) {
function TemplateWithHtmlContent (line 1954) | function TemplateWithHtmlContent(__anchor, _, __block) {
function TemplateWithHtmlAndSiblings (line 1972) | function TemplateWithHtmlAndSiblings(__anchor, _, __block) {
function LayoutWithTemplate (line 1991) | function LayoutWithTemplate(__anchor, __props, __block) {
function NestedTemplateInLayout (line 2016) | function NestedTemplateInLayout(__anchor, _, __block) {
FILE: packages/ripple/tests/hydration/compiled/client/if-children.js
function IfWithChildren (line 25) | function IfWithChildren(__anchor, __props, __block) {
function ChildItem (line 64) | function ChildItem(__anchor, __props, __block) {
function TestIfWithChildren (line 83) | function TestIfWithChildren(__anchor, _, __block) {
function IfWithStaticChildren (line 114) | function IfWithStaticChildren(__anchor, _, __block) {
function IfWithSiblingsAndChildren (line 146) | function IfWithSiblingsAndChildren(__anchor, __props, __block) {
function TestIfWithSiblingsAndChildren (line 186) | function TestIfWithSiblingsAndChildren(__anchor, _, __block) {
function ElementWithChildrenThenIf (line 217) | function ElementWithChildrenThenIf(__anchor, _, __block) {
function DeepNestingThenIf (line 254) | function DeepNestingThenIf(__anchor, _, __block) {
function DomElementChildrenThenSibling (line 291) | function DomElementChildrenThenSibling(__anchor, _, __block) {
function DomChildrenThenStaticSiblings (line 360) | function DomChildrenThenStaticSiblings(__anchor, _, __block) {
function StaticListThenStaticSiblings (line 396) | function StaticListThenStaticSiblings(__anchor, _, __block) {
FILE: packages/ripple/tests/hydration/compiled/client/if.js
function IfTruthy (line 25) | function IfTruthy(__anchor, _, __block) {
function IfFalsy (line 48) | function IfFalsy(__anchor, _, __block) {
function IfElse (line 71) | function IfElse(__anchor, _, __block) {
function ReactiveIf (line 100) | function ReactiveIf(__anchor, _, __block) {
function ReactiveIfElse (line 129) | function ReactiveIfElse(__anchor, _, __block) {
function NestedIf (line 164) | function NestedIf(__anchor, _, __block) {
function IfElseIfChain (line 219) | function IfElseIfChain(__anchor, _, __block) {
FILE: packages/ripple/tests/hydration/compiled/client/mixed-control-flow.js
function MixedControlFlowStatic (line 31) | function MixedControlFlowStatic(__anchor, _, __block) {
function MixedControlFlowReactive (line 194) | function MixedControlFlowReactive(__anchor, _, __block) {
function MixedControlFlowAsyncPending (line 364) | function MixedControlFlowAsyncPending(__anchor, _, __block) {
function AsyncRow (line 459) | function AsyncRow(__anchor, __props, __block) {
FILE: packages/ripple/tests/hydration/compiled/client/nested-control-flow.js
function ForIf (line 71) | function ForIf(__anchor, _, __block) {
function ForSwitch (line 138) | function ForSwitch(__anchor, _, __block) {
function IfSwitch (line 245) | function IfSwitch(__anchor, _, __block) {
function IfSwitchHidden (line 303) | function IfSwitchHidden(__anchor, _, __block) {
function ForIfSwitchSingle (line 361) | function ForIfSwitchSingle(__anchor, _, __block) {
function ForIfSwitchMulti (line 476) | function ForIfSwitchMulti(__anchor, _, __block) {
function ForIfSwitchWithDisabled (line 595) | function ForIfSwitchWithDisabled(__anchor, _, __block) {
function SwitchTry (line 715) | function SwitchTry(__anchor, _, __block) {
function ForSwitchTry (line 777) | function ForSwitchTry(__anchor, _, __block) {
function ForIfTry (line 960) | function ForIfTry(__anchor, _, __block) {
function ForIfSwitchTrySingle (line 1063) | function ForIfSwitchTrySingle(__anchor, _, __block) {
function ForIfSwitchTryMulti (line 1259) | function ForIfSwitchTryMulti(__anchor, _, __block) {
FILE: packages/ripple/tests/hydration/compiled/client/portal.js
function SimplePortal (line 16) | function SimplePortal(__anchor, _, __block) {
function ConditionalPortal (line 51) | function ConditionalPortal(__anchor, _, __block) {
function PortalWithMainContent (line 103) | function PortalWithMainContent(__anchor, _, __block) {
function NestedContentWithPortal (line 138) | function NestedContentWithPortal(__anchor, _, __block) {
FILE: packages/ripple/tests/hydration/compiled/client/reactivity.js
function TrackedState (line 11) | function TrackedState(__anchor, _, __block) {
function CounterWithInitial (line 31) | function CounterWithInitial(__anchor, props, __block) {
function CounterWrapper (line 55) | function CounterWrapper(__anchor, _, __block) {
function ComputedValues (line 66) | function ComputedValues(__anchor, _, __block) {
function MultipleTracked (line 88) | function MultipleTracked(__anchor, _, __block) {
function DerivedState (line 148) | function DerivedState(__anchor, _, __block) {
FILE: packages/ripple/tests/hydration/compiled/client/return.js
function DirectReturn (line 133) | function DirectReturn(__anchor, _, __block) {
function ConditionalReturnTrue (line 158) | function ConditionalReturnTrue(__anchor, _, __block) {
function ConditionalReturnFalse (line 197) | function ConditionalReturnFalse(__anchor, _, __block) {
function ContentBeforeAfterReturn (line 236) | function ContentBeforeAfterReturn(__anchor, _, __block) {
function MultipleElementsAfterGuard (line 276) | function MultipleElementsAfterGuard(__anchor, _, __block) {
function MultipleReturnsFirstHits (line 316) | function MultipleReturnsFirstHits(__anchor, _, __block) {
function MultipleReturnsSecondHits (line 385) | function MultipleReturnsSecondHits(__anchor, _, __block) {
function MultipleReturnsNoneHit (line 454) | function MultipleReturnsNoneHit(__anchor, _, __block) {
function NestedReturnsAllTrue (line 523) | function NestedReturnsAllTrue(__anchor, _, __block) {
function NestedReturnsInnerFalse (line 579) | function NestedReturnsInnerFalse(__anchor, _, __block) {
function NestedReturnsOuterFalse (line 635) | function NestedReturnsOuterFalse(__anchor, _, __block) {
function DeeplyNestedReturnsAllTrue (line 691) | function DeeplyNestedReturnsAllTrue(__anchor, _, __block) {
function DeeplyNestedReturnsInnermostFalse (line 764) | function DeeplyNestedReturnsInnermostFalse(__anchor, _, __block) {
function ElseIfChainFirst (line 837) | function ElseIfChainFirst(__anchor, _, __block) {
function ElseIfChainSecond (line 915) | function ElseIfChainSecond(__anchor, _, __block) {
function ElseIfChainElse (line 993) | function ElseIfChainElse(__anchor, _, __block) {
function ReturnWithElseNoReturn (line 1071) | function ReturnWithElseNoReturn(__anchor, _, __block) {
function ReturnWithElseBothReturn (line 1117) | function ReturnWithElseBothReturn(__anchor, _, __block) {
function ReactiveReturnTrueToFalse (line 1167) | function ReactiveReturnTrueToFalse(__anchor, _, __block) {
function ReactiveReturnFalseToTrue (line 1212) | function ReactiveReturnFalseToTrue(__anchor, _, __block) {
function ReactiveNestedReturn (line 1257) | function ReactiveNestedReturn(__anchor, _, __block) {
function ReturnInNestedElement (line 1319) | function ReturnInNestedElement(__anchor, _, __block) {
function ReturnWithMultipleElements (line 1365) | function ReturnWithMultipleElements(__anchor, _, __block) {
function ReturnAtBeginning (line 1408) | function ReturnAtBeginning(__anchor, _, __block) {
function ReturnAtEnd (line 1447) | function ReturnAtEnd(__anchor, _, __block) {
function MultipleSiblingReturns (line 1475) | function MultipleSiblingReturns(__anchor, _, __block) {
function ReactiveSiblingReturns (line 1572) | function ReactiveSiblingReturns(__anchor, _, __block) {
function ReactiveOuterInnerReturns (line 1652) | function ReactiveOuterInnerReturns(__anchor, _, __block) {
function ReactiveElseIfReturns (line 1730) | function ReactiveElseIfReturns(__anchor, _, __block) {
function ReactiveDeepNestedIndependentReturns (line 1802) | function ReactiveDeepNestedIndependentReturns(__anchor, _, __block) {
FILE: packages/ripple/tests/hydration/compiled/client/switch.js
function SwitchStatic (line 28) | function SwitchStatic(__anchor, _, __block) {
function SwitchReactive (line 77) | function SwitchReactive(__anchor, _, __block) {
function SwitchFallthrough (line 132) | function SwitchFallthrough(__anchor, _, __block) {
function SwitchNumericLevels (line 173) | function SwitchNumericLevels(__anchor, _, __block) {
function SwitchBlockScoped (line 228) | function SwitchBlockScoped(__anchor, _, __block) {
function SwitchNoBreak (line 283) | function SwitchNoBreak(__anchor, _, __block) {
FILE: packages/ripple/tests/hydration/compiled/client/try.js
function AsyncListInTryPending (line 14) | function AsyncListInTryPending(__anchor, _, __block) {
function AsyncList (line 43) | function AsyncList(__anchor, _, __block) {
function AsyncTryWithLeadingSibling (line 80) | function AsyncTryWithLeadingSibling(__anchor, _, __block) {
function AsyncContent (line 110) | function AsyncContent(__anchor, _, __block) {
FILE: packages/ripple/tests/hydration/compiled/server/basic.js
function StaticText (line 4) | function StaticText(__output) {
function MultipleElements (line 17) | function MultipleElements(__output) {
function NestedElements (line 46) | function NestedElements(__output) {
function WithAttributes (line 75) | function WithAttributes(__output) {
function ChildComponent (line 95) | function ChildComponent(__output) {
function ParentWithChild (line 109) | function ParentWithChild(__output) {
function FirstSibling (line 128) | function FirstSibling(__output) {
function SecondSibling (line 142) | function SecondSibling(__output) {
function SiblingComponents (line 156) | function SiblingComponents(__output) {
function Greeting (line 176) | function Greeting(__output, props) {
function WithGreeting (line 189) | function WithGreeting(__output) {
function ExpressionContent (line 202) | function ExpressionContent(__output) {
function StaticHeader (line 227) | function StaticHeader(__output) {
function StaticChildWithSiblings (line 259) | function StaticChildWithSiblings(__output) {
function Header (line 292) | function Header(__output) {
function Actions (line 320) | function Actions(__output, { playgroundVisible = false }) {
function Layout (line 369) | async function Layout(__output, { children }) {
function Content (line 403) | function Content(__output) {
function WebsiteIndex (line 424) | function WebsiteIndex(__output) {
function LastChild (line 475) | function LastChild(__output) {
function ComponentAsLastSibling (line 489) | function ComponentAsLastSibling(__output) {
function InnerContent (line 525) | function InnerContent(__output) {
function NestedComponentAsLastSibling (line 553) | function NestedComponentAsLastSibling(__output) {
FILE: packages/ripple/tests/hydration/compiled/server/composite.js
function Layout (line 4) | async function Layout(__output, { children }) {
function SingleChild (line 31) | function SingleChild(__output) {
function MultiRootChild (line 45) | function MultiRootChild(__output) {
function EmptyLayout (line 66) | function EmptyLayout(__output) {
function LayoutWithSingleChild (line 79) | function LayoutWithSingleChild(__output) {
function LayoutWithMultipleChildren (line 109) | function LayoutWithMultipleChildren(__output) {
function LayoutWithMultiRootChild (line 148) | function LayoutWithMultiRootChild(__output) {
FILE: packages/ripple/tests/hydration/compiled/server/events.js
function ClickCounter (line 4) | function ClickCounter(__output) {
function IncrementDecrement (line 37) | function IncrementDecrement(__output) {
function MultipleEvents (line 79) | function MultipleEvents(__output) {
function MultiStateUpdate (line 122) | function MultiStateUpdate(__output) {
function ToggleButton (line 170) | function ToggleButton(__output) {
function ChildButton (line 194) | function ChildButton(__output, props) {
function ParentWithChildButton (line 208) | function ParentWithChildButton(__output) {
FILE: packages/ripple/tests/hydration/compiled/server/for.js
function StaticForLoop (line 4) | function StaticForLoop(__output) {
function ForLoopWithIndex (line 33) | function ForLoopWithIndex(__output) {
function KeyedForLoop (line 65) | function KeyedForLoop(__output) {
function ReactiveForLoopAdd (line 98) | function ReactiveForLoopAdd(__output) {
function ReactiveForLoopRemove (line 136) | function ReactiveForLoopRemove(__output) {
function ForLoopInteractive (line 174) | function ForLoopInteractive(__output) {
function NestedForLoop (line 224) | function NestedForLoop(__output) {
function EmptyForLoop (line 275) | function EmptyForLoop(__output) {
function ForLoopComplexObjects (line 305) | function ForLoopComplexObjects(__output) {
function KeyedForLoopReorder (line 355) | function KeyedForLoopReorder(__output) {
function KeyedForLoopUpdate (line 398) | function KeyedForLoopUpdate(__output) {
function ForLoopMixedOperations (line 437) | function ForLoopMixedOperations(__output) {
function ForLoopInsideIf (line 476) | function ForLoopInsideIf(__output) {
function ForLoopEmptyToPopulated (line 531) | function ForLoopEmptyToPopulated(__output) {
function ForLoopPopulatedToEmpty (line 570) | function ForLoopPopulatedToEmpty(__output) {
function NestedForLoopReactive (line 609) | function NestedForLoopReactive(__output) {
function ForLoopDeeplyNested (line 678) | function ForLoopDeeplyNested(__output) {
function ForLoopIndexUpdate (line 777) | function ForLoopIndexUpdate(__output) {
function KeyedForLoopWithIndex (line 819) | function KeyedForLoopWithIndex(__output) {
function ForLoopWithSiblings (line 866) | function ForLoopWithSiblings(__output) {
function ForLoopItemState (line 924) | function ForLoopItemState(__output) {
function TodoItem (line 955) | function TodoItem(__output, props) {
function ForLoopSingleItem (line 985) | function ForLoopSingleItem(__output) {
function ForLoopAddAtBeginning (line 1015) | function ForLoopAddAtBeginning(__output) {
function ForLoopAddInMiddle (line 1054) | function ForLoopAddInMiddle(__output) {
function ForLoopRemoveFromMiddle (line 1093) | function ForLoopRemoveFromMiddle(__output) {
function ForLoopLargeList (line 1132) | function ForLoopLargeList(__output) {
function ForLoopSwap (line 1166) | function ForLoopSwap(__output) {
function ForLoopReverse (line 1205) | function ForLoopReverse(__output) {
FILE: packages/ripple/tests/hydration/compiled/server/head.js
function StaticTitle (line 4) | function StaticTitle(__output) {
function ReactiveTitle (line 28) | function ReactiveTitle(__output) {
function MultipleHeadElements (line 62) | function MultipleHeadElements(__output) {
function ReactiveMetaTags (line 94) | function ReactiveMetaTags(__output) {
function TitleWithTemplate (line 125) | function TitleWithTemplate(__output) {
function EmptyTitle (line 152) | function EmptyTitle(__output) {
function ConditionalTitle (line 176) | function ConditionalTitle(__output) {
function ComputedTitle (line 204) | function ComputedTitle(__output) {
function MultipleHeadBlocks (line 239) | function MultipleHeadBlocks(__output) {
function HeadWithStyle (line 268) | function HeadWithStyle(__output) {
FILE: packages/ripple/tests/hydration/compiled/server/hmr.js
function Layout (line 4) | async function Layout(__output, { children }) {
function Content (line 48) | function Content(__output) {
function LayoutWithContent (line 79) | function LayoutWithContent(__output) {
FILE: packages/ripple/tests/hydration/compiled/server/html-in-template.js
function SimpleTemplateHtml (line 4) | function SimpleTemplateHtml(__output) {
function TemplateWithJSON (line 25) | function TemplateWithJSON(__output) {
function TemplateAroundIfBlock (line 46) | function TemplateAroundIfBlock(__output) {
FILE: packages/ripple/tests/hydration/compiled/server/html.js
function StaticHtml (line 4) | function StaticHtml(__output) {
function DynamicHtml (line 24) | function DynamicHtml(__output) {
function EmptyHtml (line 44) | function EmptyHtml(__output) {
function ComplexHtml (line 64) | function ComplexHtml(__output) {
function MultipleHtml (line 84) | function MultipleHtml(__output) {
function HtmlWithReactivity (line 111) | function HtmlWithReactivity(__output) {
function HtmlWrapper (line 134) | async function HtmlWrapper(__output, { children }) {
function HtmlInChildren (line 169) | function HtmlInChildren(__output) {
function HtmlInChildrenWithSiblings (line 206) | function HtmlInChildrenWithSiblings(__output) {
function MultipleHtmlInChildren (line 251) | function MultipleHtmlInChildren(__output) {
function HtmlWithComments (line 295) | function HtmlWithComments(__output) {
function HtmlWithEmptyComment (line 315) | function HtmlWithEmptyComment(__output) {
function HtmlWithCommentsInChildren (line 335) | function HtmlWithCommentsInChildren(__output) {
function DocFooter (line 372) | function DocFooter(__output) {
function DocLayout (line 386) | async function DocLayout(
function HtmlWithServerData (line 541) | function HtmlWithServerData(__output) {
function HtmlWithClientDefaults (line 585) | function HtmlWithClientDefaults(__output) {
function HtmlWithUndefinedContent (line 622) | function HtmlWithUndefinedContent(__output) {
function DynamicHeading (line 659) | async function DynamicHeading(__output, { level, children }) {
function CodeBlock (line 709) | function CodeBlock(__output, { code }) {
function ContentWrapper (line 763) | async function ContentWrapper(__output, { children }) {
function HtmlAfterSwitchInChildren (line 798) | function HtmlAfterSwitchInChildren(__output) {
function NavItem (line 871) | function NavItem(__output, { href, text, active = false }) {
function SidebarSection (line 910) | async function SidebarSection(__output, { title, children }) {
function SideNav (line 978) | function SideNav(__output, { currentPath }) {
function PageHeader (line 1108) | function PageHeader(__output) {
function LayoutWithSidebarAndMain (line 1130) | function LayoutWithSidebarAndMain(__output) {
function ArticleWrapper (line 1234) | async function ArticleWrapper(__output, { children }) {
function SimpleFooter (line 1268) | function SimpleFooter(__output) {
function ArticleWithChildrenThenSibling (line 1282) | function ArticleWithChildrenThenSibling(__output) {
function ArticleWithHtmlChildThenSibling (line 1380) | function ArticleWithHtmlChildThenSibling(__output) {
function InlineArticleLayout (line 1455) | async function InlineArticleLayout(__output, { children }) {
function InlineArticleWithHtmlChild (line 1527) | function InlineArticleWithHtmlChild(__output) {
function HeaderStub (line 1564) | function HeaderStub(__output) {
function SidebarStub (line 1578) | function SidebarStub(__output) {
function FooterStub (line 1592) | function FooterStub(__output) {
function DocsLayoutInner (line 1606) | async function DocsLayoutInner(__output, { children, editPath = '', next...
function DocsLayoutWithData (line 1755) | function DocsLayoutWithData(__output) {
function DocsLayoutWithoutData (line 1794) | function DocsLayoutWithoutData(__output) {
function DocsLayoutExact (line 1831) | async function DocsLayoutExact(
function DocsLayoutExactWithData (line 2077) | function DocsLayoutExactWithData(__output) {
function DocsLayoutExactWithoutData (line 2122) | function DocsLayoutExactWithoutData(__output) {
function TemplateWithHtmlContent (line 2167) | function TemplateWithHtmlContent(__output) {
function TemplateWithHtmlAndSiblings (line 2204) | function TemplateWithHtmlAndSiblings(__output) {
function LayoutWithTemplate (line 2250) | async function LayoutWithTemplate(__output, { children, data }) {
function NestedTemplateInLayout (line 2297) | function NestedTemplateInLayout(__output) {
FILE: packages/ripple/tests/hydration/compiled/server/if-children.js
function IfWithChildren (line 4) | async function IfWithChildren(__output, { children }) {
function ChildItem (line 58) | function ChildItem(__output, { text }) {
function TestIfWithChildren (line 72) | function TestIfWithChildren(__output) {
function IfWithStaticChildren (line 109) | function IfWithStaticChildren(__output) {
function IfWithSiblingsAndChildren (line 165) | async function IfWithSiblingsAndChildren(__output, { children }) {
function TestIfWithSiblingsAndChildren (line 254) | function TestIfWithSiblingsAndChildren(__output) {
function ElementWithChildrenThenIf (line 291) | function ElementWithChildrenThenIf(__output) {
function DeepNestingThenIf (line 356) | function DeepNestingThenIf(__output) {
function DomElementChildrenThenSibling (line 436) | function DomElementChildrenThenSibling(__output) {
function DomChildrenThenStaticSiblings (line 513) | function DomChildrenThenStaticSiblings(__output) {
function StaticListThenStaticSiblings (line 582) | function StaticListThenStaticSiblings(__output) {
FILE: packages/ripple/tests/hydration/compiled/server/if.js
function IfTruthy (line 4) | function IfTruthy(__output) {
function IfFalsy (line 27) | function IfFalsy(__output) {
function IfElse (line 50) | function IfElse(__output) {
function ReactiveIf (line 83) | function ReactiveIf(__output) {
function ReactiveIfElse (line 115) | function ReactiveIfElse(__output) {
function NestedIf (line 157) | function NestedIf(__output) {
function IfElseIfChain (line 214) | function IfElseIfChain(__output) {
FILE: packages/ripple/tests/hydration/compiled/server/mixed-control-flow.js
function MixedControlFlowStatic (line 4) | async function MixedControlFlowStatic(__output) {
function MixedControlFlowReactive (line 94) | async function MixedControlFlowReactive(__output) {
function MixedControlFlowAsyncPending (line 209) | async function MixedControlFlowAsyncPending(__output) {
function AsyncRow (line 280) | async function AsyncRow(__output, { label }) {
FILE: packages/ripple/tests/hydration/compiled/server/nested-control-flow.js
function ForIf (line 4) | function ForIf(__output) {
function ForSwitch (line 45) | function ForSwitch(__output) {
function IfSwitch (line 95) | function IfSwitch(__output) {
function IfSwitchHidden (line 142) | function IfSwitchHidden(__output) {
function ForIfSwitchSingle (line 198) | function ForIfSwitchSingle(__output) {
function ForIfSwitchMulti (line 250) | function ForIfSwitchMulti(__output) {
function ForIfSwitchWithDisabled (line 305) | function ForIfSwitchWithDisabled(__output) {
function SwitchTry (line 361) | async function SwitchTry(__output) {
function ForSwitchTry (line 420) | async function ForSwitchTry(__output) {
function ForIfTry (line 500) | async function ForIfTry(__output) {
function ForIfSwitchTrySingle (line 560) | async function ForIfSwitchTrySingle(__output) {
function ForIfSwitchTryMulti (line 646) | async function ForIfSwitchTryMulti(__output) {
FILE: packages/ripple/tests/hydration/compiled/server/portal.js
function SimplePortal (line 6) | async function SimplePortal(__output) {
function ConditionalPortal (line 61) | async function ConditionalPortal(__output) {
function PortalWithMainContent (line 125) | async function PortalWithMainContent(__output) {
function NestedContentWithPortal (line 190) | async function NestedContentWithPortal(__output) {
FILE: packages/ripple/tests/hydration/compiled/server/reactivity.js
function TrackedState (line 4) | function TrackedState(__output) {
function CounterWithInitial (line 21) | function CounterWithInitial(__output, props) {
function CounterWrapper (line 45) | function CounterWrapper(__output) {
function ComputedValues (line 58) | function ComputedValues(__output) {
function MultipleTracked (line 77) | function MultipleTracked(__output) {
function DerivedState (line 114) | function DerivedState(__output) {
FILE: packages/ripple/tests/hydration/compiled/server/return.js
function DirectReturn (line 4) | function DirectReturn(__output) {
function ConditionalReturnTrue (line 37) | function ConditionalReturnTrue(__output) {
function ConditionalReturnFalse (line 77) | function ConditionalReturnFalse(__output) {
function ContentBeforeAfterReturn (line 117) | function ContentBeforeAfterReturn(__output) {
function MultipleElementsAfterGuard (line 166) | function MultipleElementsAfterGuard(__output) {
function MultipleReturnsFirstHits (line 215) | function MultipleReturnsFirstHits(__output) {
function MultipleReturnsSecondHits (line 279) | function MultipleReturnsSecondHits(__output) {
function MultipleReturnsNoneHit (line 343) | function MultipleReturnsNoneHit(__output) {
function NestedReturnsAllTrue (line 407) | function NestedReturnsAllTrue(__output) {
function NestedReturnsInnerFalse (line 463) | function NestedReturnsInnerFalse(__output) {
function NestedReturnsOuterFalse (line 519) | function NestedReturnsOuterFalse(__output) {
function DeeplyNestedReturnsAllTrue (line 575) | function DeeplyNestedReturnsAllTrue(__output) {
function DeeplyNestedReturnsInnermostFalse (line 647) | function DeeplyNestedReturnsInnermostFalse(__output) {
function ElseIfChainFirst (line 719) | function ElseIfChainFirst(__output) {
function ElseIfChainSecond (line 789) | function ElseIfChainSecond(__output) {
function ElseIfChainElse (line 859) | function ElseIfChainElse(__output) {
function ReturnWithElseNoReturn (line 929) | function ReturnWithElseNoReturn(__output) {
function ReturnWithElseBothReturn (line 979) | function ReturnWithElseBothReturn(__output) {
function ReactiveReturnTrueToFalse (line 1031) | function ReactiveReturnTrueToFalse(__output) {
function ReactiveReturnFalseToTrue (line 1080) | function ReactiveReturnFalseToTrue(__output) {
function ReactiveNestedReturn (line 1129) | function ReactiveNestedReturn(__output) {
function ReturnInNestedElement (line 1194) | function ReturnInNestedElement(__output) {
function ReturnWithMultipleElements (line 1251) | function ReturnWithMultipleElements(__output) {
function ReturnAtBeginning (line 1327) | function ReturnAtBeginning(__output) {
function ReturnAtEnd (line 1375) | function ReturnAtEnd(__output) {
function MultipleSiblingReturns (line 1417) | function MultipleSiblingReturns(__output) {
function ReactiveSiblingReturns (line 1503) | function ReactiveSiblingReturns(__output) {
function ReactiveOuterInnerReturns (line 1575) | function ReactiveOuterInnerReturns(__output) {
function ReactiveElseIfReturns (line 1649) | function ReactiveElseIfReturns(__output) {
function ReactiveDeepNestedIndependentReturns (line 1725) | function ReactiveDeepNestedIndependentReturns(__output) {
FILE: packages/ripple/tests/hydration/compiled/server/switch.js
function SwitchStatic (line 4) | function SwitchStatic(__output) {
function SwitchReactive (line 46) | function SwitchReactive(__output) {
function SwitchFallthrough (line 97) | function SwitchFallthrough(__output) {
function SwitchNumericLevels (line 131) | function SwitchNumericLevels(__output) {
function SwitchBlockScoped (line 183) | function SwitchBlockScoped(__output) {
function SwitchNoBreak (line 235) | function SwitchNoBreak(__output) {
FILE: packages/ripple/tests/hydration/compiled/server/try.js
function AsyncListInTryPending (line 4) | async function AsyncListInTryPending(__output) {
function AsyncList (line 39) | async function AsyncList(__output) {
function AsyncTryWithLeadingSibling (line 75) | async function AsyncTryWithLeadingSibling(__output) {
function AsyncContent (line 119) | async function AsyncContent(__output) {
FILE: packages/ripple/tests/hydration/hmr.test.js
function UpdatedLayout (line 28) | function UpdatedLayout(anchor, props, block) {
FILE: packages/ripple/tests/server.d.ts
type CustomMatchers (line 10) | interface CustomMatchers<R = unknown> {
type Assertion (line 19) | interface Assertion<T = any> extends CustomMatchers<T> {}
type AsymmetricMatchersContaining (line 20) | interface AsymmetricMatchersContaining extends CustomMatchers {}
FILE: packages/ripple/tests/setup-hydration.js
function hydrateComponent (line 15) | async function hydrateComponent(serverComponent, clientComponent) {
function stripHydrationMarkers (line 36) | function stripHydrationMarkers(html) {
method toBeHtml (line 46) | toBeHtml(received, expected) {
FILE: packages/ripple/tests/setup-server.js
function stripHydrationMarkers (line 17) | function stripHydrationMarkers(html) {
function parseAsFullHtml (line 27) | function parseAsFullHtml(head, body) {
method toBeHtml (line 33) | toBeHtml(received, expected) {
FILE: packages/ripple/types/index.d.ts
type Component (line 1) | type Component<T = Record<string, any>> = (props: T) => void;
type CompatApi (line 3) | type CompatApi = {
type CompatOptions (line 9) | type CompatOptions = {
type RippleArrayStatics (line 31) | interface RippleArrayStatics {
type RippleArrayCallable (line 62) | interface RippleArrayCallable extends RippleArrayStatics {
type RippleArrayConstructor (line 65) | interface RippleArrayConstructor extends RippleArrayStatics {
type RippleArray (line 68) | interface RippleArray<T> extends Array<T> {}
type ContextCallable (line 71) | interface ContextCallable {
type ContextConstructor (line 74) | interface ContextConstructor {
type Context (line 78) | interface Context<T = undefined> {
type RippleSetCallable (line 85) | interface RippleSetCallable {
type RippleSetConstructor (line 88) | interface RippleSetConstructor {
type RippleSet (line 92) | interface RippleSet<T> extends Set<T> {
type RippleMapCallable (line 105) | interface RippleMapCallable {
type RippleMapConstructor (line 108) | interface RippleMapConstructor {
type RippleMap (line 112) | interface RippleMap<K, V> extends Map<K, V> {
type Tracked (line 145) | interface Tracked<V> {
type Tracked (line 151) | interface Tracked<V> {
type InferComponent (line 157) | type InferComponent<T> = T extends () => infer R ? (R extends Component<...
type Props (line 159) | type Props<K extends PropertyKey = any, V = unknown> = Record<K, V>;
type PropsWithExtras (line 160) | type PropsWithExtras<T extends object> = Props & T & Record<string, unkn...
type PropsWithChildren (line 161) | type PropsWithChildren<T extends object = {}> = Expand<
type PropsWithChildrenOptional (line 164) | type PropsWithChildrenOptional<T extends object = {}> = Expand<
type PropsNoChildren (line 167) | type PropsNoChildren<T extends object = {}> = Expand<T>;
type Expand (line 169) | type Expand<T> = T extends infer O ? { [K in keyof O]: O[K] } : never;
type WrapTracked (line 171) | type WrapTracked<V> = V extends Tracked<any> ? V : Tracked<V>;
type PickKeys (line 173) | type PickKeys<T, K extends readonly (keyof T)[]> = {
type RestKeys (line 177) | type RestKeys<T, K extends readonly (keyof T)[]> = Expand<Omit<T, K[numb...
type SplitResult (line 179) | type SplitResult<T extends Props, K extends readonly (keyof T)[]> = [
type AddEventOptions (line 204) | interface AddEventOptions extends ExtendedEventOptions {
type AddEventObject (line 208) | interface AddEventObject extends AddEventOptions, EventListenerObject {}
type ExtendedEventOptions (line 210) | interface ExtendedEventOptions extends AddEventListenerOptions, EventLis...
type OnEventListenerRemover (line 214) | type OnEventListenerRemover = () => void;
type RippleObjectShallow (line 251) | type RippleObjectShallow<T> = {
type RippleObjectDeep (line 255) | type RippleObjectDeep<T> = T extends
type RippleObjectCallable (line 282) | interface RippleObjectCallable {
type RippleObjectConstructor (line 285) | interface RippleObjectConstructor {
type RippleObject (line 288) | interface RippleObject<T> extends Object {}
type RippleDateCallable (line 291) | interface RippleDateCallable {
type RippleDateConstructor (line 304) | interface RippleDateConstructor {
type RippleDate (line 318) | interface RippleDate extends Date {
type RippleURLSearchParamsCallable (line 323) | interface RippleURLSearchParamsCallable {
type RippleURLSearchParamsConstructor (line 333) | interface RippleURLSearchParamsConstructor {
type RippleURLSearchParams (line 345) | interface RippleURLSearchParams extends URLSearchParams {
type RippleURLCallable (line 351) | interface RippleURLCallable {
type RippleURLConstructor (line 354) | interface RippleURLConstructor {
type RippleURL (line 358) | interface RippleURL extends URL {
type ReactiveValue (line 367) | interface ReactiveValue<V> extends Tracked<V> {
type MediaQueryCallable (line 372) | interface MediaQueryCallable {
type MediaQueryConstructor (line 375) | interface MediaQueryConstructor {
type MediaQuery (line 379) | interface MediaQuery extends Tracked<boolean> {
type GetFunction (line 392) | type GetFunction<V> = () => V;
type SetFunction (line 393) | type SetFunction<V> = (v: V) => void;
type ServerBlock (line 548) | type ServerBlock = {};
type RippleNamespace (line 550) | interface RippleNamespace {
FILE: packages/ripple/types/server.d.ts
type SSRRenderOutput (line 20) | interface SSRRenderOutput {
type SSRComponent (line 28) | interface SSRComponent {
type SSRRenderResult (line 33) | interface SSRRenderResult {
type SSRRender (line 39) | type SSRRender = (component: SSRComponent) => Promise<SSRRenderResult>;
type render (line 40) | type render = (component: SSRComponent) => Promise<SSRRenderResult>;
type renderToStream (line 41) | type renderToStream = (component: SSRComponent) => Readable;
FILE: packages/rollup-plugin/index.js
constant PREFIX (line 5) | const PREFIX = '[@ripple-ts/rollup-plugin]';
method load (line 40) | load(id) {
method transform (line 48) | async transform(code, id) {
FILE: packages/sublime-text-plugin/src/plugin.py
function plugin_loaded (line 11) | def plugin_loaded() -> None:
function plugin_unloaded (line 15) | def plugin_unloaded() -> None:
class LspRipplePlugin (line 18) | class LspRipplePlugin(NpmClientHandler):
method required_node_version (line 31) | def required_node_version(cls) -> str:
method on_start (line 35) | def on_start(
method _determine_external_binary (line 48) | def _determine_external_binary(
method _find_local_binary (line 64) | def _find_local_binary(
method _node_modules_dirs_from_path (line 98) | def _node_modules_dirs_from_path(cls, path: str) -> Iterable[str]:
method _find_global_binary (line 118) | def _find_global_binary(cls) -> Optional[str]:
method _workspace_folder_path (line 128) | def _workspace_folder_path(folder: object) -> Optional[str]:
method _binary_name (line 140) | def _binary_name(cls) -> str:
method _maybe_windows_script (line 144) | def _maybe_windows_script(cls, script_path: str) -> Optional[str]:
FILE: packages/typescript-plugin/src/language.js
function getRippleLanguagePlugin (line 24) | function getRippleLanguagePlugin() {
class RippleVirtualCode (line 89) | class RippleVirtualCode {
method constructor (line 126) | constructor(file_name, snapshot, ripple) {
method update (line 148) | update(snapshot) {
method #buildMappingCache (line 328) | #buildMappingCache() {
method findMappingByGeneratedRange (line 361) | findMappingByGeneratedRange(start, end) {
method findMappingBySourceRange (line 372) | findMappingBySourceRange(start, end) {
function extractCssFromSource (line 383) | function extractCssFromSource(code) {
function restore_typed_dot_in_transpiled_code (line 449) | function restore_typed_dot_in_transpiled_code(transpiled, dotPosition) {
function normalizeFileNameOrUri (line 580) | function normalizeFileNameOrUri(fileNameOrUri) {
function getRippleCompiler (line 590) | function getRippleCompiler(normalized_file_name) {
function getRippleDirForFile (line 602) | function getRippleDirForFile(normalized_file_name) {
function getCachedTypeDefinitionFile (line 664) | function getCachedTypeDefinitionFile(typesFilePath) {
function getCachedTypeMatches (line 694) | function getCachedTypeMatches(typeName, text) {
FILE: packages/typescript-plugin/src/utils.js
constant DEBUG (line 1) | const DEBUG = process.env.RIPPLE_DEBUG === 'true';
function createLogging (line 14) | function createLogging(label) {
function getWordFromPosition (line 40) | function getWordFromPosition(text, start) {
FILE: packages/vite-plugin/src/constants.js
constant DEFAULT_OUTDIR (line 1) | const DEFAULT_OUTDIR = 'dist';
constant ENTRY_FILENAME (line 2) | const ENTRY_FILENAME = 'entry.js';
FILE: packages/vite-plugin/src/index.js
constant VITE_FS_PREFIX (line 31) | const VITE_FS_PREFIX = '/@fs/';
constant IS_WINDOWS (line 32) | const IS_WINDOWS = process.platform === 'win32';
function getDevAsyncContext (line 49) | function getDevAsyncContext(config) {
function existsInRoot (line 75) | function existsInRoot(filename, root) {
function createVirtualImportId (line 88) | function createVirtualImportId(filename, root, type) {
function hasRippleSource (line 110) | function hasRippleSource(packageJsonPath, subpath = '.') {
function hasRippleFilesInDirectory (line 185) | function hasRippleFilesInDirectory(dir, maxDepth = 3) {
function resolvePackageJson (line 221) | function resolvePackageJson(packageName, fromDir) {
function scanForRipplePackages (line 236) | function scanForRipplePackages(rootDir) {
function ripple (line 303) | function ripple(inlineOptions = {}) {
function defineConfig (line 1055) | function defineConfig(/** @type {RippleConfigOptions} */ options) {
function nodeRequestToWebRequest (line 1068) | function nodeRequestToWebRequest(nodeRequest) {
function sendWebResponse (line 1101) | async function sendWebResponse(nodeResponse, webResponse) {
function handleRpcRequest (line 1142) | async function handleRpcRequest(req, res, vite, trustProxy, config) {
function escapeHtml (line 1187) | function escapeHtml(str) {
FILE: packages/vite-plugin/src/load-config.js
function resolveRippleConfig (line 37) | function resolveRippleConfig(raw, options = {}) {
function getRippleConfigPath (line 100) | function getRippleConfigPath(projectRoot) {
function rippleConfigExists (line 113) | function rippleConfigExists(projectRoot) {
function loadRippleConfig (line 133) | async function loadRippleConfig(projectRoot, options = {}) {
FILE: packages/vite-plugin/src/routes.js
class RenderRoute (line 11) | class RenderRoute {
method constructor (line 30) | constructor(options) {
class ServerRoute (line 41) | class ServerRoute {
method constructor (line 63) | constructor(options) {
FILE: packages/vite-plugin/src/server/middleware.js
function compose (line 14) | function compose(middlewares) {
function createContext (line 63) | function createContext(request, params) {
function runMiddlewareChain (line 83) | async function runMiddlewareChain(
function runAfterMiddlewares (line 118) | async function runAfterMiddlewares(context, middlewares, response) {
FILE: packages/vite-plugin/src/server/production.js
function createHandler (line 49) | function createHandler(manifest, options) {
function handleRenderRoute (line 143) | async function handleRenderRoute(
function handleServerRoute (line 245) | async function handleServerRoute(route, context, globalMiddlewares) {
function createPropsWrapper (line 266) | function createPropsWrapper(Component, props) {
function createLayoutWrapper (line 279) | function createLayoutWrapper(Layout, Page, pageProps) {
function escapeScript (line 297) | function escapeScript(str) {
FILE: packages/vite-plugin/src/server/render-route.js
function handleRenderRoute (line 26) | async function handleRenderRoute(route, context, vite) {
function getDefaultExport (line 132) | function getDefaultExport(module) {
function createPropsWrapper (line 152) | function createPropsWrapper(Component, props) {
function createLayoutWrapper (line 171) | function createLayoutWrapper(Layout, Page, pageProps) {
function escapeScript (line 191) | function escapeScript(str) {
function generateErrorHtml (line 202) | function generateErrorHtml(error, route) {
function escapeHtml (line 233) | function escapeHtml(str) {
FILE: packages/vite-plugin/src/server/router.js
function compilePath (line 31) | function compilePath(path) {
function escapeRegex (line 73) | function escapeRegex(str) {
function createRouter (line 82) | function createRouter(routes) {
FILE: packages/vite-plugin/src/server/server-route.js
function handleServerRoute (line 17) | async function handleServerRoute(route, context, globalMiddlewares) {
FILE: packages/vite-plugin/src/server/virtual-entry.js
function generateServerEntry (line 43) | function generateServerEntry(options) {
FILE: packages/vite-plugin/types/index.d.ts
class RenderRoute (line 26) | class RenderRoute {
class ServerRoute (line 35) | class ServerRoute {
type Route (line 45) | type Route = RenderRoute | ServerRoute;
type RenderRouteOptions (line 51) | interface RenderRouteOptions {
type ServerRouteOptions (line 62) | interface ServerRouteOptions {
type Context (line 79) | interface Context {
type NextFunction (line 90) | type NextFunction = () => Promise<Response>;
type Middleware (line 91) | type Middleware = (context: Context, next: NextFunction) => Response | P...
type RouteHandler (line 92) | type RouteHandler = (context: Context) => Response | Promise<Response>;
type RipplePluginOptions (line 98) | interface RipplePluginOptions {
type RippleConfigOptions (line 102) | interface RippleConfigOptions {
type ResolvedRippleConfig (line 150) | interface ResolvedRippleConfig {
type AdapterServeFunction (line 176) | type AdapterServeFunction = (
FILE: packages/vite-plugin/types/production.d.ts
type ClientAssetEntry (line 14) | interface ClientAssetEntry {
type ServerManifest (line 21) | interface ServerManifest {
type RenderResult (line 42) | interface RenderResult {
type HandlerOptions (line 48) | interface HandlerOptions {
FILE: packages/vscode-plugin/scripts/repack-vsix.js
function fail (line 10) | function fail(message) {
function emptyDirSafe (line 18) | function emptyDirSafe(dir) {
constant DIR_NAME (line 35) | const DIR_NAME = 'vscode-plugin';
function addDirectory (line 82) | function addDirectory(dir, prefix = '') {
FILE: packages/vscode-plugin/src/extension.js
function activate (line 64) | async function activate(context) {
function setupDynamicContexts (line 264) | function setupDynamicContexts(context) {
function addCustomCommands (line 326) | function addCustomCommands(context) {
function configurePrettier (line 396) | async function configurePrettier() {
function registerFormatter (line 422) | function registerFormatter() {
function deactivate (line 447) | async function deactivate() {
function patchTypeScriptExtension (line 496) | async function patchTypeScriptExtension() {
FILE: packages/vscode-plugin/tsdown.config.js
constant ROOT_EXTERNAL_PACKAGES (line 10) | const ROOT_EXTERNAL_PACKAGES = [
constant ALWAYS_EXTERNAL (line 18) | const ALWAYS_EXTERNAL = ['vscode', '@ripple-ts/typescript-plugin'];
constant OUT_DIR (line 19) | const OUT_DIR = 'dist';
FILE: packages/zed-plugin/src/lib.rs
type RippleExtension (line 7) | struct RippleExtension {
method language_server_binary_path (line 15) | fn language_server_binary_path(
method system_binary_path (line 35) | fn system_binary_path(worktree: &zed::Worktree) -> Option<PathBuf> {
method install_language_server (line 62) | fn install_language_server(
method should_install_or_update (line 98) | fn should_install_or_update(&self, required_version: &str) -> bool {
method get_installed_version (line 109) | fn get_installed_version(&self) -> Option<String> {
method binary_exists (line 116) | fn binary_exists() -> bool {
method installed_binary_path (line 120) | fn installed_binary_path() -> Result<PathBuf, String> {
method extension_dir (line 155) | fn extension_dir() -> Result<PathBuf, String> {
method required_version (line 159) | fn required_version(&mut self) -> Result<String, String> {
method read_required_version (line 169) | fn read_required_version() -> Result<String, String> {
method is_exact_semver (line 195) | fn is_exact_semver(spec: &str) -> bool {
method new (line 208) | fn new() -> Self {
method language_server_command (line 215) | fn language_server_command(
constant PACKAGE_NAME (line 12) | const PACKAGE_NAME: &str = "@ripple-ts/language-server";
FILE: playground/ssr-dev.js
constant PORT (line 8) | const PORT = process.env.PORT || '5173';
constant DEBUG (line 9) | const DEBUG = process.env.DEBUG_APP === 'true';
constant APP_PATH (line 10) | const APP_PATH = path.resolve(DEBUG ? './debug/server/App.js' : './src/A...
function get_request_body (line 25) | function get_request_body(req) {
FILE: scripts/collect-external-deps.js
function findWorkspaceRoot (line 12) | function findWorkspaceRoot() {
function resolvePackagePath (line 29) | function resolvePackagePath(packageName, workspaceRoot) {
function collectDependencies (line 78) | function collectDependencies(packageName, workspaceRoot, collected = new...
function getAllExternalPackages (line 126) | function getAllExternalPackages(rootPackages) {
function getPackagePaths (line 142) | function getPackagePaths(rootPackages) {
FILE: scripts/copy-external-deps.js
function copyDir (line 22) | function copyDir(src, dest, visited = new Set()) {
function removeDir (line 78) | function removeDir(dir) {
FILE: scripts/copy-tree-sitter-queries.js
function createTarget (line 24) | function createTarget(name, subdir) {
function copyAll (line 42) | async function copyAll(files, destinationDir) {
FILE: scripts/regenerate-textmate.js
function writeTargets (line 11) | function writeTargets(targets, sourcePath) {
FILE: website-new/api/handler.js
method fetch (line 16) | async fetch(request) {
FILE: website-new/src/lib/markdown.js
function escape_html (line 12) | function escape_html(text) {
constant DOCS_GLOB_PREFIX (line 25) | const DOCS_GLOB_PREFIX = '../../docs/';
function highlight (line 61) | function highlight(text, lang) {
function parse_frontmatter (line 82) | function parse_frontmatter(content) {
function process_containers (line 106) | function process_containers(content) {
function process_code_tabs (line 124) | function process_code_tabs(content) {
function process_badges (line 138) | function process_badges(content) {
function strip_npm_commands (line 149) | function strip_npm_commands(content) {
function extract_toc (line 158) | function extract_toc(content) {
function get_prev_next (line 186) | function get_prev_next(slug) {
function get_doc (line 235) | function get_doc(slug) {
FILE: website-new/src/middlewares.ts
function loggingMiddleware (line 1) | async function loggingMiddleware(context: any, next: any) {
FILE: website/.vitepress/components/PlaygroundProps.ts
type PlaygroundProps (line 3) | type PlaygroundProps = {
FILE: website/.vitepress/config.js
method config (line 17) | config(md) {
method shikiSetup (line 22) | async shikiSetup(highlighter) {
function nav (line 107) | function nav() {
function docs_sidebar (line 127) | function docs_sidebar() {
FILE: website/.vitepress/theme/index.js
method enhanceApp (line 9) | enhanceApp({ app }) {
Copy disabled (too large)
Download .json
Condensed preview — 733 files, each showing path, character count, and a content snippet. Download the .json file for the full structured content (10,922K chars).
[
{
"path": ".changeset/README.md",
"chars": 510,
"preview": "# Changesets\n\nHello and welcome! This folder has been automatically generated by\n`@changesets/cli`, a build tool that wo"
},
{
"path": ".changeset/config.json",
"chars": 982,
"preview": "{\n \"$schema\": \"https://unpkg.com/@changesets/config@3.1.2/schema.json\",\n \"changelog\": [\"@changesets/changelog-github\","
},
{
"path": ".changeset/large-snails-crash.md",
"chars": 106,
"preview": "---\n'@ripple-ts/cli': patch\n'create-ripple': patch\n'@ripple-ts/vite-plugin': patch\n---\n\nUpgrade to Vite 8\n"
},
{
"path": ".changeset/tame-snails-sneeze.md",
"chars": 181,
"preview": "---\n'@ripple-ts/vite-plugin': patch\n---\n\nSplit the production subpath declarations into a dedicated type file so the exp"
},
{
"path": ".cursor/environment.json",
"chars": 72,
"preview": "{\n \"name\": \"ripple-monorepo\",\n \"install\": \"bash .cursor/install.sh\"\n}\n"
},
{
"path": ".cursor/install.sh",
"chars": 1659,
"preview": "#!/usr/bin/env bash\nset -euo pipefail\n\nWORKSPACE_ROOT=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")/..\" && pwd)\"\nLOCKFILE_PATH=\""
},
{
"path": ".cursor/rules/project.mdc",
"chars": 27452,
"preview": "---\ndescription: Ripple project overview and development guidelines\nglobs: **/*\n---\n\n# Ripple Project Guide for AI Agent"
},
{
"path": ".editorconfig",
"chars": 145,
"preview": "root = true\n\n[*]\ncharset = utf-8\nend_of_line = lf\nindent_size = 2\nindent_style = tab\ninsert_final_newline = true\ntrim_tr"
},
{
"path": ".gitattributes",
"chars": 55,
"preview": "grammars/tree-sitter/src/parser.c -linguist-detectable\n"
},
{
"path": ".github/ISSUE_TEMPLATE/bug-report.yml",
"chars": 2268,
"preview": "name: \"🐛 Bug Report\"\ndescription: \"Report a bug or unexpected behavior in Ripple\"\ntitle: \"[Bug]: \"\nlabels: [\"bug\", \"tria"
},
{
"path": ".github/ISSUE_TEMPLATE/config.yml",
"chars": 321,
"preview": "blank_issues_enabled: true\ncontact_links:\n - name: Discord Chat\n url: https://discord.gg/JBF2ySrh2W\n about: Ask q"
},
{
"path": ".github/ISSUE_TEMPLATE/feature-request.yml",
"chars": 2101,
"preview": "name: \"✨ Feature Request\"\ndescription: \"Suggest a new feature or enhancement for Ripple\"\ntitle: \"[Feature]: \"\nlabels: [\""
},
{
"path": ".github/agents/ripple.agent.md",
"chars": 1468,
"preview": "---\nname: Ripple\ndescription: An AI assistant specialized in the Ripple TypeScript UI framework\n---\n\nYou are a helpful a"
},
{
"path": ".github/copilot-instructions.md",
"chars": 27367,
"preview": "# Ripple Project Guide for AI Agents\n\nRipple is a TypeScript UI framework that combines the best parts of React, Solid,\n"
},
{
"path": ".github/workflows/ci.yml",
"chars": 1915,
"preview": "name: CI\n\non:\n push:\n branches: [main, develop]\n tags: [\"!**\"]\n paths:\n - \"packages/**\"\n - \"package."
},
{
"path": ".github/workflows/copilot-setup-steps.yml",
"chars": 818,
"preview": "# GitHub Copilot agent environment setup\n# See: https://gh.io/copilot/actions-setup-steps\n\nname: Copilot Setup Steps\n\non"
},
{
"path": ".github/workflows/livecodes-post-comment.yml",
"chars": 470,
"preview": "name: comment\n\non:\n workflow_run:\n workflows: [\"livecodes\"] # the workflow that created the artifact\n types:\n "
},
{
"path": ".github/workflows/livecodes-preview.yml",
"chars": 490,
"preview": "name: livecodes\n\non:\n workflow_run:\n workflows: [\"Publish to pkg.pr.new\"]\n types:\n - completed\n\njobs:\n buil"
},
{
"path": ".github/workflows/pkg.pr.new.yml",
"chars": 3556,
"preview": "name: Publish to pkg.pr.new\non:\n push:\n branches: [main, develop]\n tags: [\"!**\"]\n paths: [\"packages/**\"]\n pul"
},
{
"path": ".github/workflows/provenance.yml",
"chars": 836,
"preview": "on:\n push:\n branches: [main, develop]\n tags: [\"!**\"]\n paths: [\"packages/**\"]\n pull_request:\n branches: [\"m"
},
{
"path": ".github/workflows/release.yml",
"chars": 1021,
"preview": "name: Release\n\non:\n push:\n branches:\n - main\n\nconcurrency:\n group: ${{ github.workflow }}\n\npermissions: {}\n\njo"
},
{
"path": ".github/workflows/rulesync.yml",
"chars": 719,
"preview": "name: RuleSync Check\n\non:\n pull_request:\n paths:\n - \".rulesync/**\"\n - \"rulesync.jsonc\"\n - \"CLAUDE.md\""
},
{
"path": ".github/workflows/vsix-manual.yml",
"chars": 1541,
"preview": "on: workflow_dispatch\n\nname: Publish VSC Extension (Manual)\njobs:\n build:\n runs-on: ubuntu-latest\n steps:\n -"
},
{
"path": ".github/workflows/vsix.yml",
"chars": 2984,
"preview": "on:\n push:\n branches: [main]\n tags: [\"!**\"]\n paths: [\"packages/vscode-plugin/**\"]\n\nname: Publish VSC Extension"
},
{
"path": ".gitignore",
"chars": 513,
"preview": "# Dependency directories\nnode_modules/\n\n# IDE related\n.idea\n\n# Test coverage\ncoverage\n*.lcov\n\npackages/vscode-plugin/*.v"
},
{
"path": ".livecodes/playground.json",
"chars": 971,
"preview": "{\n \"appUrl\": \"https://ripple.livecodes.pages.dev\",\n \"config\": {\n \"customSettings\": {\n \"ripple\": { \"version\": \""
},
{
"path": ".prettierignore",
"chars": 511,
"preview": "# pnpm files - can have formatting differences between environments\npnpm-lock.yaml\npnpm-workspace.yaml\n\n# RuleSync gener"
},
{
"path": ".prettierrc",
"chars": 574,
"preview": "{\n\t\"useTabs\": true,\n\t\"tabWidth\": 2,\n\t\"singleQuote\": true,\n\t\"jsxSingleQuote\": false,\n\t\"printWidth\": 100,\n\t\"plugins\": [\"@r"
},
{
"path": ".rulesync/rules/project.md",
"chars": 27484,
"preview": "---\nroot: true\ntargets: ['*']\ndescription: 'Ripple project overview and development guidelines'\nglobs: ['**/*']\n---\n\n# R"
},
{
"path": ".vscode/launch.json",
"chars": 5029,
"preview": "{\n \"version\": \"0.2.1\",\n \"configurations\": [\n {\n \"name\": \"VSCode Extension\",\n \"type\": \"extensionHost\",\n "
},
{
"path": ".vscode/settings.json",
"chars": 1129,
"preview": "{\n \"editor.defaultFormatter\": \"esbenp.prettier-vscode\",\n \"editor.detectIndentation\": false,\n \"editor.formatOnSave\": t"
},
{
"path": ".vscode/tasks.json",
"chars": 538,
"preview": "{\n \"version\": \"2.0.0\",\n \"tasks\": [\n {\n \"label\": \"wait-for-vite\",\n \"type\": \"process\",\n \"command\": \"pn"
},
{
"path": "AGENTS.md",
"chars": 27547,
"preview": "# Additional Conventions Beyond the Built-in Functions\n\nAs this project's AI coding tool, you must follow the additional"
},
{
"path": "CLAUDE.md",
"chars": 27367,
"preview": "# Ripple Project Guide for AI Agents\n\nRipple is a TypeScript UI framework that combines the best parts of React, Solid,\n"
},
{
"path": "CODE_OF_CONDUCT.md",
"chars": 2163,
"preview": "# Code of Conduct\n\nThis project is built by people who want to create something cool together. Let's\nkeep it fun, welcom"
},
{
"path": "CONTRIBUTING.md",
"chars": 7912,
"preview": "# Contributing to Ripple\n\nRipple is a TypeScript UI framework that combines the best parts of React, Solid,\nand Svelte i"
},
{
"path": "GEMINI.md",
"chars": 27547,
"preview": "# Additional Conventions Beyond the Built-in Functions\n\nAs this project's AI coding tool, you must follow the additional"
},
{
"path": "LICENSE",
"chars": 1073,
"preview": "MIT License\n\nCopyright (c) 2025 Dominic Gannaway\n\nPermission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "README.md",
"chars": 10063,
"preview": "<a href=\"https://ripplejs.com\">\n <picture>\n <source media=\"(min-width: 768px)\" srcset=\"assets/ripple-desktop.png\">\n "
},
{
"path": "assets/Ripple.tmbundle/README.md",
"chars": 936,
"preview": "This provides syntax highlighting for Ripple files in editors that support\nTextMate grammars, such as WebStorm/IntelliJ "
},
{
"path": "assets/Ripple.tmbundle/Syntaxes/ripple.tmLanguage",
"chars": 369760,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
},
{
"path": "assets/Ripple.tmbundle/info.plist",
"chars": 231,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\"\n \"http://www.apple.com/DTDs"
},
{
"path": "grammars/textmate/info.plist",
"chars": 231,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\"\n \"http://www.apple.com/DTDs"
},
{
"path": "grammars/textmate/ripple.tmLanguage.json",
"chars": 289098,
"preview": "{\n \"information_for_contributors\": [\n \"This file has been converted from https://github.com/microsoft/TypeScript-TmL"
},
{
"path": "grammars/tree-sitter/.gitignore",
"chars": 84,
"preview": "node_modules/\nbuild/\n*.log\npackage-lock.json\nyarn.lock\n*.exp\n*.lib\n*.obj\n*.dll\n*.so\n"
},
{
"path": "grammars/tree-sitter/Cargo.toml",
"chars": 375,
"preview": "[package]\nname = \"tree-sitter\"\ndescription = \"Ripple grammar for tree-sitter\"\nversion = \"0.0.1\"\nkeywords = [\"incremental"
},
{
"path": "grammars/tree-sitter/LICENSE",
"chars": 1077,
"preview": "MIT License\n\nCopyright (c) 2025 Ripple Contributors\n\nPermission is hereby granted, free of charge, to any person obtaini"
},
{
"path": "grammars/tree-sitter/README.md",
"chars": 266,
"preview": "# @ripple-ts/tree-sitter\n\nTree-sitter grammar for [Ripple](https://www.ripplejs.com).\n\n## Overview\n\nRipple is a JS/TS-fi"
},
{
"path": "grammars/tree-sitter/binding.gyp",
"chars": 400,
"preview": "{\n \"targets\": [\n {\n \"target_name\": \"tree_sitter_ripple_binding\",\n \"include_dirs\": [\n \"node_modules/"
},
{
"path": "grammars/tree-sitter/bindings/node/binding.cc",
"chars": 314,
"preview": "#include \"napi.h\"\n\ntypedef struct TSLanguage TSLanguage;\n\nextern \"C\" TSLanguage *tree_sitter_ripple();\n\nNapi::Object Ini"
},
{
"path": "grammars/tree-sitter/grammar.js",
"chars": 28589,
"preview": "const PREC = {\n\tCOMMA: -1,\n\tDECLARATION: 1,\n\tASSIGN: 0,\n\tOBJECT: 1,\n\tTERNARY: 1,\n\tOR: 2,\n\tAND: 3,\n\tREL: 4,\n\tPLUS: 5,\n\tTI"
},
{
"path": "grammars/tree-sitter/package.json",
"chars": 945,
"preview": "{\n \"name\": \"@ripple-ts/tree-sitter\",\n \"version\": \"0.2.208\",\n \"description\": \"Ripple grammar for tree-sitter\",\n \"priv"
},
{
"path": "grammars/tree-sitter/queries/brackets.scm",
"chars": 258,
"preview": "; Bracket pairs for cursor navigation\n(jsx_opening_element\n \"<\" @open\n \">\" @close)\n\n(jsx_closing_element\n \"</\" @open\n"
},
{
"path": "grammars/tree-sitter/queries/folds.scm",
"chars": 384,
"preview": "; Folds for code blocks\n[\n (statement_block)\n (component_body)\n (class_body)\n (object)\n (object_pattern)\n (array)\n"
},
{
"path": "grammars/tree-sitter/queries/highlights.scm",
"chars": 6007,
"preview": "; Keywords\n(component_declaration \"component\" @keyword)\n(fragment_declaration \"fragment\" @keyword)\n(server_block \"#rippl"
},
{
"path": "grammars/tree-sitter/queries/indents.nvim.scm",
"chars": 985,
"preview": "; Neovim (nvim-treesitter) indentation rules.\n[\n (statement_block \"}\" @indent.end)\n (component_body \"}\" @indent.end)\n "
},
{
"path": "grammars/tree-sitter/queries/indents.scm",
"chars": 428,
"preview": "; Helix indentation rules.\n[\n (statement_block)\n (component_body)\n (class_body)\n (switch_body)\n (object)\n (object_"
},
{
"path": "grammars/tree-sitter/queries/indents.zed.scm",
"chars": 733,
"preview": "; Zed indents use @indent plus @end markers.\n[\n (statement_block \"}\" @end)\n (component_body \"}\" @end)\n (class_body \"}"
},
{
"path": "grammars/tree-sitter/queries/injections.scm",
"chars": 692,
"preview": "; Inject CSS into style elements\n(style_element\n (raw_text) @injection.content\n (#set! injection.combined)\n (#set! in"
},
{
"path": "grammars/tree-sitter/queries/locals.scm",
"chars": 1110,
"preview": "; Scopes\n[\n (statement_block)\n (function_declaration)\n (arrow_function)\n (function_expression)\n (component_declarat"
},
{
"path": "grammars/tree-sitter/queries/outline.scm",
"chars": 467,
"preview": "; Code outline/structure for symbol navigation\n\n; Components\n(component_declaration\n name: (identifier) @name) @item\n\n;"
},
{
"path": "grammars/tree-sitter/queries/textobjects.scm",
"chars": 1627,
"preview": "; Functions / components\n(function_declaration) @function.around\n(function_declaration) @function.outer\n(function_declar"
},
{
"path": "grammars/tree-sitter/src/grammar.json",
"chars": 181040,
"preview": "{\n \"$schema\": \"https://tree-sitter.github.io/tree-sitter/assets/schemas/grammar.schema.json\",\n \"name\": \"ripple\",\n \"wo"
},
{
"path": "grammars/tree-sitter/src/node-types.json",
"chars": 76155,
"preview": "[\n {\n \"type\": \"declaration\",\n \"named\": true,\n \"subtypes\": [\n {\n \"type\": \"class_declaration\",\n "
},
{
"path": "grammars/tree-sitter/src/parser.c",
"chars": 5073700,
"preview": "/* Automatically @generated by tree-sitter */\n\n#include \"tree_sitter/parser.h\"\n\n#if defined(__GNUC__) || defined(__clang"
},
{
"path": "grammars/tree-sitter/src/scanner.c",
"chars": 4638,
"preview": "#include <tree_sitter/parser.h>\n#include <wctype.h>\n\nenum TokenType {\n AUTOMATIC_SEMICOLON,\n TEMPLATE_CHARS,\n TERNARY"
},
{
"path": "grammars/tree-sitter/src/tree_sitter/alloc.h",
"chars": 985,
"preview": "#ifndef TREE_SITTER_ALLOC_H_\n#define TREE_SITTER_ALLOC_H_\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include <stdbool.h>\n"
},
{
"path": "grammars/tree-sitter/src/tree_sitter/array.h",
"chars": 13269,
"preview": "#ifndef TREE_SITTER_ARRAY_H_\n#define TREE_SITTER_ARRAY_H_\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include \"./alloc.h\"\n"
},
{
"path": "grammars/tree-sitter/src/tree_sitter/parser.h",
"chars": 7624,
"preview": "#ifndef TREE_SITTER_PARSER_H_\n#define TREE_SITTER_PARSER_H_\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include <stdbool.h"
},
{
"path": "grammars/tree-sitter/test/corpus/components.txt",
"chars": 4209,
"preview": "==================\nComponent Declaration\n==================\n\ncomponent Button(props: { text: string }) {\n <button>{prop"
},
{
"path": "grammars/tree-sitter/test/corpus/control-flow.txt",
"chars": 9612,
"preview": "==================\nFor-of Loop\n==================\n\ncomponent List({ items }) {\n <ul>\n for (const item of items) {\n "
},
{
"path": "grammars/tree-sitter/test/corpus/javascript.txt",
"chars": 6616,
"preview": "==================\nImport Statements\n==================\n\nimport { track } from 'ripple';\nimport type { Component } from "
},
{
"path": "grammars/tree-sitter/test/corpus/jsx.txt",
"chars": 6594,
"preview": "==================\nDynamic Component\n==================\n\ncomponent App() {\n let Current = #ripple.track(() => Component"
},
{
"path": "grammars/tree-sitter/test/corpus/main.txt",
"chars": 0,
"preview": ""
},
{
"path": "grammars/tree-sitter/test/corpus/reactivity.txt",
"chars": 6622,
"preview": "==================\nReactive Primitives - track and unbox\n==================\n\ncomponent Counter() {\n let count = #ripple"
},
{
"path": "grammars/tree-sitter/tree-sitter.json",
"chars": 777,
"preview": "{\n \"$schema\": \"https://tree-sitter.github.io/tree-sitter/assets/schemas/config.schema.json\",\n \"grammars\": [\n {\n "
},
{
"path": "package.json",
"chars": 1495,
"preview": "{\n \"name\": \"ripple-monorepo\",\n \"private\": true,\n \"type\": \"module\",\n \"description\": \"\",\n \"author\": \"Dominic Gannaway"
},
{
"path": "packages/adapter/CHANGELOG.md",
"chars": 1390,
"preview": "# @ripple-ts/adapter\n\n## 0.3.3\n\n## 0.3.2\n\n## 0.3.1\n\n## 0.3.0\n\n## 0.2.216\n\n## 0.2.215\n\n## 0.2.214\n\n## 0.2.213\n\n## 0.2.212"
},
{
"path": "packages/adapter/README.md",
"chars": 884,
"preview": "# @ripple-ts/adapter\n\n[](https://www.npmjs.c"
},
{
"path": "packages/adapter/package.json",
"chars": 839,
"preview": "{\n \"name\": \"@ripple-ts/adapter\",\n \"description\": \"Shared adapter primitives for Ripple metaframework adapters\",\n \"lic"
},
{
"path": "packages/adapter/src/index.js",
"chars": 2986,
"preview": "export const DEFAULT_HOSTNAME = 'localhost';\nexport const DEFAULT_PORT = 3000;\nexport const DEFAULT_STATIC_PREFIX = '/';"
},
{
"path": "packages/adapter/src/rpc.js",
"chars": 6894,
"preview": "/**\n * Shared RPC utilities for Ripple metaframework.\n *\n * These functions are platform-agnostic — they use only standa"
},
{
"path": "packages/adapter/tests/index.test.js",
"chars": 2842,
"preview": "import { describe, expect, it } from 'vitest';\nimport {\n\tDEFAULT_HOSTNAME,\n\tDEFAULT_PORT,\n\tget_mime_type,\n\tget_static_ca"
},
{
"path": "packages/adapter/tests/types.test.js",
"chars": 693,
"preview": "import { readFileSync } from 'node:fs';\nimport { describe, expect, it } from 'vitest';\n\nconst types_source = readFileSyn"
},
{
"path": "packages/adapter/tsconfig.json",
"chars": 155,
"preview": "{\n \"compilerOptions\": {\n \"allowJs\": true,\n \"noEmit\": true\n },\n \"include\": [\"./src/**/*\", \"./tests/**/*\"],\n \"ex"
},
{
"path": "packages/adapter/types/index.d.ts",
"chars": 2258,
"preview": "export type FetchHandler<Platform = any, ResultValue = Response> = (\n\trequest: Request,\n\tplatform?: Platform,\n) => Resul"
},
{
"path": "packages/adapter/types/rpc.d.ts",
"chars": 3675,
"preview": "/**\n * Async context abstraction — wraps platform-specific implementations\n * (e.g., Node.js AsyncLocalStorage, Bun Asyn"
},
{
"path": "packages/adapter-bun/CHANGELOG.md",
"chars": 2578,
"preview": "# @ripple-ts/adapter-bun\n\n## 0.3.3\n\n### Patch Changes\n\n- Updated dependencies []:\n - @ripple-ts/adapter@0.3.3\n\n## 0.3.2"
},
{
"path": "packages/adapter-bun/README.md",
"chars": 2302,
"preview": "# @ripple-ts/adapter-bun\n\n[](https://www"
},
{
"path": "packages/adapter-bun/package.json",
"chars": 915,
"preview": "{\n \"name\": \"@ripple-ts/adapter-bun\",\n \"description\": \"Bun adapter for Ripple metaframework (Web Request/Response bridg"
},
{
"path": "packages/adapter-bun/src/index.js",
"chars": 5486,
"preview": "/** @typedef {typeof import('bun')} Bun */\n/** @typedef {Bun.Server<undefined>} Server */\n\nimport {\n\tDEFAULT_HOSTNAME,\n\t"
},
{
"path": "packages/adapter-bun/tests/serve.test.js",
"chars": 10446,
"preview": "import {\n\texistsSync,\n\tmkdirSync,\n\tmkdtempSync,\n\treadFileSync,\n\trmSync,\n\tstatSync,\n\twriteFileSync,\n} from 'node:fs';\nimp"
},
{
"path": "packages/adapter-bun/tests/types.test.js",
"chars": 773,
"preview": "import { readFileSync } from 'node:fs';\nimport { describe, expect, it } from 'vitest';\n\nconst types_source = readFileSyn"
},
{
"path": "packages/adapter-bun/tsconfig.json",
"chars": 155,
"preview": "{\n \"compilerOptions\": {\n \"allowJs\": true,\n \"noEmit\": true\n },\n \"include\": [\"./src/**/*\", \"./tests/**/*\"],\n \"ex"
},
{
"path": "packages/adapter-bun/types/index.d.ts",
"chars": 908,
"preview": "import type {\n\tAdapterCoreOptions,\n\tNextMiddleware,\n\tRuntimePrimitives,\n\tServeFunction,\n\tServeStaticOptions as BaseServe"
},
{
"path": "packages/adapter-node/CHANGELOG.md",
"chars": 2579,
"preview": "# @ripple-ts/adapter-node\n\n## 0.3.3\n\n### Patch Changes\n\n- Updated dependencies []:\n - @ripple-ts/adapter@0.3.3\n\n## 0.3."
},
{
"path": "packages/adapter-node/README.md",
"chars": 2929,
"preview": "# @ripple-ts/adapter-node\n\n[](https://w"
},
{
"path": "packages/adapter-node/package.json",
"chars": 809,
"preview": "{\n \"name\": \"@ripple-ts/adapter-node\",\n \"description\": \"Node.js adapter for Ripple metaframework (Web Request/Response "
},
{
"path": "packages/adapter-node/src/index.js",
"chars": 11333,
"preview": "import { createServer } from 'node:http';\nimport { createReadStream, existsSync, statSync } from 'node:fs';\nimport { res"
},
{
"path": "packages/adapter-node/tests/serve.test.js",
"chars": 10999,
"preview": "import { request as node_http_request } from 'node:http';\nimport { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "
},
{
"path": "packages/adapter-node/tests/types.test.js",
"chars": 774,
"preview": "import { readFileSync } from 'node:fs';\nimport { describe, expect, it } from 'vitest';\n\nconst types_source = readFileSyn"
},
{
"path": "packages/adapter-node/tsconfig.json",
"chars": 155,
"preview": "{\n \"compilerOptions\": {\n \"allowJs\": true,\n \"noEmit\": true\n },\n \"include\": [\"./src/**/*\", \"./tests/**/*\"],\n \"ex"
},
{
"path": "packages/adapter-node/types/index.d.ts",
"chars": 1748,
"preview": "import type {\n\tAdapterCoreOptions,\n\tRuntimePrimitives,\n\tServeFunction,\n\tServeStaticOptions as BaseServeStaticOptions,\n\tS"
},
{
"path": "packages/adapter-vercel/CHANGELOG.md",
"chars": 988,
"preview": "# @ripple-ts/adapter-vercel\n\n## 0.3.3\n\n### Patch Changes\n\n- Updated dependencies []:\n - @ripple-ts/adapter@0.3.3\n - @r"
},
{
"path": "packages/adapter-vercel/README.md",
"chars": 6150,
"preview": "# @ripple-ts/adapter-vercel\n\nVercel adapter for the Ripple metaframework.\n\nDeploys your Ripple SSR application to [Verce"
},
{
"path": "packages/adapter-vercel/package.json",
"chars": 954,
"preview": "{\n \"name\": \"@ripple-ts/adapter-vercel\",\n \"description\": \"Vercel adapter for Ripple metaframework (Build Output API v3)"
},
{
"path": "packages/adapter-vercel/src/adapt.js",
"chars": 13628,
"preview": "/**\n * Build output generator for Vercel's Build Output API v3.\n *\n * Takes the Ripple build output (dist/client + dist/"
},
{
"path": "packages/adapter-vercel/src/bin/adapt.js",
"chars": 1574,
"preview": "#!/usr/bin/env node\n\n/**\n * CLI entry point for `ripple-adapt-vercel`.\n *\n * Runs the adapt() function to generate Verce"
},
{
"path": "packages/adapter-vercel/src/index.js",
"chars": 394,
"preview": "/**\n * @ripple-ts/adapter-vercel — Vercel adapter for the Ripple metaframework.\n *\n * Re-exports Node.js runtime primiti"
},
{
"path": "packages/adapter-vercel/tests/adapt.test.js",
"chars": 13606,
"preview": "import { describe, expect, it, vi, beforeEach, afterEach } from 'vitest';\nimport { mkdirSync, mkdtempSync, rmSync, write"
},
{
"path": "packages/adapter-vercel/tests/types.test.js",
"chars": 3183,
"preview": "import { describe, it, expect } from 'vitest';\nimport { readFileSync } from 'node:fs';\nimport { join, dirname } from 'no"
},
{
"path": "packages/adapter-vercel/tsconfig.json",
"chars": 155,
"preview": "{\n \"compilerOptions\": {\n \"allowJs\": true,\n \"noEmit\": true\n },\n \"include\": [\"./src/**/*\", \"./tests/**/*\"],\n \"ex"
},
{
"path": "packages/adapter-vercel/types/index.d.ts",
"chars": 5383,
"preview": "import type {\n\tAdapterCoreOptions,\n\tNextMiddleware,\n\tRuntimePrimitives,\n\tServeFunction,\n\tServeStaticOptions as BaseServe"
},
{
"path": "packages/cli/CHANGELOG.md",
"chars": 153,
"preview": "# @ripple-ts/cli\n\n## 0.3.3\n\n## 0.3.2\n\n## 0.3.1\n\n## 0.3.0\n\n## 0.2.216\n\n## 0.2.215\n\n## 0.2.214\n\n## 0.2.213\n\n## 0.2.212\n\n##"
},
{
"path": "packages/cli/LICENSE",
"chars": 1063,
"preview": "MIT License\n\nCopyright (c) 2025 Ripple\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof "
},
{
"path": "packages/cli/README.md",
"chars": 1963,
"preview": "# @ripple-ts/cli\n\n[](https://www.npmjs.com/packa"
},
{
"path": "packages/cli/package.json",
"chars": 1426,
"preview": "{\n \"name\": \"@ripple-ts/cli\",\n \"version\": \"0.3.3\",\n \"description\": \"Interactive CLI tool for creating Ripple applicati"
},
{
"path": "packages/cli/src/commands/create.js",
"chars": 5457,
"preview": "/** @import {PackageManager} from '../lib/project-creator.js' */\n\n/**\n * @typedef {{ template?: string, packageManager?:"
},
{
"path": "packages/cli/src/constants.js",
"chars": 422,
"preview": "/**\n * Available templates configuration\n */\nexport const TEMPLATES = [\n\t{\n\t\tname: 'basic',\n\t\tdisplay: 'Basic Ripple App"
},
{
"path": "packages/cli/src/index.js",
"chars": 1822,
"preview": "#!/usr/bin/env node\n\n/** @import {CommandOptions} from './commands/create.js' */\n\nimport { Command } from 'commander';\ni"
},
{
"path": "packages/cli/src/lib/is-folder-empty.js",
"chars": 2558,
"preview": "import { lstatSync, readdirSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { green, blue } from 'kleur/c"
},
{
"path": "packages/cli/src/lib/package-manager.js",
"chars": 1523,
"preview": "/** @import {PackageManager} from '../lib/project-creator.js' */\n\n/**\n * Detect the package manager used to run the curr"
},
{
"path": "packages/cli/src/lib/project-creator.js",
"chars": 9736,
"preview": "/**\n * @typedef {import('type-fest').PackageJson & {scripts?: Record<string, string>;}} Package\n * @typedef PackageManag"
},
{
"path": "packages/cli/src/lib/prompts.js",
"chars": 4105,
"preview": "/** @import {PackageManager} from '../lib/project-creator.js' */\n\nimport prompts from 'prompts';\nimport { validateProjec"
},
{
"path": "packages/cli/src/lib/templates.js",
"chars": 3522,
"preview": "import { join } from 'node:path';\nimport { existsSync, mkdirSync } from 'node:fs';\nimport { tmpdir } from 'node:os';\nimp"
},
{
"path": "packages/cli/src/lib/validation.js",
"chars": 3361,
"preview": "import { basename, resolve } from 'node:path';\n\n/**\n * Validation utilities for project creation\n */\n\n/**\n * Validates a"
},
{
"path": "packages/cli/tests/integration/cli.test.js",
"chars": 8466,
"preview": "import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';\nimport { spawn } from 'node:child_process';\nim"
},
{
"path": "packages/cli/tests/integration/project-creator.test.js",
"chars": 10329,
"preview": "import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';\nimport { existsSync, mkdirSync, rmSync, readFi"
},
{
"path": "packages/cli/tests/unit/prompts.test.js",
"chars": 8645,
"preview": "import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';\nimport prompts from 'prompts';\n\n// Mock prompt"
},
{
"path": "packages/cli/tests/unit/templates.test.js",
"chars": 4460,
"preview": "import { describe, it, expect, beforeEach, vi } from 'vitest';\nimport { existsSync } from 'node:fs';\nimport {\n\tgetTempla"
},
{
"path": "packages/cli/tests/unit/validation.test.js",
"chars": 5892,
"preview": "import { describe, it, expect } from 'vitest';\nimport {\n\tvalidateProjectName,\n\tsanitizeDirectoryName,\n\tvalidateDirectory"
},
{
"path": "packages/cli/tsconfig.json",
"chars": 139,
"preview": "{\n \"compilerOptions\": {\n \"allowJs\": true,\n \"noEmit\": true\n },\n \"include\": [\"./src/**/*\"],\n \"exclude\": [\"dist\","
},
{
"path": "packages/cli/tsdown.config.js",
"chars": 313,
"preview": "import { defineConfig } from 'tsdown';\n\nexport default defineConfig({\n\tinlineOnly: false,\n\tentry: 'src/index.js',\n\toutpu"
},
{
"path": "packages/cli/vitest.config.js",
"chars": 495,
"preview": "import { defineConfig } from 'vitest/config';\n\nexport default defineConfig({\n\ttest: {\n\t\tinclude: ['tests/**/*.test.js'],"
},
{
"path": "packages/compat-react/CHANGELOG.md",
"chars": 3211,
"preview": "# @ripple-ts/compat-react\n\n## 0.3.3\n\n### Patch Changes\n\n- Updated dependencies\n [[`cd1073f`](https://github.com/Ripple-"
},
{
"path": "packages/compat-react/LICENSE",
"chars": 1073,
"preview": "MIT License\n\nCopyright (c) 2025 Dominic Gannaway\n\nPermission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "packages/compat-react/package.json",
"chars": 775,
"preview": "{\n \"name\": \"@ripple-ts/compat-react\",\n \"version\": \"0.3.3\",\n \"description\": \"Ripple compatibility layer for React\",\n "
},
{
"path": "packages/compat-react/src/index.js",
"chars": 6592,
"preview": "/** @import { Tsx } from '../types' */\n/** @import { ReactNode } from 'react' */\n\nimport { jsx, jsxs, Fragment } from 'r"
},
{
"path": "packages/compat-react/tests/client.d.ts",
"chars": 549,
"preview": "declare var container: HTMLDivElement;\ndeclare var error: string | undefined;\ndeclare function render(component: () => v"
},
{
"path": "packages/compat-react/tests/index.test.ripple",
"chars": 19159,
"preview": "import { track, flushSync } from 'ripple';\nimport { act, createContext, useContext, Suspense } from 'react';\nimport { vi"
},
{
"path": "packages/compat-react/tests/setup.js",
"chars": 1308,
"preview": "import { beforeEach, afterEach, vi } from 'vitest';\nimport { mount } from 'ripple';\nimport { createReactCompat } from '."
},
{
"path": "packages/compat-react/tsconfig.json",
"chars": 669,
"preview": "{\n \"compilerOptions\": {\n \"module\": \"esnext\",\n \"lib\": [\"esnext\", \"dom\", \"dom.iterable\"],\n \"target\": \"esnext\",\n "
},
{
"path": "packages/compat-react/types/index.d.ts",
"chars": 556,
"preview": "import type { Component } from 'ripple';\n\nexport type Tsx = {\n\tjsx: typeof import('react/jsx-runtime').jsx;\n\tjsxs: typeo"
},
{
"path": "packages/create-ripple/CHANGELOG.md",
"chars": 1032,
"preview": "# create-ripple\n\n## 0.3.3\n\n### Patch Changes\n\n- Updated dependencies []:\n - @ripple-ts/cli@0.3.3\n\n## 0.3.2\n\n### Patch C"
},
{
"path": "packages/create-ripple/README.md",
"chars": 1603,
"preview": "# create-ripple\n\n[](https://www.npmjs.com/package/cre"
},
{
"path": "packages/create-ripple/package.json",
"chars": 823,
"preview": "{\n \"name\": \"create-ripple\",\n \"version\": \"0.3.3\",\n \"type\": \"module\",\n \"license\": \"MIT\",\n \"author\": \"Ripple Team\",\n "
},
{
"path": "packages/create-ripple/src/index.js",
"chars": 45,
"preview": "#!/usr/bin/env node\nimport '@ripple-ts/cli';\n"
},
{
"path": "packages/create-ripple/tsconfig.json",
"chars": 139,
"preview": "{\n \"compilerOptions\": {\n \"allowJs\": true,\n \"noEmit\": true\n },\n \"include\": [\"./src/**/*\"],\n \"exclude\": [\"dist\","
},
{
"path": "packages/create-ripple/tsdown.config.js",
"chars": 325,
"preview": "import { defineConfig } from 'tsdown';\n\nexport default defineConfig({\n\tinlineOnly: false,\n\tentry: 'src/index.js',\n\toutpu"
},
{
"path": "packages/eslint-parser/.npmignore",
"chars": 78,
"preview": "src/\nnode_modules/\n*.test.ts\n*.test.js\ndebug-parse.js\ntsconfig.json\n.DS_Store\n"
},
{
"path": "packages/eslint-parser/CHANGELOG.md",
"chars": 844,
"preview": "# @ripple-ts/eslint-parser\n\n## 0.3.3\n\n## 0.3.2\n\n## 0.3.1\n\n## 0.3.0\n\n### Minor Changes\n\n- [#779](https://github.com/Rippl"
},
{
"path": "packages/eslint-parser/README.md",
"chars": 3217,
"preview": "# @ripple-ts/eslint-parser\n\n[](https:/"
},
{
"path": "packages/eslint-parser/package.json",
"chars": 1106,
"preview": "{\n \"name\": \"@ripple-ts/eslint-parser\",\n \"version\": \"0.3.3\",\n \"description\": \"ESLint parser for Ripple (.ripple files)"
},
{
"path": "packages/eslint-parser/src/index.ts",
"chars": 6000,
"preview": "import type { Program } from 'estree';\nimport type { AST, Linter } from 'eslint';\nimport { createRequire } from 'module'"
},
{
"path": "packages/eslint-parser/src/loader.ts",
"chars": 1179,
"preview": "/**\n * Loader module that initializes the Ripple compiler for the parser\n * This should be imported before using the par"
},
{
"path": "packages/eslint-parser/tsconfig.json",
"chars": 458,
"preview": "{\n \"compilerOptions\": {\n \"target\": \"ES2022\",\n \"module\": \"ESNext\",\n \"lib\": [\"ES2022\"],\n \"moduleResolution\": "
},
{
"path": "packages/eslint-parser/tsdown.config.js",
"chars": 404,
"preview": "import { defineConfig } from 'tsdown';\n\nexport default defineConfig({\n\tinlineOnly: false,\n\tentry: 'src/index.ts',\n\tforma"
},
{
"path": "packages/eslint-plugin/.npmignore",
"chars": 77,
"preview": "src/\ntests/\nnode_modules/\n*.test.ts\ntsconfig.json\nvitest.config.ts\n.DS_Store\n"
},
{
"path": "packages/eslint-plugin/CHANGELOG.md",
"chars": 1942,
"preview": "# @ripple-ts/eslint-plugin\n\n## 0.3.3\n\n### Patch Changes\n\n- Updated dependencies []:\n - @ripple-ts/eslint-parser@0.3.3\n\n"
},
{
"path": "packages/eslint-plugin/README.md",
"chars": 5719,
"preview": "# @ripple-ts/eslint-plugin\n\n[](https:/"
},
{
"path": "packages/eslint-plugin/package.json",
"chars": 1609,
"preview": "{\n \"name\": \"@ripple-ts/eslint-plugin\",\n \"version\": \"0.3.3\",\n \"description\": \"ESLint plugin for Ripple\",\n \"type\": \"mo"
},
{
"path": "packages/eslint-plugin/src/index.ts",
"chars": 2731,
"preview": "import { createRequire } from 'module';\nimport noModuleScopeTrack from './rules/no-module-scope-track.js';\nimport prefer"
},
{
"path": "packages/eslint-plugin/src/rules/control-flow-jsx.ts",
"chars": 2401,
"preview": "import type { Rule } from 'eslint';\nimport type * as AST from 'ripple/types/estree';\n\nconst rule: Rule.RuleModule = {\n\tm"
},
{
"path": "packages/eslint-plugin/src/rules/no-introspect-in-modules.ts",
"chars": 973,
"preview": "import type { Rule } from 'eslint';\nimport type * as AST from 'ripple/types/estree';\n\nconst rule: Rule.RuleModule = {\n\tm"
},
{
"path": "packages/eslint-plugin/src/rules/no-module-scope-track.ts",
"chars": 1622,
"preview": "import type { Rule } from 'eslint';\nimport type * as AST from 'ripple/types/estree';\n\nconst rule: Rule.RuleModule = {\n\tm"
},
{
"path": "packages/eslint-plugin/src/rules/no-return-in-component.ts",
"chars": 1340,
"preview": "import type { Rule } from 'eslint';\nimport type * as AST from 'ripple/types/estree';\n\nconst rule: Rule.RuleModule = {\n\tm"
},
{
"path": "packages/eslint-plugin/src/rules/prefer-oninput.ts",
"chars": 1836,
"preview": "import type { Rule } from 'eslint';\nimport type * as AST from 'ripple/types/estree';\nimport type * as ESTreeJSX from 'ri"
},
{
"path": "packages/eslint-plugin/src/rules/unbox-tracked-values.ts",
"chars": 2111,
"preview": "import type { Rule } from 'eslint';\nimport type * as AST from 'ripple/types/estree';\n\nconst rule: Rule.RuleModule = {\n\tm"
},
{
"path": "packages/eslint-plugin/src/rules/valid-for-of-key.ts",
"chars": 3475,
"preview": "import type { Rule } from 'eslint';\nimport type * as AST from 'ripple/types/estree';\nimport type { Scope } from 'eslint'"
},
{
"path": "packages/eslint-plugin/tests/rules/control-flow-jsx.test.ts",
"chars": 2956,
"preview": "import { RuleTester } from 'eslint';\nimport rule from '../../src/rules/control-flow-jsx.js';\nimport * as parser from '@r"
},
{
"path": "packages/eslint-plugin/tests/rules/no-introspect-in-modules.test.ts",
"chars": 3062,
"preview": "import { RuleTester } from 'eslint';\nimport rule from '../../src/rules/no-introspect-in-modules.js';\nimport * as parser "
},
{
"path": "packages/eslint-plugin/tests/rules/no-module-scope-track.test.ts",
"chars": 1163,
"preview": "import { RuleTester } from 'eslint';\nimport rule from '../../src/rules/no-module-scope-track.js';\nimport * as parser fro"
},
{
"path": "packages/eslint-plugin/tests/rules/no-return-in-component.test.ts",
"chars": 658,
"preview": "import { RuleTester } from 'eslint';\nimport rule from '../../src/rules/no-return-in-component.js';\nimport * as parser fr"
},
{
"path": "packages/eslint-plugin/tests/rules/prefer-oninput.test.ts",
"chars": 1025,
"preview": "import { RuleTester } from 'eslint';\nimport rule from '../../src/rules/prefer-oninput.js';\nimport * as parser from '@rip"
},
{
"path": "packages/eslint-plugin/tests/rules/unbox-tracked-values.test.ts",
"chars": 2157,
"preview": "import { RuleTester } from 'eslint';\nimport rule from '../../src/rules/unbox-tracked-values.js';\nimport * as parser from"
},
{
"path": "packages/eslint-plugin/tests/rules/valid-for-of-key.test.ts",
"chars": 2005,
"preview": "import { RuleTester } from 'eslint';\nimport rule from '../../src/rules/valid-for-of-key.js';\nimport * as parser from '@r"
},
{
"path": "packages/eslint-plugin/tsconfig.json",
"chars": 467,
"preview": "{\n \"compilerOptions\": {\n \"target\": \"ES2022\",\n \"module\": \"ESNext\",\n \"lib\": [\"ES2022\"],\n \"moduleResolution\": "
},
{
"path": "packages/eslint-plugin/tsdown.config.js",
"chars": 451,
"preview": "import { defineConfig } from 'tsdown';\n\nexport default defineConfig({\n\tinlineOnly: false,\n\tentry: 'src/index.ts',\n\tforma"
},
{
"path": "packages/eslint-plugin/vitest.config.ts",
"chars": 169,
"preview": "import { defineConfig } from 'vitest/config';\n\nexport default defineConfig({\n\ttest: {\n\t\tglobals: true,\n\t\tenvironment: 'n"
},
{
"path": "packages/intellij-plugin/.gitignore",
"chars": 603,
"preview": ".run/\n.intellijPlatform/\n.gradle\nbuild/\n!gradle/wrapper/gradle-wrapper.jar\n!**/src/main/**/build/\n!**/src/test/**/build/"
},
{
"path": "packages/intellij-plugin/README.md",
"chars": 1038,
"preview": "# Ripple for IntelliJ\n\nRipple language support for IntelliJ Platform IDEs.\n\n## Features\n\n- TextMate-based syntax highlig"
},
{
"path": "packages/intellij-plugin/build.gradle.kts",
"chars": 1064,
"preview": "plugins {\n\tid(\"java\")\n\tid(\"org.jetbrains.kotlin.jvm\") version \"2.1.20\"\n\tid(\"org.jetbrains.intellij.platform\") version \"2"
},
{
"path": "packages/intellij-plugin/gradle/wrapper/gradle-wrapper.properties",
"chars": 202,
"preview": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributi"
},
{
"path": "packages/intellij-plugin/gradle.properties",
"chars": 355,
"preview": "# Enable Gradle Configuration Cache -> https://docs.gradle.org/current/userguide/configuration_cache.html\norg.gradle.con"
},
{
"path": "packages/intellij-plugin/gradlew",
"chars": 8047,
"preview": "#!/bin/sh\n\n#\n# Copyright © 2015-2021 the original authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"Lice"
},
{
"path": "packages/intellij-plugin/gradlew.bat",
"chars": 2674,
"preview": "@rem\n@rem Copyright 2015 the original author or authors.\n@rem\n@rem Licensed under the Apache License, Version 2.0 (the \""
},
{
"path": "packages/intellij-plugin/package.json",
"chars": 85,
"preview": "{\n \"name\": \"@ripple-ts/intellij-plugin\",\n \"private\": true,\n \"version\": \"0.0.82\"\n}\n"
},
{
"path": "packages/intellij-plugin/settings.gradle.kts",
"chars": 37,
"preview": "rootProject.name = \"intellij-plugin\"\n"
},
{
"path": "packages/intellij-plugin/src/main/kotlin/com/ripple_ts/intellij_plugin/RippleCommenter.kt",
"chars": 401,
"preview": "package com.ripple_ts.intellij_plugin\n\nimport com.intellij.lang.Commenter\n\nclass RippleCommenter : Commenter {\n\toverride"
},
{
"path": "packages/intellij-plugin/src/main/kotlin/com/ripple_ts/intellij_plugin/RippleFileType.kt",
"chars": 644,
"preview": "package com.ripple_ts.intellij_plugin\n\nimport com.intellij.openapi.fileTypes.LanguageFileType\nimport com.intellij.openap"
},
{
"path": "packages/intellij-plugin/src/main/kotlin/com/ripple_ts/intellij_plugin/RippleIcons.kt",
"chars": 214,
"preview": "package com.ripple_ts.intellij_plugin\n\nimport com.intellij.openapi.util.IconLoader\nimport javax.swing.Icon\n\nobject Rippl"
},
{
"path": "packages/intellij-plugin/src/main/kotlin/com/ripple_ts/intellij_plugin/RippleLanguage.kt",
"chars": 117,
"preview": "package com.ripple_ts.intellij_plugin\n\nimport com.intellij.lang.Language\n\nobject RippleLanguage : Language(\"Ripple\")\n"
},
{
"path": "packages/intellij-plugin/src/main/kotlin/com/ripple_ts/intellij_plugin/RippleLanguageServer.kt",
"chars": 8475,
"preview": "package com.ripple_ts.intellij_plugin\n\nimport com.intellij.execution.configurations.GeneralCommandLine\nimport com.intell"
},
{
"path": "packages/intellij-plugin/src/main/kotlin/com/ripple_ts/intellij_plugin/RippleLspServerDescriptor.kt",
"chars": 762,
"preview": "package com.ripple_ts.intellij_plugin\n\nimport com.intellij.execution.configurations.GeneralCommandLine\nimport com.intell"
},
{
"path": "packages/intellij-plugin/src/main/kotlin/com/ripple_ts/intellij_plugin/RippleLspServerSupportProvider.kt",
"chars": 615,
"preview": "package com.ripple_ts.intellij_plugin\n\nimport com.intellij.openapi.project.Project\nimport com.intellij.openapi.vfs.Virtu"
},
{
"path": "packages/intellij-plugin/src/main/kotlin/com/ripple_ts/intellij_plugin/RippleTextMateBundleProvider.kt",
"chars": 4175,
"preview": "package com.ripple_ts.intellij_plugin\n\nimport com.intellij.ide.plugins.PluginManagerCore\nimport com.intellij.openapi.app"
},
{
"path": "packages/intellij-plugin/src/main/resources/META-INF/plugin.xml",
"chars": 2381,
"preview": "<!-- Plugin Configuration File: https://plugins.jetbrains.com/docs/intellij/plugin-configuration-file.html -->\n<idea-plu"
},
{
"path": "packages/intellij-plugin/src/main/resources/META-INF/ripple-lsp.xml",
"chars": 210,
"preview": "<idea-plugin>\n\t<extensions defaultExtensionNs=\"com.intellij.platform.lsp\">\n\t\t<serverSupportProvider implementation=\"com."
},
{
"path": "packages/intellij-plugin/src/main/resources/lsp-version.txt",
"chars": 8,
"preview": "0.2.208\n"
},
{
"path": "packages/language-server/CHANGELOG.md",
"chars": 3194,
"preview": "# @ripple-ts/language-server\n\n## 0.3.3\n\n### Patch Changes\n\n- Updated dependencies []:\n - @ripple-ts/typescript-plugin@0"
}
]
// ... and 533 more files (download for full content)
About this extraction
This page contains the full source code of the Ripple-TS/ripple GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 733 files (29.1 MB), approximately 2.6M tokens, and a symbol index with 2064 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.