import { PersonalityDataType, HorizontalAlignment, VerticalAlignment, ButtonSize, ImageSize, TextType, ButtonType, ImageType, SectionType, SocialType, SocialNetworkType, SocialIconSize, SocialIconStyle, } from "../types/Types"; import { getSocialIconPath, hasPngIcon, getSocialColor, getSocialSvgIcon, } from "./socialIcons"; export const exportPersonalityToHTML = async ( data: PersonalityDataType ): Promise => { console.log( "🔥 [ExportHTML] Starting export with data:", JSON.stringify(data, null, 2) ); // Helper functions const getHorizontalAlign = (alignment?: HorizontalAlignment) => { switch (alignment) { case HorizontalAlignment.LEFT: return "left"; case HorizontalAlignment.RIGHT: return "right"; case HorizontalAlignment.CENTER: default: return "center"; } }; const getVerticalAlign = (verticalAlignment?: VerticalAlignment) => { switch (verticalAlignment) { case VerticalAlignment.TOP: return "top"; case VerticalAlignment.BOTTOM: return "bottom"; case VerticalAlignment.MIDDLE: default: return "middle"; } }; // Render TextRenderer equivalent const renderTexts = (texts: TextType[]) => { console.log("🔥 [ExportHTML] renderTexts called with:", texts); if (!texts || texts.length === 0) { console.log("🔥 [ExportHTML] No texts to render"); return ""; } return texts .map( (textItem, textIndex) => `
${textItem.text}
` ) .join(""); }; // Render ButtonRenderer equivalent const renderButtons = (buttons: ButtonType[]) => { console.log("🔥 [ExportHTML] renderButtons called with:", buttons); if (!buttons || buttons.length === 0) { console.log("🔥 [ExportHTML] No buttons to render"); return ""; } return `
${buttons .slice(0, 2) .map( (button, buttonIndex) => `` ) .join("")}
${button.text}
`; }; // Render ImageRenderer equivalent const renderImages = (images: ImageType[]) => { console.log("🔥 [ExportHTML] renderImages called with:", images); if (!images || images.length === 0) { console.log("🔥 [ExportHTML] No images to render"); return ""; } const shouldUseBackgroundImage = (imageSize: ImageSize) => { return ( imageSize === ImageSize.REPEAT || imageSize === ImageSize.REPEAT_X || imageSize === ImageSize.REPEAT_Y ); }; const getBackgroundStyle = (image: ImageType) => { let backgroundRepeat = "no-repeat"; switch (image.size) { case ImageSize.REPEAT: backgroundRepeat = "repeat"; break; case ImageSize.REPEAT_X: backgroundRepeat = "repeat-x"; break; case ImageSize.REPEAT_Y: backgroundRepeat = "repeat-y"; break; default: backgroundRepeat = "no-repeat"; break; } const horizontal = image.alignment === HorizontalAlignment.LEFT ? "left" : image.alignment === HorizontalAlignment.RIGHT ? "right" : "center"; const vertical = image.verticalAlignment === VerticalAlignment.TOP ? "top" : image.verticalAlignment === VerticalAlignment.BOTTOM ? "bottom" : "center"; return `background-image: url(${ image.src }); background-position: ${horizontal} ${vertical}; background-repeat: ${backgroundRepeat}; width: ${ image.width || "100%" }; height: ${image.height || "100px"};`; }; const renderImage = (image: ImageType) => { if (shouldUseBackgroundImage(image.size)) { return `
 
`; } if (image.size === ImageSize.CONTAIN) { return `
${
          image.alt ||
`; } return `${
        image.alt || `; }; return images .map( (image, imageIndex) => `
${renderImage(image)}
` ) .join(""); }; // Render SocialRenderer equivalent const renderSocials = (socials: SocialType[]) => { console.log("🔥 [ExportHTML] renderSocials called with:", socials); if (!socials || socials.length === 0) { console.log("🔥 [ExportHTML] No socials to render"); return ""; } const getIconSize = (size: SocialIconSize) => { switch (size) { case SocialIconSize.SMALL: return "24px"; case SocialIconSize.MEDIUM: return "32px"; case SocialIconSize.LARGE: return "40px"; default: return "32px"; } }; const getIconStyle = (social: SocialType) => { const size = getIconSize(social.size); const baseStyle = `width: ${size}; height: ${size}; display: inline-flex; align-items: center; justify-content: center; text-decoration: none; color: ${ social.color || getSocialColor(social.networkType) }; margin: 2px;`; switch (social.style) { case SocialIconStyle.CIRCLE: return `${baseStyle} border-radius: 50%;`; case SocialIconStyle.SQUARE: return `${baseStyle} border-radius: 0;`; case SocialIconStyle.ROUNDED: return `${baseStyle} border-radius: 8px;`; default: return baseStyle; } }; const getSocialIcon = (networkType: SocialNetworkType) => { // Check if PNG icon is available, if so use it if (hasPngIcon(networkType)) { const iconPath = getSocialIconPath(networkType); return `${networkType} icon`; } // Use shared SVG function return getSocialSvgIcon(networkType, false) as string; }; return `
${socials .map( (social) => ` ${getSocialIcon(social.networkType)} ` ) .join("")}
`; }; // Helper functions for button alignment (same as in React components) const getButtonHorizontalAlign = (button?: { alignment?: HorizontalAlignment; }) => { if (!button || !button.alignment) return "center"; switch (button.alignment) { case HorizontalAlignment.LEFT: return "left"; case HorizontalAlignment.RIGHT: return "right"; case HorizontalAlignment.CENTER: default: return "center"; } }; const getButtonVerticalAlign = (button?: { verticalAlignment?: VerticalAlignment; }) => { if (!button || !button.verticalAlignment) return "middle"; switch (button.verticalAlignment) { case VerticalAlignment.TOP: return "top"; case VerticalAlignment.BOTTOM: return "bottom"; case VerticalAlignment.MIDDLE: default: return "middle"; } }; // Render section equivalent (HeaderSection, ContentSection, FooterSection) const renderSection = ( section: SectionType, sectionHeight: string, paddingTop = "" ) => { console.log(`🔥 [ExportHTML] Rendering section:`, { columnsCount: section.columnsCount, itemsLength: section.items?.length || 0, sectionHeight, items: section.items, }); if (section.columnsCount > 0) { return ` ${paddingTop ? `` : ""}
${Array.from( { length: section.columnsCount }, (_, index) => { const item = section.items[index]; const hasButtons = item?.buttons && item.buttons.length > 0; const hasTexts = item?.texts && item.texts.length > 0; const hasImages = item?.images && item.images.length > 0; const hasSocials = item?.socials && item.socials.length > 0; console.log( `🔥 [ExportHTML] Item ${index} content check:`, { hasButtons, hasTexts, hasImages, hasSocials, sectionHeight, item: item, } ); let result = ``; // فاصله بین ستون‌ها if (index < section.columnsCount - 1) { result += ``; } return result; } ).join("")}
`; // اگر محتوایی وجود دارد (متن، دکمه، تصویر، یا شبکه اجتماعی) if ( hasTexts || hasButtons || hasImages || hasSocials ) { // اگر فقط دکمه داریم و متن نداریم if (!hasTexts && hasButtons) { result += ``; } else { // ردیف اصلی برای متن و تصاویر const mainHeight = hasButtons ? sectionHeight === "123px" ? "60" : sectionHeight === "246px" ? "203" : "40" : sectionHeight === "123px" ? "87" : sectionHeight === "246px" ? "230" : "67"; result += ``; // ردیف دکمه‌ها if (hasButtons) { result += ``; } } } else { // اگر هیچ محتوایی نداریم و content section است console.log( "🔥 [ExportHTML] Empty content section detected, adding {{content}} placeholder" ); if (sectionHeight === "246px") { result += ``; } } result += `
${renderImages(item?.images || [])} ${renderSocials(item?.socials || [])} ${ sectionHeight === "246px" ? '
{{content}}
' : "" } ${renderButtons(item.buttons)}
${renderTexts(item?.texts || [])} ${renderImages(item?.images || [])} ${renderSocials(item?.socials || [])} ${ sectionHeight === "246px" && !hasTexts && !hasImages && !hasSocials ? '
{{content}}
' : "" }
${renderButtons(item.buttons)}
{{content}}
`; } else { // حالت خالی const emptyMessages = { "123px": "سربرگ ایمیل", "246px": "محتوای ایمیل", }; const emptyMessage = emptyMessages[sectionHeight as keyof typeof emptyMessages] || "فوتر ایمیل"; return ` ${paddingTop ? `` : ""}
${emptyMessage}
`; } }; // Generate complete HTML exactly like Personality.tsx structure const html = `
${renderSection(data.header, "123px")} ${renderSection(data.content, "246px", "")} ${renderSection(data.footer, "123px", "")}
`; console.log("🔥 [ExportHTML] Final HTML generated:", html); return html; }; export const copyHTMLToClipboard = async (html: string): Promise => { try { await navigator.clipboard.writeText(html); return true; } catch (error) { console.error("Failed to copy HTML to clipboard:", error); return false; } };