Skip to content

Language editors#956

Merged
hatemhosny merged 10 commits intodevelopfrom
language-editors
Mar 1, 2026
Merged

Language editors#956
hatemhosny merged 10 commits intodevelopfrom
language-editors

Conversation

@hatemhosny
Copy link
Collaborator

@hatemhosny hatemhosny commented Feb 28, 2026

This PR refactors LanguageSpecs:

  • add editorSupport: loads editor language support
  • add compilerOptions to editorSupport
  • rename parser to prettier and move it inside formatter

These changes allow easily adding languages without changing code editors and compiler options.

Summary by CodeRabbit

  • New Features

    • On-demand editor integrations (Monaco, CodeMirror, CodeJar) added for many languages, plus per-language editor/compiler options and a go-to-definition helper.
  • Chores

    • Migrated many languages to a Prettier-based formatter model and centralized dynamic language specs.
    • Removed several less-common Monaco language bundles to slim ES module builds.
  • Bug Fixes

    • Formatting toolbar now appears only when an actual formatter is available; improved JSX/TypeScript editor option handling.
  • Style

    • Adjusted toolbar stacking to reduce overlap with editor UI.

@netlify
Copy link

netlify bot commented Feb 28, 2026

Deploy Preview for livecodes ready!

Name Link
🔨 Latest commit a6c7b7c
🔍 Latest deploy log https://app.netlify.com/projects/livecodes/deploys/69a380fcd84d8b0008151eb8
😎 Deploy Preview https://deploy-preview-956--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.

@github-actions
Copy link
Contributor

github-actions bot commented Feb 28, 2026

Size Change: +18.4 kB (+1.8%)

Total Size: 1.04 MB

Filename Size Change
./build/livecodes/app.js 112 kB +719 B (+0.64%)
./build/livecodes/blockly.js 15 kB +1.58 kB (+11.79%) ⚠️
./build/livecodes/codemirror.js 16 kB +9.7 kB (+154.24%) 🆘
./build/livecodes/compile.worker.js 15.1 kB +601 B (+4.14%)
./build/livecodes/editor-settings.js 19.3 kB +1.58 kB (+8.92%) 🔍
./build/livecodes/embed.js 90.7 kB +746 B (+0.83%)
./build/livecodes/format.worker.js 14.4 kB +861 B (+6.36%) 🔍
./build/livecodes/headless.js 79.3 kB +709 B (+0.9%)
./build/livecodes/import-src.js 17.8 kB +1.61 kB (+9.97%) ⚠️
./build/livecodes/import.js 16.3 kB +1.63 kB (+11.11%) ⚠️
./build/livecodes/lang-cpp-script.js 1.96 kB +225 B (+12.96%) ⚠️
./build/livecodes/lang-wat-script.js 1.97 kB +390 B (+24.65%) 🚨
./build/livecodes/monaco-lang-astro.js 0 B -947 B (removed) 🏆
./build/livecodes/monaco-lang-clio.js 0 B -639 B (removed) 🏆
./build/livecodes/monaco-lang-imba.js 0 B -7.35 kB (removed) 🏆
./build/livecodes/monaco-lang-minizinc.js 0 B -1.74 kB (removed) 🏆
./build/livecodes/monaco-lang-prolog.js 0 B -580 B (removed) 🏆
./build/livecodes/monaco-lang-wat.js 0 B -2.46 kB (removed) 🏆
./build/livecodes/monaco.js 19.9 kB +9.75 kB (+96.32%) 🆘
ℹ️ View Unchanged
Filename Size Change
./build/404.html 1 kB 0 B
./build/app.html 250 B 0 B
./build/index.html 2.47 kB +4 B (+0.16%)
./build/livecodes/app.css 22.6 kB -17 B (-0.08%)
./build/livecodes/assets.js 8.67 kB +41 B (+0.48%)
./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.74 kB +30 B (+0.81%)
./build/livecodes/broadcast.js 1.19 kB 0 B
./build/livecodes/bundle-types.js 4.41 kB +44 B (+1.01%)
./build/livecodes/code-to-image.js 9.16 kB +36 B (+0.39%)
./build/livecodes/codejar.js 17.6 kB +24 B (+0.14%)
./build/livecodes/compile.page.js 2.45 kB +46 B (+1.91%)
./build/livecodes/compiler-utils.js 3.17 kB -8 B (-0.25%)
./build/livecodes/custom-editor-utils.js 198 B 0 B
./build/livecodes/deploy.js 6.92 kB +18 B (+0.26%)
./build/livecodes/embed-ui.js 5.55 kB -7 B (-0.13%)
./build/livecodes/export.js 3.94 kB +57 B (+1.47%)
./build/livecodes/firebase.js 22.7 kB 0 B
./build/livecodes/google-fonts.js 7.12 kB 0 B
./build/livecodes/i18n-ar-language-info.json 5.34 kB 0 B
./build/livecodes/i18n-ar-translation.json 9.32 kB 0 B
./build/livecodes/i18n-bn-language-info.json 5.76 kB 0 B
./build/livecodes/i18n-bn-translation.json 9.66 kB 0 B
./build/livecodes/i18n-de-language-info.json 5.4 kB 0 B
./build/livecodes/i18n-de-translation.json 9.45 kB 0 B
./build/livecodes/i18n-en-language-info.json 4.63 kB 0 B
./build/livecodes/i18n-en-translation.json 8.04 kB 0 B
./build/livecodes/i18n-es-language-info.json 5.12 kB 0 B
./build/livecodes/i18n-es-translation.json 9.18 kB 0 B
./build/livecodes/i18n-fa-language-info.json 5.52 kB 0 B
./build/livecodes/i18n-fa-translation.json 9.47 kB 0 B
./build/livecodes/i18n-fr-language-info.json 5.31 kB 0 B
./build/livecodes/i18n-fr-translation.json 9.42 kB 0 B
./build/livecodes/i18n-hi-language-info.json 5.93 kB 0 B
./build/livecodes/i18n-hi-translation.json 9.97 kB 0 B
./build/livecodes/i18n-id-language-info.json 4.87 kB 0 B
./build/livecodes/i18n-id-translation.json 8.7 kB 0 B
./build/livecodes/i18n-it-language-info.json 5.17 kB 0 B
./build/livecodes/i18n-it-translation.json 9.25 kB 0 B
./build/livecodes/i18n-ja-language-info.json 5.72 kB 0 B
./build/livecodes/i18n-ja-translation.json 9.62 kB 0 B
./build/livecodes/i18n-nl-language-info.json 5.07 kB 0 B
./build/livecodes/i18n-nl-translation.json 8.9 kB 0 B
./build/livecodes/i18n-pt-language-info.json 5.16 kB 0 B
./build/livecodes/i18n-pt-translation.json 9.37 kB 0 B
./build/livecodes/i18n-ru-language-info.json 5.7 kB 0 B
./build/livecodes/i18n-ru-translation.json 10.3 kB 0 B
./build/livecodes/i18n-tr-language-info.json 5.3 kB 0 B
./build/livecodes/i18n-tr-translation.json 9.27 kB 0 B
./build/livecodes/i18n-ur-language-info.json 5.97 kB 0 B
./build/livecodes/i18n-ur-translation.json 9.8 kB 0 B
./build/livecodes/i18n-zh-CN-language-info.json 5.01 kB 0 B
./build/livecodes/i18n-zh-CN-translation.json 8.66 kB 0 B
./build/livecodes/i18n.js 20.4 kB +41 B (+0.2%)
./build/livecodes/index.js 5.39 kB +24 B (+0.45%)
./build/livecodes/lang-art-template-compiler.js 1.68 kB +27 B (+1.63%)
./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.37 kB +31 B (+1.33%)
./build/livecodes/lang-clio-compiler.js 1.58 kB +33 B (+2.13%)
./build/livecodes/lang-commonlisp-script.js 123 B 0 B
./build/livecodes/lang-cpp-wasm-script.js 2.88 kB +38 B (+1.34%)
./build/livecodes/lang-csharp-wasm-script.js 2.21 kB +33 B (+1.52%)
./build/livecodes/lang-diagrams-compiler-esm.js 5.11 kB +22 B (+0.43%)
./build/livecodes/lang-dot-compiler.js 1.69 kB +31 B (+1.87%)
./build/livecodes/lang-ejs-compiler.js 1.66 kB +30 B (+1.85%)
./build/livecodes/lang-eta-compiler.js 1.68 kB +28 B (+1.69%)
./build/livecodes/lang-fennel-compiler.js 1.64 kB +34 B (+2.11%)
./build/livecodes/lang-gleam-compiler.js 3.12 kB +33 B (+1.07%)
./build/livecodes/lang-go-wasm-script.js 3.29 kB +32 B (+0.98%)
./build/livecodes/lang-haml-compiler.js 1.69 kB +42 B (+2.55%)
./build/livecodes/lang-handlebars-compiler.js 1.98 kB +28 B (+1.44%)
./build/livecodes/lang-imba-compiler.js 147 B 0 B
./build/livecodes/lang-java-script.js 4.08 kB +36 B (+0.89%)
./build/livecodes/lang-jinja-compiler.js 1.67 kB +20 B (+1.22%)
./build/livecodes/lang-julia-script.js 3.32 kB +8 B (+0.24%)
./build/livecodes/lang-liquid-compiler.js 1.71 kB +31 B (+1.84%)
./build/livecodes/lang-lua-wasm-script.js 205 B 0 B
./build/livecodes/lang-malina-compiler.js 2.98 kB +19 B (+0.64%)
./build/livecodes/lang-minizinc-script.js 2.09 kB +35 B (+1.7%)
./build/livecodes/lang-mustache-compiler.js 1.68 kB +36 B (+2.19%)
./build/livecodes/lang-nunjucks-compiler.js 1.99 kB +33 B (+1.69%)
./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.76 kB +27 B (+1.56%)
./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.89 kB +30 B (+1.61%)
./build/livecodes/lang-r-script-esm.js 2.46 kB +28 B (+1.15%)
./build/livecodes/lang-rescript-compiler-esm.js 2.19 kB +37 B (+1.72%)
./build/livecodes/lang-rescript-formatter.js 1.55 kB +38 B (+2.5%)
./build/livecodes/lang-riot-compiler.js 2.84 kB +32 B (+1.14%)
./build/livecodes/lang-ruby-wasm-script.js 1.75 kB +41 B (+2.4%)
./build/livecodes/lang-scss-compiler.js 1.85 kB -2 B (-0.11%)
./build/livecodes/lang-solid-compiler.js 263 B 0 B
./build/livecodes/lang-sql-compiler.js 1.67 kB +30 B (+1.83%)
./build/livecodes/lang-sql-script.js 2.08 kB +126 B (+6.45%) 🔍
./build/livecodes/lang-svelte-compiler.js 4.72 kB +36 B (+0.77%)
./build/livecodes/lang-tcl-script.js 1.85 kB +31 B (+1.7%)
./build/livecodes/lang-teal-compiler.js 1.75 kB +31 B (+1.81%)
./build/livecodes/lang-twig-compiler.js 1.67 kB +30 B (+1.82%)
./build/livecodes/lang-vento-compiler.js 1.72 kB +36 B (+2.14%)
./build/livecodes/lang-vue-compiler.js 6.13 kB +48 B (+0.79%)
./build/livecodes/lang-vue2-compiler.js 3.5 kB +30 B (+0.86%)
./build/livecodes/lang-wat-compiler.js 348 B 0 B
./build/livecodes/language-info.js 7.91 kB -6 B (-0.08%)
./build/livecodes/open.js 6.24 kB +26 B (+0.42%)
./build/livecodes/processor-lightningcss-compiler.js 1.91 kB +33 B (+1.76%)
./build/livecodes/processor-postcss-compiler.js 2.06 kB +34 B (+1.68%)
./build/livecodes/processor-tailwindcss-compiler.js 5.3 kB +57 B (+1.09%)
./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.86 kB +49 B (+0.84%)
./build/livecodes/resources.js 3.43 kB +1 B (+0.03%)
./build/livecodes/result-utils.js 1.17 kB 0 B
./build/livecodes/share.js 3.85 kB +35 B (+0.92%)
./build/livecodes/snippets.js 6.08 kB +24 B (+0.4%)
./build/livecodes/sync-ui.js 3.29 kB +42 B (+1.29%)
./build/livecodes/sync.js 3.56 kB +22 B (+0.62%)
./build/livecodes/sync.worker.js 29.7 kB +11 B (+0.04%)
./build/livecodes/templates.js 26.6 kB +63 B (+0.24%)
./build/sdk/livecodes.js 3.95 kB 0 B
./build/sdk/livecodes.umd.js 4.02 kB 0 B
./build/sdk/package.json 292 B 0 B
./build/sdk/react.js 4.24 kB 0 B
./build/sdk/vue.js 4.36 kB 0 B

compressed-size-action

@coderabbitai
Copy link

coderabbitai bot commented Feb 28, 2026

Walkthrough

Removes several Monaco language grammar files and build entries, migrates per-language parser configs into formatter.prettier, adds editor-specific editorSupport hooks, centralizes JSX detection and language mapping, and refactors Monaco/CodeMirror loaders to load language integrations on demand.

Changes

Cohort / File(s) Summary
Build
scripts/build.js
Removed multiple Monaco language entry points from the ES module build list.
Removed Monaco grammars
src/livecodes/editor/monaco/languages/...
Deleted Monaco language definition files for astro, clio, imba, minizinc, prolog, sql, wat.
Monaco editor refactor
src/livecodes/editor/monaco/monaco.ts
Switched to spec-driven, on-demand Monaco language loading (loadMonacoLanguage), model reuse helpers, unified mapLanguage(language, 'monaco'), go-to-definition support, and merged compiler options from language specs.
CodeMirror & helpers
src/livecodes/editor/codemirror/codemirror.ts, src/livecodes/editor/codemirror/utils.ts, src/livecodes/editor/codemirror/editor-languages.ts
Added codemirrorLegacy helper and codemirrorImports; changed language support lookup to read getLanguageSpecs(...).editorSupport; reduced built-in editorLanguages to json; mapLanguage now receives editor context.
CodeJar
src/livecodes/editor/codejar/codejar.ts
mapLanguage invocation updated to pass editor context ('codejar') and removed previous two-step fallback mapping.
TypeScript env & compiler options
src/livecodes/compiler/compile.worker.ts, src/livecodes/editor/ts-compiler-options.ts
compile.worker merges global getCompilerOptions() with language-specific editorSupport.compilerOptions; getCompilerOptions signature simplified to parameterless constant return.
Core API & JSX detection
src/livecodes/core.ts, src/livecodes/languages/utils.ts
Introduced exported hasJsx(scriptLanguage) and centralized JSX detection; mapLanguage now accepts optional editor context and resolves editor-specific mappings.
Formatter types & loader
src/livecodes/formatter/format.worker.ts
Switched parser typings to PrettierParser, updated parser/formatter loader types and validation to use formatter.prettier shape.
Language specs (mass edits)
src/livecodes/languages/*/lang-*.ts
Many language specs: moved parserformatter.prettier, added editorSupport where applicable (Monaco URLs, CodeMirror dynamic loaders via codemirrorLegacy, codejar mappings, and editor/compiler options for JSX/TS). Several files added dynamic imports and vendor baseUrl usage.
Models & SDK types
src/sdk/models.ts
Added swift language; introduced LanguageEditorSupport type and optional editorSupport on LanguageSpecs; renamed ParserPrettierParser; updated LanguageFormatter union and EditorOptions.mapLanguage signature.
Vendors & config
src/livecodes/vendors.ts, tsconfig.json
Added monacoLanguagesBaseUrl and typescriptVersion exports; typescriptUrl uses version constant; TS lib bumped to es2022.
Styling & small utils
src/livecodes/styles/app.scss, src/livecodes/utils/utils.ts
Removed toolbar z-index; explicit cast to ArrayBuffer in typedArrayToBuffer().

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant App as App Core
    participant Map as mapLanguage
    participant Specs as getLanguageSpecs
    participant Editor as Editor Impl
    participant Loader as LanguageLoader

    User->>App: open file / switch language
    App->>Map: mapLanguage(lang, editor)
    Map->>Specs: getLanguageSpecs(lang)
    Specs-->>Map: LanguageSpecs (editorSupport)
    Map-->>App: mapped language id
    App->>Editor: init editor with mapped language
    Editor->>Specs: request editorSupport for mapped language
    Specs-->>Editor: editorSupport (monaco/codemirror/codejar)
    Editor->>Loader: load language support (dynamic import / URL)
    Loader-->>Editor: language support module
    Editor->>Editor: register language, compiler options, formatters
    Editor-->>App: editor ready
Loading
sequenceDiagram
    participant UI
    participant FormatterSvc as Formatter Service
    participant Worker as Format Worker
    participant Specs as getLanguageSpecs
    participant Plugins as PluginLoader

    UI->>FormatterSvc: request format(code, lang)
    FormatterSvc->>Worker: format request
    Worker->>Specs: getLanguageSpecs(lang)
    Specs-->>Worker: LanguageSpecs (formatter.prettier + pluginUrls)
    Worker->>Plugins: load Prettier + plugins (pluginUrls)
    Plugins-->>Worker: Prettier instance
    Worker->>FormatterSvc: formatted code
    FormatterSvc-->>UI: formatted result
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • sharno
🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Language editors' is vague and generic, failing to convey the specific refactoring changes (editorSupport, formatter restructuring, parser renaming) introduced in this substantial PR. Consider a more descriptive title like 'Refactor language specs: add editorSupport and move parser to formatter' to clearly communicate the primary changes.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch language-editors

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.

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: 11

🧹 Nitpick comments (8)
src/livecodes/languages/react-native/lang-react-native-tsx.ts (1)

8-13: Optional: deduplicate shared Prettier plugin list across RN specs.

This block is correct, but the same plugin URL array appears in both RN language files. Extracting a shared constant can reduce drift when plugin requirements change.

♻️ Optional refactor sketch
+// e.g. in a shared react-native language helper/module
+export const reactNativePrettierPlugins = [parserPlugins.babel, parserPlugins.html];
 formatter: {
   prettier: {
     name: 'babel-ts',
-    pluginUrls: [parserPlugins.babel, parserPlugins.html],
+    pluginUrls: reactNativePrettierPlugins,
   },
 },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/livecodes/languages/react-native/lang-react-native-tsx.ts` around lines 8
- 13, Extract the repeated Prettier pluginUrls array into a shared constant
(e.g., RN_PRETTIER_PLUGIN_URLS) and use it in the formatter.prettier
configuration instead of the inline array; update the occurrence where
formatter.prettier has name 'babel-ts' and pluginUrls: [parserPlugins.babel,
parserPlugins.html] to reference RN_PRETTIER_PLUGIN_URLS, and import or export
that constant so the other React Native TSX/TS language spec can reuse the same
value to avoid duplication and drift.
src/livecodes/editor/ts-compiler-options.ts (1)

13-15: Use named constants instead of magic numbers for compiler options.

The numeric literals (7, 99, 2) correspond to correct Monaco enum values, but storing them as module-level constants would improve maintainability and reduce drift during Monaco/TypeScript upgrades.

♻️ Suggested refactor
+const SCRIPT_TARGET_ES2020 = 7; // monaco.languages.typescript.ScriptTarget.ES2020
+const MODULE_KIND_ESNEXT = 99; // monaco.languages.typescript.ModuleKind.ESNext
+const MODULE_RESOLUTION_NODEJS = 2; // monaco.languages.typescript.ModuleResolutionKind.NodeJs
+
 export const getCompilerOptions = (): Monaco.languages.typescript.CompilerOptions => ({
   allowUmdGlobalAccess: true,
   esModuleInterop: true,
-  target: 7, // monaco.languages.typescript.ScriptTarget.ES2020,
-  module: 99, // monaco.languages.typescript.ModuleKind.ESNext,
-  moduleResolution: 2, // monaco.languages.typescript.ModuleResolutionKind.NodeJs,
+  target: SCRIPT_TARGET_ES2020,
+  module: MODULE_KIND_ESNEXT,
+  moduleResolution: MODULE_RESOLUTION_NODEJS,
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/livecodes/editor/ts-compiler-options.ts` around lines 13 - 15, Replace
the magic numbers used for compiler options with module-level named constants:
instead of numeric literals assigned to target, module, and moduleResolution
(currently 7, 99, 2), declare descriptive constants (e.g., SCRIPT_TARGET_ES2020,
MODULE_KIND_ESNEXT, MODULE_RESOLUTION_NODEJS) and use those constants when
setting target, module, and moduleResolution in ts-compiler-options.ts; if
Monaco/TypeScript enums are available (monaco.languages.typescript.ScriptTarget,
ModuleKind, ModuleResolutionKind), initialize the constants from those enums to
keep them in sync.
src/livecodes/languages/solid/lang-solid-tsx.ts (1)

19-20: checkJs is redundant without allowJs in this TypeScript configuration.

The checkJs compiler option only affects .js/.jsx files when used alongside allowJs. Since allowJs is not set, checkJs has no effect. TypeScript files are type-checked regardless of this setting.

♻️ Suggested cleanup
   editorSupport: {
     compilerOptions: {
-      checkJs: true,
       strictNullChecks: true,
       jsx: 1, // monaco.languages.typescript.JsxEmit.Preserve,
       jsxImportSource: 'solid-js',
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/livecodes/languages/solid/lang-solid-tsx.ts` around lines 19 - 20, The
tsconfig snippet sets checkJs: true while allowJs is not present, so checkJs is
a no-op; either remove checkJs from the compilerOptions in lang-solid-tsx.ts to
clean up redundant config, or explicitly add allowJs: true if you intended to
enable JS/JSX type checking—locate the compilerOptions object where checkJs and
strictNullChecks are defined and apply the appropriate change (remove checkJs OR
add allowJs: true).
src/livecodes/languages/rescript/lang-rescript-formatter.ts (1)

21-23: Empty catch block silently swallows formatting errors.

If compiler[language].format(value) throws, users won't know why formatting failed. Consider logging the error or returning error information.

💡 Suggested improvement
     } catch {
-      //
+      // Formatting failed; return original value unchanged.
+      // Consider logging: console.warn('ReScript format failed:', e);
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/livecodes/languages/rescript/lang-rescript-formatter.ts` around lines 21
- 23, The empty catch in lang-rescript-formatter.ts around the call to
compiler[language].format(value) silently swallows errors; change the catch to
capture the error (e.g., catch (err)) and log the error with context (include
language and value or a short identifier) using the existing logger (or
console.error) and then return a safe fallback (such as the original value or an
object indicating formatting failed) instead of ignoring it so callers get
diagnostics; update the block around compiler[language].format, the catch
clause, and the formatter return path accordingly.
src/livecodes/languages/jsx/lang-jsx.ts (1)

17-29: Consider extracting the magic number to a named constant for maintainability.

The value jsx: 4 correctly corresponds to monaco.languages.typescript.JsxEmit.ReactJSX, but extracting it to a named constant would improve code maintainability, especially since this pattern is repeated across multiple language files in the codebase.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/livecodes/languages/jsx/lang-jsx.ts` around lines 17 - 29, Extract the
magic number 4 used for JSX emit into a named constant and use that constant in
editorSupport.compilerOptions.jsx; specifically, define a constant (e.g.,
JSX_EMIT_REACTJSX) and replace the literal in the jsx property inside the
editorSupport object in lang-jsx.ts so the value is clear and reusable across
other language files that follow the same pattern (search for
editorSupport.compilerOptions.jsx to update other occurrences).
src/livecodes/languages/css/lang-css.ts (1)

19-28: Consistent with HTML, but differs from other languages.

Same observation as lang-html.ts — this uses a bare module specifier (@codemirror/lang-css) while most other languages use the codeMirrorBaseUrl URL pattern. If HTML and CSS are intentionally handled differently (e.g., bundled as core dependencies), a brief comment would help future maintainers understand this design choice.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/livecodes/languages/css/lang-css.ts` around lines 19 - 28, The import in
editorSupport.codemirror.languageSupport currently uses a bare specifier
('@codemirror/lang-css') unlike other languages that use the codeMirrorBaseUrl
pattern; either change this dynamic import to use the same codeMirrorBaseUrl URL
construction used elsewhere so it loads from the shared CDN/asset path, or add a
concise comment above languageSupport explaining why CSS is treated as a
core/bundled dependency (and thus uses the bare specifier) so future maintainers
understand the intentional difference.
src/livecodes/languages/html/lang-html.ts (1)

19-28: Import pattern differs from other optional languages; consider adding a comment if intentional.

HTML (and CSS) use bare module specifiers (@codemirror/lang-html) while optional languages use the codeMirrorBaseUrl + 'codemirror-lang-*.js' pattern. This suggests they're bundled or core dependencies. If intentional, a brief comment explaining the distinction would improve clarity for future maintainers.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/livecodes/languages/html/lang-html.ts` around lines 19 - 28, The import
of '@codemirror/lang-html' inside editorSupport.codemirror.languageSupport uses
a bare module specifier unlike other optional languages that use
codeMirrorBaseUrl + 'codemirror-lang-*.js'; add a short inline comment above
this import explaining that HTML (and CSS) are bundled/core dependencies and
therefore intentionally imported via bare specifiers (mentioning that optional
languages use the dynamic URL pattern) so future maintainers understand the
distinction when they see the html() import in languageSupport.
src/livecodes/languages/csharp-wasm/lang-csharp-wasm.ts (1)

9-14: Intentional use of Java parser for C# formatting.

This uses the Java Prettier parser for C# code, which is a reasonable approximation since Prettier lacks native C# support and both languages share similar syntax patterns. Consider adding a brief comment to document this design choice for future maintainers.

📝 Optional: Add clarifying comment
   formatter: {
     prettier: {
-      name: 'java',
+      name: 'java', // C# uses Java parser (closest syntax match available)
       pluginUrls: [parserPlugins.java],
     },
   },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/livecodes/languages/csharp-wasm/lang-csharp-wasm.ts` around lines 9 - 14,
Add a brief inline comment near the formatter.prettier configuration (e.g.,
above or next to the name: 'java' line) explaining that Prettier lacks a native
C# parser so the Java parser (parserPlugins.java) is intentionally used as an
approximation for C# formatting; mention that this is a conscious trade-off for
similar syntax and note to revisit if a native C# formatter becomes available.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/livecodes/editor/codejar/codejar.ts`:
- Around line 41-43: The mapLanguage implementation currently can return a
function object as a fallback; change it so mapLanguage always returns a
Language string. Replace the body of mapLanguage to call options.mapLanguage
when present and otherwise return the input lang (e.g. const mapLanguage =
(lang: Language) => options.mapLanguage?.(lang, 'codejar') ?? lang), then keep
mappedLanguage = language === 'wat' ? 'wasm' : mapLanguage(language).

In `@src/livecodes/editor/codemirror/codemirror.ts`:
- Around line 72-84: In getLanguageSupport, the fallback mistakenly indexes
editorLanguages with the outer-scope variable `language` instead of the function
parameter `lang`; update the fallback to use `lang` (i.e., replace
editorLanguages[language]?.() with editorLanguages[lang]?.()) so the function
correctly returns the intended LanguageSupport for the requested language in
getLanguageSupport.

In `@src/livecodes/editor/monaco/monaco.ts`:
- Around line 303-305: The current guard that only pushes editors when
editorId.includes('.') causes normal Monaco instances to be omitted from the
editors registry; remove that conditional and always push the editor into the
editors array so active Monaco instances are registered (locate the block
referencing editorId and editors in monaco.ts and update the registration logic
in the function that builds the editors registry to unconditionally add the
editor).
- Around line 242-244: The code marks a language as loaded before its dynamic
initializer succeeds (loadedLanguages.add(lang) runs too early), preventing
retries after a failed import/initialization; change the flow in the block
handling langSupport/loadLanguage so that you only add to loadedLanguages after
the loadLanguage promise resolves successfully (or the initializer completes),
and on any error catch and do not add (or remove) the lang from loadedLanguages
so subsequent attempts can retry; update the error handling around
loadLanguage/initialize logic to ensure failures aren’t cached.

In `@src/livecodes/languages/javascript/lang-javascript.ts`:
- Around line 19-28: Replace the bare dynamic import of
'@codemirror/lang-javascript' inside the
editorSupport.codemirror.languageSupport async function with a CDN-based import
using codeMirrorBaseUrl (same pattern used elsewhere): compute the module URL by
concatenating codeMirrorBaseUrl + 'codemirror-lang-javascript.js', await
import(...) from that URL, then call .javascript() on the imported module and
return it; ensure the change is applied similarly for the other language files
(lang-typescript.ts, lang-jsx.ts, lang-tsx.ts, lang-html.ts, lang-css.ts) so all
editorSupport.codemirror.languageSupport functions use codeMirrorBaseUrl instead
of bare '@codemirror' specifiers.

In `@src/livecodes/languages/jsx/lang-tsx.ts`:
- Around line 17-31: The dynamic import in
editorSupport.codemirror.languageSupport (the async function that does await
import('@codemirror/lang-javascript')) triggers the same module resolution/build
failure as in lang-typescript.ts; fix it by replacing the dynamic import with a
static top-level import of { javascript } from '@codemirror/lang-javascript' and
change the languageSupport implementation to synchronously return javascript({
jsx: true, typescript: true }); update any added import accordingly and remove
the async/dynamic import code inside languageSupport.

In `@src/livecodes/languages/pug/lang-pug.ts`:
- Around line 9-16: Remove the stale explanatory comment above the formatter
configuration and leave the formatter.prettier block intact; specifically delete
the two-line comment referencing `@prettier/plugin-pug` support for Prettier v3
while keeping the existing formatter: { prettier: { name: 'pug', pluginUrls:
[parserPlugins.pug], }, } configuration and ensure there are no leftover TODOs
or disabling notes around parserPlugins.pug.

In `@src/livecodes/languages/typescript/lang-typescript.ts`:
- Line 14: The RegExp construction in lang-typescript.ts using new RegExp is
suffering from alternation precedence so the second token can match outside the
JSDoc comment; update the pattern used in that new RegExp call so the
alternation is grouped immediately after the JSDoc prefix (i.e., ensure the
prefix matching '/**' plus following whitespace/asterisks is required before
either '@jsx' or '@jsxImportSource'), use a grouped alternation (prefer a
non-capturing group) and keep the trailing whitespace matcher and global flag
intact.
- Around line 51-64: Change the dynamic bare import of
'@codemirror/lang-javascript' inside the languageSupport async function to use
the codeMirrorBaseUrl pattern like other language files: replace the await
import('@codemirror/lang-javascript') call in the languageSupport implementation
(function name: languageSupport) with await import(codeMirrorBaseUrl +
'codemirror-lang-javascript.js') and keep returning javascript({ typescript:
true }); so the module resolves consistently with the build externals; apply the
same pattern for the analogous imports in the JavaScript, JSX and TSX language
modules.

In `@src/livecodes/languages/vue/lang-vue.ts`:
- Line 57: The current spread in editorSupport for vue-app replaces the entire
monaco object and drops vue.editorSupport.monaco.languageSupport; update the
override so you merge nested properties instead of replacing monaco: when
setting editorSupport on the vue-app entry, keep the outer spread of
vue.editorSupport and set monaco to a nested spread that preserves existing
monaco fields (referencing editorSupport, vue.editorSupport, and monaco) while
only changing the language property to 'vue' so languageSupport remains intact.

In `@src/livecodes/utils/utils.ts`:
- Around line 232-233: The function typedArrayToBuffer narrows a possibly
SharedArrayBuffer-backed Uint8Array to ArrayBuffer using a cast; replace that
unsafe cast by creating a fresh ArrayBuffer-backed copy—use
Uint8Array.from(array).buffer (or equivalent) to produce a new Uint8Array copy
and return its .buffer so the function always returns a true ArrayBuffer
suitable for WebAssembly instantiation; update typedArrayToBuffer to construct
the copy from the input parameter `array` and return its .buffer.

---

Nitpick comments:
In `@src/livecodes/editor/ts-compiler-options.ts`:
- Around line 13-15: Replace the magic numbers used for compiler options with
module-level named constants: instead of numeric literals assigned to target,
module, and moduleResolution (currently 7, 99, 2), declare descriptive constants
(e.g., SCRIPT_TARGET_ES2020, MODULE_KIND_ESNEXT, MODULE_RESOLUTION_NODEJS) and
use those constants when setting target, module, and moduleResolution in
ts-compiler-options.ts; if Monaco/TypeScript enums are available
(monaco.languages.typescript.ScriptTarget, ModuleKind, ModuleResolutionKind),
initialize the constants from those enums to keep them in sync.

In `@src/livecodes/languages/csharp-wasm/lang-csharp-wasm.ts`:
- Around line 9-14: Add a brief inline comment near the formatter.prettier
configuration (e.g., above or next to the name: 'java' line) explaining that
Prettier lacks a native C# parser so the Java parser (parserPlugins.java) is
intentionally used as an approximation for C# formatting; mention that this is a
conscious trade-off for similar syntax and note to revisit if a native C#
formatter becomes available.

In `@src/livecodes/languages/css/lang-css.ts`:
- Around line 19-28: The import in editorSupport.codemirror.languageSupport
currently uses a bare specifier ('@codemirror/lang-css') unlike other languages
that use the codeMirrorBaseUrl pattern; either change this dynamic import to use
the same codeMirrorBaseUrl URL construction used elsewhere so it loads from the
shared CDN/asset path, or add a concise comment above languageSupport explaining
why CSS is treated as a core/bundled dependency (and thus uses the bare
specifier) so future maintainers understand the intentional difference.

In `@src/livecodes/languages/html/lang-html.ts`:
- Around line 19-28: The import of '@codemirror/lang-html' inside
editorSupport.codemirror.languageSupport uses a bare module specifier unlike
other optional languages that use codeMirrorBaseUrl + 'codemirror-lang-*.js';
add a short inline comment above this import explaining that HTML (and CSS) are
bundled/core dependencies and therefore intentionally imported via bare
specifiers (mentioning that optional languages use the dynamic URL pattern) so
future maintainers understand the distinction when they see the html() import in
languageSupport.

In `@src/livecodes/languages/jsx/lang-jsx.ts`:
- Around line 17-29: Extract the magic number 4 used for JSX emit into a named
constant and use that constant in editorSupport.compilerOptions.jsx;
specifically, define a constant (e.g., JSX_EMIT_REACTJSX) and replace the
literal in the jsx property inside the editorSupport object in lang-jsx.ts so
the value is clear and reusable across other language files that follow the same
pattern (search for editorSupport.compilerOptions.jsx to update other
occurrences).

In `@src/livecodes/languages/react-native/lang-react-native-tsx.ts`:
- Around line 8-13: Extract the repeated Prettier pluginUrls array into a shared
constant (e.g., RN_PRETTIER_PLUGIN_URLS) and use it in the formatter.prettier
configuration instead of the inline array; update the occurrence where
formatter.prettier has name 'babel-ts' and pluginUrls: [parserPlugins.babel,
parserPlugins.html] to reference RN_PRETTIER_PLUGIN_URLS, and import or export
that constant so the other React Native TSX/TS language spec can reuse the same
value to avoid duplication and drift.

In `@src/livecodes/languages/rescript/lang-rescript-formatter.ts`:
- Around line 21-23: The empty catch in lang-rescript-formatter.ts around the
call to compiler[language].format(value) silently swallows errors; change the
catch to capture the error (e.g., catch (err)) and log the error with context
(include language and value or a short identifier) using the existing logger (or
console.error) and then return a safe fallback (such as the original value or an
object indicating formatting failed) instead of ignoring it so callers get
diagnostics; update the block around compiler[language].format, the catch
clause, and the formatter return path accordingly.

In `@src/livecodes/languages/solid/lang-solid-tsx.ts`:
- Around line 19-20: The tsconfig snippet sets checkJs: true while allowJs is
not present, so checkJs is a no-op; either remove checkJs from the
compilerOptions in lang-solid-tsx.ts to clean up redundant config, or explicitly
add allowJs: true if you intended to enable JS/JSX type checking—locate the
compilerOptions object where checkJs and strictNullChecks are defined and apply
the appropriate change (remove checkJs OR add allowJs: true).

ℹ️ Review info

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 45c8e71 and e3a3bae.

📒 Files selected for processing (92)
  • scripts/build.js
  • src/livecodes/compiler/compile.worker.ts
  • src/livecodes/core.ts
  • src/livecodes/editor/codejar/codejar.ts
  • src/livecodes/editor/codemirror/codemirror.ts
  • src/livecodes/editor/codemirror/editor-languages.ts
  • src/livecodes/editor/codemirror/utils.ts
  • src/livecodes/editor/monaco/languages/monaco-lang-astro.ts
  • src/livecodes/editor/monaco/languages/monaco-lang-clio.ts
  • src/livecodes/editor/monaco/languages/monaco-lang-imba.ts
  • src/livecodes/editor/monaco/languages/monaco-lang-minizinc.ts
  • src/livecodes/editor/monaco/languages/monaco-lang-prolog.ts
  • src/livecodes/editor/monaco/languages/monaco-lang-sql.ts
  • src/livecodes/editor/monaco/languages/monaco-lang-wat.ts
  • src/livecodes/editor/monaco/monaco.ts
  • src/livecodes/editor/ts-compiler-options.ts
  • src/livecodes/formatter/format.worker.ts
  • src/livecodes/languages/art-template/lang-art-template.ts
  • src/livecodes/languages/assemblyscript/lang-assemblyscript.ts
  • src/livecodes/languages/astro/lang-astro.ts
  • src/livecodes/languages/babel/lang-babel.ts
  • src/livecodes/languages/clojurescript/lang-clojurescript.ts
  • src/livecodes/languages/coffeescript/lang-coffeescript.ts
  • src/livecodes/languages/commonlisp/lang-commonlisp.ts
  • src/livecodes/languages/cpp/lang-cpp.ts
  • src/livecodes/languages/csharp-wasm/lang-csharp-wasm.ts
  • src/livecodes/languages/css/lang-css.ts
  • src/livecodes/languages/diagrams/lang-diagrams.ts
  • src/livecodes/languages/dot/lang-dot.ts
  • src/livecodes/languages/ejs/lang-ejs.ts
  • src/livecodes/languages/eta/lang-eta.ts
  • src/livecodes/languages/flow/lang-flow.ts
  • src/livecodes/languages/gleam/lang-gleam.ts
  • src/livecodes/languages/go/lang-go.ts
  • src/livecodes/languages/handlebars/lang-handlebars.ts
  • src/livecodes/languages/html/lang-html.ts
  • src/livecodes/languages/java/lang-java.ts
  • src/livecodes/languages/javascript/lang-javascript.ts
  • src/livecodes/languages/jsx/lang-jsx.ts
  • src/livecodes/languages/jsx/lang-tsx.ts
  • src/livecodes/languages/julia/lang-julia.ts
  • src/livecodes/languages/less/lang-less.ts
  • src/livecodes/languages/liquid/lang-liquid.ts
  • src/livecodes/languages/livescript/lang-livescript.ts
  • src/livecodes/languages/lua/lang-lua.ts
  • src/livecodes/languages/malina/lang-malina.ts
  • src/livecodes/languages/markdown/lang-markdown.ts
  • src/livecodes/languages/mdx/lang-mdx.ts
  • src/livecodes/languages/minizinc/lang-minizinc.ts
  • src/livecodes/languages/mjml/lang-mjml.ts
  • src/livecodes/languages/mustache/lang-mustache.ts
  • src/livecodes/languages/nunjucks/lang-nunjucks.ts
  • src/livecodes/languages/ocaml/lang-ocaml.ts
  • src/livecodes/languages/perl/lang-perl.ts
  • src/livecodes/languages/php-wasm/lang-php-wasm.ts
  • src/livecodes/languages/php/lang-php.ts
  • src/livecodes/languages/prolog/lang-prolog.ts
  • src/livecodes/languages/pug/lang-pug.ts
  • src/livecodes/languages/python/lang-python.ts
  • src/livecodes/languages/r/lang-r.ts
  • src/livecodes/languages/react-native/lang-react-native-tsx.ts
  • src/livecodes/languages/react-native/lang-react-native.ts
  • src/livecodes/languages/react/lang-react-tsx.ts
  • src/livecodes/languages/react/lang-react.ts
  • src/livecodes/languages/reason/lang-reason.ts
  • src/livecodes/languages/rescript/lang-rescript-formatter.ts
  • src/livecodes/languages/rescript/lang-rescript.ts
  • src/livecodes/languages/riot/lang-riot.ts
  • src/livecodes/languages/ruby/lang-ruby.ts
  • src/livecodes/languages/scheme/lang-scheme.ts
  • src/livecodes/languages/scss/lang-sass.ts
  • src/livecodes/languages/scss/lang-scss.ts
  • src/livecodes/languages/solid/lang-solid-tsx.ts
  • src/livecodes/languages/solid/lang-solid.ts
  • src/livecodes/languages/sql/lang-sql.ts
  • src/livecodes/languages/stencil/lang-stencil.ts
  • src/livecodes/languages/stylus/lang-stylus.ts
  • src/livecodes/languages/sucrase/lang-sucrase.ts
  • src/livecodes/languages/svelte/lang-svelte.ts
  • src/livecodes/languages/tcl/lang-tcl.ts
  • src/livecodes/languages/twig/lang-twig.ts
  • src/livecodes/languages/typescript/lang-typescript.ts
  • src/livecodes/languages/utils.ts
  • src/livecodes/languages/vento/lang-vento.ts
  • src/livecodes/languages/vue/lang-vue.ts
  • src/livecodes/languages/vue2/lang-vue2.ts
  • src/livecodes/languages/wat/lang-wat.ts
  • src/livecodes/styles/app.scss
  • src/livecodes/utils/utils.ts
  • src/livecodes/vendors.ts
  • src/sdk/models.ts
  • tsconfig.json
💤 Files with no reviewable changes (9)
  • scripts/build.js
  • src/livecodes/editor/monaco/languages/monaco-lang-prolog.ts
  • src/livecodes/editor/monaco/languages/monaco-lang-wat.ts
  • src/livecodes/editor/monaco/languages/monaco-lang-astro.ts
  • src/livecodes/styles/app.scss
  • src/livecodes/editor/monaco/languages/monaco-lang-clio.ts
  • src/livecodes/editor/monaco/languages/monaco-lang-sql.ts
  • src/livecodes/editor/monaco/languages/monaco-lang-imba.ts
  • src/livecodes/editor/monaco/languages/monaco-lang-minizinc.ts

Comment on lines 41 to 43
const mapLanguage = (lang: Language) =>
options.mapLanguage?.(lang, 'codejar') || ((lang: Language) => lang);
let mappedLanguage = language === 'wat' ? 'wasm' : mapLanguage(language);
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Fix fallback bug: mapLanguage returns a function instead of a language value.

At Line 42, the fallback expression returns a function object, not lang. This makes mappedLanguage invalid (e.g., class name becomes language-(lang)=>lang) when options.mapLanguage is absent.

🐛 Proposed fix
-  const mapLanguage = (lang: Language) =>
-    options.mapLanguage?.(lang, 'codejar') || ((lang: Language) => lang);
+  const mapLanguage = (lang: Language) => options.mapLanguage?.(lang, 'codejar') || lang;
📝 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 mapLanguage = (lang: Language) =>
options.mapLanguage?.(lang, 'codejar') || ((lang: Language) => lang);
let mappedLanguage = language === 'wat' ? 'wasm' : mapLanguage(language);
const mapLanguage = (lang: Language) => options.mapLanguage?.(lang, 'codejar') || lang;
let mappedLanguage = language === 'wat' ? 'wasm' : mapLanguage(language);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/livecodes/editor/codejar/codejar.ts` around lines 41 - 43, The
mapLanguage implementation currently can return a function object as a fallback;
change it so mapLanguage always returns a Language string. Replace the body of
mapLanguage to call options.mapLanguage when present and otherwise return the
input lang (e.g. const mapLanguage = (lang: Language) =>
options.mapLanguage?.(lang, 'codejar') ?? lang), then keep mappedLanguage =
language === 'wat' ? 'wasm' : mapLanguage(language).

Comment on lines +242 to +244
if (langSupport && !loadedLanguages.has(lang)) {
loadedLanguages.add(lang);
const loadLanguage =
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Don’t mark a language as loaded before support initialization succeeds.

A failed dynamic import/initializer currently still caches the language as loaded, which prevents any retry in the same session.

🔧 Suggested fix
-    if (langSupport && !loadedLanguages.has(lang)) {
-      loadedLanguages.add(lang);
+    if (langSupport && !loadedLanguages.has(lang)) {
       const loadLanguage =
         typeof langSupport === 'string'
           ? (await import(langSupport)).default
           : typeof langSupport === 'function'
             ? langSupport
             : () => undefined;
       await loadLanguage(monaco, () => editor);
+      loadedLanguages.add(lang);
     }
📝 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
if (langSupport && !loadedLanguages.has(lang)) {
loadedLanguages.add(lang);
const loadLanguage =
if (langSupport && !loadedLanguages.has(lang)) {
const loadLanguage =
typeof langSupport === 'string'
? (await import(langSupport)).default
: typeof langSupport === 'function'
? langSupport
: () => undefined;
await loadLanguage(monaco, () => editor);
loadedLanguages.add(lang);
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/livecodes/editor/monaco/monaco.ts` around lines 242 - 244, The code marks
a language as loaded before its dynamic initializer succeeds
(loadedLanguages.add(lang) runs too early), preventing retries after a failed
import/initialization; change the flow in the block handling
langSupport/loadLanguage so that you only add to loadedLanguages after the
loadLanguage promise resolves successfully (or the initializer completes), and
on any error catch and do not add (or remove) the lang from loadedLanguages so
subsequent attempts can retry; update the error handling around
loadLanguage/initialize logic to ensure failures aren’t cached.

Comment on lines +303 to 305
if (editorId.includes('.')) {
editors.push(editor);
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Editor registry condition breaks Monaco cross-editor features.

editorId.includes('.') filters out normal editor IDs, so editors misses active Monaco instances. This breaks downstream logic that depends on that registry (e.g., script-model linkage for tests and in-app go-to-definition targeting).

🔧 Suggested fix
-  if (editorId.includes('.')) {
-    editors.push(editor);
-  }
+  editors.push(editor);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/livecodes/editor/monaco/monaco.ts` around lines 303 - 305, The current
guard that only pushes editors when editorId.includes('.') causes normal Monaco
instances to be omitted from the editors registry; remove that conditional and
always push the editor into the editors array so active Monaco instances are
registered (locate the block referencing editorId and editors in monaco.ts and
update the registration logic in the function that builds the editors registry
to unconditionally add the editor).

Comment on lines 9 to 16
// disable formatter, till @prettier/plugin-pug supports prettier v3
// (https://github.com/prettier/plugin-pug/pull/411)
parser: {
name: 'pug',
pluginUrls: [parserPlugins.pug],
formatter: {
prettier: {
name: 'pug',
pluginUrls: [parserPlugins.pug],
},
},
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🌐 Web query:

@prettier/plugin-pug prettier v3 support

💡 Result:

@prettier/plugin-pug does support Prettier v3—current main branch package.json declares peerDependencies: { "prettier": "^3.0.0" } and the package is ESM ("type": "module"). [1]

What to do:

  • Upgrade to a v3.x release of the plugin and Prettier v3, e.g.
    • npm i -D prettier@^3 @prettier/plugin-pug@^3 [1]
  • If you run Prettier via CLI and it doesn’t auto-load plugins, explicitly pass it:
    • prettier --write "**/*.pug" --plugin=@prettier/plugin-pug [2]

(Prettier v3 changed plugin loading/APIs and moved to ESM-first behavior, so older plugin versions can break.) [3]

Sources: [1] [2] [3]


🏁 Script executed:

# Let's examine the actual file to confirm the current state
head -20 src/livecodes/languages/pug/lang-pug.ts

Repository: live-codes/livecodes

Length of output: 599


Remove stale comment: @prettier/plugin-pug now supports Prettier v3.

The comment on lines 9-10 is outdated. The plugin has released v3.x versions with support for Prettier v3. Delete the comment block and keep the formatter.prettier configuration as-is since it is correctly defined and no longer needs to be disabled.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/livecodes/languages/pug/lang-pug.ts` around lines 9 - 16, Remove the
stale explanatory comment above the formatter configuration and leave the
formatter.prettier block intact; specifically delete the two-line comment
referencing `@prettier/plugin-pug` support for Prettier v3 while keeping the
existing formatter: { prettier: { name: 'pug', pluginUrls: [parserPlugins.pug],
}, } configuration and ensure there are no leftover TODOs or disabling notes
around parserPlugins.pug.

Comment on lines 51 to 64
editorSupport: {
codemirror: {
languageSupport: async () => {
// @ts-ignore
// eslint-disable-next-line import/no-unresolved
const { javascript } = await import('@codemirror/lang-javascript');
return javascript({ typescript: true });
},
},
compilerOptions: {
checkJs: true,
strictNullChecks: 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 | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# First, let's find all language files to understand the structure
find src/livecodes/languages -type f -name "lang-*.ts" | head -20

Repository: live-codes/livecodes

Length of output: 1152


🏁 Script executed:

#!/bin/bash
# Check how other language files handle codemirror imports
rg -n "codeMirrorBaseUrl" --type ts src/livecodes/languages/ -A 5 -B 2

Repository: live-codes/livecodes

Length of output: 33509


🏁 Script executed:

#!/bin/bash
# Check how the typescript file currently imports codemirror
cat -n src/livecodes/languages/typescript/lang-typescript.ts | head -70

Repository: live-codes/livecodes

Length of output: 2404


🏁 Script executed:

#!/bin/bash
# Look for the vendors file mentioned in the diff
find src -name "vendors*" -type f

Repository: live-codes/livecodes

Length of output: 88


🏁 Script executed:

#!/bin/bash
# Check the vendors.ts file
head -100 src/livecodes/vendors.ts | grep -A 5 -B 2 "codeMirrorBaseUrl"

Repository: live-codes/livecodes

Length of output: 304


🏁 Script executed:

#!/bin/bash
# Search for any reference to javascript language support in codemirror
rg -i "javascript" src/livecodes/vendors.ts -A 2 -B 2

Repository: live-codes/livecodes

Length of output: 46


🏁 Script executed:

#!/bin/bash
# Check if there's any existing reference to `@codemirror/lang-javascript` elsewhere in the project
rg "@codemirror/lang-javascript" --type ts

Repository: live-codes/livecodes

Length of output: 555


🏁 Script executed:

#!/bin/bash
# Look for package.json to see dependencies
find . -name "package.json" -type f | head -5

Repository: live-codes/livecodes

Length of output: 145


🏁 Script executed:

#!/bin/bash
# Check if there's a codemirror-lang-javascript.js file in the expected location
rg "codemirror-lang-javascript" --type ts

Repository: live-codes/livecodes

Length of output: 46


🏁 Script executed:

#!/bin/bash
# Check the JavaScript language file to understand the context better
cat -n src/livecodes/languages/javascript/lang-javascript.ts | head -70

Repository: live-codes/livecodes

Length of output: 986


🏁 Script executed:

#!/bin/bash
# Look for how the `@codemirror/lang-javascript` import is resolved - check tsconfig or bundler config
find . -name "tsconfig.json" -o -name "webpack.config.js" -o -name "vite.config.ts" -o -name "rollup.config.js" | head -5

Repository: live-codes/livecodes

Length of output: 126


🏁 Script executed:

#!/bin/bash
# Check JSX and TSX language files
cat -n src/livecodes/languages/jsx/lang-jsx.ts | head -40
echo "---"
cat -n src/livecodes/languages/jsx/lang-tsx.ts | head -40

Repository: live-codes/livecodes

Length of output: 2129


🏁 Script executed:

#!/bin/bash
# Check if there's a codemirror-lang-javascript.js referenced anywhere
find src -type f -name "*.ts" -exec grep -l "codemirror-lang-javascript" {} \;

Repository: live-codes/livecodes

Length of output: 46


🏁 Script executed:

#!/bin/bash
# Check build output or dist to see if pre-built files exist
find . -path ./node_modules -prune -o -type f -name "*codemirror-lang-javascript*" -print 2>/dev/null

Repository: live-codes/livecodes

Length of output: 46


🏁 Script executed:

#!/bin/bash
# Check if there's any special bundler handling for `@codemirror` imports
cat tsconfig.json | grep -A 10 "compilerOptions"

Repository: live-codes/livecodes

Length of output: 546


🏁 Script executed:

#!/bin/bash
# Look at the root package.json to understand build setup
head -50 package.json

Repository: live-codes/livecodes

Length of output: 2757


🏁 Script executed:

#!/bin/bash
# Check for any webpack/vite alias configuration that might handle `@codemirror` imports
rg "alias|@codemirror" tsconfig.json package.json vite.config.ts webpack.config.js 2>/dev/null | head -20

Repository: live-codes/livecodes

Length of output: 46


🏁 Script executed:

#!/bin/bash
# Look for build output structure to see if there are pre-built modules
ls -la src/livecodes/vendors/ 2>/dev/null || echo "vendors dir not found"

Repository: live-codes/livecodes

Length of output: 85


🏁 Script executed:

#!/bin/bash
# Check the build script to understand how modules are resolved
head -100 scripts/build.js 2>/dev/null || echo "Not found in head"

Repository: live-codes/livecodes

Length of output: 3290


🏁 Script executed:

#!/bin/bash
# Final check: look for any existing codemirror-lang-javascript references in build outputs or documentation
rg "codemirror.*javascript" --type ts --type js -i

Repository: live-codes/livecodes

Length of output: 555


Apply codeMirrorBaseUrl pattern to JavaScript, TypeScript, JSX, and TSX editor support—this is inconsistent with all other language files and conflicts with build configuration.

The bare @codemirror/lang-javascript import is used in four files (JavaScript, TypeScript, JSX, TSX), while all other language files use codeMirrorBaseUrl + 'codemirror-lang-*.js'. Since @codemirror/* is marked external in the build configuration, the bare import may fail to resolve.

Affected files and suggested fix

Files to update:

  • src/livecodes/languages/typescript/lang-typescript.ts (line 56)
  • src/livecodes/languages/javascript/lang-javascript.ts (line 24)
  • src/livecodes/languages/jsx/lang-jsx.ts (line 22)
  • src/livecodes/languages/jsx/lang-tsx.ts (line 22)

Replace the bare import with the codeMirrorBaseUrl pattern used by all other language files:

+import { codeMirrorBaseUrl } from '../../vendors';
+
 editorSupport: {
   codemirror: {
     languageSupport: async () => {
-      // `@ts-ignore`
-      // eslint-disable-next-line import/no-unresolved
-      const { javascript } = await import('@codemirror/lang-javascript');
+      const { javascript } = await import(codeMirrorBaseUrl + 'codemirror-lang-javascript.js');
       return javascript({ typescript: true });
     },
   },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/livecodes/languages/typescript/lang-typescript.ts` around lines 51 - 64,
Change the dynamic bare import of '@codemirror/lang-javascript' inside the
languageSupport async function to use the codeMirrorBaseUrl pattern like other
language files: replace the await import('@codemirror/lang-javascript') call in
the languageSupport implementation (function name: languageSupport) with await
import(codeMirrorBaseUrl + 'codemirror-lang-javascript.js') and keep returning
javascript({ typescript: true }); so the module resolves consistently with the
build externals; apply the same pattern for the analogous imports in the
JavaScript, JSX and TSX language modules.

extensions: ['app.vue'],
editor: 'markup',
editorLanguage: 'html',
editorSupport: { ...vue.editorSupport, monaco: { language: 'vue' } }, // avoid duplicate registration
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "1) Inspect LanguageSpecs/editorSupport shape"
rg -n -C3 "interface LanguageSpecs|type LanguageSpecs|editorSupport|languageSupport|compilerOptions" src/livecodes

echo
echo "2) Inspect Monaco integration path for languageSupport usage"
rg -n -C4 "editorSupport\.monaco|languageSupport|language:\s*'|importScripts|load.*language" \
  src/livecodes/editor/monaco src/livecodes/core.ts src/livecodes/compiler/compile.worker.ts

echo
echo "3) Compare patterns in other *-app language specs"
rg -n -C2 "name:\s*'.*-app'|editorSupport:\s*\{\s*\.\.\.[^\\n]*editorSupport|monaco:\s*\{.*language:" \
  src/livecodes/languages

Repository: live-codes/livecodes

Length of output: 50376


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== 1) Examine vue language spec definition ==="
sed -n '30,50p' src/livecodes/languages/vue/lang-vue.ts

echo
echo "=== 2) Examine vue-app language spec definition ==="
sed -n '50,60p' src/livecodes/languages/vue/lang-vue.ts

echo
echo "=== 3) Check if there's a fallback for missing languageSupport ==="
rg -n "languageSupport|getLanguageSpecs.*vue|loadMonacoLanguage" \
  src/livecodes/editor/monaco/monaco.ts -A2 -B2 | head -100

echo
echo "=== 4) Look for where vue spec is registered/used ==="
rg -n "vue.*editorSupport|vueApp.*editorSupport|getLanguageSpecs.*vue" \
  src/livecodes --type ts -A3 | head -80

echo
echo "=== 5) Check how editorLanguage is used for vue-app ==="
rg -n "editorLanguage.*vue|getEditorLanguageByAlias" \
  src/livecodes/languages/vue/lang-vue.ts -A2

echo
echo "=== 6) Search for 'vue-app' to see if it aliases to 'vue' ==="
rg -n "vue-app" src/livecodes --type ts -B2 -A2 | head -50

Repository: live-codes/livecodes

Length of output: 2153


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== How is the 'language' property used in monaco editorSupport? ==="
rg -n "editorSupport.*language|\.language\s*:" src/livecodes/languages --type ts -B1 -A1 | head -100

echo
echo "=== Search for usage of editorSupport.monaco.language ==="
rg -n "\.monaco\.language|language:\s*'vue'|language:\s*'svelte'" src/livecodes --type ts -B2 -A2 | head -80

echo
echo "=== Check getEditorLanguageByAlias implementation ==="
rg -n "getEditorLanguageByAlias" src/livecodes/languages/utils.ts -A5

echo
echo "=== Check how vue is set as editor for vue-app ==="
sed -n '48,62p' src/livecodes/languages/vue/lang-vue.ts

echo
echo "=== Look for language registration patterns ==="
rg -n "registerLanguage|setMonacoTheme|loadMonaco" src/livecodes/editor/monaco/monaco.ts | head -20

Repository: live-codes/livecodes

Length of output: 3941


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Check how model language is set in Monaco ==="
rg -n "setModel|model.*language|createModel" src/livecodes/editor/monaco/monaco.ts -B2 -A2 | head -60

echo
echo "=== Check loadMonacoLanguage function in detail ==="
sed -n '240,260p' src/livecodes/editor/monaco/monaco.ts

echo
echo "=== Check getLanguageByAlias implementation ==="
rg -n "getLanguageByAlias" src/livecodes/languages/utils.ts -B3 -A8

Repository: live-codes/livecodes

Length of output: 4121


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Check mapLanguage function to understand language mapping ==="
rg -n "export.*mapLanguage|function mapLanguage" src/livecodes --type ts -A8 | head -40

echo
echo "=== Check if 'vue' language spec is registered globally or on-demand ==="
rg -n "vue.*registerLanguage|registerLanguage.*vue" src/livecodes --type ts -B2 -A2

echo
echo "=== Check the actual call to loadMonacoLanguage for setLanguage ==="
sed -n '395,420p' src/livecodes/editor/monaco/monaco.ts

echo
echo "=== Verify vue-app inherits from vue properly ==="
cat src/livecodes/languages/vue/lang-vue.ts

Repository: live-codes/livecodes

Length of output: 834


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Full lang-vue.ts file ==="
cat src/livecodes/languages/vue/lang-vue.ts

echo
echo "=== setLanguage implementation in Monaco ==="
sed -n '395,430p' src/livecodes/editor/monaco/monaco.ts

Repository: live-codes/livecodes

Length of output: 2766


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Check if vue is preloaded or guaranteed to load ==="
rg -n "preload|vue.*load|loadLanguage" src/livecodes/core.ts -B2 -A2 | head -80

echo
echo "=== Check how languages are initialized ==="
rg -n "languages.*initialize|setupLanguages" src/livecodes --type ts | head -20

echo
echo "=== Check setModel to see if language maps to 'vue' somewhere ==="
sed -n '256,302p' src/livecodes/editor/monaco/monaco.ts

echo
echo "=== Verify what mapLanguage returns for 'vue-app' ==="
rg -n "editorLanguage.*vue" src/livecodes/languages/vue/lang-vue.ts

Repository: live-codes/livecodes

Length of output: 119


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Understand the flow: trace what happens when setModel is called with language='vue' ==="
echo "Step 1: Check how editorSupport affects model creation"
sed -n '256,310p' src/livecodes/editor/monaco/monaco.ts

echo
echo "Step 2: Check if there's a default Monaco language registration or fallback"
rg -n "registerLanguage|languages.register|onLanguage" src/livecodes/editor/monaco --type ts | head -30

echo
echo "Step 3: Trace what mapLanguage('vue-app', 'monaco') returns"
echo "It should call: getLanguageSpecs('vue-app')?.editorSupport?.['monaco']?.language"
echo "Which accesses: vueApp.editorSupport.monaco.language = 'vue'"

echo
echo "Step 4: But is 'vue' language actually registered in Monaco before being needed?"
rg -n "vue.editorSupport.monaco.languageSupport|monacoLanguagesBaseUrl.*vue" src/livecodes --type ts

Repository: live-codes/livecodes

Length of output: 3237


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Critical: Trace the exact issue ==="
echo "When vue-app is opened:"
echo "1. loadMonacoLanguage('vue-app') is called"
echo "2. It tries to get: getLanguageSpecs('vue-app')?.editorSupport?.monaco?.languageSupport"
echo "3. But vueApp.editorSupport.monaco = { language: 'vue' } (NO languageSupport!)"
echo "4. So nothing is loaded"
echo "5. Then setModel tries to create a model with language='vue' (mapped from vue-app)"
echo "6. But if 'vue' language support was never loaded, Monaco might fail"
echo ""

echo "=== Check if there's a fallback or if vue language is always pre-registered ==="
rg -n "createModel.*vue|getLanguageId|language.*vue" src/livecodes/editor/monaco/monaco.ts -B1 -A1 | head -40

echo
echo "=== Check if vue is loaded elsewhere or pre-registered ==="
rg -n "loadMonacoLanguage\('vue'\)|vue.*registerLanguage" src/livecodes --type ts

echo
echo "=== Compare with svelte-app to see if it has the same issue ==="
cat src/livecodes/languages/svelte/lang-svelte.ts

Repository: live-codes/livecodes

Length of output: 972


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Check if 'vue' language is built-in to Monaco or must be loaded ==="
rg -n "monaco.languages.*define|builtinLanguages" src/livecodes/editor/monaco --type ts | head -20

echo
echo "=== Check what happens if languageSupport is undefined in loadMonacoLanguage ==="
sed -n '240,253p' src/livecodes/editor/monaco/monaco.ts

echo
echo "=== Check if there's initialization that loads all language supports ==="
rg -n "initialize.*languages|loadAll|preload" src/livecodes --type ts -B2 -A4 | head -60

echo
echo "=== Look for where languages are registered/initialized ==="
fd -e ts -e tsx src/livecodes | xargs rg -l "getAllLanguages|registerAllLanguages|initLanguages" | head -10

echo
echo "=== Check if the issue comment 'avoid duplicate registration' explains the intent ==="
git log --all --oneline --grep="duplicate registration\|vue-app\|vueApp" 2>/dev/null | head -10 || echo "Git history not available"

Repository: live-codes/livecodes

Length of output: 135


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Check how languages are registered and if there's a load order ==="
rg -n "window.deps.languages|allLanguages|getLanguages" src/livecodes --type ts -B2 -A2 | head -80

echo
echo "=== Check the vue-app test or example usage to see the expected behavior ==="
fd -e spec.ts -e test.ts -e example.ts src/livecodes | xargs rg -l "vue-app\|vueApp" 2>/dev/null | head -5

echo
echo "=== Final check: Is the Monaco 'vue' language ID a built-in or custom? ==="
echo "Looking for where vue language is defined in Monaco registration..."
rg -n "'vue'.*language|language.*'vue'" src/livecodes/editor/monaco --type ts | head -20

Repository: live-codes/livecodes

Length of output: 6235


Preserve vue.editorSupport.monaco.languageSupport when overriding the language property for vue-app.

On Line 57, the object spread { ...vue.editorSupport, monaco: { language: 'vue' } } completely replaces the monaco property, removing languageSupport. If vue-app loads before the vue language, Monaco support won't be registered. Use nested spread instead: monaco: { ...vue.editorSupport.monaco, language: 'vue' } to ensure languageSupport is preserved.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/livecodes/languages/vue/lang-vue.ts` at line 57, The current spread in
editorSupport for vue-app replaces the entire monaco object and drops
vue.editorSupport.monaco.languageSupport; update the override so you merge
nested properties instead of replacing monaco: when setting editorSupport on the
vue-app entry, keep the outer spread of vue.editorSupport and set monaco to a
nested spread that preserves existing monaco fields (referencing editorSupport,
vue.editorSupport, and monaco) while only changing the language property to
'vue' so languageSupport remains intact.

Comment on lines 232 to +233
export const typedArrayToBuffer = /* @__PURE__ */ (array: Uint8Array): ArrayBuffer =>
array.buffer.slice(array.byteOffset, array.byteLength + array.byteOffset);
array.buffer.slice(array.byteOffset, array.byteLength + array.byteOffset) as ArrayBuffer;
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# Search for usage of typedArrayToBuffer in the codebase
rg "typedArrayToBuffer" --type ts --type js -B 2 -A 2

Repository: live-codes/livecodes

Length of output: 2076


🌐 Web query:

TypeScript Uint8Array.buffer type ArrayBufferLike vs ArrayBuffer

💡 Result:

In TypeScript:

  • ArrayBuffer is the standard, non-shared binary buffer.
  • ArrayBufferLike is a type alias that represents “an ArrayBuffer-compatible buffer” and (when the relevant libs are included) effectively becomes ArrayBuffer | SharedArrayBuffer via lib declaration merging. This exists because JS has two buffer kinds: ArrayBuffer and SharedArrayBuffer. [3], [4]

Why Uint8Array.buffer is ArrayBufferLike (not ArrayBuffer)

As of TS 5.7, TypedArrays are generic over their backing buffer type:

interface Uint8Array<TArrayBuffer extends ArrayBufferLike = ArrayBufferLike> {
  readonly buffer: TArrayBuffer;
}

So a Uint8Array might be backed by either ArrayBuffer or SharedArrayBuffer, therefore .buffer is typed as ArrayBufferLike by default. [1], [3]

Why this causes errors

Because ArrayBufferLike might be SharedArrayBuffer, TypeScript won’t let you pass it to something requiring a definite ArrayBuffer (you’ll see errors like “ArrayBufferLike is not assignable to ArrayBuffer”). This became more visible with newer lib updates (notably around TS 5.7+ / ES2024+). [1], [2]

Common fixes

  1. If you know you have an ArrayBuffer, type it explicitly:
const u8: Uint8Array<ArrayBuffer> = new Uint8Array(new ArrayBuffer(10));
const ab: ArrayBuffer = u8.buffer;
  1. If you might have SharedArrayBuffer, copy into a real ArrayBuffer:
function toArrayBuffer(u8: Uint8Array<ArrayBufferLike>): ArrayBuffer {
  const ab = new ArrayBuffer(u8.byteLength);
  new Uint8Array(ab).set(u8);
  return ab;
}

Sources: TypeScript 5.7 release notes (TypedArrays become generic) [1]; TypeScript 5.9 release notes (resulting assignability errors) [2]; MDN (ArrayBuffer vs SharedArrayBuffer) [3]; explanation of ArrayBufferLike via lib/interface merging [4].


🏁 Script executed:

# Check TypeScript definitions for Uint8Array and verify the proposed fix approach
# Let's look at what Uint8Array.from() returns
python3 << 'EOF'
# TypeScript/JavaScript verification of Uint8Array.from() behavior

# Key facts to verify:
# 1. Uint8Array.from() creates a new instance with a new ArrayBuffer
# 2. The original intent: get a copy that respects byteOffset and byteLength

test_code = """
// Original approach (unsafe cast):
const arr = new Uint8Array([1, 2, 3]);
const buffer1 = arr.buffer.slice(arr.byteOffset, arr.byteLength + arr.byteOffset) as ArrayBuffer;

// Proposed fix:
const buffer2 = Uint8Array.from(arr).buffer;

// Both should produce an ArrayBuffer, but:
// - buffer1: Uses slice() which is guaranteed to return ArrayBuffer (not SharedArrayBuffer)
// - buffer2: Creates new Uint8Array -> guaranteed ArrayBuffer backing
"""

print("Analysis of proposed fix:")
print("1. Uint8Array.from(array) creates a NEW Uint8Array instance")
print("2. A newly created Uint8Array is ALWAYS backed by a fresh ArrayBuffer (not SharedArrayBuffer)")
print("3. Therefore, Uint8Array.from(array).buffer is guaranteed to be ArrayBuffer")
print()
print("However, there's a subtle issue:")
print("- Original code: array.buffer.slice(...) returns an ArrayBuffer (slice() spec guarantees this)")
print("- The cast 'as ArrayBuffer' is redundant IF the input Uint8Array is backed by ArrayBuffer")
print("- But IF input is backed by SharedArrayBuffer, slice() would return SharedArrayBuffer")
print()
print("The real issue: The function doesn't guarantee ArrayBuffer-only input,")
print("but the function signature promises to return ArrayBuffer")
EOF

Repository: live-codes/livecodes

Length of output: 754


🏁 Script executed:

# Check if there's any SharedArrayBuffer usage in the codebase
rg "SharedArrayBuffer" --type ts --type js

Repository: live-codes/livecodes

Length of output: 325


🌐 Web query:

ArrayBuffer.slice() return type SharedArrayBuffer behavior

💡 Result:

  • SharedArrayBuffer.prototype.slice(start, end) returns a new SharedArrayBuffer (a copy of the selected byte range). [1][2]
  • ArrayBuffer.prototype.slice(start, end) does not work on a SharedArrayBuffer: it throws TypeError because the spec explicitly rejects shared buffers (If IsSharedArrayBuffer(O) is true, throw a TypeError). [3]
    • So ArrayBuffer.prototype.slice.call(new SharedArrayBuffer(...), ...) throws, rather than returning an ArrayBuffer or SharedArrayBuffer. [3]

Sources: [1] MDN SharedArrayBuffer.prototype.slice(); [2] ECMAScript 2026 § SharedArrayBuffer.prototype.slice; [3] ECMAScript 2026 § ArrayBuffer.prototype.slice.


Unsafe narrowing to ArrayBuffer at line 233; use a guaranteed conversion instead.

Uint8Array.buffer is typed as ArrayBufferLike and can be backed by SharedArrayBuffer. The cast as ArrayBuffer masks this type mismatch; if the input were SharedArrayBuffer-backed, array.buffer.slice() would return a SharedArrayBuffer, violating the function's ArrayBuffer return type. This matters for WebAssembly module instantiation, which requires ArrayBuffer.

Use Uint8Array.from(array).buffer instead—it creates a fresh Uint8Array with guaranteed ArrayBuffer backing:

Proposed fix
-export const typedArrayToBuffer = /* `@__PURE__` */ (array: Uint8Array): ArrayBuffer =>
-  array.buffer.slice(array.byteOffset, array.byteLength + array.byteOffset) as ArrayBuffer;
+export const typedArrayToBuffer = /* `@__PURE__` */ (array: Uint8Array): ArrayBuffer =>
+  Uint8Array.from(array).buffer;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/livecodes/utils/utils.ts` around lines 232 - 233, The function
typedArrayToBuffer narrows a possibly SharedArrayBuffer-backed Uint8Array to
ArrayBuffer using a cast; replace that unsafe cast by creating a fresh
ArrayBuffer-backed copy—use Uint8Array.from(array).buffer (or equivalent) to
produce a new Uint8Array copy and return its .buffer so the function always
returns a true ArrayBuffer suitable for WebAssembly instantiation; update
typedArrayToBuffer to construct the copy from the input parameter `array` and
return its .buffer.

@cloudflare-workers-and-pages
Copy link

cloudflare-workers-and-pages bot commented Feb 28, 2026

Deploying livecodes with  Cloudflare Pages  Cloudflare Pages

Latest commit: a6c7b7c
Status: ✅  Deploy successful!
Preview URL: https://4e9ce374.livecodes.pages.dev
Branch Preview URL: https://language-editors.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.

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

15-15: ⚠️ Potential issue | 🟡 Minor

Fix JSX pragma regex alternation scope.

At Line 15, the alternation is not grouped, so @jsxImportSource can match outside the intended JSDoc pragma context and incorrectly flip hasCustomJsxRuntime.

🐛 Proposed fix
-      new RegExp(/\/\*\*[\s\*]*(`@jsx`)|(`@jsxImportSource`)\s/g).test(code),
+      /\/\*\*[\s\*]*(?:`@jsx`|@jsxImportSource)\s/g.test(code),
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/livecodes/languages/typescript/lang-typescript.ts` at line 15, The regex
used to detect JSDoc JSX pragmas (the RegExp literal
/\/\*\*[\s\*]*(`@jsx`)|(`@jsxImportSource`)\s/g) is missing grouping so
`@jsxImportSource` can match outside the JSDoc and wrongly flip
hasCustomJsxRuntime; change the pattern to group the alternation inside the
JSDoc context (e.g. /\/\*\*[\s\*]*(?:`@jsx`|@jsxImportSource)\s/g) wherever that
RegExp is used so both `@jsx` and `@jsxImportSource` are only matched inside the /**
... */ JSDoc and hasCustomJsxRuntime is set correctly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@src/livecodes/languages/typescript/lang-typescript.ts`:
- Line 15: The regex used to detect JSDoc JSX pragmas (the RegExp literal
/\/\*\*[\s\*]*(`@jsx`)|(`@jsxImportSource`)\s/g) is missing grouping so
`@jsxImportSource` can match outside the JSDoc and wrongly flip
hasCustomJsxRuntime; change the pattern to group the alternation inside the
JSDoc context (e.g. /\/\*\*[\s\*]*(?:`@jsx`|@jsxImportSource)\s/g) wherever that
RegExp is used so both `@jsx` and `@jsxImportSource` are only matched inside the /**
... */ JSDoc and hasCustomJsxRuntime is set correctly.

ℹ️ Review info

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e3a3bae and 5c87dde.

📒 Files selected for processing (7)
  • src/livecodes/editor/codemirror/utils.ts
  • src/livecodes/languages/css/lang-css.ts
  • src/livecodes/languages/html/lang-html.ts
  • src/livecodes/languages/javascript/lang-javascript.ts
  • src/livecodes/languages/jsx/lang-jsx.ts
  • src/livecodes/languages/jsx/lang-tsx.ts
  • src/livecodes/languages/typescript/lang-typescript.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/livecodes/languages/javascript/lang-javascript.ts
  • src/livecodes/editor/codemirror/utils.ts

@sonarqubecloud
Copy link

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.

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

41-42: ⚠️ Potential issue | 🔴 Critical

Restore a non-undefined fallback for language mapping.

At Line 41, mapLanguage() can return undefined when options.mapLanguage is not provided, which makes mappedLanguage invalid at Line 42 and breaks Prism language class/loading paths.

🐛 Proposed fix
-  const mapLanguage = (lang: Language) => options.mapLanguage?.(lang, 'codejar');
+  const mapLanguage = (lang: Language) => options.mapLanguage?.(lang, 'codejar') ?? lang;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/livecodes/editor/codejar/codejar.ts` around lines 41 - 42, mapLanguage
can yield undefined when options.mapLanguage is absent, breaking Prism
class/loading; change the initialization of mappedLanguage so that after calling
mapLanguage(language) you fall back to a non-undefined value (e.g., the original
language or a safe default) whenever mapLanguage returns undefined. Update the
code around the mapLanguage function and the mappedLanguage assignment to use
options.mapLanguage?.(lang, 'codejar') result || language (or another agreed
safe default) so mappedLanguage is never undefined for downstream Prism usage.
src/livecodes/languages/pug/lang-pug.ts (1)

10-15: ⚠️ Potential issue | 🟠 Major

Re-enable formatter.prettier for Pug instead of leaving it disabled.

On Lines 10-15, the formatter block is commented out, which effectively drops formatter support for this language and diverges from the PR’s parser → formatter.prettier migration goal. Please restore the active formatter config and remove the disable-only state.

Suggested change
-  // formatter: {
-  //   prettier: {
-  //     name: 'pug',
-  //     pluginUrls: [parserPlugins.pug],
-  //   },
-  // },
+  formatter: {
+    prettier: {
+      name: 'pug',
+      pluginUrls: [parserPlugins.pug],
+    },
+  },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/livecodes/languages/pug/lang-pug.ts` around lines 10 - 15, Uncomment and
restore the formatter.prettier configuration for the Pug language so formatter
support is active again: re-enable the formatter block containing
formatter.prettier with name: 'pug' and pluginUrls: [parserPlugins.pug] (i.e.,
remove the comment markers around the formatter block in lang-pug.ts) so the
parser → formatter.prettier migration is honored and Pug uses the provided
parser plugin.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@src/livecodes/editor/codejar/codejar.ts`:
- Around line 41-42: mapLanguage can yield undefined when options.mapLanguage is
absent, breaking Prism class/loading; change the initialization of
mappedLanguage so that after calling mapLanguage(language) you fall back to a
non-undefined value (e.g., the original language or a safe default) whenever
mapLanguage returns undefined. Update the code around the mapLanguage function
and the mappedLanguage assignment to use options.mapLanguage?.(lang, 'codejar')
result || language (or another agreed safe default) so mappedLanguage is never
undefined for downstream Prism usage.

In `@src/livecodes/languages/pug/lang-pug.ts`:
- Around line 10-15: Uncomment and restore the formatter.prettier configuration
for the Pug language so formatter support is active again: re-enable the
formatter block containing formatter.prettier with name: 'pug' and pluginUrls:
[parserPlugins.pug] (i.e., remove the comment markers around the formatter block
in lang-pug.ts) so the parser → formatter.prettier migration is honored and Pug
uses the provided parser plugin.

ℹ️ Review info

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5c87dde and a6c7b7c.

📒 Files selected for processing (5)
  • src/livecodes/editor/codejar/codejar.ts
  • src/livecodes/editor/codemirror/codemirror.ts
  • src/livecodes/languages/pug/lang-pug.ts
  • src/livecodes/languages/typescript/lang-typescript.ts
  • src/livecodes/languages/wat/lang-wat.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/livecodes/languages/wat/lang-wat.ts
  • src/livecodes/editor/codemirror/codemirror.ts
  • src/livecodes/languages/typescript/lang-typescript.ts

@hatemhosny hatemhosny merged commit e53cdfd into develop Mar 1, 2026
18 checks passed
@hatemhosny hatemhosny deleted the language-editors branch March 1, 2026 00:12
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.

1 participant