FE_Dev / app /api /cn-html-preview /route.ts
GitHub Actions
Deploy from GitHub Actions [dev] - 2025-10-31 07:28:50
68f7925
import { generateContentsHtmlWithImages } from '@/server/services/html-preview/contents/contents-html.service';
import { getSessionId } from '@/utils/session';
import { NextResponse } from 'next/server';
export async function POST(request: Request) {
try {
// リクエストから��ッションIDを生成
const sessionId = getSessionId(request);
console.log('[CN-SAMPLE API] Session ID:', sessionId);
const body = await request.json();
const { cnData, forceEnableInDummyMode } = body; // forceEnableInDummyModeパラメータを追加
console.log('[CN-SAMPLE API] Request received:', {
sessionId,
cnDataType: typeof cnData,
cnDataIsArray: Array.isArray(cnData),
cnDataKeys: cnData && typeof cnData === 'object' ? Object.keys(cnData) : null,
forceEnableInDummyMode,
});
// CNデータを配列形式に変換
const cnSections: Array<Record<string, unknown>> = [];
// rawデータの構造に対応: オブジェクトから各戦略のCNデータを抽出
if (cnData && typeof cnData === 'object') {
// 配列の場合は最初の要素を使用
const rawData = Array.isArray(cnData) ? cnData[0] : cnData;
// 各戦略タイプからCNデータを抽出
Object.values(rawData).forEach((strategy) => {
if (strategy && typeof strategy === 'object') {
Object.values(strategy as Record<string, unknown>).forEach((tabData) => {
const tabDataTyped = tabData as { cn?: Array<Record<string, unknown>> };
if (tabDataTyped?.cn && Array.isArray(tabDataTyped.cn)) {
// 制作意図フィールドを追加(必須の場合)
const sectionsWithIntent = tabDataTyped.cn.map((section) => ({
...section,
制作意図: (section as { 制作意図?: string }).制作意図 || 'CNサンプルページでのプレビュー用',
}));
cnSections.push(...sectionsWithIntent);
}
});
}
});
}
if (cnSections.length === 0) {
return NextResponse.json({ error: '有効なCNデータが見つかりません。' }, { status: 400 });
}
console.log('[CN-SAMPLE API] Processing CN sections:', {
sectionsCount: cnSections.length,
firstSection: cnSections[0],
});
// HTML生成(画像生成を有効化)
const { html, css, batchId } = await generateContentsHtmlWithImages(
'CNサンプル',
cnSections as Parameters<typeof generateContentsHtmlWithImages>[1],
false, // isDummyMode = false で画像生成を有効化
true, // forceImageGeneration = true で開発環境でも画像生成を強制
forceEnableInDummyMode, // ダミーモードでも画像生成を強制するパラメータを渡す
undefined, // ownUrl (エラーログ用、サンプルでは不要)
undefined, // userEmail (エラーログ用、サンプルでは不要)
undefined, // テーマはCSSのみで適用するため、画像生成時には渡さない
);
console.log('[CN-SAMPLE API] HTML generated successfully', batchId ? `with batch ID: ${batchId}` : 'without image generation');
// デバッグ: 生成直後のHTMLを確認
const allImageIds = html.match(/id="[^"]*-img-[^"]*"/g);
if (allImageIds) {
const uniqueIds = [...new Set(allImageIds)];
console.log('[CN-SAMPLE API] Unique image IDs count:', uniqueIds.length);
console.log('[CN-SAMPLE API] First 3 unique IDs:', uniqueIds.slice(0, 3));
}
// デバッグ: 生成されたHTMLの最初の画像タグを確認
const imgMatches = html.match(/<img[^>]*id="([^"]*)"[^>]*>/g);
if (imgMatches && imgMatches.length > 0) {
console.log('[CN-SAMPLE API] First 5 img tags in generated HTML:');
imgMatches.slice(0, 5).forEach((img, i) => {
const idMatch = img.match(/id="([^"]*)"/);
const altMatch = img.match(/alt="([^"]*)"/);
console.log(` ${i + 1}. id="${idMatch?.[1]}", alt="${altMatch?.[1]?.substring(0, 50)}..."`);
});
}
// 完全なHTML文書を生成(FVなし版)
const fullHtmlDocument = `<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CNサンプル - プレビュー</title>
<style>
${css}
</style>
</head>
<body>
${html}
<script>
// FAQ toggle function
function toggleFaq(element) {
const faqItem = element.closest('.faq-item');
if (faqItem) {
faqItem.classList.toggle('open');
}
}
// Scroll to top function
function scrollToTop() {
window.scrollTo({ top: 0, behavior: 'smooth' });
}
</script>
</body>
</html>`;
// JSONレスポンスとして返す
return NextResponse.json({
html: fullHtmlDocument,
css: css,
batchId: batchId,
message: batchId ? 'HTMLと画像生成バッチが開始されました。' : 'HTMLが生成されました。',
});
} catch (error) {
console.error('[CN-SAMPLE API] Error:', error);
return NextResponse.json({ error: error instanceof Error ? error.message : 'HTML生成に失敗しました。' }, { status: 500 });
}
}