Initial commit to new repository
This commit is contained in:
132
src/AxCopilot/Handlers/JsonHandler.cs
Normal file
132
src/AxCopilot/Handlers/JsonHandler.cs
Normal file
@@ -0,0 +1,132 @@
|
||||
using System.Text.Json;
|
||||
using System.Windows;
|
||||
using AxCopilot.SDK;
|
||||
using AxCopilot.Themes;
|
||||
|
||||
namespace AxCopilot.Handlers;
|
||||
|
||||
/// <summary>
|
||||
/// JSON 검증/포맷 핸들러. "json" 프리픽스로 사용합니다.
|
||||
/// 예: json → 클립보드의 JSON을 파싱하여 미리보기 표시
|
||||
/// json {"a":1} → 인라인 JSON 파싱 + 미리보기
|
||||
/// json minify → 클립보드 JSON 미니파이 → 클립보드 복사
|
||||
/// json format → 클립보드 JSON 예쁘게 포맷 → 클립보드 복사
|
||||
/// </summary>
|
||||
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<IEnumerable<LauncherItem>> 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<IEnumerable<LauncherItem>>(
|
||||
[
|
||||
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<LauncherItem> 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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user