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
JavaScript
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 = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": '''
};
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