Skip to content

Comments

Add syntax highlighting for YAML and Markdown in playground editor#16710

Merged
Mossaka merged 2 commits intomainfrom
feat/editor-syntax-highlight
Feb 19, 2026
Merged

Add syntax highlighting for YAML and Markdown in playground editor#16710
Mossaka merged 2 commits intomainfrom
feat/editor-syntax-highlight

Conversation

@Mossaka
Copy link
Collaborator

@Mossaka Mossaka commented Feb 19, 2026

Summary

  • Replace the plain <textarea> editor with CodeMirror 6 for full syntax highlighting
  • Input panel: Markdown language support (highlights headers, emphasis, links, code blocks, etc.)
  • Output panel: YAML language support in read-only mode with line numbers
  • Dark/light theme: CodeMirror themes switch dynamically via Compartment when toggling dark mode (uses oneDark for dark mode)
  • Remove custom line-number gutter and scroll-sync code (CodeMirror handles these natively)
  • All existing functionality preserved: auto-compile, Ctrl+Enter shortcut, draggable divider, status badges, error/warning banners

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

  • Open https://github.github.com/gh-aw/editor/index.html after deploy
  • Verify Markdown syntax highlighting in editor panel (headers, formatting)
  • Verify YAML syntax highlighting in compiled output panel
  • Toggle dark/light mode - both panels should switch themes
  • Auto-compile works on typing
  • Ctrl+Enter / Cmd+Enter compiles manually
  • Draggable divider still works
  • Error/warning banners display correctly on compilation errors

🤖 Generated with Claude Code

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>
Copilot AI review requested due to automatic review settings February 19, 2026 01:36
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

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.

Comment on lines 394 to 407
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();
}
}),
],
Copy link

Copilot AI Feb 19, 2026

Choose a reason for hiding this comment

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

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.

Copilot uses AI. Check for mistakes.
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

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),
Copy link

Copilot AI Feb 19, 2026

Choose a reason for hiding this comment

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

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.

Suggested change
EditorView.editable.of(false),

Copilot uses AI. Check for mistakes.
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

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.

Comment on lines 294 to 299
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';
Copy link

Copilot AI Feb 19, 2026

Choose a reason for hiding this comment

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

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.

Suggested change
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';

Copilot uses AI. Check for mistakes.
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done. Pinned all imports to their current latest versions (e.g. codemirror@6.0.2, @codemirror/state@6.5.4, etc.).

Comment on lines 325 to +326
const outputPlaceholder = $('outputPlaceholder');
const outputMount = $('outputMount');
Copy link

Copilot AI Feb 19, 2026

Choose a reason for hiding this comment

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

The editorMount element is referenced directly using $('editorMount') on line 408, but unlike other DOM elements (lines 325-342), it's not stored in a constant. Consider adding const editorMount = $('editorMount'); to the DOM Elements section for consistency with the established pattern.

Copilot uses AI. Check for mistakes.
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

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>
@Mossaka Mossaka merged commit 6788ded into main Feb 19, 2026
170 checks passed
@Mossaka Mossaka deleted the feat/editor-syntax-highlight branch February 19, 2026 01:52
Mossaka added a commit that referenced this pull request Feb 19, 2026
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>
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