using System.Text.Json; using System.Windows; using AxCopilot.SDK; using AxCopilot.Themes; namespace AxCopilot.Handlers; /// /// JSON 검증/포맷 핸들러. "json" 프리픽스로 사용합니다. /// 예: json → 클립보드의 JSON을 파싱하여 미리보기 표시 /// json {"a":1} → 인라인 JSON 파싱 + 미리보기 /// json minify → 클립보드 JSON 미니파이 → 클립보드 복사 /// json format → 클립보드 JSON 예쁘게 포맷 → 클립보드 복사 /// public class JsonHandler : IActionHandler { public string? Prefix => "json"; public PluginMetadata Metadata => new( "JsonFormatter", "JSON 검증/포맷 — json 뒤에 내용 또는 명령 입력", "1.0", "AX"); private static readonly JsonSerializerOptions _prettyOpts = new() { WriteIndented = true }; private static readonly JsonSerializerOptions _compactOpts = new() { WriteIndented = false }; public Task> GetItemsAsync(string query, CancellationToken ct) { var q = query.Trim(); // ─── 빈 쿼리 or format/minify: 클립보드에서 JSON 읽기 ───────────────── if (string.IsNullOrWhiteSpace(q) || q.Equals("format", StringComparison.OrdinalIgnoreCase) || q.Equals("minify", StringComparison.OrdinalIgnoreCase) || q.Equals("min", StringComparison.OrdinalIgnoreCase)) { string clipText = ""; try { clipText = Clipboard.GetText(); } catch { } if (string.IsNullOrWhiteSpace(clipText)) return Task.FromResult>( [ new LauncherItem( "클립보드가 비어 있습니다", "클립보드에 JSON 텍스트를 복사한 뒤 실행하세요", null, null, Symbol: Symbols.Clipboard) ]); return Task.FromResult(BuildItems(clipText, isMinify: q.StartsWith("min", StringComparison.OrdinalIgnoreCase))); } // ─── 인라인 JSON ────────────────────────────────────────────────────── return Task.FromResult(BuildItems(q, isMinify: false)); } private static IEnumerable BuildItems(string input, bool isMinify) { try { using var doc = JsonDocument.Parse(input, new JsonDocumentOptions { AllowTrailingCommas = true, CommentHandling = JsonCommentHandling.Skip }); // 포맷된 버전 var pretty = JsonSerializer.Serialize(doc.RootElement, _prettyOpts); var compact = JsonSerializer.Serialize(doc.RootElement, _compactOpts); // 루트 타입 정보 var rootType = doc.RootElement.ValueKind switch { JsonValueKind.Object => $"Object ({doc.RootElement.EnumerateObject().Count()}개 키)", JsonValueKind.Array => $"Array ({doc.RootElement.GetArrayLength()}개 항목)", _ => doc.RootElement.ValueKind.ToString() }; var targetText = isMinify ? compact : pretty; var actionLabel = isMinify ? "미니파이" : "포맷"; // 미리보기 (처음 100자) var preview = compact.Length > 100 ? compact[..97] + "…" : compact; return [ new LauncherItem( $"✅ 유효한 JSON — {rootType}", $"{preview} · Enter로 {actionLabel} 결과 클립보드 복사", null, targetText, Symbol: Symbols.JsonValid), new LauncherItem( "포맷 (Pretty Print) 복사", $"{pretty.Length}자 · 들여쓰기 2스페이스", null, pretty, Symbol: Symbols.JsonFormat), new LauncherItem( "미니파이 (Minify) 복사", $"{compact.Length}자 · 공백 제거", null, compact, Symbol: Symbols.JsonMinify), ]; } catch (JsonException ex) { var msg = ex.Message.Length > 100 ? ex.Message[..97] + "…" : ex.Message; return [ new LauncherItem( "❌ JSON 오류", msg, null, null, Symbol: Symbols.Error) ]; } } public Task ExecuteAsync(LauncherItem item, CancellationToken ct) { if (item.Data is string text) { try { Clipboard.SetText(text); } catch { } } return Task.CompletedTask; } }