Skip to content

Latest commit

 

History

History
42 lines (29 loc) · 2.78 KB

File metadata and controls

42 lines (29 loc) · 2.78 KB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Commands

pnpm install        # Install dependencies
pnpm dev            # Start dev server (http://localhost:5173)
pnpm build          # Production build
pnpm preview        # Preview production build
pnpm format         # Run Prettier on all files

There are no tests. The pre-commit hook runs lint-staged, which auto-formats staged files with Prettier (.{ts,tsx,js,jsx,css,json,md}).

Architecture

Execly is a fully client-side JS/TS playground — no backend. All compilation and execution happen in the browser tab.

Data flow

App.tsx owns all state. When the user runs code:

  1. Editor (via editorRef) exposes the current text through EditorHandle.getValue()
  2. linter.ts runs diagnostics synchronously (getJSLint for JS, getTSDiagnostics via ts.createProgram for TS)
  3. runner.ts compiles (compileTS via ts.transpileModule or transpileJS via Babel) then calls execute()
  4. execute() wraps the compiled code in an async IIFE inside new Function, injecting a sandboxed console proxy and a whitelist of globals — the real window is not accessible
  5. Console output streams line-by-line into consoleLines state, rendered in OutputPanel

Key architectural decisions

  • CodeMirror 6 compartments: langCompartment, linterCompartment, and themeCompartment in Editor.tsx are module-level singletons. Lang/theme switches use view.dispatch({ effects: compartment.reconfigure(...) }) rather than re-mounting the editor — this preserves undo history.
  • Per-language code persistence: savedCode ref in Editor.tsx stores the editor content for each language ({ js: string, ts: string }). Switching languages saves the current buffer and restores the saved content for the new language.
  • Callback refs pattern: onRunRef, onCursorRef, onProblemsRef are kept in sync via useEffect so the stable CM6 updateListener closure always calls the latest React callbacks without needing the editor to remount.
  • Linting is dual-purpose: getCM6Diagnostics feeds inline CM6 squiggles; getTSDiagnostics/getJSLint return Problem[] for the Problems panel and are called again at run-time. Both paths share the same diagnostic logic.
  • Theme: Light/dark is toggled via data-theme on <html> (CSS custom properties in App.css) plus themeCompartment.reconfigure(oneDark | []) for the CM6 editor.
  • Layout: layoutDir ('lr' | 'tb') switches between left-right and top-bottom split panes. The Resizer component drives outWidth/outHeight state in App.

Shared types (src/types.ts)

Lang, Problem, CursorPos, ConsoleLine, EditorHandle — import from here rather than redefining locally.