UNPKG

html-ad-generator-mcp

Version:

MCP server for generating HTML ad templates from JSON input for Google Ads and Meta Ads

92 lines 5.41 kB
import { readFileSync } from 'fs'; import { join, dirname } from 'path'; import { fileURLToPath } from 'url'; const __dirname = dirname(fileURLToPath(import.meta.url)); export function processMetaTemplate(input) { // Read the base template const templatePath = join(__dirname, '../../templates/meta-base.html'); let html = readFileSync(templatePath, 'utf-8'); const content = input.content; // Replace headline - use first element from array const firstHeadline = content.headline[0] || ''; html = html.replace(/value="Ad Headline"/g, `value="${escapeHtml(firstHeadline)}"`); html = html.replace(/<h1 class="ad-headline" id="headline-preview">.*?<\/h1>/, `<h1 class="ad-headline" id="headline-preview">${escapeHtml(firstHeadline)}</h1>`); // Replace description - use first element from array const firstDescription = content.description[0] || ''; html = html.replace(/value="Ad Description"/g, `value="${escapeHtml(firstDescription)}"`); html = html.replace(/<p class="ad-description" id="description-preview">.*?<\/p>/, `<p class="ad-description" id="description-preview">${escapeHtml(firstDescription)}</p>`); // Replace primary text - use first element from array const firstPrimaryText = content.primaryText[0] || ''; const primaryTextEscaped = escapeHtml(firstPrimaryText); html = html.replace(/<textarea id="primary-text" placeholder="Enter primary text\.\.\." style="min-height:80px">.*?<\/textarea>/s, `<textarea id="primary-text" placeholder="Enter primary text..." style="min-height:80px">${primaryTextEscaped}</textarea>`); html = html.replace(/<p class="ad-text" id="text-preview">.*?<\/p>/, `<p class="ad-text" id="text-preview">${primaryTextEscaped}</p>`); // Replace CTA - use first element from array const firstCta = content.cta[0] || ''; html = html.replace(/value="Call to Action"/g, `value="${escapeHtml(firstCta)}"`); html = html.replace(/<a href="#" class="ad-cta" id="cta-preview">.*?<\/a>/, `<a href="#" class="ad-cta" id="cta-preview">${escapeHtml(firstCta)}</a>`); // Replace business name if provided if (content.businessName) { html = html.replace(/<h3 id="business-name">.*?<\/h3>/, `<h3 id="business-name">${escapeHtml(content.businessName)}</h3>`); } // Replace profile image if provided if (content.profileImageUrl) { html = html.replace(/src="https:\/\/via\.placeholder\.com\/40"/, `src="${escapeHtml(content.profileImageUrl)}"`); } // Replace main image if provided if (content.mainImageUrl) { html = html.replace(/src="https:\/\/via\.placeholder\.com\/500x500\?text=Ad\+Image"/, `src="${escapeHtml(content.mainImageUrl)}"`); } // Update character counts html = updateCharacterCounts(html, content); // Update the dropdown options to include the new values html = updateDropdownOptions(html, content); return html; } function escapeHtml(text) { const map = { '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#039;' }; return text.replace(/[&<>"']/g, m => map[m]); } function updateCharacterCounts(html, content) { // Update headline count - use first element const firstHeadline = content.headline[0] || ''; html = html.replace(/id="headline-count">\d+ characters \(max 40\)</, `id="headline-count">${firstHeadline.length} characters (max 40)<`); // Update description count - use first element const firstDescription = content.description[0] || ''; html = html.replace(/id="description-count">\d+ characters \(max 30\)</, `id="description-count">${firstDescription.length} characters (max 30)<`); // Update primary text count - use first element const firstPrimaryText = content.primaryText[0] || ''; const textLength = firstPrimaryText.length; const textCountMessage = `${textLength} characters (max 125)`; html = html.replace(/id="text-count">.*?<\/div>/, `id="text-count">${textCountMessage}</div>`); return html; } function updateDropdownOptions(html, content) { // Dynamically populate dropdowns from provided arrays // Helper to insert multiple options function insertOptions(selectRegex, options, fieldId) { const match = html.match(selectRegex); if (match) { const existing = match[1]; let newOptions = ''; options.forEach(opt => { if (opt && !existing.includes(opt)) { newOptions += `\n <div class="dropdown-option" onclick="selectOption('${fieldId}', this)">${escapeHtml(opt)}</div>`; } }); html = html.replace(selectRegex, `<div class="dropdown-options" id="${fieldId.split('-')[0]}-options">${newOptions}${existing}</div>`); } } // Content fields are now arrays insertOptions(/<div class="dropdown-options" id="headline-options">([\s\S]*?)<\/div>/, content.headline, 'headline-text'); insertOptions(/<div class="dropdown-options" id="description-options">([\s\S]*?)<\/div>/, content.description, 'description-text'); insertOptions(/<div class="dropdown-options" id="text-options">([\s\S]*?)<\/div>/, content.primaryText, 'primary-text'); insertOptions(/<div class="dropdown-options" id="cta-options">([\s\S]*?)<\/div>/, content.cta, 'cta-text'); return html; } //# sourceMappingURL=meta.js.map