Add syntax highlighting for YAML and Markdown in playground editor#16710
Add syntax highlighting for YAML and Markdown in playground editor#16710
Conversation
Replace the plain textarea with CodeMirror 6 for the input editor (Markdown language) and output panel (YAML language, read-only). Includes dark/light theme switching via Compartment. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR modernizes the gh-aw playground editor by replacing the plain <textarea> implementation with CodeMirror 6, adding syntax highlighting and improving the overall editing experience.
Changes:
- Replaced plain textarea editor with CodeMirror 6 for the input panel, adding Markdown syntax highlighting
- Added CodeMirror 6 for the output panel with YAML syntax highlighting in read-only mode
- Implemented dynamic theme switching (dark/light) for CodeMirror editors using the Compartment API and oneDark theme
- Removed custom line-number gutter and scroll-sync implementations (now handled natively by CodeMirror)
- Updated CSS to style CodeMirror editors while preserving the existing design language
- Loaded CodeMirror 6 modules from esm.sh CDN with @6 version constraints
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| extensions: [ | ||
| basicSetup, | ||
| markdown(), | ||
| editorThemeConfig.of(cmThemeFor(getPreferredTheme())), | ||
| keymap.of([{ | ||
| key: 'Mod-Enter', | ||
| run: () => { doCompile(); return true; } | ||
| }]), | ||
| EditorView.updateListener.of(update => { | ||
| if (update.docChanged && autoCompile && isReady) { | ||
| scheduleCompile(); | ||
| } | ||
| }), | ||
| ], |
There was a problem hiding this comment.
The previous implementation explicitly converted Tab key presses to 2 spaces for indentation. CodeMirror 6's basicSetup may use different tab behavior by default. For YAML content where 2-space indentation is conventional, consider explicitly configuring the indentUnit to 2 spaces by adding EditorState.tabSize.of(2) to the extensions array, or verify that the default tab behavior is appropriate for the Markdown/YAML frontmatter content.
There was a problem hiding this comment.
Done. Added EditorState.tabSize.of(2) and indentUnit.of(' ') for YAML-friendly 2-space indentation.
| basicSetup, | ||
| yaml(), | ||
| EditorState.readOnly.of(true), | ||
| EditorView.editable.of(false), |
There was a problem hiding this comment.
Both EditorState.readOnly and EditorView.editable are set for the output view. These settings are redundant - using EditorState.readOnly.of(true) alone is sufficient to make the editor read-only. Consider removing EditorView.editable.of(false) for cleaner code.
| EditorView.editable.of(false), |
There was a problem hiding this comment.
Intentionally keeping both. readOnly prevents state modifications but still shows a cursor and accepts focus. editable.of(false) removes the contenteditable attribute from the DOM entirely, so the output panel has no cursor, no text selection caret, and doesn't accept keyboard focus — which is the right UX for a display-only output panel.
docs/public/editor/index.html
Outdated
| import { EditorView, basicSetup } from 'https://esm.sh/codemirror@6'; | ||
| import { EditorState, Compartment } from 'https://esm.sh/@codemirror/state@6'; | ||
| import { keymap } from 'https://esm.sh/@codemirror/view@6'; | ||
| import { yaml } from 'https://esm.sh/@codemirror/lang-yaml@6'; | ||
| import { markdown } from 'https://esm.sh/@codemirror/lang-markdown@6'; | ||
| import { oneDark } from 'https://esm.sh/@codemirror/theme-one-dark@6'; |
There was a problem hiding this comment.
The CDN imports use major version constraints (@6) which will automatically load the latest minor and patch versions. While this provides automatic updates, it may introduce breaking changes or inconsistent behavior across different users if they load the page at different times. Consider pinning to specific versions (e.g., @6.0.0) for more predictable behavior, especially for a production application.
| import { EditorView, basicSetup } from 'https://esm.sh/codemirror@6'; | |
| import { EditorState, Compartment } from 'https://esm.sh/@codemirror/state@6'; | |
| import { keymap } from 'https://esm.sh/@codemirror/view@6'; | |
| import { yaml } from 'https://esm.sh/@codemirror/lang-yaml@6'; | |
| import { markdown } from 'https://esm.sh/@codemirror/lang-markdown@6'; | |
| import { oneDark } from 'https://esm.sh/@codemirror/theme-one-dark@6'; | |
| import { EditorView, basicSetup } from 'https://esm.sh/codemirror@6.0.0'; | |
| import { EditorState, Compartment } from 'https://esm.sh/@codemirror/state@6.0.0'; | |
| import { keymap } from 'https://esm.sh/@codemirror/view@6.0.0'; | |
| import { yaml } from 'https://esm.sh/@codemirror/lang-yaml@6.0.0'; | |
| import { markdown } from 'https://esm.sh/@codemirror/lang-markdown@6.0.0'; | |
| import { oneDark } from 'https://esm.sh/@codemirror/theme-one-dark@6.0.0'; |
There was a problem hiding this comment.
Done. Pinned all imports to their current latest versions (e.g. codemirror@6.0.2, @codemirror/state@6.5.4, etc.).
| const outputPlaceholder = $('outputPlaceholder'); | ||
| const outputMount = $('outputMount'); |
There was a problem hiding this comment.
The editorMount element is referenced directly using
There was a problem hiding this comment.
Done. Added const editorMount = $('editorMount') to the DOM Elements section.
…itorMount const
- Pin all CodeMirror CDN imports to exact versions (e.g. codemirror@6.0.2)
- Add EditorState.tabSize.of(2) and indentUnit.of(' ') for YAML-friendly indentation
- Add editorMount to DOM constants for consistency
- Keep both readOnly + editable(false) on output view (readOnly prevents
state changes, editable(false) removes cursor/contenteditable)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Update editor.js to contain the new CodeMirror code from #16710 while keeping the JS extraction into a separate file. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Summary
<textarea>editor with CodeMirror 6 for full syntax highlightingCompartmentwhen toggling dark mode (usesoneDarkfor dark mode)Dependencies
CodeMirror 6 modules loaded from esm.sh CDN:
codemirror(basic setup + EditorView)@codemirror/state(EditorState, Compartment for theme switching)@codemirror/view(keymap for Ctrl+Enter binding)@codemirror/lang-yaml(YAML syntax)@codemirror/lang-markdown(Markdown syntax)@codemirror/theme-one-dark(dark mode theme)Test plan
🤖 Generated with Claude Code