From 8b72a00127fc2770ac17a32420be9a49996a5317 Mon Sep 17 00:00:00 2001 From: Scrum4Me Agent <30029041+madhura68@users.noreply.github.com> Date: Wed, 13 May 2026 23:39:29 +0200 Subject: [PATCH] feat(caddy): replace textarea with CodeMirror 6 editor in caddy-editor Replaces the plain textarea on /caddy/edit with a CodeMirror 6 component that provides live Caddyfile syntax highlighting (keywords, named matchers, comments). The editor is dynamically imported (ssr: false) to prevent hydration errors. The write/validate/save/reload state machine and content flow remain unchanged. Bundle impact: ~300 kB additional for the /caddy/edit route (CodeMirror 6 core + @uiw/react-codemirror). Co-Authored-By: Claude Sonnet 4.6 --- app/caddy/_components/caddy-codemirror.tsx | 25 ++++++++++++++++++++++ app/caddy/_components/caddy-editor.tsx | 20 +++++++++++------ 2 files changed, 38 insertions(+), 7 deletions(-) create mode 100644 app/caddy/_components/caddy-codemirror.tsx diff --git a/app/caddy/_components/caddy-codemirror.tsx b/app/caddy/_components/caddy-codemirror.tsx new file mode 100644 index 0000000..15b010c --- /dev/null +++ b/app/caddy/_components/caddy-codemirror.tsx @@ -0,0 +1,25 @@ +'use client' +import CodeMirror from '@uiw/react-codemirror' +import { caddyfileLanguage } from '@/lib/codemirror/caddyfile-mode' +import { EditorView } from '@codemirror/view' + +type Props = { + value: string + onChange: (next: string) => void + readOnly?: boolean +} + +export default function CaddyCodeMirror({ value, onChange, readOnly }: Props) { + return ( + + ) +} diff --git a/app/caddy/_components/caddy-editor.tsx b/app/caddy/_components/caddy-editor.tsx index 14a4427..6d5f0d1 100644 --- a/app/caddy/_components/caddy-editor.tsx +++ b/app/caddy/_components/caddy-editor.tsx @@ -1,11 +1,21 @@ 'use client' import { useCallback, useEffect, useState } from 'react' +import dynamic from 'next/dynamic' import Link from 'next/link' import { useFlowRun } from '@/hooks/useFlowRun' import ConfirmDialog from '@/components/ConfirmDialog' import StreamingTerminal from '@/components/StreamingTerminal' +const CaddyCodeMirror = dynamic(() => import('./caddy-codemirror'), { + ssr: false, + loading: () => ( +
+ Loading editor… +
+ ), +}) + type Phase = 'edit' | 'writing' | 'validating' | 'validated' | 'saving' | 'saved' type DialogPending = 'validate' | 'save' | null @@ -106,17 +116,13 @@ export default function CaddyEditor({ initialContent, initialError }: Props) { )} -