refactor(JsonTools): 规范化页面组件目录结构

- 将子组件移至 components/ 子目录(JsonDiffInput、DiffResult、JsonFormatSection、JsonConvertSection、DiffNavigator、JsonTree)
- 将 diffEngine.ts 工具函数移至 src/utils/
- 提取 ConvertFunction/ConvertResult 类型到 types.ts,解决循环依赖
- 创建 __tests__/ 目录结构
- 更新所有相关导入路径

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
雨霖铃
2026-06-10 20:39:40 +08:00
parent 30d3561726
commit 016173a9c5
12 changed files with 33 additions and 20 deletions
@@ -0,0 +1,11 @@
import { render, screen } from '@testing-library/react';
import { describe, it, expect } from 'vitest';
import Index from '../index';
describe('JsonTools 页面', () => {
it('应该渲染页面标题', () => {
render(<Index />);
// 基本渲染测试
expect(screen.getByRole('button')).toBeInTheDocument();
});
});
@@ -2,7 +2,7 @@ import React from 'react';
import { useI18n } from '@/utils/chromeI18n'; import { useI18n } from '@/utils/chromeI18n';
import { cn } from '@/lib/utils'; import { cn } from '@/lib/utils';
import JsonTree from './JsonTree'; import JsonTree from './JsonTree';
import type { DiffNode, DiffResult as DiffResultType, DiffType, ViewMode } from './types'; import type { DiffNode, DiffResult as DiffResultType, DiffType, ViewMode } from '../types';
export interface DiffResultProps extends React.HTMLAttributes<HTMLDivElement> { export interface DiffResultProps extends React.HTMLAttributes<HTMLDivElement> {
result: DiffResultType; result: DiffResultType;
@@ -5,14 +5,7 @@ import { CopyButton } from '@/components/CopyButton';
import TextInputArea from '@/components/TextInputArea'; import TextInputArea from '@/components/TextInputArea';
import { validateJson } from '@/utils/jsonFormatter'; import { validateJson } from '@/utils/jsonFormatter';
import { cn } from '@/lib/utils'; import { cn } from '@/lib/utils';
import type { ConvertFunction, ConvertResult } from '../types';
export interface ConvertResult {
output: string;
originalBytes: number;
outputBytes: number;
}
export type ConvertFunction = (text: string) => ConvertResult;
interface JsonConvertSectionProps extends React.HTMLAttributes<HTMLDivElement> { interface JsonConvertSectionProps extends React.HTMLAttributes<HTMLDivElement> {
translationPrefix: string; translationPrefix: string;
@@ -1,6 +1,6 @@
import React, { useEffect, useMemo, useRef, useState } from 'react'; import React, { useEffect, useMemo, useRef, useState } from 'react';
import { ChevronDown, ChevronRight } from 'lucide-react'; // 用正统的矢量箭头平替原生的字符 '▾' '▸' import { ChevronDown, ChevronRight } from 'lucide-react'; // 用正统的矢量箭头平替原生的字符 '▾' '▸'
import type { DiffNode, DiffType } from './types'; import type { DiffNode, DiffType } from '../types';
import { cn } from '@/lib/utils'; import { cn } from '@/lib/utils';
export type TreeSide = 'left' | 'right'; export type TreeSide = 'left' | 'right';
+5 -5
View File
@@ -1,9 +1,9 @@
import { useI18n } from '@/utils/chromeI18n'; import { useI18n } from '@/utils/chromeI18n';
import JsonDiffInput from './JsonDiffInput'; import JsonDiffInput from './components/JsonDiffInput';
import DiffResult from './DiffResult'; import DiffResult from './components/DiffResult';
import DiffNavigator from './DiffNavigator'; import DiffNavigator from './components/DiffNavigator';
import JsonFormatSection from './JsonFormatSection'; import JsonFormatSection from './components/JsonFormatSection';
import JsonConvertSection from './JsonConvertSection'; import JsonConvertSection from './components/JsonConvertSection';
import SwitchButtonGroup from '@/components/SwitchButtonGroup'; import SwitchButtonGroup from '@/components/SwitchButtonGroup';
import { useJsonTools } from './useJsonTools'; import { useJsonTools } from './useJsonTools';
import type { JsonToolsPageMode } from '@/types/storage'; import type { JsonToolsPageMode } from '@/types/storage';
+10
View File
@@ -53,3 +53,13 @@ export interface DiffResult {
/** 差异核心总计数(等价于 diffPaths.length),注入 tabular-nums 配合渲染 */ /** 差异核心总计数(等价于 diffPaths.length),注入 tabular-nums 配合渲染 */
diffCount: number; diffCount: number;
} }
/** JSON 转换结果 */
export interface ConvertResult {
output: string;
originalBytes: number;
outputBytes: number;
}
/** JSON 转换函数类型 */
export type ConvertFunction = (text: string) => ConvertResult;
+2 -3
View File
@@ -1,14 +1,13 @@
import { useCallback, useEffect, useMemo, useState } from 'react'; import { useCallback, useEffect, useMemo, useState } from 'react';
import { useI18n } from '@/utils/chromeI18n'; import { useI18n } from '@/utils/chromeI18n';
import { useStorageState } from '@/utils/useStorageState'; import { useStorageState } from '@/utils/useStorageState';
import { diffJson } from './diffEngine'; import { diffJson } from '@/utils/diffEngine';
import { jsonToYaml } from '@/utils/jsonToYaml'; import { jsonToYaml } from '@/utils/jsonToYaml';
import { jsonToToml } from '@/utils/jsonToToml'; import { jsonToToml } from '@/utils/jsonToToml';
import { minifyJson } from '@/utils/jsonFormatter'; import { minifyJson } from '@/utils/jsonFormatter';
import { isValidPageMode, tryParse } from './constants'; import { isValidPageMode, tryParse } from './constants';
import type { JsonToolsPageMode } from '@/types/storage'; import type { JsonToolsPageMode } from '@/types/storage';
import type { ConvertFunction } from './JsonConvertSection'; import type { ConvertFunction, ViewMode } from './types';
import type { ViewMode } from './types';
export interface UseJsonToolsReturn { export interface UseJsonToolsReturn {
pageMode: JsonToolsPageMode; pageMode: JsonToolsPageMode;
+1 -1
View File
@@ -1,5 +1,5 @@
import { describe, it, expect } from 'vitest'; import { describe, it, expect } from 'vitest';
import { diffJson } from '../../pages/JsonTools/diffEngine'; import { diffJson } from '../diffEngine';
describe('diffJson', () => { describe('diffJson', () => {
it('should detect added property', () => { it('should detect added property', () => {
@@ -1,4 +1,4 @@
import type { DiffNode, DiffResult, DiffType } from './types'; import type { DiffNode, DiffResult, DiffType } from '@/pages/JsonTools/types';
const ROOT_PATH = '$'; const ROOT_PATH = '$';
const SENTINEL = Symbol('missing'); const SENTINEL = Symbol('missing');