← GPT-AI-LP
CODE · 2.0 KB

src/export-bundle.js

Workspace snapshot · 08/31 23:51

import JSZip from "jszip";
import { exportHtml, exportThanksHtml } from "./export-html.js";

const extensionFor = (contentType = "") => {
  if (contentType.includes("png")) return "png";
  if (contentType.includes("webp")) return "webp";
  if (contentType.includes("svg")) return "svg";
  return "jpg";
};

export async function buildExportBundle({ project, sections, tone, images, publicUrl = "", fetcher = fetch }) {
  const zip = new JSZip();
  const embedded = [];
  const visualSections = (Array.isArray(sections) ? sections : []).filter((section) => section.imageBrief);
  for (const [index, image] of (Array.isArray(images) ? images : []).entries()) {
    const record = typeof image === "string"
      ? { src: image, sectionId: visualSections[index]?.id || "" }
      : image;
    if (!record?.src) continue;
    const response = await fetcher(record.src);
    if (!response.ok) throw new Error("生成画像を納品ZIPへ保存できませんでした。再生成してからお試しください");
    const blob = await response.blob();
    const extension = extensionFor(blob.type || response.headers.get("content-type") || "");
    const layer = String(record.layer || "content").replace(/[^a-z0-9_-]/giu, "") || "content";
    const filename = `images/${record.sectionId || `visual-${index + 1}`}-${layer}.${extension}`;
    zip.file(filename, await blob.arrayBuffer());
    embedded.push({ ...record, src: filename });
  }
  const html = exportHtml(project, sections, tone, embedded, { publicUrl });
  zip.file("index.html", html);
  zip.file("thanks.html", exportThanksHtml(project, tone));
  zip.file("README.txt", "index.htmlをブラウザで開いてください。画像はimages/へ同梱済みです。公開前にフォーム送信先、個人情報の取り扱い、計測ID、正式表記を最終確認してください。送信完了ページはthanks.htmlです。\n");
  zip.file("design.json", JSON.stringify({ project: { name: project?.name, answers: project?.answers }, tone, sections }, null, 2));
  return zip.generateAsync({ type: "blob" });
}