Skip to content

Conversation

@hatemhosny
Copy link
Collaborator

@hatemhosny hatemhosny commented Aug 30, 2025

What type of PR is this? (check all applicable)

  • ✨ Feature

Description

This PR adds initial support for the new JS framework: Ripple

Docs: https://ripple.livecodes.pages.dev/docs/languages/ripple/

Related Tickets & Documents

See Ripple-TS/ripple#9

Demo

https://ripple.livecodes.pages.dev/?x=id/m2i8xe7ixdt

image

TODO

  • Syntax highlighting
    • Monaco
    • CodeMirror
  • change compiler version in runtime
  • Editor intellisesne
  • Re-use TypeScript compiler
  • Add docs
  • Add starter template
  • Formatter?

Summary by CodeRabbit

  • New Features

    • Added Ripple language support: live preview, auto-mount runtime, formatting, and compilation.
    • Monaco editor syntax highlighting for Ripple via TextMate.
    • New Ripple starter template, added to templates list, command menu, and sliders.
    • Language info panel updated with Ripple details and quick links.
  • Improvements

    • Formatter now accepts configuration and supports optional post-format processing.
  • Documentation

    • New Ripple language guide and added translations/language info entries.
  • Chores

    • Included vendor URLs/assets for grammars and formatting plugins.

@netlify
Copy link

netlify bot commented Aug 30, 2025

Deploy Preview for livecodes ready!

Name Link
🔨 Latest commit 7a6fe48
🔍 Latest deploy log https://app.netlify.com/projects/livecodes/deploys/68e6d620cb123c00080a2c4c
😎 Deploy Preview https://deploy-preview-865--livecodes.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai
Copy link

coderabbitai bot commented Aug 30, 2025

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

Adds Ripple language support across the codebase: language registration, Monaco TextMate wiring, formatter and compiler factories/workers with dynamic version resolution, runtime bootstrap, vendor URLs, starter template, docs and i18n, formatter/init payload/config threading, import-map tweak, and build entries.

Changes

Cohort / File(s) Summary of Changes
Language registration & runtime mapping
src/livecodes/languages/languages.ts, src/livecodes/languages/ripple/index.ts, src/livecodes/languages/ripple/lang-ripple.ts, src/livecodes/languages/ripple/ripple-runtime.ts, src/livecodes/result/result-page.ts
Register Ripple; add barrel export; add ripple: LanguageSpecs with worker-based formatter/compiler factories; add ripple runtime bootstrap and map it in JSX runtimes.
Ripple compiler & formatter modules
src/livecodes/languages/ripple/lang-ripple-compiler.ts, src/livecodes/languages/ripple/lang-ripple-formatter.ts
Add global async factories createRippleCompiler and createRippleFormatter; dynamic version resolution and dynamic imports for compiler and Prettier plugin; CSS injection and import-map creation on compile; formatter uses Prettier ESM + plugin.
Formatter worker / pipeline & APIs
src/livecodes/formatter/format.worker.ts, src/livecodes/formatter/formatter.ts, src/livecodes/formatter/get-formatter.ts, src/livecodes/formatter/models.ts, src/sdk/models.ts
Thread Config through formatter init; init payload nested as { payload: { baseUrl, config } }; loadParser/loadFormatter are async and use config; dynamic plugin loading (ripple via dynamic import, others via importScripts); optional parser.postFormat hook; LanguageFormatter factory signature extended; ParserName/TemplateName include ripple; CDNService adds getPkgLatestVersion.
Monaco editor TextMate integration
src/livecodes/editor/monaco/monaco.ts, scripts/build.js, eslint.config.mjs, typos.toml
Add Monaco custom language entry for Ripple; runtime TextMate wiring using onigasm/monaco-textmate; build entries for Monaco language and Ripple formatter/compiler workers; ESLint/typo ignores updated for generated Monaco file.
Vendors / external URLs
src/livecodes/vendors.ts, scripts/build.js
Add URLs/constants for monaco-editor-textmate, monaco-textmate, onigasm (+ WASM), prettier ESM, and prettier-plugin-ripple; include Ripple build entry points.
Starter templates, UI, docs, i18n
src/livecodes/templates/starter/ripple-starter.ts, src/livecodes/templates/starter/index.ts, src/livecodes/UI/command-menu-actions.ts, docs/docs/languages/ripple.mdx, docs/src/components/LanguageSliders.tsx, docs/src/components/TemplateList.tsx, src/livecodes/html/language-info.html, src/livecodes/i18n/locales/en/translation.lokalise.json, src/livecodes/i18n/locales/en/translation.ts, src/livecodes/i18n/locales/en/language-info.lokalise.json, src/livecodes/i18n/locales/en/language-info.ts
Add Ripple starter template and register it in templates/UI; add documentation page; add language info HTML and English locale entries; add Ripple to language sliders and template list.
Compiler import-map tweak
src/livecodes/compiler/import-map.ts
Add isStyleImport and exclude style imports from SFC import collection in replaceSFCImports.
CDN/package info service
src/livecodes/services/pkgInfo.ts
Add getPkgLatestVersion(pkgName: string): Promise<string> and export it via pkgInfoService.
Docs/tooling config
docs/docusaurus.config.ts, eslint.config.mjs, typos.toml
Add skipErrorChecking: true for typedoc; ignore new generated Monaco file in ESLint and typo checks.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant App as Caller
  participant Formatter as Formatter (main)
  participant Worker as Format Worker
  participant Prettier as Prettier+Plugins
  note over App,Worker: Initialization
  App->>Formatter: createFormatter(baseUrl, config)
  Formatter->>Worker: postMessage({type:'init', payload:{baseUrl, config}})
  Worker-->>Formatter: ack

  note over App,Prettier: Format request (ripple)
  App->>Formatter: format(code, {language:'ripple', cursorOffset})
  Formatter->>Worker: postMessage({type:'format', ...})
  Worker->>Worker: loadParser('ripple') (async)
  alt Ripple path
    Worker->>Prettier: dynamic import(prettier ESM) & plugin
    Worker-->>Worker: parser with plugins
  else Other languages
    Worker->>Prettier: importScripts plugin URLs
  end
  Worker->>Prettier: formatWithCursor(code, options)
  alt parser.postFormat present
    Worker->>Worker: await parser.postFormat(result)
  end
  Worker-->>Formatter: {formatted, cursorOffset}
  Formatter-->>App: result
Loading
sequenceDiagram
  autonumber
  participant Runner as Result Page
  participant RippleRT as rippleRuntime
  participant AppMod as Compiled App Module
  participant Compiler as Ripple Compiler Factory
  participant CDN as pkgInfo/modulesService
  note over Runner,RippleRT: Load runtime for script.language='ripple'
  Runner->>RippleRT: evaluate rippleRuntime
  RippleRT->>Runner: select mount target (#livecodes-app or new div)
  RippleRT->>AppMod: import "./script" (built output)
  activate AppMod
  AppMod->>Compiler: request compile (worker)
  Compiler->>CDN: getPkgLatestVersion('ripple') (if needed)
  Compiler->>CDN: dynamic import ripple@<ver>/compiler
  Compiler-->>AppMod: compiled JS/CSS + import-map info
  AppMod-->>RippleRT: default export (component)
  RippleRT->>Runner: mount(App, target)
  deactivate AppMod
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

I twitch my ears at Ripple’s light,
New grammars hum in Monaco night.
A formatter hops, compiles with care,
Imports mapped and styles in air.
Templates bloom — thump, ship it! 🐇✨

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title succinctly describes the primary change—adding support for Ripple—and directly relates to the contents of the pull request.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Contributor

github-actions bot commented Aug 30, 2025

Size Change: +36 kB (+3.76%)

Total Size: 992 kB

Filename Size Change
./build/livecodes/headless.js 78.5 kB +248 B (+0.32%)
./build/livecodes/monaco.js 10.5 kB +341 B (+3.37%)
./build/livecodes/lang-ripple-compiler.js 5.64 kB +5.64 kB (new file) 🆕
./build/livecodes/lang-ripple-formatter.js 3.03 kB +3.03 kB (new file) 🆕
./build/livecodes/monaco-lang-ripple.js 25.9 kB +25.9 kB (new file) 🆕
ℹ️ View Unchanged
Filename Size Change
./build/404.html 1 kB 0 B
./build/app.html 250 B 0 B
./build/index.html 2.46 kB +1 B (+0.04%)
./build/livecodes/app.css 22.4 kB 0 B
./build/livecodes/app.js 111 kB +155 B (+0.14%)
./build/livecodes/assets.js 8.62 kB -15 B (-0.17%)
./build/livecodes/assets/noop.js 18 B 0 B
./build/livecodes/assets/templates/diagrams-starter.html 2.19 kB 0 B
./build/livecodes/backup.js 3.73 kB -1 B (-0.03%)
./build/livecodes/blockly.js 13.3 kB -11 B (-0.08%)
./build/livecodes/broadcast.js 1.19 kB 0 B
./build/livecodes/bundle-types.js 4.37 kB -5 B (-0.11%)
./build/livecodes/code-to-image.js 9.1 kB +10 B (+0.11%)
./build/livecodes/codejar.js 17.6 kB -38 B (-0.22%)
./build/livecodes/codemirror.js 6.35 kB +21 B (+0.33%)
./build/livecodes/compile.page.js 2.4 kB +9 B (+0.38%)
./build/livecodes/compile.worker.js 14.4 kB +106 B (+0.74%)
./build/livecodes/compiler-utils.js 3.18 kB -2 B (-0.06%)
./build/livecodes/custom-editor-utils.js 198 B 0 B
./build/livecodes/deploy.js 6.89 kB +20 B (+0.29%)
./build/livecodes/editor-settings.js 17.7 kB -29 B (-0.16%)
./build/livecodes/embed-ui.js 5.54 kB +6 B (+0.11%)
./build/livecodes/embed.js 89.7 kB +128 B (+0.14%)
./build/livecodes/export.js 3.89 kB -1 B (-0.03%)
./build/livecodes/firebase.js 22.7 kB 0 B
./build/livecodes/format.worker.js 13.5 kB +136 B (+1.02%)
./build/livecodes/google-fonts.js 7.12 kB 0 B
./build/livecodes/i18n-ar-language-info.json 5.23 kB 0 B
./build/livecodes/i18n-ar-translation.json 9.33 kB 0 B
./build/livecodes/i18n-de-language-info.json 5.25 kB 0 B
./build/livecodes/i18n-de-translation.json 9.44 kB 0 B
./build/livecodes/i18n-en-language-info.json 4.56 kB +36 B (+0.8%)
./build/livecodes/i18n-en-translation.json 8.04 kB +9 B (+0.11%)
./build/livecodes/i18n-es-language-info.json 5 kB 0 B
./build/livecodes/i18n-es-translation.json 9.17 kB 0 B
./build/livecodes/i18n-fa-language-info.json 5.35 kB 0 B
./build/livecodes/i18n-fa-translation.json 9.48 kB 0 B
./build/livecodes/i18n-fr-language-info.json 5.17 kB 0 B
./build/livecodes/i18n-fr-translation.json 9.42 kB 0 B
./build/livecodes/i18n-hi-language-info.json 5.78 kB 0 B
./build/livecodes/i18n-hi-translation.json 9.95 kB 0 B
./build/livecodes/i18n-it-language-info.json 5.04 kB 0 B
./build/livecodes/i18n-it-translation.json 9.26 kB 0 B
./build/livecodes/i18n-ja-language-info.json 5.57 kB 0 B
./build/livecodes/i18n-ja-translation.json 9.61 kB 0 B
./build/livecodes/i18n-pt-language-info.json 5.05 kB 0 B
./build/livecodes/i18n-pt-translation.json 9.35 kB 0 B
./build/livecodes/i18n-ru-language-info.json 5.56 kB 0 B
./build/livecodes/i18n-ru-translation.json 10.3 kB 0 B
./build/livecodes/i18n-ur-language-info.json 5.81 kB 0 B
./build/livecodes/i18n-ur-translation.json 9.78 kB 0 B
./build/livecodes/i18n-zh-CN-language-info.json 4.9 kB 0 B
./build/livecodes/i18n-zh-CN-translation.json 8.64 kB 0 B
./build/livecodes/i18n.js 20.2 kB -15 B (-0.07%)
./build/livecodes/import-src.js 16 kB -5 B (-0.03%)
./build/livecodes/import.js 14.5 kB +10 B (+0.07%)
./build/livecodes/index.js 5.35 kB 0 B
./build/livecodes/lang-art-template-compiler.js 1.65 kB 0 B
./build/livecodes/lang-assemblyscript-compiler.js 290 B 0 B
./build/livecodes/lang-assemblyscript-script.js 386 B 0 B
./build/livecodes/lang-astro-compiler.js 2.34 kB +2 B (+0.09%)
./build/livecodes/lang-clio-compiler.js 1.55 kB 0 B
./build/livecodes/lang-commonlisp-script.js 123 B 0 B
./build/livecodes/lang-cpp-script.js 1.75 kB 0 B
./build/livecodes/lang-cpp-wasm-script.js 2.84 kB 0 B
./build/livecodes/lang-csharp-wasm-script.js 2.18 kB +1 B (+0.05%)
./build/livecodes/lang-diagrams-compiler-esm.js 5.09 kB 0 B
./build/livecodes/lang-dot-compiler.js 1.66 kB 0 B
./build/livecodes/lang-ejs-compiler.js 1.63 kB 0 B
./build/livecodes/lang-eta-compiler.js 1.65 kB 0 B
./build/livecodes/lang-fennel-compiler.js 1.61 kB 0 B
./build/livecodes/lang-gleam-compiler.js 3.09 kB 0 B
./build/livecodes/lang-go-wasm-script.js 3.26 kB 0 B
./build/livecodes/lang-haml-compiler.js 1.65 kB 0 B
./build/livecodes/lang-handlebars-compiler.js 1.92 kB 0 B
./build/livecodes/lang-imba-compiler.js 147 B 0 B
./build/livecodes/lang-java-script.js 4.05 kB 0 B
./build/livecodes/lang-jinja-compiler.js 1.65 kB 0 B
./build/livecodes/lang-julia-script.js 3.3 kB 0 B
./build/livecodes/lang-liquid-compiler.js 1.68 kB 0 B
./build/livecodes/lang-lua-wasm-script.js 205 B 0 B
./build/livecodes/lang-malina-compiler.js 2.96 kB +3 B (+0.1%)
./build/livecodes/lang-mustache-compiler.js 1.65 kB 0 B
./build/livecodes/lang-nunjucks-compiler.js 1.93 kB +6 B (+0.31%)
./build/livecodes/lang-perl-script.js 268 B 0 B
./build/livecodes/lang-php-wasm-script.js 347 B 0 B
./build/livecodes/lang-postgresql-compiler-esm.js 1.73 kB 0 B
./build/livecodes/lang-prolog-script.js 204 B 0 B
./build/livecodes/lang-pug-compiler.js 371 B 0 B
./build/livecodes/lang-python-wasm-script.js 1.86 kB 0 B
./build/livecodes/lang-r-script-esm.js 2.43 kB -4 B (-0.16%)
./build/livecodes/lang-rescript-compiler-esm.js 2.16 kB +1 B (+0.05%)
./build/livecodes/lang-rescript-formatter.js 1.52 kB 0 B
./build/livecodes/lang-riot-compiler.js 2.81 kB 0 B
./build/livecodes/lang-ruby-wasm-script.js 1.71 kB 0 B
./build/livecodes/lang-scss-compiler.js 1.71 kB 0 B
./build/livecodes/lang-solid-compiler.js 263 B 0 B
./build/livecodes/lang-sql-compiler.js 1.63 kB -9 B (-0.55%)
./build/livecodes/lang-sql-script.js 1.96 kB +11 B (+0.56%)
./build/livecodes/lang-svelte-compiler.js 4.71 kB +26 B (+0.55%)
./build/livecodes/lang-tcl-script.js 1.82 kB 0 B
./build/livecodes/lang-teal-compiler.js 1.72 kB 0 B
./build/livecodes/lang-twig-compiler.js 1.64 kB 0 B
./build/livecodes/lang-vento-compiler.js 1.68 kB 0 B
./build/livecodes/lang-vue-compiler.js 6.14 kB +51 B (+0.84%)
./build/livecodes/lang-vue2-compiler.js 3.47 kB 0 B
./build/livecodes/lang-wat-compiler.js 348 B 0 B
./build/livecodes/lang-wat-script.js 1.58 kB -1 B (-0.06%)
./build/livecodes/language-info.js 7.77 kB +58 B (+0.75%)
./build/livecodes/monaco-lang-astro.js 947 B 0 B
./build/livecodes/monaco-lang-clio.js 639 B 0 B
./build/livecodes/monaco-lang-imba.js 7.35 kB 0 B
./build/livecodes/monaco-lang-wat.js 2.46 kB 0 B
./build/livecodes/open.js 6.2 kB +4 B (+0.06%)
./build/livecodes/processor-lightningcss-compiler.js 1.88 kB 0 B
./build/livecodes/processor-postcss-compiler.js 2.02 kB -2 B (-0.1%)
./build/livecodes/processor-tailwindcss-compiler.js 5.2 kB +13 B (+0.25%)
./build/livecodes/processor-unocss-compiler.js 355 B 0 B
./build/livecodes/processor-windicss-compiler.js 450 B 0 B
./build/livecodes/quill.css 697 B 0 B
./build/livecodes/quill.js 5.76 kB +1 B (+0.02%)
./build/livecodes/resources.js 3.48 kB +47 B (+1.37%)
./build/livecodes/result-utils.js 1.17 kB 0 B
./build/livecodes/share.js 3.81 kB 0 B
./build/livecodes/snippets.js 6.05 kB -8 B (-0.13%)
./build/livecodes/sync-ui.js 3.25 kB -2 B (-0.06%)
./build/livecodes/sync.js 3.54 kB +16 B (+0.45%)
./build/livecodes/sync.worker.js 29.7 kB -5 B (-0.02%)
./build/livecodes/templates.js 25.5 kB +115 B (+0.45%)
./build/sdk/livecodes.js 3.96 kB 0 B
./build/sdk/livecodes.umd.js 4.02 kB 0 B
./build/sdk/package.json 291 B 0 B
./build/sdk/react.js 4.26 kB 0 B
./build/sdk/vue.js 4.35 kB 0 B

compressed-size-action

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (2)
src/livecodes/languages/ripple/ripple-runtime.ts (1)

6-7: Stabilize mount target element and give it an id.

Creating an anonymous div hinders future queries and can cause multiple roots. Assign an id and reuse it.

(Handled in the diff above by creating/using a single element with id livecodes-app.)

src/livecodes/languages/ripple/lang-ripple.ts (1)

20-25: Deduplicate style injection and avoid innerHTML.

Repeated compiles will accumulate <style> tags and innerHTML is unnecessary. Use a stable id and textContent.

-        const cssCode =
-          css === ''
-            ? ''
-            : `\n\nconst styles = document.createElement('style');\nstyles.innerHTML = ${JSON.stringify(css)};\ndocument.head.appendChild(styles);\n`;
-        return `${js.code}${cssCode}`;
+        const cssCode = css
+          ? `
+const STYLE_ID = 'livecodes-ripple-styles';
+let styles = document.getElementById(STYLE_ID);
+if (!styles) {
+  styles = document.createElement('style');
+  styles.id = STYLE_ID;
+  document.head.appendChild(styles);
+}
+styles.textContent = ${JSON.stringify(css)};`
+          : '';
+        return \`${js.code}\n\n\${cssCode}\`;
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 3586b5e and bb8c04f.

📒 Files selected for processing (7)
  • src/livecodes/languages/languages.ts (2 hunks)
  • src/livecodes/languages/ripple/index.ts (1 hunks)
  • src/livecodes/languages/ripple/lang-ripple.ts (1 hunks)
  • src/livecodes/languages/ripple/ripple-runtime.ts (1 hunks)
  • src/livecodes/result/result-page.ts (3 hunks)
  • src/livecodes/vendors.ts (1 hunks)
  • src/sdk/models.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (3)
src/livecodes/languages/languages.ts (1)
src/livecodes/languages/ripple/lang-ripple.ts (1)
  • ripple (5-31)
src/livecodes/result/result-page.ts (1)
src/livecodes/languages/ripple/ripple-runtime.ts (1)
  • rippleRuntime (1-9)
src/livecodes/languages/ripple/lang-ripple.ts (3)
src/sdk/models.ts (1)
  • LanguageSpecs (1193-1206)
src/livecodes/languages/prettier.ts (1)
  • parserPlugins (4-14)
src/livecodes/vendors.ts (1)
  • rippleUrl (392-392)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (12)
  • GitHub Check: Codacy Static Code Analysis
  • GitHub Check: Redirect rules - livecodes
  • GitHub Check: Header rules - livecodes
  • GitHub Check: Pages changed - livecodes
  • GitHub Check: tests (18.x, 5)
  • GitHub Check: tests (18.x, 3)
  • GitHub Check: tests (18.x, 4)
  • GitHub Check: tests (18.x, 1)
  • GitHub Check: tests (18.x, 2)
  • GitHub Check: build
  • GitHub Check: type-check (18.x)
  • GitHub Check: build (18.x)
🔇 Additional comments (8)
src/livecodes/languages/ripple/index.ts (1)

1-1: Barrel looks good

Re-exports are correct; keeps import sites clean.

src/sdk/models.ts (1)

971-971: Type union update is correct; consider template support when ready

Adding 'ripple' to Language is fine. When the starter template is added (per PR TODO), also add its name to TemplateName.

src/livecodes/languages/languages.ts (2)

62-62: Import is correct and consistent with barrel

No issues.


132-132: Placement in the languages array is fine

Positioned after malina as intended. Make sure docs/i18n entries list Ripple in the same order.

src/livecodes/result/result-page.ts (2)

14-14: Import added correctly

No side effects; matches other runtime imports.


444-450: JSX runtime injection condition remains appropriate

No changes needed; gating on hasDefaultExport, custom runtime, and script-imports aligns with other frameworks.

src/livecodes/languages/ripple/lang-ripple.ts (2)

9-12: Parser config looks reasonable.

Using babel-ts with babel and html plugins is sensible for a first pass.


14-17: Confirm compiler module shape and version.

Assure [email protected]/compiler exposes compile as a named export and supports ESM dynamic import in your environment.

Would you like me to add a quick smoke test that imports rippleUrl and logs Object.keys(module) to validate this?

Comment on lines 17 to 19
return async (code) => {
if (!code.trim()) return '';
const { js, css } = await compile(code, './src/App.ripple');
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Avoid empty module when editor content is blank.

Returning '' yields a module with no exports; the runtime import then fails. Emit a tiny no-op component instead.

-      return async (code) => {
-        if (!code.trim()) return '';
+      return async (code) => {
+        if (!code.trim()) return "export default () => null;";
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
return async (code) => {
if (!code.trim()) return '';
const { js, css } = await compile(code, './src/App.ripple');
return async (code) => {
if (!code.trim()) return "export default () => null;";
const { js, css } = await compile(code, './src/App.ripple');
🤖 Prompt for AI Agents
In src/livecodes/languages/ripple/lang-ripple.ts around lines 17 to 19,
returning an empty string when the editor content is blank produces a module
with no exports and causes runtime import failures; change this to emit a
minimal no-op component module string instead (for example return a JS module
that exports a default no-op component/function or a minimal component export)
so the runtime can import it successfully.

Comment on lines +1 to +9
export const rippleRuntime = `
import { mount } from 'ripple';
import App from "./script";
(() => {
mount(App, {
target: document.querySelector("#livecodes-app") || document.body.appendChild(document.createElement('div')),
});
})();
`;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Make runtime resilient to non-default exports from compiled script.

If the Ripple compiler doesn’t emit a default export, import App from "./script" will throw at runtime. Import the namespace and pick the best candidate.

-export const rippleRuntime = `
-import { mount } from 'ripple';
-import App from "./script";
-(() => {
-  mount(App, {
-    target: document.querySelector("#livecodes-app") || document.body.appendChild(document.createElement('div')),
-  });
-})();
-`;
+export const rippleRuntime = `
+import { mount } from 'ripple';
+import * as AppModule from "./script";
+(() => {
+  const App = AppModule.default || AppModule.App || AppModule;
+  const target =
+    document.querySelector("#livecodes-app") ||
+    (() => { const el = document.createElement('div'); el.id = 'livecodes-app'; return document.body.appendChild(el); })();
+  mount(App, { target });
+})();
+`;

🏁 Script executed:

#!/bin/bash
# List all files under the Ripple language integration directory
fd src/livecodes/languages/ripple -t f

# Locate any compiler or codegen files in that directory
fd compile src/livecodes/languages/ripple -t f

# Search for default export patterns in the ripple language code
rg -n "export default" src/livecodes/languages/ripple

# Search for named export patterns (const/function/class) in the same directory
rg -n "export (const|function|class) " src/livecodes/languages/ripple

Length of output: 812


🏁 Script executed:

#!/bin/bash
sed -n '1,200p' src/livecodes/languages/ripple/ripple-runtime.ts

Length of output: 308


🏁 Script executed:

#!/bin/bash
# Preview the first 200 lines of the Ripple language spec to see how compiled script is generated
sed -n '1,200p' src/livecodes/languages/ripple/lang-ripple.ts

Length of output: 1003


Use namespace import with export fallbacks and assign id="livecodes-app" for a single mount node
Replace the default import with import * as AppModule and pick AppModule.default || AppModule.App || AppModule; when creating the mount container, set its id so subsequent runs reuse it.

File: src/livecodes/languages/ripple/ripple-runtime.ts

-export const rippleRuntime = `
-import { mount } from 'ripple';
-import App from "./script";
-(() => {
-  mount(App, {
-    target: document.querySelector("#livecodes-app") || document.body.appendChild(document.createElement('div')),
-  });
-})();
-`;
+export const rippleRuntime = `
+import { mount } from 'ripple';
+import * as AppModule from "./script";
+(() => {
+  const App = AppModule.default || AppModule.App || AppModule;
+  const target =
+    document.querySelector("#livecodes-app") ||
+    (() => {
+      const el = document.createElement('div');
+      el.id = 'livecodes-app';
+      return document.body.appendChild(el);
+    })();
+  mount(App, { target });
+})();
+`;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const rippleRuntime = `
import { mount } from 'ripple';
import App from "./script";
(() => {
mount(App, {
target: document.querySelector("#livecodes-app") || document.body.appendChild(document.createElement('div')),
});
})();
`;
export const rippleRuntime = `
import { mount } from 'ripple';
import * as AppModule from "./script";
(() => {
const App = AppModule.default || AppModule.App || AppModule;
const target =
document.querySelector("#livecodes-app") ||
(() => {
const el = document.createElement('div');
el.id = 'livecodes-app';
return document.body.appendChild(el);
})();
mount(App, { target });
})();
`;
🤖 Prompt for AI Agents
In src/livecodes/languages/ripple/ripple-runtime.ts around lines 1 to 9, replace
the default import and the mount container creation: import the module as a
namespace (e.g. import * as AppModule from "ripple script path") and select the
component as AppModule.default || AppModule.App || AppModule, and when creating
the mount container ensure you create or reuse an element with
id="livecodes-app" (set id on newly created div and query by that id so
subsequent runs reuse the same mount node).

Comment on lines +214 to 215
ripple: rippleRuntime,
};
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Ensure Ripple runtime dependency is version-pinned in import map

jsxRuntimes.ripple insertion is good, but without a pinned import map entry for "ripple" you risk loading a different runtime than the compiler version. Prefer adding compiler.imports = { ripple: rippleModuleUrl } in the Ripple language spec (see vendors comment) so compilerImports here injects a pinned mapping.


🏁 Script executed:

#!/bin/bash
# Locate the result-page.ts file
FILE=$(fd result-page.ts)
echo "Found file: $FILE"

# Show lines around the snippet (200–240)
sed -n '200,240p' "$FILE"

# Search for any compiler.imports usage across TypeScript files
rg -n "compiler\.imports" -g '*.ts'

# Search for import map or importMap references
rg -n "importMap" -g '*.ts'
rg -n "import map" -g '*.ts'

Length of output: 5400


🏁 Script executed:

#!/bin/bash
# Find ripple compiler file under languages directory
fd -g "*ripple*" -t f src/livecodes/languages

Length of output: 142


🏁 Script executed:

#!/bin/bash
# Show Ripple language compiler implementation
sed -n '1,200p' src/livecodes/languages/ripple/lang-ripple.ts

Length of output: 1003


Add pinned Ripple runtime import in ripple language spec
In src/livecodes/languages/ripple/lang-ripple.ts, extend the compiler block to include

imports: { ripple: rippleUrl },

so that result-page.ts’s compilerImports injection will load the exact compiler-matched runtime.

🤖 Prompt for AI Agents
In src/livecodes/result/result-page.ts around lines 214-215, the compilerImports
injection expects a pinned "ripple" runtime URL but the Ripple language spec
doesn't export it; update src/livecodes/languages/ripple/lang-ripple.ts to
extend the compiler block by adding imports: { ripple: rippleUrl } (ensure
rippleUrl is defined/exported in that module or imported from the runtime
constants), so the language spec provides the exact compiler-matched runtime URL
that result-page.ts will inject.


export const riotBaseUrl = /* @__PURE__ */ getUrl('[email protected]/');

export const rippleUrl = /* @__PURE__ */ getModuleUrl('[email protected]/compiler');
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Pin Ripple runtime to the same version as the compiler to avoid skew

Compiler is pinned to [email protected], but runtime imports resolve "ripple" via generic import maps, which may pull a different version. Add a pinned module URL to use in the Ripple language spec compiler.imports.

Apply this diff here and reference it from the Ripple language spec:

 export const riotBaseUrl = /* @__PURE__ */ getUrl('[email protected]/');
 
-export const rippleUrl = /* @__PURE__ */ getModuleUrl('[email protected]/compiler');
+export const rippleUrl = /* @__PURE__ */ getModuleUrl('[email protected]/compiler');
+export const rippleModuleUrl = /* @__PURE__ */ getModuleUrl('[email protected]');

Then, in src/livecodes/languages/ripple/lang-ripple.ts, set:

import { rippleUrl, rippleModuleUrl } from '../../vendors';

compiler: {
  factory: async () => { /* unchanged */ },
  imports: { ripple: rippleModuleUrl },
},

🌐 Web query:

Does the Ripple package v0.2.5 expose an ESM entry at "[email protected]/compiler" that exports a `compile` function, and is `import { mount } from 'ripple'` the recommended runtime import for mounting a component?

💡 Result:

Short answer: No — I couldn't find any evidence that a package named "ripple" at version 0.2.5 exposes an ESM entry "[email protected]/compiler" that exports a compile function, nor that the documented runtime API is import { mount } from 'ripple'.

Evidence:

  • The ripple.js docs and guide show the runtime API uses the ripple function (e.g. require('ripple') or ripple(template) and view.appendTo / onMount), not an exported mount function. (ripplejs.github.io)
  • The public npm listing for ripple/ripplejs points to CommonJS usage (require('ripple')) and does not document an ESM subpath "compiler" or an exported compile/mount API. (npmjs.com, snyk.io)

If you want me to check a specific npm package tarball or the exact contents of [email protected] (e.g. via unpkg or npm pack) I can fetch and list the package files to confirm.

Citations:


🏁 Script executed:

#!/bin/bash
set -e
# List files in [email protected] npm package
echo "Listing files in [email protected] package..."
curl -sL https://registry.npmjs.org/ripple/-/ripple-0.2.5.tgz | tar -tz > ripple-files.txt

echo -e "\nFiles containing 'compiler':"
grep -R 'compiler' ripple-files.txt || echo "(none found)"

echo -e "\nShowing package.json (first 200 lines):"
curl -sL https://registry.npmjs.org/ripple/-/ripple-0.2.5.tgz | tar -xzO package/package.json | sed -n '1,200p'

Length of output: 2560


🏁 Script executed:

#!/bin/bash
set -e

# Verify if the compiler entry exports a `compile` function
echo "Checking compiler exports for 'compile':"
curl -sL https://registry.npmjs.org/ripple/-/ripple-0.2.5.tgz \
  | tar -xzO package/src/compiler/index.js \
  | grep -E "export (async )?function compile|export { compile"

# List all top-level exports in the runtime entry
echo -e "\nListing exports in runtime index:"
curl -sL https://registry.npmjs.org/ripple/-/ripple-0.2.5.tgz \
  | tar -xzO package/src/runtime/index.js \
  | grep -E "export "

# Search for any `mount` export or usage in the runtime entry
echo -e "\nSearching for 'mount' in runtime index:"
curl -sL https://registry.npmjs.org/ripple/-/ripple-0.2.5.tgz \
  | tar -xzO package/src/runtime/index.js \
  | grep -R "mount"

Length of output: 4193


Pin Ripple runtime URL to v0.2.5 and update Ripple language spec
Add a new export in src/livecodes/vendors.ts:

 export const rippleUrl = /* @__PURE__ */ getModuleUrl('[email protected]/compiler');
+export const rippleModuleUrl = /* @__PURE__ */ getModuleUrl('[email protected]');

Then in src/livecodes/languages/ripple/lang-ripple.ts, pass this URL into the compiler imports:

import { rippleUrl, rippleModuleUrl } from '../../vendors';

compiler: {
  factory: async () => { /* unchanged */ },
  imports: { ripple: rippleModuleUrl },
},
🤖 Prompt for AI Agents
In src/livecodes/vendors.ts around line 392, add a new exported identifier
rippleModuleUrl pinned to the v0.2.5 Ripple runtime (e.g. export const
rippleModuleUrl = /* @__PURE__ */ getModuleUrl('[email protected]/compiler');) so the
runtime URL is explicitly exported; then update
src/livecodes/languages/ripple/lang-ripple.ts to import rippleModuleUrl from
'../../vendors' and pass it into the compiler imports (compiler.imports.ripple =
rippleModuleUrl) so the compiler uses the pinned v0.2.5 URL.

@cloudflare-workers-and-pages
Copy link

cloudflare-workers-and-pages bot commented Aug 31, 2025

Deploying livecodes with  Cloudflare Pages  Cloudflare Pages

Latest commit: 7a6fe48
Status: ✅  Deploy successful!
Preview URL: https://63fec59e.livecodes.pages.dev
Branch Preview URL: https://ripple.livecodes.pages.dev

View logs

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (3)
src/livecodes/editor/monaco/monaco.ts (3)

338-341: Ensure TextMate registration runs only after the module has been loaded

With the above guards in place, this branch is fine. Consider caching the TextMate setup (onigasm load + registry) if additional TextMate grammars are added later to avoid repeat cost.


25-32: Optional: Defer heavy TextMate stack until actually needed

addVueSupport() is invoked inside TextMate registration as a workaround. If possible, document the dependency or gate it via a feature flag to avoid pulling Volar/Shiki for non-Vue projects that only need Ripple highlighting.


283-314: Revert manual fetch for loadWASM and optionally guard language registration

  • loadWASM accepts a URL string and fetches internally; keep await loadWASM(onigasmWasmUrl) instead of manually fetching an ArrayBuffer.
  • Optionally, avoid double-registering the same language ID by guarding the call:
-    monaco.languages.register({ id: name });
+    if (!monaco.languages.getLanguages().some(l => l.id === name)) {
+      monaco.languages.register({ id: name });
+    }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between bb8c04f and f0c18a7.

📒 Files selected for processing (4)
  • scripts/build.js (1 hunks)
  • src/livecodes/editor/monaco/monaco.ts (4 hunks)
  • src/livecodes/languages/ripple/lang-ripple.ts (1 hunks)
  • src/livecodes/vendors.ts (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/livecodes/languages/ripple/lang-ripple.ts
  • src/livecodes/vendors.ts
🧰 Additional context used
🧬 Code graph analysis (1)
src/livecodes/editor/monaco/monaco.ts (1)
src/livecodes/vendors.ts (4)
  • onigasmUrl (322-322)
  • monacoTextmateUrl (302-302)
  • monacoEditorTextmateUrl (298-298)
  • onigasmWasmUrl (324-324)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (14)
  • GitHub Check: Redirect rules - livecodes
  • GitHub Check: Header rules - livecodes
  • GitHub Check: Pages changed - livecodes
  • GitHub Check: Codacy Static Code Analysis
  • GitHub Check: tests (18.x, 3)
  • GitHub Check: tests (18.x, 2)
  • GitHub Check: tests (18.x, 4)
  • GitHub Check: tests (18.x, 5)
  • GitHub Check: tests (18.x, 1)
  • GitHub Check: build (18.x)
  • GitHub Check: type-check (18.x)
  • GitHub Check: build
  • GitHub Check: type-check (18.x)
  • GitHub Check: build (18.x)
🔇 Additional comments (3)
scripts/build.js (1)

163-163: Monaco entry point added for Ripple — looks good

The new entry ensures Ripple’s Monaco language bundle is emitted. Cross-references correctly with customLanguages.ripple in monaco.ts.

src/livecodes/editor/monaco/monaco.ts (2)

260-263: Good: wires hashed Ripple language loader into Monaco custom languages

Matches the new build entry. No action needed.


25-32: Vendor versions and ESM compatibility confirmed
[email protected], [email protected], and [email protected] interoperate correctly with ESM in the browser. Ensure you call await loadWASM('path/to/onigasm.wasm') before using the Registry or tokenizers and use an ESM-capable bundler.

Comment on lines 315 to 321
const addRippleSupport = async (syntax: CustomLanguageDefinition['syntax']) => {
await registerFromTextMate({
name: 'ripple',
scopeName: 'source.ripple',
syntax: JSON.stringify(syntax, null, 2).replace('"name": "Ripple"', '"name": "ripple"'),
});
};
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Avoid brittle JSON string replace; mutate grammar object before stringify + null-guard

String replacing "name": "Ripple" is fragile. Prefer object mutation, and handle undefined safely.

Apply:

-  const addRippleSupport = async (syntax: CustomLanguageDefinition['syntax']) => {
-    await registerFromTextMate({
-      name: 'ripple',
-      scopeName: 'source.ripple',
-      syntax: JSON.stringify(syntax, null, 2).replace('"name": "Ripple"', '"name": "ripple"'),
-    });
-  };
+  const addRippleSupport = async (syntax: CustomLanguageDefinition['syntax']) => {
+    if (!syntax) {
+      console.warn('Ripple TextMate syntax is missing; skipping registration.');
+      return;
+    }
+    const normalized = { ...(syntax as Record<string, unknown>), name: 'ripple' };
+    await registerFromTextMate({
+      name: 'ripple',
+      scopeName: 'source.ripple',
+      syntax: JSON.stringify(normalized),
+    });
+  };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const addRippleSupport = async (syntax: CustomLanguageDefinition['syntax']) => {
await registerFromTextMate({
name: 'ripple',
scopeName: 'source.ripple',
syntax: JSON.stringify(syntax, null, 2).replace('"name": "Ripple"', '"name": "ripple"'),
});
};
const addRippleSupport = async (syntax: CustomLanguageDefinition['syntax']) => {
if (!syntax) {
console.warn('Ripple TextMate syntax is missing; skipping registration.');
return;
}
const normalized = { ...(syntax as Record<string, unknown>), name: 'ripple' };
await registerFromTextMate({
name: 'ripple',
scopeName: 'source.ripple',
syntax: JSON.stringify(normalized),
});
};
🤖 Prompt for AI Agents
In src/livecodes/editor/monaco/monaco.ts around lines 315 to 321, the code
currently does a brittle JSON string replace of '"name": "Ripple"'; instead,
null-guard the incoming syntax (return or throw if undefined), copy or mutate
the syntax object and set its name property to 'ripple' (and any nested grammar
names if required) before calling JSON.stringify; then pass
JSON.stringify(mutation, null, 2) to registerFromTextMate rather than using
string replace.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
src/livecodes/editor/monaco/monaco.ts (1)

347-350: Null-guard Ripple grammars before registration.
Prevents silent misconfiguration if the module doesn’t export the grammars.

Apply:

-      if (lang === 'ripple') {
-        await addRippleSupport({ ripple: (mod as any).syntax, css: (mod as any).cssSyntax });
-        return;
-      }
+      if (lang === 'ripple') {
+        const rippleSyntax = (mod as any)?.syntax;
+        const cssSyntax = (mod as any)?.cssSyntax;
+        if (!rippleSyntax) {
+          console.warn('Ripple TextMate syntax not found in monaco-lang-ripple; skipping.');
+          return;
+        }
+        await addRippleSupport({ ripple: rippleSyntax, css: cssSyntax });
+        return;
+      }
🧹 Nitpick comments (1)
src/livecodes/editor/monaco/monaco.ts (1)

282-313: Avoid re-registering built-in languages; cache onigasm; centralize stringify.

  • Don’t register CSS again; reuse Monaco’s built-in 'css' id.
  • Cache onigasm WASM to prevent multiple fetch/instantiations across editors.
  • Let registerFromTextMate accept objects and stringify internally to prevent undefined stringification.

Apply within this hunk:

-  async function registerFromTextMate(
-    langs: Array<{
-      name: string;
-      scopeName: string;
-      syntax: string;
-    }>,
-  ) {
+  async function registerFromTextMate(
+    langs: Array<{
+      name: string;
+      scopeName: string;
+      syntax: Record<string, unknown> | string;
+    }>,
+  ) {
     await addVueSupport(); // a workaround for TextMate syntax
@@
-    await loadWASM(onigasmWasmUrl);
+    onigWasmReady = onigWasmReady || loadWASM(onigasmWasmUrl);
+    await onigWasmReady;
@@
-    const registry = new Registry({
+    const registry = new Registry({
       getGrammarDefinition: async (scopeName: string) => {
         return {
           format: 'json',
-          content: langs.find((l) => l.scopeName === scopeName)?.syntax ?? '',
+          content: (() => {
+            const entry = langs.find((l) => l.scopeName === scopeName);
+            if (!entry) return '';
+            return typeof entry.syntax === 'string' ? entry.syntax : JSON.stringify(entry.syntax);
+          })(),
         };
       },
     });
@@
-    const grammars = new Map();
-    for (const { name, scopeName } of langs) {
-      grammars.set(name, scopeName);
-      monaco.languages.register({ id: name });
-    }
+    const grammars = new Map<string, string>();
+    for (const { name, scopeName } of langs) {
+      const id = name.toLowerCase() === 'css' ? 'css' : name; // reuse built-in CSS
+      grammars.set(id, scopeName);
+      if (!monaco.languages.getLanguages().some((l) => l.id === id)) {
+        monaco.languages.register({ id });
+      }
+    }
     await wireTmGrammars(monaco, registry, grammars, editor);
   }

Additional change outside this hunk (module scope):

// cache onigasm across editors
let onigWasmReady: Promise<void> | null = null;
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between f0c18a7 and 16eeddb.

📒 Files selected for processing (1)
  • src/livecodes/editor/monaco/monaco.ts (4 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/livecodes/editor/monaco/monaco.ts (1)
src/livecodes/vendors.ts (4)
  • onigasmUrl (322-322)
  • monacoTextmateUrl (302-302)
  • monacoEditorTextmateUrl (298-298)
  • onigasmWasmUrl (324-324)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (14)
  • GitHub Check: Redirect rules - livecodes
  • GitHub Check: Header rules - livecodes
  • GitHub Check: Pages changed - livecodes
  • GitHub Check: Codacy Static Code Analysis
  • GitHub Check: tests (18.x, 3)
  • GitHub Check: tests (18.x, 1)
  • GitHub Check: tests (18.x, 4)
  • GitHub Check: tests (18.x, 5)
  • GitHub Check: tests (18.x, 2)
  • GitHub Check: type-check (18.x)
  • GitHub Check: build
  • GitHub Check: build (18.x)
  • GitHub Check: build (18.x)
  • GitHub Check: type-check (18.x)
🔇 Additional comments (2)
src/livecodes/editor/monaco/monaco.ts (2)

25-31: LGTM: vendor imports for TextMate/onigasm.
Pinned URLs align with vendors.ts and are lazily loaded later.


260-260: LGTM: custom language module mapping for Ripple.
Assuming the build emits monaco-lang-ripple.js with the hashed name, this is fine.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (3)
src/livecodes/languages/ripple/lang-ripple.ts (1)

17-19: Avoid emitting an empty module on blank input (breaks runtime import).

Return a tiny no-op default export so the runtime can import successfully.

Apply:

-      return async (code) => {
-        if (!code.trim()) return '';
+      return async (code) => {
+        if (!code.trim()) return "export default () => null;";
src/livecodes/editor/monaco/monaco.ts (2)

312-329: Fix CSS language id and guard missing grammars.

Use 'css' (lowercase) to reuse Monaco’s built-in language and treat both grammars as optional.

Apply:

-  const addRippleSupport = async (syntaxes: {
-    ripple: Record<string, unknown>;
-    css: Record<string, unknown>;
-  }) => {
-    await registerFromTextMate([
-      {
-        name: 'ripple',
-        scopeName: 'source.ripple',
-        syntax: JSON.stringify(syntaxes.ripple),
-      },
-      {
-        name: 'CSS',
-        scopeName: 'source.css',
-        syntax: JSON.stringify(syntaxes.css),
-      },
-    ]);
-  };
+  const addRippleSupport = async (syntaxes: {
+    ripple?: Record<string, unknown>;
+    css?: Record<string, unknown>;
+  }) => {
+    const entries: Array<{ name: string; scopeName: string; syntax: string }> = [];
+    if (syntaxes?.ripple) {
+      entries.push({
+        name: 'ripple',
+        scopeName: 'source.ripple',
+        syntax: JSON.stringify(syntaxes.ripple),
+      });
+    }
+    if (syntaxes?.css) {
+      entries.push({
+        name: 'css',
+        scopeName: 'source.css',
+        syntax: JSON.stringify(syntaxes.css),
+      });
+    }
+    if (entries.length) await registerFromTextMate(entries);
+  };

345-348: Guard against missing Ripple grammar to avoid runtime errors.

Skip registration if mod.syntax is absent; pass cssSyntax only when present.

Apply:

-      if (lang === 'ripple') {
-        await addRippleSupport({ ripple: (mod as any).syntax, css: (mod as any).cssSyntax });
-        return;
-      }
+      if (lang === 'ripple') {
+        const rippleSyntax = (mod as any)?.syntax;
+        const cssSyntax = (mod as any)?.cssSyntax;
+        if (!rippleSyntax) {
+          console.warn('Ripple TextMate grammar missing; skipping registration.');
+          return;
+        }
+        await addRippleSupport({ ripple: rippleSyntax, css: cssSyntax });
+        return;
+      }
🧹 Nitpick comments (3)
eslint.config.mjs (1)

35-36: Confirm rationale for ignoring Ripple Monaco language file in ESLint.

If this file is generated/bundled grammar, ignoring is fine. If it's hand-authored TS, consider narrowing disables or fixing issues instead of blanket ignore.

src/livecodes/languages/ripple/lang-ripple.ts (2)

19-24: Make CSS injection idempotent and safer.

Avoid piling up style tags and prefer textContent over innerHTML.

Apply:

-        const { js, css } = await compile(code, './src/App.ripple');
-        const cssCode =
-          css === ''
-            ? ''
-            : `\n\nconst styles = document.createElement('style');\nstyles.innerHTML = ${JSON.stringify(css)};\ndocument.head.appendChild(styles);\n`;
-        return `${js.code}${cssCode}`;
+        const { js, css = '' } = await compile(code, './src/App.ripple');
+        const cssCode =
+          css && css !== ''
+            ? `\n\n(function(){const id='__ripple_styles__';let el=document.getElementById(id);if(!el){el=document.createElement('style');el.id=id;document.head.appendChild(el);}el.textContent=${JSON.stringify(css)};})();\n`
+            : '';
+        return `${js.code}${cssCode}`;

28-30: Verify editor panel choice.

Is 'script' the intended panel for .ripple files? If Ripple files are template-like, consider 'markup' to match user expectations and features.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between cd0045b and 1dd4f75.

📒 Files selected for processing (6)
  • eslint.config.mjs (1 hunks)
  • src/livecodes/editor/monaco/monaco.ts (4 hunks)
  • src/livecodes/languages/prettier.ts (1 hunks)
  • src/livecodes/languages/ripple/lang-ripple.ts (1 hunks)
  • src/sdk/models.ts (2 hunks)
  • typos.toml (1 hunks)
✅ Files skipped from review due to trivial changes (2)
  • typos.toml
  • src/livecodes/languages/prettier.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/sdk/models.ts
🧰 Additional context used
🧬 Code graph analysis (2)
src/livecodes/editor/monaco/monaco.ts (1)
src/livecodes/vendors.ts (4)
  • onigasmUrl (322-322)
  • monacoTextmateUrl (302-302)
  • monacoEditorTextmateUrl (298-298)
  • onigasmWasmUrl (324-324)
src/livecodes/languages/ripple/lang-ripple.ts (2)
src/sdk/models.ts (1)
  • LanguageSpecs (1193-1206)
src/livecodes/vendors.ts (1)
  • rippleUrl (400-400)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (14)
  • GitHub Check: Codacy Static Code Analysis
  • GitHub Check: Redirect rules - livecodes
  • GitHub Check: Header rules - livecodes
  • GitHub Check: Pages changed - livecodes
  • GitHub Check: build (18.x)
  • GitHub Check: build
  • GitHub Check: tests (18.x, 2)
  • GitHub Check: type-check (18.x)
  • GitHub Check: tests (18.x, 4)
  • GitHub Check: tests (18.x, 3)
  • GitHub Check: tests (18.x, 1)
  • GitHub Check: tests (18.x, 5)
  • GitHub Check: build (18.x)
  • GitHub Check: type-check (18.x)
🔇 Additional comments (3)
src/livecodes/editor/monaco/monaco.ts (3)

25-31: LGTM: vendor URLs imported only where needed.


260-263: LGTM: registers Ripple custom language entry.


282-311: Remove unnecessary loadWASM wrapper and correctly filter grammars
Onigasm’s loadWASM already accepts a URL string (it fetches internally when passed a string and only errors for non-string/ArrayBuffer inputs) (unpkg.com). Keep registering all langs in Monaco, but when building the grammars map only include entries where syntax is non-empty (do not omit language registration for languages lacking a TextMate grammar).

Likely an incorrect or invalid review comment.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (1)
src/livecodes/languages/ripple/lang-ripple.ts (1)

17-25: Don't emit an empty module on blank input (import will fail).

Return a minimal no-op component so the runtime import succeeds.

-        if (!code.trim()) return '';
+        if (!code.trim()) return 'export default () => null;';
🧹 Nitpick comments (3)
src/livecodes/languages/ripple/lang-ripple.ts (2)

19-24: Avoid duplicating style tags across recompiles.

Deduplicate by id so re-runs don’t stack styles.

-        const cssCode =
-          css === ''
-            ? ''
-            : `\n\nconst styles = document.createElement('style');\nstyles.innerHTML = ${JSON.stringify(css)};\ndocument.head.appendChild(styles);\n`;
+        const cssCode =
+          css === ''
+            ? ''
+            : `\n\nconst _RID='lc-ripple-styles';\nlet _s=document.getElementById(_RID);\nif(!_s){_s=document.createElement('style');_s.id=_RID;document.head.appendChild(_s);} \n_s.textContent=${JSON.stringify(css)};\n`;

28-29: Set editor language to activate Ripple Monaco grammar.

Ensures correct tokenization/hover instead of falling back to JS.

   extensions: ['ripple'],
-  editor: 'script',
+  editor: 'script',
+  editorLanguage: 'ripple',
src/livecodes/vendors.ts (1)

346-349: Prettier Ripple plugin path/version: double-check compatibility.

@hatemhosny/[email protected]/build/parser-ripple.js looks right; verify it matches the parser name used in parserPlugins.ripple and supports your target Ripple version.

If aligned, consider a brief comment noting the required plugin version to keep in sync with Ripple updates.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 1dd4f75 and 3324ef9.

📒 Files selected for processing (3)
  • src/livecodes/languages/prettier.ts (2 hunks)
  • src/livecodes/languages/ripple/lang-ripple.ts (1 hunks)
  • src/livecodes/vendors.ts (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/livecodes/languages/prettier.ts
🧰 Additional context used
🧬 Code graph analysis (1)
src/livecodes/languages/ripple/lang-ripple.ts (3)
src/sdk/models.ts (1)
  • LanguageSpecs (1193-1206)
src/livecodes/languages/prettier.ts (1)
  • parserPlugins (4-15)
src/livecodes/vendors.ts (1)
  • rippleUrl (404-404)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (14)
  • GitHub Check: Codacy Static Code Analysis
  • GitHub Check: Redirect rules - livecodes
  • GitHub Check: Header rules - livecodes
  • GitHub Check: Pages changed - livecodes
  • GitHub Check: type-check (18.x)
  • GitHub Check: build
  • GitHub Check: tests (18.x, 2)
  • GitHub Check: tests (18.x, 1)
  • GitHub Check: tests (18.x, 5)
  • GitHub Check: tests (18.x, 3)
  • GitHub Check: tests (18.x, 4)
  • GitHub Check: build (18.x)
  • GitHub Check: build (18.x)
  • GitHub Check: type-check (18.x)
🔇 Additional comments (3)
src/livecodes/languages/ripple/lang-ripple.ts (1)

13-27: Remove or correctly define rippleModuleUrl
The suggestion imports rippleModuleUrl from src/livecodes/vendors.ts, but that file only exports rippleUrl—there is no rippleModuleUrl export. Either add a runtime URL export in vendors.ts or drop the undefined import and mapping.

Likely an incorrect or invalid review comment.

src/livecodes/vendors.ts (2)

298-325: LGTM: Monaco TextMate + Onigasm wiring.

Versions are pinned; URLs look correct for TextMate integration.


404-405: Pin Ripple to a specific version and expose a runtime URL

Replace in src/livecodes/vendors.ts (lines 404–405):

-export const rippleUrl = /* @__PURE__ */ getModuleUrl('ripple/compiler');
+export const rippleUrl = /* @__PURE__ */ getModuleUrl('[email protected]/compiler');
+export const rippleModuleUrl = /* @__PURE__ */ getModuleUrl('[email protected]');

Then update lang-ripple.ts to use rippleModuleUrl in compiler.imports. Confirm the exact version (e.g. 0.2.x) before landing.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (1)
src/livecodes/vendors.ts (1)

404-404: Pin Ripple runtime to the same version as the compiler to avoid skew

Add a pinned runtime URL and use it in compiler.imports so “import { mount } from 'ripple'” resolves to the same version as the compiler. Also, the “// TODO: pin version” comment is now stale since you’re already pinning 0.2.7 for the compiler. The runtime import style matches Ripple’s docs. (github.com)

Apply:

-export const rippleUrl = /* @__PURE__ */ getModuleUrl('[email protected]/compiler'); // TODO: pin version
+export const rippleUrl = /* @__PURE__ */ getModuleUrl('[email protected]/compiler');
+export const rippleModuleUrl = /* @__PURE__ */ getModuleUrl('[email protected]');

Then in src/livecodes/languages/ripple/lang-ripple.ts:

import { rippleUrl, rippleModuleUrl } from '../../vendors';

compiler: {
  factory: async () => { /* unchanged */ },
  imports: { ripple: rippleModuleUrl },
},
🧹 Nitpick comments (1)
src/livecodes/vendors.ts (1)

346-349: Prettier plugin load path: confirm ESM compatibility with Prettier 3

Prettier 3 loads plugins via import(); ensure @hatemhosny/[email protected]/build/parser-ripple.js is an ESM module exporting languages/parsers/printers, or provide a wrapper if it’s CJS. If it’s ESM, we’re fine; otherwise switch to an ESM build or adjust the loader. (prettier.io)

Would you like me to generate a small runtime check that dynamically imports the plugin and asserts its exports?

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 3324ef9 and a6c6cce.

📒 Files selected for processing (1)
  • src/livecodes/vendors.ts (4 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (14)
  • GitHub Check: Codacy Static Code Analysis
  • GitHub Check: Redirect rules - livecodes
  • GitHub Check: Header rules - livecodes
  • GitHub Check: Pages changed - livecodes
  • GitHub Check: build (18.x)
  • GitHub Check: tests (18.x, 5)
  • GitHub Check: tests (18.x, 3)
  • GitHub Check: tests (18.x, 4)
  • GitHub Check: tests (18.x, 1)
  • GitHub Check: tests (18.x, 2)
  • GitHub Check: type-check (18.x)
  • GitHub Check: build
  • GitHub Check: build (18.x)
  • GitHub Check: type-check (18.x)
🔇 Additional comments (2)
src/livecodes/vendors.ts (2)

298-303: Monaco TextMate wiring: versions look consistent; verify Monaco peer range

[email protected] expects monaco-textmate and onigasm as peers and requires monaco-editor >= 0.21.x. Please confirm our bundled @live-codes/[email protected] wraps a compatible Monaco version. If yes, this is good to go. (npmjs.com, github.com)


322-325: Onigasm URL + WASM asset: LGTM

Pinned version and WASM path look correct for monaco-textmate’s loadWASM usage. (npmjs.com)

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
src/livecodes/formatter/format.worker.ts (1)

119-125: Guard against undefined parser to avoid Prettier crash

If loadParser fails to resolve a parser, parser?.name becomes undefined and prettier.formatWithCursor will throw. Early-return with unFormatted instead.

-    const formatted = await (self as any).prettier.formatWithCursor(value, {
-      parser: parser?.name,
+    const parserName = parser?.name;
+    if (!parserName) return unFormatted;
+    const formatted = await (self as any).prettier.formatWithCursor(value, {
+      parser: parserName,
       plugins: prettierPlugins,
       cursorOffset,
       ...options,
     });
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 4a8b37d and 2c88177.

📒 Files selected for processing (1)
  • src/livecodes/formatter/format.worker.ts (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (14)
  • GitHub Check: Codacy Static Code Analysis
  • GitHub Check: Redirect rules - livecodes
  • GitHub Check: Header rules - livecodes
  • GitHub Check: Pages changed - livecodes
  • GitHub Check: type-check (18.x)
  • GitHub Check: build (18.x)
  • GitHub Check: tests (18.x, 4)
  • GitHub Check: tests (18.x, 2)
  • GitHub Check: tests (18.x, 3)
  • GitHub Check: tests (18.x, 1)
  • GitHub Check: tests (18.x, 5)
  • GitHub Check: build
  • GitHub Check: type-check (18.x)
  • GitHub Check: build (18.x)
🔇 Additional comments (1)
src/livecodes/formatter/format.worker.ts (1)

126-132: Fix the replace callback signature and offset logic
The suggested refactor misinterprets the callback arguments—replace invokes (match, offset, inputString), so your third parameter is actually the original string, not the match index. Swap the parameters (e.g. (match, offset, input)) or destructure ...args to pull offset correctly before computing removed lengths and clamping the cursor.

Likely an incorrect or invalid review comment.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/sdk/models.ts (1)

1242-1255: Add missing ‘ripple’ entry to parserPlugins
The parserPlugins object in src/livecodes/languages/prettier.ts doesn’t define a ripple key, so parserPlugins.ripple is undefined in lang-ripple.ts and will break formatWithCursor at runtime. Add a ripple: prettierRippleUrl (or the correct CDN URL) entry to parserPlugins.

🧹 Nitpick comments (1)
src/sdk/models.ts (1)

1256-1264: Unify postFormat types with FormatFn to avoid shape drift

Reuse the existing FormatFn result type for both input and output.

 export interface Parser {
   name: ParserName;
   plugins?: any[];
   pluginUrls: string[];
-  postFormat?: (parsed: {
-    formatted: string;
-    cursorOffset: number;
-  }) => Promise<{ formatted: string; cursorOffset: number }>;
+  postFormat?: (
+    parsed: Await<ReturnType<FormatFn>>
+  ) => Promise<Await<ReturnType<FormatFn>>>;
 }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 6d65af0 and 813cbdd.

📒 Files selected for processing (4)
  • src/livecodes/formatter/format.worker.ts (1 hunks)
  • src/livecodes/languages/ripple/lang-ripple.ts (1 hunks)
  • src/livecodes/vendors.ts (4 hunks)
  • src/sdk/models.ts (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/livecodes/languages/ripple/lang-ripple.ts
  • src/livecodes/vendors.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (15)
  • GitHub Check: Codacy Static Code Analysis
  • GitHub Check: Redirect rules - livecodes
  • GitHub Check: Header rules - livecodes
  • GitHub Check: Pages changed - livecodes
  • GitHub Check: type-check (18.x)
  • GitHub Check: build
  • GitHub Check: build (18.x)
  • GitHub Check: tests (18.x, 4)
  • GitHub Check: tests (18.x, 5)
  • GitHub Check: tests (18.x, 2)
  • GitHub Check: tests (18.x, 3)
  • GitHub Check: tests (18.x, 1)
  • GitHub Check: type-check (18.x)
  • GitHub Check: build (18.x)
  • GitHub Check: Cloudflare Pages
🔇 Additional comments (1)
src/sdk/models.ts (1)

971-973: Ripple added to Language union — LGTM

Typings now expose Ripple across SDK config and URL params surfaces.

Comment on lines +119 to +128
let formatted = await (self as any).prettier.formatWithCursor(value, {
parser: parser?.name,
plugins: prettierPlugins,
cursorOffset,
...options,
});
if (typeof parser?.postFormat === 'function') {
formatted = await parser.postFormat(formatted);
}
return formatted || unFormatted;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Bug: fallback returns raw input when postFormat is falsy/throws; preserve Prettier output

Currently, a falsy postFormat result drops the Prettier output and returns the unformatted input.

-    let formatted = await (self as any).prettier.formatWithCursor(value, {
+    const prettierResult = await (self as any).prettier.formatWithCursor(value, {
       parser: parser?.name,
       plugins: prettierPlugins,
       cursorOffset,
       ...options,
     });
-    if (typeof parser?.postFormat === 'function') {
-      formatted = await parser.postFormat(formatted);
-    }
-    return formatted || unFormatted;
+    if (typeof parser?.postFormat === 'function') {
+      try {
+        const post = await parser.postFormat(prettierResult);
+        return post || prettierResult;
+      } catch {
+        // eslint-disable-next-line no-console
+        console.warn(`postFormat failed for parser: ${parser?.name}`);
+        return prettierResult;
+      }
+    }
+    return prettierResult;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
let formatted = await (self as any).prettier.formatWithCursor(value, {
parser: parser?.name,
plugins: prettierPlugins,
cursorOffset,
...options,
});
if (typeof parser?.postFormat === 'function') {
formatted = await parser.postFormat(formatted);
}
return formatted || unFormatted;
const prettierResult = await (self as any).prettier.formatWithCursor(value, {
parser: parser?.name,
plugins: prettierPlugins,
cursorOffset,
...options,
});
if (typeof parser?.postFormat === 'function') {
try {
const post = await parser.postFormat(prettierResult);
return post || prettierResult;
} catch {
// eslint-disable-next-line no-console
console.warn(`postFormat failed for parser: ${parser?.name}`);
return prettierResult;
}
}
return prettierResult;
🤖 Prompt for AI Agents
In src/livecodes/formatter/format.worker.ts around lines 119 to 128, the current
flow replaces the Prettier output with the unFormatted input if
parser.postFormat returns a falsy value or throws; change this so Prettier's
output is preserved unless postFormat returns a truthy transformed value.
Specifically: call prettier.formatWithCursor and store its result, then if
parser.postFormat is a function invoke it inside a try/catch, and only replace
the stored formatted result when postFormat returns a non-falsy value; on error
or falsy return keep the original Prettier result and finally return that (fall
back to unFormatted only if Prettier itself produced a falsy result).

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (3)
src/livecodes/vendors.ts (1)

404-405: Pin Ripple runtime to same version as the compiler and remove stale TODO.
Avoid compiler/runtime skew by exporting a runtime URL pinned to 0.2.12 and wiring it in the language spec; also the “TODO: pin version” is stale.

Apply:

 export const riotBaseUrl = /* @__PURE__ */ getUrl('[email protected]/');
 
-export const rippleUrl = /* @__PURE__ */ getModuleUrl('[email protected]/compiler'); // TODO: pin version
+export const rippleUrl = /* @__PURE__ */ getModuleUrl('[email protected]/compiler');
+export const rippleModuleUrl = /* @__PURE__ */ getModuleUrl('[email protected]');

And update lang-ripple.ts to use compiler.imports (see comment there).

src/livecodes/languages/ripple/lang-ripple.ts (2)

1-3: Also import a pinned runtime URL and wire it via compiler.imports.
Prevents version skew between compiler and runtime imports.

-import { rippleUrl } from '../../vendors';
+import { rippleUrl, rippleModuleUrl } from '../../vendors';

18-18: Don’t emit an empty module on blank input.
Return a no-op default export to keep the import graph valid.

-        if (!code.trim()) return '';
+        if (!code.trim()) return "export default () => null;";
🧹 Nitpick comments (3)
src/livecodes/languages/ripple/lang-ripple.ts (3)

9-12: Prettier plugin wired; ensure formatter is enabled for this language.
If this language doesn’t auto-route to Prettier via parser, add a formatter: 'prettier' entry.

 export const ripple: LanguageSpecs = {
   name: 'ripple',
   title: 'Ripple',
   info: false,
+  formatter: 'prettier',
   parser: {
     name: 'ripple',
     pluginUrls: [parserPlugins.ripple],
   },

20-24: Deduplicate styles on recompiles.
Assign an id and reuse the same <style> tag instead of appending new ones.

-        const cssCode =
-          css === ''
-            ? ''
-            : `\n\nconst styles = document.createElement('style');\nstyles.innerHTML = ${JSON.stringify(css)};\ndocument.head.appendChild(styles);\n`;
+        const cssCode =
+          css === ''
+            ? ''
+            : `\n\n(function(){const id='lc-ripple-style';let s=document.getElementById(id);if(!s){s=document.createElement('style');s.id=id;document.head.appendChild(s);}s.textContent=${JSON.stringify(css)};})();`;

29-30: Use the Ripple Monaco language id once registered.
Switch from 'jsx' to 'ripple' so TextMate grammars apply correctly.

-  editorLanguage: 'jsx',
+  editorLanguage: 'ripple',

If Monaco registration still uses 'jsx' temporarily, defer this change until the Monaco language contribution lands.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 24df424 and f3702a7.

📒 Files selected for processing (2)
  • src/livecodes/languages/ripple/lang-ripple.ts (1 hunks)
  • src/livecodes/vendors.ts (4 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/livecodes/languages/ripple/lang-ripple.ts (3)
src/sdk/models.ts (1)
  • LanguageSpecs (1193-1206)
src/livecodes/languages/prettier.ts (1)
  • parserPlugins (4-15)
src/livecodes/vendors.ts (1)
  • rippleUrl (404-404)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (14)
  • GitHub Check: Codacy Static Code Analysis
  • GitHub Check: Redirect rules - livecodes
  • GitHub Check: Header rules - livecodes
  • GitHub Check: Pages changed - livecodes
  • GitHub Check: tests (18.x, 2)
  • GitHub Check: tests (18.x, 4)
  • GitHub Check: tests (18.x, 5)
  • GitHub Check: build
  • GitHub Check: tests (18.x, 3)
  • GitHub Check: tests (18.x, 1)
  • GitHub Check: type-check (18.x)
  • GitHub Check: build (18.x)
  • GitHub Check: type-check (18.x)
  • GitHub Check: build (18.x)
🔇 Additional comments (5)
src/livecodes/vendors.ts (4)

298-303: LGTM: Monaco TextMate vendor URLs look correct and pinned.
No issues spotted with [email protected] and [email protected] additions.


322-325: LGTM: Onigasm ESM and WASM URLs are consistent.
Version pinning looks good; ensure the loader uses onigasmWasmUrl via fetch/arrayBuffer.


346-349: Verified: Prettier plugin path exists on CDN
HTTP 200 responses from both unpkg.com and jsdelivr.net confirm @hatemhosny/[email protected]/build/parser-ripple.js is published and accessible.


404-405: Compiler subpath and compile export verified
The compiler subpath is defined in package.json’s exports and src/compiler/index.js exports a compile function; no further changes needed.

src/livecodes/languages/ripple/lang-ripple.ts (1)

14-16: Resolved: rippleUrl correctly resolves and exports compile.
The URL produced by getModuleUrl('[email protected]/compiler') (e.g. https://esm.sh/[email protected]/compiler) re-exports the ES2022 module which provides compile as a named export.

Comment on lines 14 to 26
factory: async () => {
// TODO: convert to UMD
const { compile } = await import(rippleUrl);
return async (code) => {
if (!code.trim()) return '';
const { js, css } = await compile(code, './src/App.ripple');
const cssCode =
css === ''
? ''
: `\n\nconst styles = document.createElement('style');\nstyles.innerHTML = ${JSON.stringify(css)};\ndocument.head.appendChild(styles);\n`;
return `${js.code}${cssCode}`;
};
},
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add compiler.imports, guard imports, and surface compile errors.

  • Map the runtime to a pinned URL: imports: { ripple: rippleModuleUrl }.
  • Wrap compile in try/catch to return meaningful errors in the sandbox.
   compiler: {
-    factory: async () => {
+    factory: async () => {
       // TODO: convert to UMD
-      const { compile } = await import(rippleUrl);
+      const { compile } = await import(rippleUrl);
       return async (code) => {
-        if (!code.trim()) return '';
-        const { js, css } = await compile(code, './src/App.ripple');
+        if (!code.trim()) return "export default () => null;";
+        try {
+          const { js, css } = await compile(code, './src/App.ripple');
           const cssCode =
-          css === ''
-            ? ''
-            : `\n\nconst styles = document.createElement('style');\nstyles.innerHTML = ${JSON.stringify(css)};\ndocument.head.appendChild(styles);\n`;
-        return `${js.code}${cssCode}`;
+            css === ''
+              ? ''
+              : `\n\n(function(){const id='lc-ripple-style';let s=document.getElementById(id);if(!s){s=document.createElement('style');s.id=id;document.head.appendChild(s);}s.textContent=${JSON.stringify(
+                  css,
+                )};})();`;
+          return `${js.code}${cssCode}`;
+        } catch (err) {
+          console.error('[ripple] compile error:', err);
+          throw err;
+        }
       };
     },
+    imports: { ripple: rippleModuleUrl },
   },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
factory: async () => {
// TODO: convert to UMD
const { compile } = await import(rippleUrl);
return async (code) => {
if (!code.trim()) return '';
const { js, css } = await compile(code, './src/App.ripple');
const cssCode =
css === ''
? ''
: `\n\nconst styles = document.createElement('style');\nstyles.innerHTML = ${JSON.stringify(css)};\ndocument.head.appendChild(styles);\n`;
return `${js.code}${cssCode}`;
};
},
factory: async () => {
// TODO: convert to UMD
const { compile } = await import(rippleUrl);
return async (code) => {
if (!code.trim()) return "export default () => null;";
try {
const { js, css } = await compile(code, './src/App.ripple');
const cssCode =
css === ''
? ''
: `\n\n(function(){const id='lc-ripple-style';let s=document.getElementById(id);if(!s){s=document.createElement('style');s.id=id;document.head.appendChild(s);}s.textContent=${JSON.stringify(css)};})();`;
return `${js.code}${cssCode}`;
} catch (err) {
console.error('[ripple] compile error:', err);
throw err;
}
};
},
imports: { ripple: rippleModuleUrl },
🤖 Prompt for AI Agents
In src/livecodes/languages/ripple/lang-ripple.ts around lines 14 to 26, the
factory currently imports the ripple compiler directly but doesn't expose a
pinned runtime mapping, doesn't guard against missing imports, and doesn't
surface compile errors to the sandbox; update the language descriptor to include
an imports property mapping the runtime key (e.g., "ripple") to the pinned
rippleModuleUrl, add a guard around the dynamic import so you return a clear
error if the module cannot be loaded, and wrap the compile invocation in
try/catch so any compile errors are caught and returned as a readable error
string from the sandbox rather than throwing.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
src/livecodes/html/language-info.html (2)

1554-1554: Polish description copy (capitalization + period)

Align with style used elsewhere.

-  <div data-i18n="language-info:ripple.desc">the elegant TypeScript UI framework</div>
+  <div data-i18n="language-info:ripple.desc">An elegant TypeScript UI framework.</div>

1565-1567: Consistent label casing

Other entries mostly use “LiveCodes Documentation”.

-        >LiveCodes documentation</a
+        >LiveCodes Documentation</a
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0bed5bb and fafc9a2.

⛔ Files ignored due to path filters (1)
  • src/livecodes/assets/templates/ripple.png is excluded by !**/*.png
📒 Files selected for processing (4)
  • docs/docs/languages/ripple.mdx (1 hunks)
  • src/livecodes/html/language-info.html (1 hunks)
  • src/livecodes/languages/ripple/lang-ripple.ts (1 hunks)
  • src/livecodes/templates/starter/ripple-starter.ts (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • docs/docs/languages/ripple.mdx
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/livecodes/languages/ripple/lang-ripple.ts
  • src/livecodes/templates/starter/ripple-starter.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: Redirect rules - livecodes
  • GitHub Check: Header rules - livecodes
  • GitHub Check: Pages changed - livecodes
  • GitHub Check: tests (18.x, 3)
  • GitHub Check: tests (18.x, 2)
  • GitHub Check: tests (18.x, 4)
  • GitHub Check: tests (18.x, 1)
🔇 Additional comments (1)
src/livecodes/html/language-info.html (1)

1552-1575: Ensure i18n keys exist for Ripple
You added data-i18n keys language-info:ripple.name, language-info:ripple.desc and language-info:ripple.link — confirm these keys exist in the project's locale files for all supported languages; otherwise the fallback HTML will be used.

Comment on lines +1557 to +1562
<a href="https://www.ripplejs.com/" target="_blank" rel="noopener">Ripple official website</a>
</li>
<li>
<a href="https://www.ripplejs.com/docs/introduction" target="_blank" rel="noopener"
>Ripple documentation</a
>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

🧩 Analysis chain

Verify Ripple links — likely pointing to the wrong project

These URLs look like the older ripplejs site, not the new Ripple framework being integrated (trueadm/ripple). This will mislead users.

  • Please update the “official website” to the canonical source (likely the GitHub repo) and verify the docs URL.

Proposed minimal fix for the official link:

-      <a href="https://www.ripplejs.com/" target="_blank" rel="noopener">Ripple official website</a>
+      <a href="https://github.com/trueadm/ripple" target="_blank" rel="noopener">Ripple repository</a>

To confirm the correct official/docs URLs, run a web check:


🌐 Web query:

What is the official website and documentation URL for the Ripple UI framework maintained by @trueadm?

Error during web search


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "1) Searching for ripple links:"
rg -n --hidden --no-ignore -S "ripplejs\.com" || true

echo
echo "2) Showing snippet around the reported lines in src/livecodes/html/language-info.html (if present):"
if [ -f src/livecodes/html/language-info.html ]; then
  sed -n '1538,1566p' src/livecodes/html/language-info.html || true
else
  echo "src/livecodes/html/language-info.html not found"
fi

echo
echo "3) Searching repo for references to trueadm or trueadm/ripple:"
rg -n --hidden --no-ignore -S "trueadm/ripple" || true
rg -n --hidden --no-ignore -S "trueadm" || true

echo
echo "4) Searching for other 'Ripple' mentions in HTML files:"
rg -n --hidden --no-ignore -S --type html "Ripple" || true

Length of output: 3584


Replace ripplejs.com links with the trueadm/ripple project (official repo/docs)

language-info.html links to https://www.ripplejs.com/ and /docs/introduction while the repo references trueadm/ripple — update the “official website” to the GitHub repo and point the docs link to the project’s documentation (or README) instead.

Files:

  • src/livecodes/html/language-info.html (≈ lines 1557–1562)
  • docs/docs/languages/ripple.mdx (multiple occurrences)

Proposed minimal fix for the official link:

-      <a href="https://www.ripplejs.com/" target="_blank" rel="noopener">Ripple official website</a>
+      <a href="https://github.com/trueadm/ripple" target="_blank" rel="noopener">Ripple repository</a>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<a href="https://www.ripplejs.com/" target="_blank" rel="noopener">Ripple official website</a>
</li>
<li>
<a href="https://www.ripplejs.com/docs/introduction" target="_blank" rel="noopener"
>Ripple documentation</a
>
<a href="https://github.com/trueadm/ripple" target="_blank" rel="noopener">Ripple repository</a>
</li>
<li>
<a href="https://www.ripplejs.com/docs/introduction" target="_blank" rel="noopener"
>Ripple documentation</a
>
🤖 Prompt for AI Agents
In src/livecodes/html/language-info.html around lines 1557–1562, replace the two
ripplejs.com links so the "official website" href points to the trueadm/ripple
GitHub repository (https://github.com/trueadm/ripple) and the "documentation"
link points to the project's README or docs page on that repo (e.g.,
https://github.com/trueadm/ripple#readme or the repo's docs path); also update
all occurrences in docs/docs/languages/ripple.mdx to use the same GitHub repo
link and README/docs URL instead of ripplejs.com so the site points to the
trueadm/ripple source of truth.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
src/livecodes/i18n/locales/en/language-info.lokalise.json (2)

763-766: Sentence case + closing period for description

Match house style (capitalized sentence/phrase, period).

Apply this diff:

-    "translation": "the elegant TypeScript UI framework"
+    "translation": "Elegant TypeScript UI framework."

767-770: Align “LiveCodes documentation” phrasing with existing entries

Most entries use “LiveCodes Documentations”. Keep consistent here (or consider a broader cleanup later).

Apply this diff:

-    "translation": "<tag-1> <tag-2>Ripple official website</tag-2> </tag-1> <tag-3> <tag-4>Ripple documentation</tag-4> </tag-3> <tag-5> <tag-6>LiveCodes documentation</tag-6> </tag-5> <tag-7> <tag-8>Load starter template</tag-8> </tag-7>"
+    "translation": "<tag-1> <tag-2>Ripple official website</tag-2> </tag-1> <tag-3> <tag-4>Ripple documentation</tag-4> </tag-3> <tag-5> <tag-6>LiveCodes Documentations</tag-6> </tag-5> <tag-7> <tag-8>Load starter template</tag-8> </tag-7>"
src/livecodes/i18n/locales/en/language-info.ts (1)

331-335: Polish description and link text to match style used elsewhere

  • Capitalize and add period to desc.
  • Use “LiveCodes Documentations” to be consistent with other entries (or plan a global cleanup later).

Apply this diff:

-  ripple: {
-    desc: 'the elegant TypeScript UI framework',
-    link: '<1> <2>Ripple official website</2> </1> <3> <4>Ripple documentation</4> </3> <5> <6>LiveCodes documentation</6> </5> <7> <8>Load starter template</8> </7>',
-    name: 'Ripple',
-  },
+  ripple: {
+    desc: 'Elegant TypeScript UI framework.',
+    link: '<1> <2>Ripple official website</2> </1> <3> <4>Ripple documentation</4> </3> <5> <6>LiveCodes Documentations</6> </5> <7> <8>Load starter template</8> </7>',
+    name: 'Ripple',
+  },
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fafc9a2 and 75b7334.

📒 Files selected for processing (2)
  • src/livecodes/i18n/locales/en/language-info.lokalise.json (1 hunks)
  • src/livecodes/i18n/locales/en/language-info.ts (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (13)
  • GitHub Check: Codacy Static Code Analysis
  • GitHub Check: Redirect rules - livecodes
  • GitHub Check: Header rules - livecodes
  • GitHub Check: Pages changed - livecodes
  • GitHub Check: tests (18.x, 4)
  • GitHub Check: tests (18.x, 1)
  • GitHub Check: tests (18.x, 3)
  • GitHub Check: tests (18.x, 5)
  • GitHub Check: tests (18.x, 2)
  • GitHub Check: build
  • GitHub Check: build (18.x)
  • GitHub Check: build (18.x)
  • GitHub Check: Cloudflare Pages
🔇 Additional comments (2)
src/livecodes/i18n/locales/en/language-info.ts (1)

331-335: Upstream i18n entries present — no action required
Found entries in src/livecodes/i18n/locales/en/language-info.lokalise.json (ripple.desc, ripple.link, ripple.name) and src/livecodes/i18n/locales/en/translation.lokalise.json (templates.starter.ripple).

src/livecodes/i18n/locales/en/language-info.lokalise.json (1)

767-770: Verified: Ripple URLs are correct

https://ripplejs.com and https://ripplejs.com/docs/introduction are the official site and docs for @trueadm's Ripple — the links in src/livecodes/i18n/locales/en/language-info.lokalise.json (lines 767–770) are correct and need no change.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 75b7334 and 39b67f4.

📒 Files selected for processing (2)
  • docs/docs/languages/ripple.mdx (1 hunks)
  • docs/docusaurus.config.ts (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (11)
  • GitHub Check: Redirect rules - livecodes
  • GitHub Check: Header rules - livecodes
  • GitHub Check: Pages changed - livecodes
  • GitHub Check: build
  • GitHub Check: tests (18.x, 1)
  • GitHub Check: tests (18.x, 5)
  • GitHub Check: tests (18.x, 2)
  • GitHub Check: tests (18.x, 4)
  • GitHub Check: tests (18.x, 3)
  • GitHub Check: build (18.x)
  • GitHub Check: build (18.x)
🔇 Additional comments (3)
docs/docs/languages/ripple.mdx (3)

7-7: Use canonical Ripple homepage URL

As already noted by the verification agent, please swap the homepage link to the canonical domain.

Apply:

-[Ripple](https://www.ripplejs.com/)
+[Ripple](https://ripplejs.com/)

201-201: Switch params demo to RunInLiveCodes helper

Echoing the earlier review, params-based demos should go through RunInLiveCodes for consistent rendering.

Apply:

-<LiveCodes  params={importsDemo}  formatCode={false} />
+<RunInLiveCodes params={importsDemo} code={importsDemo.ripple} language="jsx" formatCode={false} />

404-424: Update documented Ripple version to current release

The version callout and JSON snippet still reference 0.2.15; please bump to the latest (0.2.23 as of 2025‑09‑06) per the prior verification note.

Apply:

-`ripple`: v0.2.15
+`ripple`: v0.2.23 (updated 2025-09-06)
-    "version": "0.2.15"
+    "version": "0.2.23"

Comment on lines +293 to 294
skipErrorChecking: true,
},
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Don't disable TypeDoc error checking globally

Turning on skipErrorChecking makes TypeDoc ignore semantic TypeScript errors, so any real typing regressions introduced by Ripple (or future work) will silently ship in the docs pipeline. Please fix the offending types or narrow the entry points instead of bypassing the checker.

-        internalModule: '_internal',
-        skipErrorChecking: true,
+        internalModule: '_internal',
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
skipErrorChecking: true,
},
internalModule: '_internal',
},
🤖 Prompt for AI Agents
In docs/docusaurus.config.ts around lines 293-294, the TypeDoc option
skipErrorChecking is set to true which disables semantic TypeScript error
checks; change this to false (or remove the option) so typedoc runs with error
checking, then run the docs build, fix the TypeScript errors reported, and if
you must limit scope instead of disabling checks, narrow the TypeDoc entryPoints
(or adjust include/exclude patterns) to only the stable packages/files that
should be documented so the checker only validates the intended surface.

@hatemhosny hatemhosny marked this pull request as draft September 27, 2025 17:29
@sonarqubecloud
Copy link

sonarqubecloud bot commented Oct 8, 2025

Quality Gate Failed Quality Gate failed

Failed conditions
27.7% Duplication on New Code (required ≤ 3%)

See analysis details on SonarQube Cloud

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants