diff --git a/README.md b/README.md
index 25fe1db7e2..9ed3c8814c 100644
--- a/README.md
+++ b/README.md
@@ -119,7 +119,7 @@ Add this code to your page:
- [Client-side!](https://livecodes.io/docs/why#client-side)
- Very [configurable](https://livecodes.io/docs/configuration/)
- Developer-friendly build-free environment
-- Powerful [SDK](https://livecodes.io/docs/sdk/) (available for [vanilla JavaScript, TypeScript](https://livecodes.io/docs/sdk/js-ts), [React](https://livecodes.io/docs/sdk/react), [Vue](https://livecodes.io/docs/sdk/vue), [Svelte](https://livecodes.io/docs/sdk/svelte) and [Solid](https://livecodes.io/docs/sdk/solid))
+- Powerful [SDK](https://livecodes.io/docs/sdk/) (available for [vanilla JavaScript, TypeScript](https://livecodes.io/docs/sdk/js-ts), [React](https://livecodes.io/docs/sdk/react), [Vue](https://livecodes.io/docs/sdk/vue), [Svelte](https://livecodes.io/docs/sdk/svelte), [Solid](https://livecodes.io/docs/sdk/solid) and [Ripple](https://livecodes.io/docs/sdk/ripple))
- Comprehensive [Documentations](https://livecodes.io/docs/)
- Focused on [privacy and security](https://livecodes.io/docs/features/security)
- Free and [Open-Source](https://livecodes.io/docs/license)
@@ -156,7 +156,7 @@ createPlayground('#container', {
});
```
-The [JavaScript SDK](https://livecodes.io/docs/sdk/js-ts) is framework/library agnostic. However, wrapper components are also provided for popular libraries (currently [React](https://livecodes.io/docs/sdk/react) and [Vue](https://livecodes.io/docs/sdk/vue)). The SDK can be used in [Svelte](https://livecodes.io/docs/sdk/svelte) and [Solid](https://livecodes.io/docs/sdk/solid) directly without wrappers. [TypeScript support](https://livecodes.io/docs/sdk/js-ts#typescript-types) provides type-safety and a great developer experience.
+The [JavaScript SDK](https://livecodes.io/docs/sdk/js-ts) is framework/library agnostic. However, wrapper components are also provided for popular libraries (currently [React](https://livecodes.io/docs/sdk/react) and [Vue](https://livecodes.io/docs/sdk/vue)). The SDK can be used in [Svelte](https://livecodes.io/docs/sdk/svelte), [Solid](https://livecodes.io/docs/sdk/solid) and [Ripple](https://livecodes.io/docs/sdk/ripple) directly without wrappers. [TypeScript support](https://livecodes.io/docs/sdk/js-ts#typescript-types) provides type-safety and a great developer experience.
React SDK example: ([open in LiveCodes](https://livecodes.io/?x=code/N4IgLglmA2CmIC4QBkIDdYGED2ATWAzgAQBKsAhgMZhEDKAIgNJH4C22IANCPgZQE4QADpGwA7RCC4gAFhVySAPK1hhyRSjPL8CqgLwAdEAFUAKgDEAtAA4jRAPQA+A2OWr1Y8isMg0EWADuQtj8YHaU4mCwYmA+ARC4YDJ6+H6UsJbxiTKcRBBiUBDk0JZ8xbB6AIwAdAAMdk7SMmCs0ACCYGA6ktDkYgDmPtHhvQQEPkbSav0EiADaALrcVJAYAKK4UCGSfIIi0qzaANYArkKIoL0DJ+T98EjNrdIRMdFgkiAAvtwEYACecAuICu-Rud0klDGz0ibw+3xAu2E7wQlz6oNu9xAACsCAAPaGvGKSCCsYKhIioDA4XhEABm-GwrCIAHJoOhYBFePZ+BRqMyANwGfguIUuF6-DTiWkQfpEPREYCisREIiHfinIQIBVKlUqkFg2Ba5lqo64bABMTMzg63UvKIxI0AYiIAAlYNBoNgiAB1ELQXAAQitNu+Ss+guFYnFNAACr0-v0GScxLg5UQABQASjljiIikpWDwhElYmlg2ALzLnyIfkCPh5BBO0DCIAcjgjLlguLJNHwtPITdj8cT2GTuA7EnhvwBhDkqlmCEWPwESIXS5AkIIMYbqg+3CEDPSYxCa6WG5Ov0ZtFUkAGC+A8JJPfv8P+QkIF1fhDA9+BaINkhvoQK77NwdqwkgXzcBgOgQOIkgAMwIVM2DYNAv7ROQABGcAKEgxTQNIKzshC4gEGh8A-GoYAXhCnq6AonyfEAA))
diff --git a/docs/docs/languages/ripple.mdx b/docs/docs/languages/ripple.mdx
new file mode 100644
index 0000000000..0d20e38610
--- /dev/null
+++ b/docs/docs/languages/ripple.mdx
@@ -0,0 +1,439 @@
+---
+toc_max_heading_level: 4
+---
+
+# Ripple
+
+[Ripple](https://www.ripplejs.com/) is a TypeScript UI framework that takes the best parts of React, Solid and Svelte and combines them into one package.
+
+Ripple components can be used in LiveCodes as documented in the [Ripple docs](https://github.com/trueadm/ripple). See below for usage.
+
+## Demo
+
+import LiveCodes from '../../src/components/LiveCodes.tsx';
+import RunInLiveCodes from '../../src/components/RunInLiveCodes.tsx';
+
+export const demo = {
+ activeEditor: 'script',
+ script: {
+ language: 'ripple',
+ content: `import { track } from 'ripple';
+
+export default component Counter() {
+ let count = track(0);
+ let doubled = track(() => @count * 2);
+
+
+
{'Counter'}
+
{\`Count: \${@count}\`}
+
{\`Doubled: \${@doubled}\`}
+
+
+
+
+
+
+}`,
+ },
+}
+
+
+
+
+## Mounting
+
+### Auto-rendering
+
+A component is mounted and rendered automatically as a Ripple component (without having to [manually mount](#manual-mount) it) if the following conditions are met:
+
+- The component is exported as the default export.
+- No [imports from `"./script"`](#exports) in markup editor.
+- Auto-rendering is not [disabled](#disabling-auto-rendering).
+
+### Root Element
+
+To mount the application instance to a specific DOM element use `"livecodes-app"` as the element `id` in the HTML. Otherwise, if that element is not found, a new `div` element is added to `document.body` and is used to mount the instance.
+In case you need more control, you can [manually mount](#manual-mount) the instance.
+
+Example:
+
+export const customRoot = {
+ markup: {
+ language: 'html',
+ content: `
Custom Root Element
+
+
...other page content
+`,
+ },
+ script: {
+ language: 'ripple',
+ content: `import { track } from 'ripple';
+
+export default component App() {
+ let name = track('Ripple');
+
{\`I'm a \${@name} component\`}
+
+}
+`,
+ },
+};
+
+
+
+
+### Manual Mount
+
+Exports from Ripple code can be imported in [markup editor](../features/projects.mdx#markup-editor) from `"./Component.ripple"` and used to mount the application instance manually.
+See [Exports](#exports) for details.
+
+Example:
+
+export const manualMount = {
+ markup: {
+ language: 'html',
+ content: `
+
+}
+`,
+ },
+};
+
+
+
+### Disabling Auto-rendering
+
+To disable [auto-rendering](#auto-rendering), set the [custom settings](#custom-settings) `disableAutoRender` property to `true`.
+
+```json title="Custom Settings"
+{
+ "ripple": {
+ "disableAutoRender": true
+ }
+}
+```
+
+## Importing Modules
+
+### NPM Modules
+
+npm modules can be imported as described in the section about [module resolution](../features/module-resolution.mdx), including bare module imports and importing from different CDNs. Stylesheets imported in the `script` block are added as `` tags in the page `head` (see [below](#importing-stylesheets)).
+
+Module imports can be customized using import maps as described in [module resolution](../features/module-resolution.mdx#custom-module-resolution) documentations.
+
+Example:
+
+export const importsDemo = {
+ ripple: `import { track, effect } from "ripple";
+import confetti from "canvas-confetti";
+
+export default component App() {
+
+ let count = track(0);
+
+ effect(() => {
+ if (@count === 2) confetti();
+ });
+
+
+
+ if (@count > 1) {
+
{'Greater than 1!'}
+ }
+
+
+
+}
+`,
+};
+
+
+
+### External Components
+
+External Ripple components can be imported.
+The import URL can be either:
+- An absolute URL ending with `.ripple` extension.
+- A [bare module import](../features/module-resolution.mdx#bare-module-imports) for a published npm module with full path to the component with extension.
+- A [data URL](../features/data-urls.mdx) starting with `data:text/ripple`.
+
+Any bare or relative imports in the imported files are resolved and compiled recursively.
+If a processor is enabled (e.g. Tailwind CSS), classes in the imported files are detected and used in the generated CSS (see [CSS Frameworks](#css-frameworks) section below).
+
+Example: ([source](https://github.com/hatemhosny/ripple-tailwind-counter-demo))
+
+export const externalComponents = {
+ activeEditor: 'script',
+ script: {
+ language: 'ripple',
+ content: `// import from npm modules
+import { track } from 'ripple';
+import { Counter } from 'ripple-tailwind-counter-demo/src/Counter.ripple';
+// alternatively use absolute URLs
+// import { Counter } from 'https://raw.githubusercontent.com/hatemhosny/ripple-tailwind-counter-demo/refs/heads/main/src/Counter.ripple';
+
+export default component App() {
+ let name = track("World");
+
+ setTimeout(() => {
+ @name = "Ripple + Tailwind!";
+ }, 2000);
+
+
+}
+`,
+ },
+ processors: ['tailwindcss'],
+}
+
+
+
+### Exports
+
+Values exported from [script editor](../features/projects.mdx#script-editor) (default or named) can be imported in the [markup editor](../features/projects.mdx#markup-editor) by importing from `"./script"` (with no extension).
+
+This can be useful, for example, for [manually mounting](#manual-mount) components in the markup editor.
+
+:::info note
+
+When values are imported from `"./script"`, [auto-rendering](#auto-rendering) is disabled, because it is assumed that you want to take control over component rendering.
+
+:::
+
+## Styles
+
+CSS can be applied to the component using various ways:
+
+### Component Styles
+
+Styles in a `style` tag in a Ripple component are applied to that component only.
+
+CSS processors (e.g. SCSS, Stylus) can be used by specifying a `lang` attribute for the `style` tag.
+
+Example:
+
+export const styleTag = {
+ ripple: `export default component App() {
+
{'Hello World!'}
+
+
+}
+`
+}
+
+
+
+
+### Style Editor
+
+Styles added in the [style editor](../features/projects.mdx#style-editor) are applied globally to the [result page](../features/result.mdx). This can use different **languages/processors** supported in LiveCodes including CSS, SCSS, Less, Stylus, ..etc. See [style documentation](../features/css.mdx) for more details.
+
+And of course, styles and stylesheets added in [markup editor](../features/projects.mdx#markup-editor) are also applied globally.
+
+### Importing Stylesheets
+
+Stylesheets imported in [script editor](../features/projects.mdx#script-editor) are added as `` tags in the page `head`.
+The stylesheet URL can be an absolute URL or a path in the npm package. The URL has to end with `".css"`.
+
+example:
+
+export const stylesDemo = {
+ ripple: `import "bootstrap/dist/css/bootstrap.css";\n\nexport default component App() {\n
{'Hello World!'}
\n}\n`,
+};
+
+
+
+### CSS Modules
+
+CSS modules are supported and are [documented separately](./cssmodules.mdx). Make sure to enable CSS modules (from style editor menu or in [`processors`](../configuration/configuration-object.mdx#processors) property of [configuration object](../configuration/configuration-object.mdx)).
+
+Demo:
+
+export const cssModulesDemo = {
+ activeEditor: 'script',
+ style: { language: 'css', content: `.title {\n color: green;\n font-family: sans-serif;\n}\n` },
+ script: {
+ language: 'ripple',
+ content: `import classes from './style.module.css';\n\nexport default component() {\n
\n {'Hello, CSS Modules!'}\n
\n}\n`,
+ },
+ processors: ['cssmodules'],
+};
+
+
+
+### CSS Frameworks
+
+[CSS Frameworks](../features/css.mdx#css-processors) supported in LiveCodes (e.g. [Tailwind CSS](./tailwindcss.mdx), [UnoCSS](./unocss.mdx), [WindiCSS](./windicss.mdx)) can detect class names added in Ripple components.
+Make sure that the required utility is enabled (from style editor menu or in `processors` property of [configuration object](../configuration/configuration-object.mdx#processors)).
+
+Example:
+
+export const tailwindDemo = {
+ activeEditor: 'script',
+ script: {
+ language: 'ripple',
+ content: `import { track } from 'ripple';
+
+export default component Counter() {
+ let count = track(0);
+
+
+
{'Ripple + Tailwind CSS'}
+
+
+ {@count}
+
+
+
+
+
+
+}
+`,
+ },
+ processors: ['tailwindcss'],
+};
+
+
+
+## Language Info
+
+### Name
+
+`ripple`
+
+### Extensions
+
+`.ripple`
+
+### Editor
+
+`script`
+
+## Compiler
+
+The official [Ripple compiler](https://github.com/trueadm/ripple).
+
+### Version
+
+`ripple`: v0.2.15
+
+## Code Formatting
+
+Using [Prettier](https://prettier.io/).
+
+## Custom Settings
+
+[Custom settings](../advanced/custom-settings.mdx) can be added to the property `ripple`.
+These include:
+
+- `"disableAutoRender"` - [disables auto-rendering](#disabling-auto-rendering) (default: `false`).
+- `"version"` - specifies the version of Ripple compiler (default: `"latest"`).
+
+Example:
+
+```json title="Custom Settings"
+{
+ "ripple": {
+ "version": "0.2.15"
+ }
+}
+```
+
+Please note that custom settings should be valid JSON (i.e. functions are not allowed).
+
+## Starter Template
+
+https://livecodes.io/?template=ripple
+
+
+
+## Links
+
+- [Ripple](https://ripplejs.com/)
+- [Ripple documentations](https://github.com/trueadm/ripple)
diff --git a/docs/docs/sdk/index.mdx b/docs/docs/sdk/index.mdx
index db5b604aef..e1e6a53b36 100644
--- a/docs/docs/sdk/index.mdx
+++ b/docs/docs/sdk/index.mdx
@@ -10,7 +10,7 @@ The Software Development Kit (SDK) provides an easy, yet powerful, interface to
The SDK is provided as a light-weight ([less than 5kb gzipped](https://bundlephobia.com/package/livecodes)), zero-dependencies [npm package](#npm-package), that is also available from [CDNs](#cdn). It can be used to create playgrounds with a wide variety of [configurations](../configuration/configuration-object.mdx) and [embed options](js-ts.mdx#embed-options). In addition, [SDK methods](js-ts.mdx#sdk-methods) allow programmatic communication and control of the playgrounds during runtime.
-The [JavaScript SDK](js-ts.mdx) is framework/library agnostic. However, wrapper components are also provided for popular libraries (currently [React](react.mdx) and [Vue](vue.mdx)). The SDK can be used in [Svelte](svelte.mdx) and [Solid](solid.mdx) directly without wrappers. [TypeScript support](js-ts.mdx#typescript-types) provides type-safety and a great developer experience.
+The [JavaScript SDK](js-ts.mdx) is framework/library agnostic. However, wrapper components are also provided for popular libraries (currently [React](react.mdx) and [Vue](vue.mdx)). The SDK can be used in [Svelte](svelte.mdx), [Solid](solid.mdx) and [Ripple](ripple.mdx) directly without wrappers. [TypeScript support](js-ts.mdx#typescript-types) provides type-safety and a great developer experience.
## SDK Demo
@@ -99,14 +99,11 @@ In the full [standalone app](../getting-started.mdx#standalone-app), the JavaScr
The SDK is currently provided in the following variations:
- [JavaScript/TypeScript](./js-ts.mdx)
-
- [React](./react.mdx)
-
- [Vue](./vue.mdx)
-
- [Svelte](./svelte.mdx)
-
- [Solid](./solid.mdx)
+- [Ripple](./ripple.mdx)
## Headless Mode
diff --git a/docs/docs/sdk/js-ts.mdx b/docs/docs/sdk/js-ts.mdx
index 1eb4ef14f4..4c12e7b659 100644
--- a/docs/docs/sdk/js-ts.mdx
+++ b/docs/docs/sdk/js-ts.mdx
@@ -602,4 +602,5 @@ export const sdkDemo = {
- [React SDK](./react.mdx)
- [Vue SDK](./vue.mdx)
- [Using SDK in Svelte](./svelte.mdx)
+- [Using SDK in Ripple](./ripple.mdx)
- [Embedded Playgrounds](../features/embeds.mdx)
diff --git a/docs/docs/sdk/react.mdx b/docs/docs/sdk/react.mdx
index ef8177c3ea..1c54af2d5d 100644
--- a/docs/docs/sdk/react.mdx
+++ b/docs/docs/sdk/react.mdx
@@ -149,4 +149,5 @@ export const reactSDKDemo = {
- [Vue SDK](./vue.mdx)
- [Using SDK in Svelte](./svelte.mdx)
- [Using SDK in Solid](./solid.mdx)
+- [Using SDK in Ripple](./ripple.mdx)
- [Embedded Playgrounds](../features/embeds.mdx)
diff --git a/docs/docs/sdk/ripple.mdx b/docs/docs/sdk/ripple.mdx
new file mode 100644
index 0000000000..cb42b14e5c
--- /dev/null
+++ b/docs/docs/sdk/ripple.mdx
@@ -0,0 +1,82 @@
+# Ripple
+
+import LiveCodes from '../../src/components/LiveCodes.tsx';
+import RunInLiveCodes from '../../src/components/RunInLiveCodes.tsx';
+
+The [JS/TS SDK](js-ts.mdx) can be used directly in [Ripple](https://ripplejs.com) components without the need for any wrappers.
+
+## Installation
+
+Please refer to the [SDK installation](./index.mdx#installation) section.
+
+## Usage
+
+This is an example of using the LiveCodes JS SDK in a Ripple component:
+
+```jsx title="App.ripple"
+import { createPlayground, type EmbedOptions, type Playground } from 'livecodes';
+
+export default component App() {
+ const options: EmbedOptions = {
+ params: {
+ html: '
+ >
+}
+`;
+ expect(await compileBlocks(code, 'style', config)).toBe(code);
+ });
+
+ test('does not take a tag inside a comment for a block', async () => {
+ const code = `
+// A ;
+export function App() @{
+ <>
+
+