@skspwork/config-doc 2.0.3 → 2.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +3 -2
- package/packages/web/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/packages/web/.next/standalone/.next/server/app/_not-found.html +1 -1
- package/packages/web/.next/standalone/.next/server/app/_not-found.rsc +2 -2
- package/packages/web/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
- package/packages/web/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
- package/packages/web/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/packages/web/.next/standalone/.next/server/app/api/config/save/route.js +1 -1
- package/packages/web/.next/standalone/.next/server/app/api/config/save/route.js.nft.json +1 -1
- package/packages/web/.next/standalone/.next/server/app/api/export/route.js +3 -3
- package/packages/web/.next/standalone/.next/server/app/api/export/route.js.nft.json +1 -1
- package/packages/web/.next/standalone/.next/server/app/index.html +1 -1
- package/packages/web/.next/standalone/.next/server/app/index.rsc +3 -3
- package/packages/web/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/packages/web/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +3 -3
- package/packages/web/.next/standalone/.next/server/app/index.segments/_index.segment.rsc +2 -2
- package/packages/web/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/packages/web/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/packages/web/.next/standalone/.next/server/chunks/[root-of-the-server]__40e87302._.js +3 -0
- package/packages/web/.next/standalone/.next/server/chunks/[root-of-the-server]__93da9fce._.js +1 -1
- package/packages/web/.next/standalone/.next/server/chunks/[root-of-the-server]__c9655ac8._.js +3 -0
- package/packages/web/.next/standalone/.next/server/chunks/[root-of-the-server]__e19366f6._.js +1 -1
- package/packages/web/.next/standalone/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_d09de205.js +368 -29
- package/packages/web/.next/standalone/.next/server/chunks/ssr/app_page_tsx_55b2e5ee._.js +1 -1
- package/packages/web/.next/standalone/.next/server/pages/404.html +1 -1
- package/packages/web/.next/standalone/.next/static/chunks/02de70e4c30afe2f.js +1 -0
- package/packages/web/.next/standalone/.next/static/chunks/862e384b52cfebf3.css +3 -0
- package/packages/web/.next/standalone/app/api/config/metadata/route.ts +5 -3
- package/packages/web/.next/standalone/package.json +2 -0
- package/packages/web/.next/standalone/playwright-report/index.html +1 -1
- package/packages/web/.next/static/chunks/02de70e4c30afe2f.js +1 -0
- package/packages/web/.next/static/chunks/862e384b52cfebf3.css +3 -0
- package/packages/web/package.json +2 -0
- package/packages/web/.next/standalone/.next/server/chunks/[root-of-the-server]__1a68b1f3._.js +0 -3
- package/packages/web/.next/standalone/.next/server/chunks/[root-of-the-server]__2c94dfea._.js +0 -3
- package/packages/web/.next/standalone/.next/static/chunks/4bbca8cd642026de.css +0 -3
- package/packages/web/.next/standalone/.next/static/chunks/54e2bd8f072e7d4e.js +0 -1
- package/packages/web/.next/standalone/app/api/config/load/route.ts +0 -57
- package/packages/web/.next/standalone/app/api/config/save/route.ts +0 -73
- package/packages/web/.next/standalone/app/api/export/route.ts +0 -75
- package/packages/web/.next/standalone/app/api/export/settings/route.ts +0 -144
- package/packages/web/.next/standalone/app/api/files/browse/route.ts +0 -46
- package/packages/web/.next/standalone/app/api/project/route.ts +0 -41
- package/packages/web/.next/standalone/app/globals.css +0 -26
- package/packages/web/.next/standalone/app/icon.svg +0 -41
- package/packages/web/.next/standalone/app/layout.tsx +0 -34
- package/packages/web/.next/standalone/app/page.tsx +0 -135
- package/packages/web/.next/standalone/components/ConfigFileTabs.tsx +0 -188
- package/packages/web/.next/standalone/components/ConfigTree.tsx +0 -176
- package/packages/web/.next/standalone/components/EditableList.tsx +0 -337
- package/packages/web/.next/standalone/components/ExportDialog.tsx +0 -234
- package/packages/web/.next/standalone/components/FieldsEditor.tsx +0 -92
- package/packages/web/.next/standalone/components/FileBrowser.tsx +0 -290
- package/packages/web/.next/standalone/components/Header.tsx +0 -37
- package/packages/web/.next/standalone/components/PropertyEditor.tsx +0 -102
- package/packages/web/.next/standalone/components/TagEditor.tsx +0 -86
- package/packages/web/.next/standalone/components/Toast.tsx +0 -91
- package/packages/web/.next/standalone/eslint.config.mjs +0 -18
- package/packages/web/.next/standalone/hooks/useConfigManager.ts +0 -633
- package/packages/web/.next/standalone/lib/configParser.ts +0 -155
- package/packages/web/.next/standalone/lib/fileSystem.ts +0 -186
- package/packages/web/.next/standalone/lib/getRootPath.ts +0 -45
- package/packages/web/.next/standalone/lib/htmlGenerator.ts +0 -839
- package/packages/web/.next/standalone/lib/jsonUtils.ts +0 -26
- package/packages/web/.next/standalone/lib/markdownGenerator.ts +0 -79
- package/packages/web/.next/standalone/lib/markdownTableGenerator.ts +0 -107
- package/packages/web/.next/standalone/lib/storage.ts +0 -104
- package/packages/web/.next/standalone/lib/utils.ts +0 -72
- package/packages/web/.next/standalone/next.config.ts +0 -10
- package/packages/web/.next/standalone/package-lock.json +0 -7977
- package/packages/web/.next/standalone/playwright.config.ts +0 -27
- package/packages/web/.next/standalone/postcss.config.mjs +0 -7
- package/packages/web/.next/standalone/test-results/.last-run.json +0 -4
- package/packages/web/.next/standalone/tsconfig.json +0 -34
- package/packages/web/.next/standalone/tsconfig.tsbuildinfo +0 -1
- package/packages/web/.next/standalone/types/index.ts +0 -74
- package/packages/web/.next/standalone/vitest.config.ts +0 -14
- package/packages/web/.next/static/chunks/4bbca8cd642026de.css +0 -3
- package/packages/web/.next/static/chunks/54e2bd8f072e7d4e.js +0 -1
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
import { NextRequest, NextResponse } from 'next/server';
|
|
2
|
-
import { FileSystemService } from '@/lib/fileSystem';
|
|
3
|
-
import { StorageService } from '@/lib/storage';
|
|
4
|
-
import { getRootPath } from '@/lib/getRootPath';
|
|
5
|
-
|
|
6
|
-
export async function POST(request: NextRequest) {
|
|
7
|
-
try {
|
|
8
|
-
let body;
|
|
9
|
-
try {
|
|
10
|
-
body = await request.json();
|
|
11
|
-
} catch {
|
|
12
|
-
return NextResponse.json(
|
|
13
|
-
{ success: false, error: 'Invalid JSON body' },
|
|
14
|
-
{ status: 400 }
|
|
15
|
-
);
|
|
16
|
-
}
|
|
17
|
-
const { configFilePath, propertyPath, propertyDoc, properties } = body;
|
|
18
|
-
|
|
19
|
-
// configFilePathは必須
|
|
20
|
-
if (!configFilePath) {
|
|
21
|
-
return NextResponse.json(
|
|
22
|
-
{ success: false, error: 'Missing configFilePath' },
|
|
23
|
-
{ status: 400 }
|
|
24
|
-
);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// プロジェクトのルートパス(ユーザーの作業ディレクトリ)
|
|
28
|
-
const rootPath = getRootPath();
|
|
29
|
-
const fsService = new FileSystemService(rootPath);
|
|
30
|
-
const storageService = new StorageService(fsService);
|
|
31
|
-
|
|
32
|
-
// .config_docディレクトリを確保
|
|
33
|
-
await fsService.ensureConfigDocDir();
|
|
34
|
-
|
|
35
|
-
// 一括更新モード(propertiesが指定されている場合)
|
|
36
|
-
if (properties) {
|
|
37
|
-
await storageService.updateAllProperties(configFilePath, properties);
|
|
38
|
-
} else if (propertyPath && propertyDoc) {
|
|
39
|
-
// 単一プロパティ更新モード
|
|
40
|
-
await storageService.savePropertyDoc(
|
|
41
|
-
configFilePath,
|
|
42
|
-
propertyPath,
|
|
43
|
-
propertyDoc
|
|
44
|
-
);
|
|
45
|
-
} else {
|
|
46
|
-
return NextResponse.json(
|
|
47
|
-
{ success: false, error: 'Missing required fields: either (propertyPath, propertyDoc) or properties required' },
|
|
48
|
-
{ status: 400 }
|
|
49
|
-
);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// メタデータの最終更新時刻を更新
|
|
53
|
-
const metadata = await fsService.loadConfigFiles();
|
|
54
|
-
if (metadata) {
|
|
55
|
-
metadata.lastModified = new Date().toISOString();
|
|
56
|
-
await fsService.saveConfigFiles(metadata);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
return NextResponse.json({
|
|
60
|
-
success: true,
|
|
61
|
-
message: 'ドキュメントを保存しました'
|
|
62
|
-
});
|
|
63
|
-
} catch (error) {
|
|
64
|
-
console.error('API Error:', error);
|
|
65
|
-
return NextResponse.json(
|
|
66
|
-
{
|
|
67
|
-
success: false,
|
|
68
|
-
error: error instanceof Error ? error.message : 'Unknown error'
|
|
69
|
-
},
|
|
70
|
-
{ status: 500 }
|
|
71
|
-
);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import { NextRequest, NextResponse } from 'next/server';
|
|
2
|
-
import { HtmlGenerator } from '@/lib/htmlGenerator';
|
|
3
|
-
import { MarkdownGenerator } from '@/lib/markdownGenerator';
|
|
4
|
-
import { MarkdownTableGenerator } from '@/lib/markdownTableGenerator';
|
|
5
|
-
import { FileSystemService } from '@/lib/fileSystem';
|
|
6
|
-
import { getRootPath } from '@/lib/getRootPath';
|
|
7
|
-
import path from 'path';
|
|
8
|
-
import fs from 'fs/promises';
|
|
9
|
-
|
|
10
|
-
export async function POST(request: NextRequest) {
|
|
11
|
-
try {
|
|
12
|
-
const rootPath = getRootPath();
|
|
13
|
-
|
|
14
|
-
// リクエストボディからフォーマット、ファイル名、出力先フォルダを取得
|
|
15
|
-
let body;
|
|
16
|
-
try {
|
|
17
|
-
body = await request.json();
|
|
18
|
-
} catch {
|
|
19
|
-
body = {};
|
|
20
|
-
}
|
|
21
|
-
const { format = 'html' } = body;
|
|
22
|
-
// fileNameが空文字列の場合はデフォルト値を使用
|
|
23
|
-
const fileName = body.fileName?.trim() || 'config-doc';
|
|
24
|
-
// outputDirが空文字列の場合はプロジェクトルートに出力
|
|
25
|
-
const outputDir = body.outputDir?.trim() || '';
|
|
26
|
-
|
|
27
|
-
// フォーマットに応じてジェネレーターを選択
|
|
28
|
-
let content: string;
|
|
29
|
-
|
|
30
|
-
if (format === 'markdown') {
|
|
31
|
-
const generator = new MarkdownGenerator(rootPath);
|
|
32
|
-
content = await generator.generateMarkdown();
|
|
33
|
-
} else if (format === 'markdown-table') {
|
|
34
|
-
const generator = new MarkdownTableGenerator(rootPath);
|
|
35
|
-
content = await generator.generateMarkdownTable();
|
|
36
|
-
} else {
|
|
37
|
-
// デフォルトはHTML
|
|
38
|
-
const generator = new HtmlGenerator(rootPath);
|
|
39
|
-
content = await generator.generateHtml();
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// 出力ファイル名を決定(拡張子付き)
|
|
43
|
-
const extension = (format === 'markdown' || format === 'markdown-table') ? 'md' : 'html';
|
|
44
|
-
const outputFileName = `${fileName}.${extension}`;
|
|
45
|
-
|
|
46
|
-
// 出力パス: {outputDir}/{fileName}.{extension}(outputDirが空ならルート直下)
|
|
47
|
-
const fsService = new FileSystemService(rootPath);
|
|
48
|
-
await fsService.ensureConfigDocDir();
|
|
49
|
-
const outputPath = outputDir
|
|
50
|
-
? path.join(rootPath, outputDir, outputFileName)
|
|
51
|
-
: path.join(rootPath, outputFileName);
|
|
52
|
-
|
|
53
|
-
// ディレクトリを確保
|
|
54
|
-
const outputDirPath = path.dirname(outputPath);
|
|
55
|
-
await fs.mkdir(outputDirPath, { recursive: true });
|
|
56
|
-
|
|
57
|
-
// ファイルを保存
|
|
58
|
-
await fs.writeFile(outputPath, content, 'utf-8');
|
|
59
|
-
|
|
60
|
-
return NextResponse.json({
|
|
61
|
-
success: true,
|
|
62
|
-
message: `${format === 'markdown' ? 'Markdown' : 'HTML'}ファイルを生成しました`,
|
|
63
|
-
outputPath
|
|
64
|
-
});
|
|
65
|
-
} catch (error) {
|
|
66
|
-
console.error('API Error:', error);
|
|
67
|
-
return NextResponse.json(
|
|
68
|
-
{
|
|
69
|
-
success: false,
|
|
70
|
-
error: error instanceof Error ? error.message : 'Unknown error'
|
|
71
|
-
},
|
|
72
|
-
{ status: 500 }
|
|
73
|
-
);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
import { NextRequest, NextResponse } from 'next/server';
|
|
2
|
-
import { getRootPath } from '@/lib/getRootPath';
|
|
3
|
-
import path from 'path';
|
|
4
|
-
import fs from 'fs/promises';
|
|
5
|
-
import { ExportSettings, UserSettings, ProjectSettings } from '@/types';
|
|
6
|
-
import { FileSystemService } from '@/lib/fileSystem';
|
|
7
|
-
import { parseJSON } from '@/lib/jsonUtils';
|
|
8
|
-
|
|
9
|
-
const USER_SETTINGS_FILE = '.user_settings.json';
|
|
10
|
-
const CONFIG_DOC_DIR = '.config_doc';
|
|
11
|
-
|
|
12
|
-
// GET: エクスポート設定を読み込み
|
|
13
|
-
export async function GET() {
|
|
14
|
-
try {
|
|
15
|
-
const rootPath = getRootPath();
|
|
16
|
-
const fsService = new FileSystemService(rootPath);
|
|
17
|
-
const userSettingsPath = path.join(rootPath, CONFIG_DOC_DIR, USER_SETTINGS_FILE);
|
|
18
|
-
|
|
19
|
-
// ユーザ設定を読み込み
|
|
20
|
-
let userSettings: UserSettings;
|
|
21
|
-
try {
|
|
22
|
-
const content = await fs.readFile(userSettingsPath, 'utf-8');
|
|
23
|
-
userSettings = parseJSON<UserSettings>(content);
|
|
24
|
-
} catch {
|
|
25
|
-
// デフォルトのユーザ設定
|
|
26
|
-
userSettings = {
|
|
27
|
-
format: 'html',
|
|
28
|
-
autoExport: true
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
// プロジェクト設定から export.fileName と outputDir を取得
|
|
33
|
-
// outputDirは空文字も有効な値(プロジェクトルートを意味する)なので、undefinedのみデフォルト値を使用
|
|
34
|
-
const projectSettings = await fsService.loadProjectSettings();
|
|
35
|
-
const fileName = projectSettings?.export?.fileName || 'config-doc';
|
|
36
|
-
const outputDir = projectSettings?.export?.outputDir !== undefined
|
|
37
|
-
? projectSettings.export.outputDir
|
|
38
|
-
: '.config_doc/output';
|
|
39
|
-
|
|
40
|
-
// 統合された設定を返す
|
|
41
|
-
const settings: ExportSettings = {
|
|
42
|
-
...userSettings,
|
|
43
|
-
fileName,
|
|
44
|
-
outputDir
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
return NextResponse.json({
|
|
48
|
-
success: true,
|
|
49
|
-
data: settings
|
|
50
|
-
});
|
|
51
|
-
} catch (error) {
|
|
52
|
-
console.error('Failed to load export settings:', error);
|
|
53
|
-
return NextResponse.json(
|
|
54
|
-
{
|
|
55
|
-
success: false,
|
|
56
|
-
error: error instanceof Error ? error.message : 'Unknown error'
|
|
57
|
-
},
|
|
58
|
-
{ status: 500 }
|
|
59
|
-
);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// POST: エクスポート設定を保存
|
|
64
|
-
export async function POST(request: NextRequest) {
|
|
65
|
-
try {
|
|
66
|
-
let body;
|
|
67
|
-
try {
|
|
68
|
-
body = await request.json();
|
|
69
|
-
} catch {
|
|
70
|
-
return NextResponse.json(
|
|
71
|
-
{ success: false, error: 'Invalid JSON body' },
|
|
72
|
-
{ status: 400 }
|
|
73
|
-
);
|
|
74
|
-
}
|
|
75
|
-
const settings: ExportSettings = body.settings;
|
|
76
|
-
|
|
77
|
-
if (!settings || !settings.format) {
|
|
78
|
-
return NextResponse.json(
|
|
79
|
-
{ success: false, error: 'Invalid settings' },
|
|
80
|
-
{ status: 400 }
|
|
81
|
-
);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
const rootPath = getRootPath();
|
|
85
|
-
const fsService = new FileSystemService(rootPath);
|
|
86
|
-
const configDocDir = path.join(rootPath, CONFIG_DOC_DIR);
|
|
87
|
-
|
|
88
|
-
// .config_doc ディレクトリを確保
|
|
89
|
-
await fs.mkdir(configDocDir, { recursive: true });
|
|
90
|
-
|
|
91
|
-
// ユーザ設定を保存(format, autoExport, lastExportedAt)
|
|
92
|
-
const userSettings: UserSettings = {
|
|
93
|
-
format: settings.format,
|
|
94
|
-
autoExport: settings.autoExport,
|
|
95
|
-
lastExportedAt: settings.lastExportedAt
|
|
96
|
-
};
|
|
97
|
-
const userSettingsPath = path.join(configDocDir, USER_SETTINGS_FILE);
|
|
98
|
-
await fs.writeFile(
|
|
99
|
-
userSettingsPath,
|
|
100
|
-
JSON.stringify(userSettings, null, 2),
|
|
101
|
-
'utf-8'
|
|
102
|
-
);
|
|
103
|
-
|
|
104
|
-
// プロジェクト設定の export.fileName と outputDir を更新
|
|
105
|
-
if (settings.fileName !== undefined || settings.outputDir !== undefined) {
|
|
106
|
-
const existingProjectSettings = await fsService.loadProjectSettings();
|
|
107
|
-
|
|
108
|
-
if (existingProjectSettings) {
|
|
109
|
-
// 既存の設定を更新
|
|
110
|
-
existingProjectSettings.export = {
|
|
111
|
-
...existingProjectSettings.export,
|
|
112
|
-
fileName: settings.fileName ?? existingProjectSettings.export?.fileName,
|
|
113
|
-
outputDir: settings.outputDir ?? existingProjectSettings.export?.outputDir
|
|
114
|
-
};
|
|
115
|
-
await fsService.saveProjectSettings(existingProjectSettings);
|
|
116
|
-
} else {
|
|
117
|
-
// 新規作成
|
|
118
|
-
const newProjectSettings: ProjectSettings = {
|
|
119
|
-
projectName: path.basename(rootPath),
|
|
120
|
-
configFiles: [],
|
|
121
|
-
export: {
|
|
122
|
-
fileName: settings.fileName,
|
|
123
|
-
outputDir: settings.outputDir
|
|
124
|
-
}
|
|
125
|
-
};
|
|
126
|
-
await fsService.saveProjectSettings(newProjectSettings);
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
return NextResponse.json({
|
|
131
|
-
success: true,
|
|
132
|
-
message: 'Export settings saved'
|
|
133
|
-
});
|
|
134
|
-
} catch (error) {
|
|
135
|
-
console.error('Failed to save export settings:', error);
|
|
136
|
-
return NextResponse.json(
|
|
137
|
-
{
|
|
138
|
-
success: false,
|
|
139
|
-
error: error instanceof Error ? error.message : 'Unknown error'
|
|
140
|
-
},
|
|
141
|
-
{ status: 500 }
|
|
142
|
-
);
|
|
143
|
-
}
|
|
144
|
-
}
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { NextRequest, NextResponse } from 'next/server';
|
|
2
|
-
import { FileSystemService } from '@/lib/fileSystem';
|
|
3
|
-
import { getRootPath } from '@/lib/getRootPath';
|
|
4
|
-
|
|
5
|
-
export async function POST(request: NextRequest) {
|
|
6
|
-
try {
|
|
7
|
-
let body: { directory?: string } = {};
|
|
8
|
-
try {
|
|
9
|
-
body = await request.json();
|
|
10
|
-
} catch {
|
|
11
|
-
// 空のボディの場合は無視
|
|
12
|
-
}
|
|
13
|
-
const { directory } = body;
|
|
14
|
-
|
|
15
|
-
if (!directory) {
|
|
16
|
-
return NextResponse.json(
|
|
17
|
-
{ success: false, error: 'directory is required' },
|
|
18
|
-
{ status: 400 }
|
|
19
|
-
);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
// プロジェクトのルートパス(ユーザーの作業ディレクトリ)
|
|
23
|
-
const rootPath = getRootPath();
|
|
24
|
-
const fsService = new FileSystemService(rootPath);
|
|
25
|
-
|
|
26
|
-
// ディレクトリ内のファイル一覧を取得
|
|
27
|
-
const items = await fsService.browseDirectory(directory);
|
|
28
|
-
|
|
29
|
-
return NextResponse.json({
|
|
30
|
-
success: true,
|
|
31
|
-
data: {
|
|
32
|
-
currentPath: directory,
|
|
33
|
-
items
|
|
34
|
-
}
|
|
35
|
-
});
|
|
36
|
-
} catch (error) {
|
|
37
|
-
console.error('API Error:', error);
|
|
38
|
-
return NextResponse.json(
|
|
39
|
-
{
|
|
40
|
-
success: false,
|
|
41
|
-
error: error instanceof Error ? error.message : 'Unknown error'
|
|
42
|
-
},
|
|
43
|
-
{ status: 500 }
|
|
44
|
-
);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { NextResponse } from 'next/server';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
import fs from 'fs/promises';
|
|
4
|
-
import { getRootPath } from '@/lib/getRootPath';
|
|
5
|
-
|
|
6
|
-
export async function GET() {
|
|
7
|
-
try {
|
|
8
|
-
// プロジェクトのルートパスを取得(ユーザーの作業ディレクトリ)
|
|
9
|
-
const rootPath = getRootPath();
|
|
10
|
-
const projectName = path.basename(rootPath);
|
|
11
|
-
|
|
12
|
-
// .config_docディレクトリの存在確認
|
|
13
|
-
const ConfigDocPath = path.join(rootPath, '.config_doc');
|
|
14
|
-
let hasConfigDoc = false;
|
|
15
|
-
|
|
16
|
-
try {
|
|
17
|
-
await fs.access(ConfigDocPath);
|
|
18
|
-
hasConfigDoc = true;
|
|
19
|
-
} catch {
|
|
20
|
-
hasConfigDoc = false;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
return NextResponse.json({
|
|
24
|
-
success: true,
|
|
25
|
-
data: {
|
|
26
|
-
projectName,
|
|
27
|
-
rootPath,
|
|
28
|
-
hasConfigDoc
|
|
29
|
-
}
|
|
30
|
-
});
|
|
31
|
-
} catch (error) {
|
|
32
|
-
console.error('API Error:', error);
|
|
33
|
-
return NextResponse.json(
|
|
34
|
-
{
|
|
35
|
-
success: false,
|
|
36
|
-
error: error instanceof Error ? error.message : 'Unknown error'
|
|
37
|
-
},
|
|
38
|
-
{ status: 500 }
|
|
39
|
-
);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
@import "tailwindcss";
|
|
2
|
-
|
|
3
|
-
:root {
|
|
4
|
-
--background: #ffffff;
|
|
5
|
-
--foreground: #171717;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
@theme inline {
|
|
9
|
-
--color-background: var(--background);
|
|
10
|
-
--color-foreground: var(--foreground);
|
|
11
|
-
--font-sans: var(--font-geist-sans);
|
|
12
|
-
--font-mono: var(--font-geist-mono);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
@media (prefers-color-scheme: dark) {
|
|
16
|
-
:root {
|
|
17
|
-
--background: #0a0a0a;
|
|
18
|
-
--foreground: #ededed;
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
body {
|
|
23
|
-
background: var(--background);
|
|
24
|
-
color: var(--foreground);
|
|
25
|
-
font-family: Arial, Helvetica, sans-serif;
|
|
26
|
-
}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 240 240" fill="none">
|
|
2
|
-
<defs>
|
|
3
|
-
<linearGradient id="bgGradient" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
4
|
-
<stop offset="0%" style="stop-color:#3B82F6"/>
|
|
5
|
-
<stop offset="50%" style="stop-color:#6366F1"/>
|
|
6
|
-
<stop offset="100%" style="stop-color:#8B5CF6"/>
|
|
7
|
-
</linearGradient>
|
|
8
|
-
<linearGradient id="docGradient" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
9
|
-
<stop offset="0%" style="stop-color:#60A5FA"/>
|
|
10
|
-
<stop offset="100%" style="stop-color:#A78BFA"/>
|
|
11
|
-
</linearGradient>
|
|
12
|
-
</defs>
|
|
13
|
-
|
|
14
|
-
<!-- 背景の角丸四角 -->
|
|
15
|
-
<rect x="8" y="8" width="224" height="224" rx="44" fill="url(#bgGradient)"/>
|
|
16
|
-
|
|
17
|
-
<!-- ドキュメントアイコン(背面) -->
|
|
18
|
-
<path d="M68 48 L148 48 L172 72 L172 192 L68 192 Z" fill="white" opacity="0.2"/>
|
|
19
|
-
<path d="M148 48 L148 72 L172 72" fill="none" stroke="white" stroke-width="4" opacity="0.2"/>
|
|
20
|
-
|
|
21
|
-
<!-- ドキュメントアイコン(前面) -->
|
|
22
|
-
<path d="M52 64 L132 64 L156 88 L156 208 L52 208 Z" fill="white"/>
|
|
23
|
-
<path d="M132 64 L132 88 L156 88" fill="none" stroke="url(#docGradient)" stroke-width="4"/>
|
|
24
|
-
|
|
25
|
-
<!-- JSON括弧 { } -->
|
|
26
|
-
<text x="104" y="152" font-family="Monaco, Consolas, monospace" font-size="48" font-weight="bold" fill="url(#bgGradient)" text-anchor="middle">{ }</text>
|
|
27
|
-
|
|
28
|
-
<!-- 歯車(右下) -->
|
|
29
|
-
<circle cx="188" cy="188" r="40" fill="url(#docGradient)"/>
|
|
30
|
-
<circle cx="188" cy="188" r="16" fill="white"/>
|
|
31
|
-
<g fill="url(#docGradient)">
|
|
32
|
-
<rect x="182" y="144" width="12" height="16" rx="4"/>
|
|
33
|
-
<rect x="182" y="216" width="12" height="16" rx="4"/>
|
|
34
|
-
<rect x="144" y="182" width="16" height="12" rx="4"/>
|
|
35
|
-
<rect x="216" y="182" width="16" height="12" rx="4"/>
|
|
36
|
-
<rect x="152" y="152" width="12" height="16" rx="4" transform="rotate(45 158 160)"/>
|
|
37
|
-
<rect x="212" y="212" width="12" height="16" rx="4" transform="rotate(45 218 220)"/>
|
|
38
|
-
<rect x="212" y="152" width="12" height="16" rx="4" transform="rotate(-45 218 160)"/>
|
|
39
|
-
<rect x="152" y="212" width="12" height="16" rx="4" transform="rotate(-45 158 220)"/>
|
|
40
|
-
</g>
|
|
41
|
-
</svg>
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import type { Metadata } from "next";
|
|
2
|
-
import { Geist, Geist_Mono } from "next/font/google";
|
|
3
|
-
import "./globals.css";
|
|
4
|
-
|
|
5
|
-
const geistSans = Geist({
|
|
6
|
-
variable: "--font-geist-sans",
|
|
7
|
-
subsets: ["latin"],
|
|
8
|
-
});
|
|
9
|
-
|
|
10
|
-
const geistMono = Geist_Mono({
|
|
11
|
-
variable: "--font-geist-mono",
|
|
12
|
-
subsets: ["latin"],
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
export const metadata: Metadata = {
|
|
16
|
-
title: "ConfigDoc Web",
|
|
17
|
-
description: "設定ファイルのドキュメント化ツール",
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
export default function RootLayout({
|
|
21
|
-
children,
|
|
22
|
-
}: Readonly<{
|
|
23
|
-
children: React.ReactNode;
|
|
24
|
-
}>) {
|
|
25
|
-
return (
|
|
26
|
-
<html lang="ja">
|
|
27
|
-
<body
|
|
28
|
-
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
|
|
29
|
-
>
|
|
30
|
-
{children}
|
|
31
|
-
</body>
|
|
32
|
-
</html>
|
|
33
|
-
);
|
|
34
|
-
}
|
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import { useState } from 'react';
|
|
4
|
-
import { FileTextIcon } from 'lucide-react';
|
|
5
|
-
import { Header } from '@/components/Header';
|
|
6
|
-
import { ConfigFileTabs } from '@/components/ConfigFileTabs';
|
|
7
|
-
import { PropertyEditor } from '@/components/PropertyEditor';
|
|
8
|
-
import { ConfigTree } from '@/components/ConfigTree';
|
|
9
|
-
import { FileBrowser } from '@/components/FileBrowser';
|
|
10
|
-
import { ExportDialog } from '@/components/ExportDialog';
|
|
11
|
-
import { ToastContainer } from '@/components/Toast';
|
|
12
|
-
import { useConfigManager } from '@/hooks/useConfigManager';
|
|
13
|
-
|
|
14
|
-
export default function Home() {
|
|
15
|
-
const [isFileBrowserOpen, setIsFileBrowserOpen] = useState(false);
|
|
16
|
-
const [isExportDialogOpen, setIsExportDialogOpen] = useState(false);
|
|
17
|
-
|
|
18
|
-
const {
|
|
19
|
-
loadedConfigs,
|
|
20
|
-
activeConfigIndex,
|
|
21
|
-
activeConfig,
|
|
22
|
-
selectedPath,
|
|
23
|
-
editingDoc,
|
|
24
|
-
originalDoc,
|
|
25
|
-
hasUnsavedChanges,
|
|
26
|
-
exportSettings,
|
|
27
|
-
availableTags,
|
|
28
|
-
projectFields,
|
|
29
|
-
toasts,
|
|
30
|
-
rootPath,
|
|
31
|
-
|
|
32
|
-
setActiveConfigIndex,
|
|
33
|
-
setEditingDoc,
|
|
34
|
-
setHasUnsavedChanges,
|
|
35
|
-
removeToast,
|
|
36
|
-
handleSelectConfigFiles,
|
|
37
|
-
handleRemoveConfig,
|
|
38
|
-
handleReorderConfigs,
|
|
39
|
-
handleSelectProperty,
|
|
40
|
-
handleSaveProperty,
|
|
41
|
-
handleExport,
|
|
42
|
-
handleAvailableTagsChange,
|
|
43
|
-
handleProjectFieldsChange,
|
|
44
|
-
checkForChanges,
|
|
45
|
-
resetSelection
|
|
46
|
-
} = useConfigManager();
|
|
47
|
-
|
|
48
|
-
return (
|
|
49
|
-
<div className="min-h-screen bg-gradient-to-br from-blue-50 via-indigo-50 to-purple-50">
|
|
50
|
-
{/* ヘッダー */}
|
|
51
|
-
<Header onExportClick={() => setIsExportDialogOpen(true)} />
|
|
52
|
-
|
|
53
|
-
{/* メインコンテンツ */}
|
|
54
|
-
<main className="container mx-auto px-6 py-8">
|
|
55
|
-
{/* ファイル選択セクション */}
|
|
56
|
-
<ConfigFileTabs
|
|
57
|
-
loadedConfigs={loadedConfigs}
|
|
58
|
-
activeConfigIndex={activeConfigIndex}
|
|
59
|
-
onTabClick={(index) => {
|
|
60
|
-
setActiveConfigIndex(index);
|
|
61
|
-
resetSelection();
|
|
62
|
-
}}
|
|
63
|
-
onRemoveConfig={handleRemoveConfig}
|
|
64
|
-
onAddFileClick={() => setIsFileBrowserOpen(true)}
|
|
65
|
-
onReorder={handleReorderConfigs}
|
|
66
|
-
/>
|
|
67
|
-
|
|
68
|
-
{/* ツリーと詳細パネル */}
|
|
69
|
-
{activeConfig && (
|
|
70
|
-
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
|
71
|
-
{/* 左パネル: JSON構造ツリー */}
|
|
72
|
-
<div className="bg-white/90 backdrop-blur-sm rounded-2xl shadow-xl border border-gray-100 p-6 flex flex-col max-h-[calc(100vh-190px)] hover:shadow-2xl transition-shadow duration-300">
|
|
73
|
-
<div className="flex items-center gap-2 mb-4">
|
|
74
|
-
<div className="w-8 h-8 bg-gradient-to-br from-purple-500 to-purple-600 rounded-lg flex items-center justify-center">
|
|
75
|
-
<FileTextIcon className="w-5 h-5 text-white" />
|
|
76
|
-
</div>
|
|
77
|
-
<h2 className="text-xl font-bold text-gray-800">JSON構造</h2>
|
|
78
|
-
</div>
|
|
79
|
-
<div className="overflow-y-auto flex-1">
|
|
80
|
-
<ConfigTree
|
|
81
|
-
config={activeConfig.configData}
|
|
82
|
-
docs={activeConfig.docs}
|
|
83
|
-
onSelectProperty={handleSelectProperty}
|
|
84
|
-
onEditProperty={handleSelectProperty}
|
|
85
|
-
selectedPath={selectedPath}
|
|
86
|
-
/>
|
|
87
|
-
</div>
|
|
88
|
-
</div>
|
|
89
|
-
|
|
90
|
-
{/* 右パネル: プロパティ詳細 */}
|
|
91
|
-
<PropertyEditor
|
|
92
|
-
selectedPath={selectedPath}
|
|
93
|
-
editingDoc={editingDoc}
|
|
94
|
-
hasUnsavedChanges={hasUnsavedChanges}
|
|
95
|
-
availableTags={availableTags}
|
|
96
|
-
projectFields={projectFields}
|
|
97
|
-
onEditingDocChange={(doc) => {
|
|
98
|
-
setEditingDoc(doc);
|
|
99
|
-
setHasUnsavedChanges(checkForChanges(doc, originalDoc));
|
|
100
|
-
}}
|
|
101
|
-
onAvailableTagsChange={handleAvailableTagsChange}
|
|
102
|
-
onProjectFieldsChange={handleProjectFieldsChange}
|
|
103
|
-
onSave={handleSaveProperty}
|
|
104
|
-
/>
|
|
105
|
-
</div>
|
|
106
|
-
)}
|
|
107
|
-
</main>
|
|
108
|
-
|
|
109
|
-
{/* ファイルブラウザ */}
|
|
110
|
-
<FileBrowser
|
|
111
|
-
isOpen={isFileBrowserOpen}
|
|
112
|
-
currentPath={rootPath}
|
|
113
|
-
multiSelect={true}
|
|
114
|
-
filterJsonOnly={true}
|
|
115
|
-
onSelect={(filePaths) => {
|
|
116
|
-
handleSelectConfigFiles(filePaths);
|
|
117
|
-
setIsFileBrowserOpen(false);
|
|
118
|
-
}}
|
|
119
|
-
onClose={() => setIsFileBrowserOpen(false)}
|
|
120
|
-
/>
|
|
121
|
-
|
|
122
|
-
{/* エクスポートダイアログ */}
|
|
123
|
-
<ExportDialog
|
|
124
|
-
isOpen={isExportDialogOpen}
|
|
125
|
-
onClose={() => setIsExportDialogOpen(false)}
|
|
126
|
-
onExport={handleExport}
|
|
127
|
-
currentSettings={exportSettings}
|
|
128
|
-
rootPath={rootPath}
|
|
129
|
-
/>
|
|
130
|
-
|
|
131
|
-
{/* トースト通知 */}
|
|
132
|
-
<ToastContainer toasts={toasts} onRemove={removeToast} />
|
|
133
|
-
</div>
|
|
134
|
-
);
|
|
135
|
-
}
|