diff --git a/src/app/api/export/route.ts b/src/app/api/export/route.ts index 0a9106c..9ecc524 100644 --- a/src/app/api/export/route.ts +++ b/src/app/api/export/route.ts @@ -52,7 +52,9 @@ const escapeHtml = (value: string): string => const escapeAttr = (value: string): string => escapeHtml(value); export const buildStaticHtml = (blocks: Block[], projectConfig?: ProjectConfig): string => { - const pageTitleRaw = (projectConfig?.title ?? "").trim() || "Page Builder Export"; + const baseTitleRaw = (projectConfig?.title ?? "").trim() || "Page Builder Export"; + const seoTitleRaw = (projectConfig?.seoTitle ?? "").trim(); + const pageTitleRaw = seoTitleRaw || baseTitleRaw; const pageTitle = escapeHtml(pageTitleRaw); const headExtraRaw = (projectConfig?.headHtml ?? "").trim(); @@ -84,6 +86,77 @@ export const buildStaticHtml = (blocks: Block[], projectConfig?: ProjectConfig): const trackingRaw = (projectConfig?.trackingScript ?? "").trim(); const trackingHtml = trackingRaw ? `\n${trackingRaw}\n` : ""; + const seoDescriptionRaw = (projectConfig?.seoDescription ?? "").trim(); + const seoOgImageRaw = (projectConfig?.seoOgImageUrl ?? "").trim(); + const seoCanonicalRaw = (projectConfig?.seoCanonicalUrl ?? "").trim(); + const seoNoIndex = projectConfig?.seoNoIndex === true; + + const seoHeadParts: string[] = []; + + if (seoDescriptionRaw) { + seoHeadParts.push( + ` `, + ); + } + + if (pageTitleRaw) { + seoHeadParts.push( + ` `, + ); + } + if (seoDescriptionRaw) { + seoHeadParts.push( + ` `, + ); + } + seoHeadParts.push(` `); + + if (seoOgImageRaw) { + seoHeadParts.push( + ` `, + ); + } + + if (seoCanonicalRaw) { + seoHeadParts.push( + ` `, + ); + } + + // Twitter 카드 메타 태그 + seoHeadParts.push( + ` `, + ); + if (pageTitleRaw) { + seoHeadParts.push( + ` `, + ); + } + if (seoDescriptionRaw) { + seoHeadParts.push( + ` `, + ); + } + if (seoOgImageRaw) { + seoHeadParts.push( + ` `, + ); + } + + if (seoCanonicalRaw) { + seoHeadParts.push( + ` `, + ); + } + + if (seoNoIndex) { + seoHeadParts.push( + ` `, + ); + } + + const seoHeadHtml = seoHeadParts.length > 0 ? `\n${seoHeadParts.join("\n")}` : ""; + const sectionBlocks = blocks.filter((b) => b.type === "section"); const rootBlocks = blocks.filter((b) => !b.sectionId && b.type !== "section"); @@ -515,7 +588,7 @@ export const buildStaticHtml = (blocks: Block[], projectConfig?: ProjectConfig): ${pageTitle} - ${headExtra} + ${seoHeadHtml}${headExtra}
diff --git a/src/app/editor/forms/FormControllerPanel.tsx b/src/app/editor/forms/FormControllerPanel.tsx index 811a67b..a3d5996 100644 --- a/src/app/editor/forms/FormControllerPanel.tsx +++ b/src/app/editor/forms/FormControllerPanel.tsx @@ -1,8 +1,6 @@ "use client"; import type { Block, ButtonBlockProps, FormBlockProps } from "@/features/editor/state/editorStore"; -import { NumericPropertyControl } from "@/features/editor/components/NumericPropertyControl"; -import { ColorPickerField, TEXT_COLOR_PALETTE } from "@/features/editor/components/ColorPickerField"; interface FormControllerPanelProps { block: Block; // type === "form" @@ -131,89 +129,6 @@ export function FormControllerPanel({ block, blocks, selectedBlockId, updateBloc )} -
-

폼 레이아웃

- - {(formProps.formWidthMode ?? "auto") === "fixed" && ( - - updateBlock(selectedBlockId, { - formWidthPx: v, - } as any) - } - /> - )} - - updateBlock(selectedBlockId, { - marginYPx: v, - } as any) - } - /> -
- -
-

폼 스타일

- { - updateBlock(selectedBlockId, { - backgroundColorCustom: hex, - } as any); - }} - palette={TEXT_COLOR_PALETTE} - onPaletteSelect={(item) => { - updateBlock(selectedBlockId, { - backgroundColorCustom: item.color, - } as any); - }} - /> -
-

폼 메시지

+
+

SEO / 메타

+ + + +