Add a Format affordance on the playground toolbar once Monaco lands (#24). Monaco wires when formatting runs; we supply what formatting does per language via monaco.languages.registerDocumentFormattingEditProvider (and/or invoking editor.getAction('editor.action.formatDocument').run() when built-ins apply).
Goals — shared platform behavior
Toolbar: visible Format button (semi-playground-aware where labels/shortcuts are shared).
Shortcuts: target Format document from keyboard (e.g. align with VS Code / platform norms). Note: In Chrome, Ctrl + Shift + I is DevTools — pick a non-conflicting chord (e.g. Shift + Alt + F like Windows VS Code, or preventDefault on editor focus) and document in shortcuts table.
Optional polish (separate milestones OK): format on save, format before run/submit (“format on run”) — gated so lesson flows stay predictable.
Architecture: thin FormatProvider (or facade) injected per LANGUAGE_RUNNER_CONFIG / Monaco model language id — no duplicated toolbar logic per formatter backend.
Disclaimer: Monaco does not ship production-grade formatters for every language — implementations tracked in: #36 (JS/TS Prettier), #37 (Python Black / backend), #38 (C# Roslyn).
Technical notes
provideDocumentFormattingEdits: replace full-model range text with formatted output.
Errors: surface formatter failures in snackbar or inline without corrupting undo stack when possible (pushEditOperations vs setValue).
Teaching: deterministic style acceptable for beginners; avoid surprising mass edits without clear affordance (“Format changed your code”).
Dependency
Blocks on Monaco migration for app-language-runner — #24. Child tickets plug real formatters beneath this facade.
Acceptance criteria
Format invoked from toolbar + keyboard on happy path.
No-op or clear message when no provider registered for current language.
Document how per-language hooks register (readme or ADR snippet).
## Summary
Add a **Format** affordance on the playground **toolbar** once **Monaco** lands (`#24`). Monaco wires **when** formatting runs; **we** supply **what** formatting does per language via `monaco.languages.registerDocumentFormattingEditProvider` (and/or invoking `editor.getAction('editor.action.formatDocument').run()` when built-ins apply).
## Goals — shared platform behavior
- **Toolbar**: visible **Format** button (semi-playground-aware where labels/shortcuts are shared).
- **Shortcuts**: target **Format document** from keyboard (e.g. align with VS Code / platform norms). **Note:** In **Chrome**, **`Ctrl + Shift + I`** is **DevTools** — pick a non-conflicting chord (e.g. **`Shift + Alt + F`** like Windows VS Code, or `preventDefault` on editor focus) and document in shortcuts table.
- **Optional polish** (separate milestones OK): format on save, format before run/submit (“format on run”) — gated so lesson flows stay predictable.
- **Architecture**: thin **FormatProvider** (or facade) injected per **`LANGUAGE_RUNNER_CONFIG` / Monaco model language id** — no duplicated toolbar logic per formatter backend.
- **Disclaimer**: Monaco does **not** ship production-grade formatters for every language — **implementations tracked in**: **#36** (JS/TS Prettier), **#37** (Python Black / backend), **#38** (C# Roslyn).
## Technical notes
- **`provideDocumentFormattingEdits`**: replace full-model range text with formatted output.
- **Errors**: surface formatter failures in snackbar or inline without corrupting undo stack when possible (`pushEditOperations` vs `setValue`).
- **Teaching**: deterministic style acceptable for beginners; avoid surprising mass edits without clear affordance (“Format changed your code”).
## Dependency
- Blocks on Monaco migration for **`app-language-runner`** — `#24`. Child tickets plug real formatters beneath this facade.
## Acceptance criteria
- [ ] Format invoked from toolbar + keyboard on happy path.
- [ ] No-op or clear message when no provider registered for current language.
- [ ] Document how per-language hooks register (readme or ADR snippet).
Verified 2026-08-07 against spikersoft-angular@8e5a4048: only the JS runner registers a Monaco formatting provider (Prettier, ticket #36); no shared FormatProvider seam, no toolbar button, no shortcut, no other language covered.
Status: partially done — JS/TS Prettier (#36) landed; the shared toolbar/facade/shortcut layer this ticket describes is still missing.
Closing here. Work now lives in the repo that holds the fix, so fixes #<N> in a PR will
auto-close it on merge. The umbrella tracker keeps cross-repo epics only.
— Opus 5 Agent
Migrated to **spikerj/spikersoft-angular#665** as part of the umbrella-tracker breakup.
Verified 2026-08-07 against `spikersoft-angular@8e5a4048`: only the JS runner registers a Monaco formatting provider (Prettier, ticket #36); no shared FormatProvider seam, no toolbar button, no shortcut, no other language covered.
Status: partially done — JS/TS Prettier (#36) landed; the shared toolbar/facade/shortcut layer this ticket describes is still missing.
Closing here. Work now lives in the repo that holds the fix, so `fixes #<N>` in a PR will
auto-close it on merge. The umbrella tracker keeps cross-repo epics only.
— Opus 5 Agent
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
Add a Format affordance on the playground toolbar once Monaco lands (
#24). Monaco wires when formatting runs; we supply what formatting does per language viamonaco.languages.registerDocumentFormattingEditProvider(and/or invokingeditor.getAction('editor.action.formatDocument').run()when built-ins apply).Goals — shared platform behavior
Ctrl + Shift + Iis DevTools — pick a non-conflicting chord (e.g.Shift + Alt + Flike Windows VS Code, orpreventDefaulton editor focus) and document in shortcuts table.LANGUAGE_RUNNER_CONFIG/ Monaco model language id — no duplicated toolbar logic per formatter backend.Technical notes
provideDocumentFormattingEdits: replace full-model range text with formatted output.pushEditOperationsvssetValue).Dependency
app-language-runner—#24. Child tickets plug real formatters beneath this facade.Acceptance criteria
Migrated to spikerj/spikersoft-angular#665 as part of the umbrella-tracker breakup.
Verified 2026-08-07 against
spikersoft-angular@8e5a4048: only the JS runner registers a Monaco formatting provider (Prettier, ticket #36); no shared FormatProvider seam, no toolbar button, no shortcut, no other language covered.Status: partially done — JS/TS Prettier (#36) landed; the shared toolbar/facade/shortcut layer this ticket describes is still missing.
Closing here. Work now lives in the repo that holds the fix, so
fixes #<N>in a PR willauto-close it on merge. The umbrella tracker keeps cross-repo epics only.
— Opus 5 Agent