seo-generator-server/public/prompt-engine-interface.html
StillHammer f51c4095f6 Add modular pipeline demo system with real module integration
- Add complete modular demo interface (public/modular-pipeline-demo.html)
- Add standalone demo server (simple-server.js) on port 3333
- Integrate real SelectiveCore, AdversarialCore, HumanSimulation, PatternBreaking modules
- Add configurable pipeline with step-by-step content transformation display
- Add new trend management and workflow configuration modules
- Add comprehensive test suite for full pipeline validation
- Update core modules for better modular integration and demo compatibility

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-23 16:03:20 +08:00

1046 lines
34 KiB
HTML

<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>🧠 Dynamic Prompt Engine - Interface Complète</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
color: #333;
overflow-x: hidden;
}
.header {
background: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(10px);
padding: 20px 0;
box-shadow: 0 2px 20px rgba(0,0,0,0.1);
position: sticky;
top: 0;
z-index: 100;
}
.header-content {
max-width: 1600px;
margin: 0 auto;
padding: 0 20px;
display: flex;
justify-content: space-between;
align-items: center;
}
.logo {
font-size: 1.5em;
font-weight: 700;
color: #4a5568;
}
.status-indicator {
display: flex;
align-items: center;
gap: 10px;
font-size: 0.9em;
color: #718096;
}
.status-dot {
width: 8px;
height: 8px;
border-radius: 50%;
background: #68d391;
animation: pulse 2s infinite;
}
@keyframes pulse {
0% { opacity: 1; }
50% { opacity: 0.5; }
100% { opacity: 1; }
}
.container {
max-width: 1600px;
margin: 0 auto;
padding: 30px 20px;
display: grid;
grid-template-columns: 450px 1fr;
gap: 30px;
min-height: calc(100vh - 100px);
}
.controls-panel {
background: white;
border-radius: 20px;
padding: 30px;
box-shadow: 0 15px 40px rgba(0,0,0,0.1);
height: fit-content;
position: sticky;
top: 120px;
}
.results-panel {
display: flex;
flex-direction: column;
gap: 20px;
}
.prompt-preview {
background: white;
border-radius: 20px;
padding: 30px;
box-shadow: 0 15px 40px rgba(0,0,0,0.1);
min-height: 500px;
display: flex;
flex-direction: column;
}
.metadata-panel {
background: white;
border-radius: 20px;
padding: 30px;
box-shadow: 0 15px 40px rgba(0,0,0,0.1);
}
h1 {
color: #2d3748;
margin-bottom: 30px;
text-align: center;
font-size: 1.8em;
font-weight: 700;
}
h2 {
color: #2d3748;
margin-bottom: 20px;
font-size: 1.3em;
font-weight: 600;
display: flex;
align-items: center;
gap: 10px;
}
h3 {
color: #4a5568;
margin-bottom: 15px;
font-size: 1.1em;
font-weight: 600;
}
.form-section {
background: #f8fafc;
border-radius: 12px;
padding: 20px;
margin-bottom: 20px;
border: 1px solid #e2e8f0;
}
.form-section h3 {
margin-bottom: 15px;
color: #2d3748;
font-size: 1em;
font-weight: 600;
}
.form-group {
margin-bottom: 20px;
}
label {
display: block;
font-weight: 600;
margin-bottom: 8px;
color: #4a5568;
font-size: 0.9em;
}
select, input[type="number"], input[type="text"], textarea {
width: 100%;
padding: 12px 15px;
border: 2px solid #e2e8f0;
border-radius: 10px;
font-size: 14px;
transition: all 0.2s;
font-family: inherit;
}
select:focus, input:focus, textarea:focus {
outline: none;
border-color: #667eea;
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
}
textarea {
resize: vertical;
min-height: 100px;
}
.option-description {
font-size: 12px;
color: #718096;
margin-top: 5px;
font-style: italic;
}
.button-group {
display: flex;
gap: 12px;
margin-top: 25px;
}
button {
flex: 1;
padding: 15px 20px;
border: none;
border-radius: 10px;
font-weight: 600;
cursor: pointer;
transition: all 0.3s;
font-size: 14px;
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
}
.btn-primary {
background: linear-gradient(135deg, #667eea, #764ba2);
color: white;
}
.btn-primary:hover {
transform: translateY(-2px);
box-shadow: 0 8px 25px rgba(102, 126, 234, 0.4);
}
.btn-secondary {
background: #f7fafc;
color: #4a5568;
border: 2px solid #e2e8f0;
}
.btn-secondary:hover {
background: #edf2f7;
border-color: #cbd5e0;
}
.btn-trend {
background: linear-gradient(135deg, #48bb78, #38a169);
color: white;
}
.btn-trend:hover {
transform: translateY(-2px);
box-shadow: 0 8px 25px rgba(72, 187, 120, 0.4);
}
.trend-selector {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
gap: 8px;
margin-top: 10px;
}
.trend-button {
padding: 8px 12px;
border: 2px solid #e2e8f0;
border-radius: 8px;
background: white;
color: #4a5568;
font-size: 12px;
font-weight: 500;
cursor: pointer;
transition: all 0.2s;
text-align: center;
}
.trend-button:hover {
border-color: #cbd5e0;
}
.trend-button.active {
background: linear-gradient(135deg, #48bb78, #38a169);
color: white;
border-color: #38a169;
}
.status {
padding: 15px 20px;
border-radius: 10px;
margin-bottom: 20px;
font-weight: 500;
text-align: center;
display: none;
align-items: center;
justify-content: center;
gap: 10px;
}
.status.success {
background: #c6f6d5;
color: #22543d;
border: 1px solid #9ae6b4;
}
.status.error {
background: #fed7d7;
color: #822727;
border: 1px solid #f56565;
}
.status.loading {
background: #bee3f8;
color: #2b6cb0;
border: 1px solid #63b3ed;
}
.prompt-output {
background: #1a202c;
color: #e2e8f0;
border-radius: 12px;
padding: 25px;
font-family: 'Fira Code', 'Monaco', monospace;
font-size: 13px;
line-height: 1.6;
flex: 1;
overflow-y: auto;
white-space: pre-wrap;
border: 1px solid #2d3748;
position: relative;
}
.prompt-output:empty::before {
content: "Le prompt généré apparaîtra ici...";
color: #718096;
font-style: italic;
}
.copy-button {
position: absolute;
top: 15px;
right: 15px;
background: #4a5568;
color: white;
border: none;
padding: 8px 12px;
border-radius: 6px;
font-size: 11px;
cursor: pointer;
transition: all 0.2s;
}
.copy-button:hover {
background: #2d3748;
}
.metadata-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 15px;
margin-bottom: 20px;
}
.metadata-card {
background: #f8fafc;
padding: 20px;
border-radius: 12px;
text-align: center;
border: 1px solid #e2e8f0;
}
.metadata-number {
font-size: 28px;
font-weight: 700;
color: #2d3748;
margin-bottom: 5px;
}
.metadata-label {
font-size: 12px;
color: #718096;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.context-analysis {
background: #f0fff4;
border: 1px solid #9ae6b4;
border-radius: 10px;
padding: 15px;
margin-top: 15px;
}
.context-analysis h4 {
color: #22543d;
margin-bottom: 10px;
font-size: 0.9em;
}
.context-item {
display: flex;
justify-content: space-between;
margin-bottom: 5px;
font-size: 13px;
}
.context-key {
color: #2f855a;
font-weight: 500;
}
.context-value {
color: #22543d;
}
.progress-bar {
width: 100%;
height: 6px;
background: #e2e8f0;
border-radius: 3px;
overflow: hidden;
margin-bottom: 15px;
display: none;
}
.progress-fill {
height: 100%;
background: linear-gradient(90deg, #667eea, #764ba2);
width: 0%;
transition: width 0.3s ease;
}
.history-panel {
background: white;
border-radius: 20px;
padding: 30px;
box-shadow: 0 15px 40px rgba(0,0,0,0.1);
max-height: 400px;
overflow-y: auto;
}
.history-item {
background: #f8fafc;
border-radius: 10px;
padding: 15px;
margin-bottom: 10px;
border-left: 4px solid #667eea;
cursor: pointer;
transition: all 0.2s;
}
.history-item:hover {
background: #edf2f7;
transform: translateX(5px);
}
.history-meta {
font-size: 12px;
color: #718096;
margin-bottom: 5px;
}
.history-config {
font-size: 13px;
color: #4a5568;
font-weight: 500;
}
.spinner {
width: 20px;
height: 20px;
border: 2px solid #e2e8f0;
border-top: 2px solid #667eea;
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.tabs {
display: flex;
background: #f8fafc;
border-radius: 10px;
padding: 4px;
margin-bottom: 20px;
}
.tab {
flex: 1;
padding: 10px 15px;
border-radius: 6px;
background: transparent;
border: none;
color: #718096;
font-weight: 500;
cursor: pointer;
transition: all 0.2s;
}
.tab.active {
background: white;
color: #2d3748;
box-shadow: 0 2px 4px rgba(0,0,0,0.05);
}
.tab-content {
display: none;
}
.tab-content.active {
display: block;
}
@media (max-width: 1200px) {
.container {
grid-template-columns: 1fr;
gap: 20px;
}
.controls-panel {
position: relative;
top: 0;
}
}
</style>
</head>
<body>
<div class="header">
<div class="header-content">
<div class="logo">🧠 Dynamic Prompt Engine</div>
<div class="status-indicator">
<div class="status-dot"></div>
<span>Interface Prête</span>
</div>
</div>
</div>
<div class="container">
<div class="controls-panel">
<h1>⚙️ Configuration</h1>
<!-- Template Type Selection -->
<div class="form-section">
<h3>🎯 Type de Template</h3>
<select id="templateType">
<option value="technical" selected>Technical</option>
<option value="style">Style</option>
<option value="adversarial">Adversarial</option>
</select>
<div class="option-description">Type de prompt à générer</div>
</div>
<!-- Content Simulation -->
<div class="form-section">
<h3>📝 Contenu (Simulation)</h3>
<div class="form-group">
<label for="mockContent">Mot-clé principal</label>
<input type="text" id="mockContent" value="plaque signalétique aluminium" placeholder="Ex: plaque gravée, bijou personnalisé...">
</div>
<div class="form-group">
<label for="mockTitle">Titre à traiter</label>
<input type="text" id="mockTitle" value="Guide installation panneau signalétique" placeholder="Titre du contenu...">
</div>
</div>
<!-- Trend Management -->
<div class="form-section">
<h3>🎨 Tendances</h3>
<div class="trend-selector" id="trendSelector">
<div class="trend-button" data-trend="">Aucune</div>
<div class="trend-button" data-trend="eco-responsable">Éco</div>
<div class="trend-button" data-trend="tech-innovation">Tech</div>
<div class="trend-button" data-trend="artisanal-premium">Artisanal</div>
<div class="trend-button" data-trend="generation-z">Gen Z</div>
<div class="trend-button" data-trend="millenial-pro">Millennial</div>
<div class="trend-button" data-trend="automne-cocooning">Automne</div>
<div class="trend-button" data-trend="printemps-renouveau">Printemps</div>
</div>
<div class="option-description">Sélectionnez une tendance pour adapter le prompt</div>
</div>
<!-- Advanced Configuration -->
<div class="form-section">
<h3>⚡ Configuration Avancée</h3>
<div class="form-group">
<label for="intensity">Intensité</label>
<input type="number" id="intensity" value="1.0" min="0.1" max="2.0" step="0.1">
<div class="option-description">Intensité de l'adaptation (0.1 - 2.0)</div>
</div>
<div class="form-group">
<label for="targetTerms">Termes cibles (optionnel)</label>
<textarea id="targetTerms" placeholder="durable, écologique, moderne..."></textarea>
<div class="option-description">Termes à intégrer naturellement (séparés par des virgules)</div>
</div>
</div>
<!-- Workflow Configuration -->
<div class="form-section">
<h3>🔄 Configuration Workflow</h3>
<div class="form-group">
<label for="workflowSequence">Séquence de traitement</label>
<select id="workflowSequence">
<option value="default" selected>Default (Selective → Adversarial → Human → Pattern)</option>
<option value="human-first">Human-First (Human → Pattern → Selective → Pattern)</option>
<option value="stealth-intensive">Stealth Intensive (Pattern → Adversarial → Human → Pattern → Adversarial)</option>
<option value="quality-first">Quality-First (Selective → Human → Selective → Pattern)</option>
<option value="balanced">Balanced (Selective → Human → Adversarial → Pattern → Selective)</option>
<option value="custom">Séquence personnalisée</option>
</select>
<div class="option-description">Ordre d'exécution des phases modulaires</div>
</div>
<div class="form-group" id="customSequenceGroup" style="display: none;">
<label for="customSequence">Séquence personnalisée (JSON)</label>
<textarea id="customSequence" rows="8" placeholder='
{
"name": "Ma Séquence",
"description": "Description de ma séquence",
"phases": [
{"type": "human", "config": {"enabled": true}},
{"type": "pattern", "config": {"enabled": true, "iteration": 1}},
{"type": "selective", "config": {"enabled": true}},
{"type": "pattern", "config": {"enabled": true, "iteration": 2}}
]
}'></textarea>
<div class="option-description">Types disponibles: selective, adversarial, human, pattern</div>
</div>
</div>
<!-- Actions -->
<div class="button-group">
<button class="btn-primary" onclick="generatePrompt()">
🚀 Générer Prompt
</button>
<button class="btn-secondary" onclick="clearAll()">
🗑️ Reset
</button>
</div>
<div class="button-group">
<button class="btn-trend" onclick="testAllTrends()">
🎯 Test Toutes Tendances
</button>
<button class="btn-secondary" onclick="exportConfig()">
💾 Export Config
</button>
</div>
</div>
<div class="results-panel">
<!-- Status & Progress -->
<div class="status" id="status"></div>
<div class="progress-bar" id="progressBar">
<div class="progress-fill" id="progressFill"></div>
</div>
<!-- Prompt Preview -->
<div class="prompt-preview">
<h2>📜 Prompt Généré</h2>
<div class="prompt-output" id="promptOutput">
<button class="copy-button" onclick="copyPrompt()" style="display: none;">📋 Copier</button>
</div>
</div>
<!-- Metadata -->
<div class="metadata-panel">
<h2>📊 Métadonnées</h2>
<div class="tabs">
<button class="tab active" onclick="switchTab('stats')">Statistiques</button>
<button class="tab" onclick="switchTab('analysis')">Analyse</button>
<button class="tab" onclick="switchTab('variables')">Variables</button>
</div>
<div class="tab-content active" id="stats-content">
<div class="metadata-grid" id="metadataGrid">
<!-- Metadata cards will be inserted here -->
</div>
</div>
<div class="tab-content" id="analysis-content">
<div class="context-analysis" id="contextAnalysis">
<!-- Context analysis will be inserted here -->
</div>
</div>
<div class="tab-content" id="variables-content">
<div id="variablesList" style="font-family: monospace; font-size: 12px; background: #f8fafc; padding: 15px; border-radius: 8px;">
<!-- Variables list will be inserted here -->
</div>
</div>
</div>
<!-- History -->
<div class="history-panel">
<h2>📚 Historique</h2>
<div id="historyContainer">
<div style="text-align: center; color: #718096; font-style: italic; padding: 20px;">
Aucun prompt généré encore
</div>
</div>
</div>
</div>
</div>
<script>
let currentTrend = null;
let promptHistory = [];
// Initialize
document.addEventListener('DOMContentLoaded', function() {
setupTrendSelector();
loadHistory();
});
// Setup trend selector
function setupTrendSelector() {
const buttons = document.querySelectorAll('.trend-button');
buttons.forEach(button => {
button.addEventListener('click', function() {
buttons.forEach(b => b.classList.remove('active'));
this.classList.add('active');
currentTrend = this.dataset.trend || null;
});
});
// Select "Aucune" by default
buttons[0].classList.add('active');
}
// Switch tabs
function switchTab(tabName) {
// Update tab buttons
document.querySelectorAll('.tab').forEach(tab => tab.classList.remove('active'));
event.target.classList.add('active');
// Update tab content
document.querySelectorAll('.tab-content').forEach(content => content.classList.remove('active'));
document.getElementById(tabName + '-content').classList.add('active');
}
// Show status
function showStatus(message, type) {
const statusDiv = document.getElementById('status');
statusDiv.innerHTML = type === 'loading' ?
`<div class="spinner"></div> ${message}` : message;
statusDiv.className = `status ${type}`;
statusDiv.style.display = 'flex';
}
// Hide status
function hideStatus() {
document.getElementById('status').style.display = 'none';
}
// Show progress
function showProgress(percentage) {
const progressBar = document.getElementById('progressBar');
const progressFill = document.getElementById('progressFill');
progressBar.style.display = 'block';
progressFill.style.width = percentage + '%';
}
// Hide progress
function hideProgress() {
document.getElementById('progressBar').style.display = 'none';
}
// Generate prompt
async function generatePrompt() {
const config = {
templateType: document.getElementById('templateType').value,
content: {
mc0: document.getElementById('mockContent').value,
title: document.getElementById('mockTitle').value
},
csvData: {
mc0: document.getElementById('mockContent').value,
personality: { nom: 'Marc', style: 'technique' }
},
trend: currentTrend,
layerConfig: {
intensity: parseFloat(document.getElementById('intensity').value),
targetTerms: document.getElementById('targetTerms').value
.split(',')
.map(t => t.trim())
.filter(t => t.length > 0)
}
};
showStatus('🧠 Génération du prompt en cours...', 'loading');
showProgress(10);
try {
const response = await fetch('/api/generate-prompt', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(config)
});
showProgress(50);
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const result = await response.json();
showProgress(100);
setTimeout(() => hideProgress(), 500);
if (result.success) {
showStatus('✅ Prompt généré avec succès!', 'success');
displayPrompt(result.prompt, result.metadata);
addToHistory(config, result);
setTimeout(hideStatus, 3000);
} else {
showStatus('❌ Erreur: ' + (result.error || 'Erreur inconnue'), 'error');
}
} catch (error) {
hideProgress();
showStatus('❌ Erreur: ' + error.message, 'error');
console.error('Prompt generation failed:', error);
}
}
// Display prompt
function displayPrompt(prompt, metadata) {
// Show prompt
const promptOutput = document.getElementById('promptOutput');
promptOutput.textContent = prompt;
promptOutput.querySelector('.copy-button').style.display = 'block';
// Show metadata stats
displayMetadata(metadata);
// Show context analysis
displayContextAnalysis(metadata.contextAnalysis || {});
// Show variables
displayVariables(metadata.dynamicVariables || []);
}
// Display metadata
function displayMetadata(metadata) {
const grid = document.getElementById('metadataGrid');
grid.innerHTML = '';
const stats = metadata.stats || {};
const metadataCards = [
{ label: 'Longueur', value: stats.promptLength || 0, unit: 'chars' },
{ label: 'Variables', value: stats.variablesCount || 0, unit: '' },
{ label: 'Règles', value: stats.adaptationRules || 0, unit: '' },
{ label: 'Complexité', value: stats.contextComplexity || 'N/A', unit: '' },
{ label: 'Template', value: stats.templateType || 'N/A', unit: '' },
{ label: 'Tendance', value: currentTrend || 'Aucune', unit: '' }
];
metadataCards.forEach(card => {
const cardElement = document.createElement('div');
cardElement.className = 'metadata-card';
cardElement.innerHTML = `
<div class="metadata-number">${card.value}${card.unit}</div>
<div class="metadata-label">${card.label}</div>
`;
grid.appendChild(cardElement);
});
}
// Display context analysis
function displayContextAnalysis(contextAnalysis) {
const container = document.getElementById('contextAnalysis');
container.innerHTML = '<h4>🔍 Analyse Contextuelle</h4>';
Object.entries(contextAnalysis).forEach(([key, value]) => {
const item = document.createElement('div');
item.className = 'context-item';
item.innerHTML = `
<span class="context-key">${key}:</span>
<span class="context-value">${value}</span>
`;
container.appendChild(item);
});
if (Object.keys(contextAnalysis).length === 0) {
container.innerHTML += '<div style="color: #718096; font-style: italic;">Aucune analyse disponible</div>';
}
}
// Display variables
function displayVariables(variables) {
const container = document.getElementById('variablesList');
if (variables.length === 0) {
container.innerHTML = '<div style="color: #718096; font-style: italic;">Aucune variable dynamique</div>';
return;
}
container.innerHTML = `
<div style="margin-bottom: 10px; font-weight: 600; color: #2d3748;">
Variables Dynamiques (${variables.length})
</div>
${variables.map(variable => `<div>• ${variable}</div>`).join('')}
`;
}
// Add to history
function addToHistory(config, result) {
const historyItem = {
timestamp: new Date().toISOString(),
config,
result,
id: Date.now()
};
promptHistory.unshift(historyItem);
if (promptHistory.length > 10) {
promptHistory = promptHistory.slice(0, 10);
}
updateHistoryDisplay();
saveHistory();
}
// Update history display
function updateHistoryDisplay() {
const container = document.getElementById('historyContainer');
if (promptHistory.length === 0) {
container.innerHTML = '<div style="text-align: center; color: #718096; font-style: italic; padding: 20px;">Aucun prompt généré encore</div>';
return;
}
container.innerHTML = promptHistory.map(item => {
const time = new Date(item.timestamp).toLocaleString('fr-FR');
const trendText = item.config.trend || 'Aucune';
return `
<div class="history-item" onclick="loadHistoryItem('${item.id}')">
<div class="history-meta">${time}</div>
<div class="history-config">
${item.config.templateType}${trendText} • Intensité ${item.config.layerConfig.intensity}
</div>
</div>
`;
}).join('');
}
// Load history item
function loadHistoryItem(id) {
const item = promptHistory.find(h => h.id == id);
if (!item) return;
// Load config
document.getElementById('templateType').value = item.config.templateType;
document.getElementById('mockContent').value = item.config.content.mc0;
document.getElementById('mockTitle').value = item.config.content.title;
document.getElementById('intensity').value = item.config.layerConfig.intensity;
document.getElementById('targetTerms').value = item.config.layerConfig.targetTerms.join(', ');
// Load trend
document.querySelectorAll('.trend-button').forEach(b => b.classList.remove('active'));
const trendButton = document.querySelector(`[data-trend="${item.config.trend || ''}"]`);
if (trendButton) trendButton.classList.add('active');
currentTrend = item.config.trend;
// Display result
displayPrompt(item.result.prompt, item.result.metadata);
}
// Test all trends
async function testAllTrends() {
const trends = ['', 'eco-responsable', 'tech-innovation', 'artisanal-premium', 'generation-z'];
showStatus('🎯 Test de toutes les tendances...', 'loading');
for (let i = 0; i < trends.length; i++) {
showProgress((i / trends.length) * 100);
// Set trend
document.querySelectorAll('.trend-button').forEach(b => b.classList.remove('active'));
const trendButton = document.querySelector(`[data-trend="${trends[i]}"]`);
if (trendButton) trendButton.classList.add('active');
currentTrend = trends[i];
// Generate
await generatePrompt();
await new Promise(resolve => setTimeout(resolve, 1000));
}
hideProgress();
showStatus('✅ Test de toutes les tendances terminé!', 'success');
setTimeout(hideStatus, 3000);
}
// Copy prompt
function copyPrompt() {
const promptText = document.getElementById('promptOutput').textContent;
navigator.clipboard.writeText(promptText).then(() => {
const button = document.querySelector('.copy-button');
const originalText = button.textContent;
button.textContent = '✅ Copié!';
setTimeout(() => {
button.textContent = originalText;
}, 2000);
});
}
// Clear all
function clearAll() {
document.getElementById('promptOutput').textContent = '';
document.querySelector('.copy-button').style.display = 'none';
document.getElementById('metadataGrid').innerHTML = '';
document.getElementById('contextAnalysis').innerHTML = '<h4>🔍 Analyse Contextuelle</h4>';
document.getElementById('variablesList').innerHTML = '';
hideStatus();
hideProgress();
}
// Export config
function exportConfig() {
const config = {
templateType: document.getElementById('templateType').value,
mockContent: document.getElementById('mockContent').value,
mockTitle: document.getElementById('mockTitle').value,
trend: currentTrend,
intensity: document.getElementById('intensity').value,
targetTerms: document.getElementById('targetTerms').value
};
const blob = new Blob([JSON.stringify(config, null, 2)], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'prompt-engine-config.json';
a.click();
URL.revokeObjectURL(url);
showStatus('💾 Configuration exportée!', 'success');
setTimeout(hideStatus, 2000);
}
// Save/Load history
function saveHistory() {
localStorage.setItem('prompt-engine-history', JSON.stringify(promptHistory));
}
function loadHistory() {
const saved = localStorage.getItem('prompt-engine-history');
if (saved) {
promptHistory = JSON.parse(saved);
updateHistoryDisplay();
}
}
</script>
</body>
</html>