humanizer / index.html
sqibhe's picture
Add 2 files
c26a6d2 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Advanced AI Content Analyzer & Humanizer</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
.gradient-bg {
background: linear-gradient(135deg, #6e8efb 0%, #a777e3 100%);
}
.analyzer-bg {
background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
}
.humanizer-bg {
background: linear-gradient(135deg, #a18cd1 0%, #fbc2eb 100%);
}
.textarea-container {
position: relative;
}
.word-count {
position: absolute;
bottom: 10px;
right: 15px;
font-size: 0.8rem;
color: #6b7280;
background-color: rgba(255, 255, 255, 0.7);
padding: 2px 6px;
border-radius: 10px;
}
.pulse {
animation: pulse 2s infinite;
}
@keyframes pulse {
0% { opacity: 0.6; }
50% { opacity: 1; }
100% { opacity: 0.6; }
}
.progress-bar {
height: 10px;
border-radius: 5px;
background-color: #e5e7eb;
overflow: hidden;
}
.progress-fill {
height: 100%;
border-radius: 5px;
transition: width 0.5s ease;
}
.tab {
cursor: pointer;
transition: all 0.3s ease;
}
.tab.active {
transform: translateY(-2px);
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
}
.metric-card {
transition: all 0.3s ease;
}
.metric-card:hover {
transform: translateY(-3px);
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
}
.highlight-ai {
background-color: rgba(255, 0, 0, 0.1);
border-bottom: 2px dashed red;
}
.highlight-human {
background-color: rgba(0, 255, 0, 0.1);
border-bottom: 2px dashed green;
}
.highlight-neutral {
background-color: rgba(255, 255, 0, 0.1);
border-bottom: 2px dashed orange;
}
.analysis-tag {
display: inline-block;
padding: 2px 8px;
border-radius: 12px;
font-size: 0.75rem;
font-weight: 600;
margin-right: 4px;
margin-bottom: 4px;
}
.tag-ai {
background-color: #fee2e2;
color: #b91c1c;
}
.tag-human {
background-color: #dcfce7;
color: #166534;
}
.tag-neutral {
background-color: #fef3c7;
color: #92400e;
}
.tag-warning {
background-color: #fef3c7;
color: #92400e;
}
.tag-danger {
background-color: #fee2e2;
color: #b91c1c;
}
.tag-success {
background-color: #dcfce7;
color: #166534;
}
.sentence-complexity {
height: 4px;
border-radius: 2px;
margin-top: 2px;
}
.tooltip {
position: relative;
display: inline-block;
}
.tooltip .tooltiptext {
visibility: hidden;
width: 200px;
background-color: #555;
color: #fff;
text-align: center;
border-radius: 6px;
padding: 5px;
position: absolute;
z-index: 1;
bottom: 125%;
left: 50%;
margin-left: -100px;
opacity: 0;
transition: opacity 0.3s;
}
.tooltip:hover .tooltiptext {
visibility: visible;
opacity: 1;
}
.settings-panel {
transition: all 0.3s ease;
max-height: 0;
overflow: hidden;
}
.settings-panel.open {
max-height: 500px;
}
</style>
</head>
<body class="min-h-screen bg-gray-50 p-4">
<div class="max-w-6xl mx-auto">
<!-- Settings Panel -->
<div class="bg-white rounded-xl shadow-lg mb-6 overflow-hidden">
<div class="gradient-bg px-4 py-3 flex justify-between items-center cursor-pointer" id="settingsToggle">
<h2 class="text-lg font-semibold text-white">
<i class="fas fa-cog mr-2"></i> API Settings
</h2>
<i class="fas fa-chevron-down text-white transition-transform duration-300" id="settingsIcon"></i>
</div>
<div class="settings-panel" id="settingsPanel">
<div class="p-4">
<div class="mb-4">
<label class="block text-sm font-medium text-gray-700 mb-1">DeepSeek API Key</label>
<input
type="password"
id="apiKeyInput"
class="w-full border border-gray-300 rounded-md py-2 px-3 focus:outline-none focus:ring-2 focus:ring-blue-500"
placeholder="Enter your DeepSeek API key">
<p class="text-xs text-gray-500 mt-1">Your API key is stored locally in your browser and never sent to our servers.</p>
</div>
<div class="mb-4">
<label class="block text-sm font-medium text-gray-700 mb-1">API Endpoint</label>
<input
type="text"
id="apiEndpointInput"
class="w-full border border-gray-300 rounded-md py-2 px-3 focus:outline-none focus:ring-2 focus:ring-blue-500"
value="https://api.deepseek.com/v1"
placeholder="https://api.deepseek.com/v1">
</div>
<div class="flex justify-between items-center">
<div>
<label class="inline-flex items-center">
<input type="checkbox" id="saveSettingsCheckbox" class="rounded border-gray-300 text-blue-600 shadow-sm focus:border-blue-300 focus:ring focus:ring-blue-200 focus:ring-opacity-50" checked>
<span class="ml-2 text-sm text-gray-700">Remember settings</span>
</label>
</div>
<button
id="saveSettingsBtn"
class="bg-blue-600 hover:bg-blue-700 text-white font-medium py-2 px-4 rounded-md shadow-sm">
Save Settings
</button>
</div>
</div>
</div>
</div>
<div class="text-center mb-8">
<h1 class="text-3xl font-bold text-gray-800 mb-2">Advanced AI Content Analyzer & Humanizer</h1>
<p class="text-gray-600">Comprehensive analysis of AI-generated content with detailed metrics and humanization</p>
</div>
<!-- Tabs -->
<div class="flex justify-center mb-6">
<div class="inline-flex rounded-lg bg-white shadow">
<div id="analyzerTab" class="tab analyzer-bg text-white font-medium py-2 px-6 rounded-l-lg active">
<i class="fas fa-chart-bar mr-2"></i>Analyzer
</div>
<div id="humanizerTab" class="tab humanizer-bg text-white font-medium py-2 px-6 rounded-r-lg">
<i class="fas fa-user mr-2"></i>Humanizer
</div>
</div>
</div>
<!-- Analyzer Panel -->
<div id="analyzerPanel" class="grid grid-cols-1 lg:grid-cols-2 gap-6">
<!-- Input Section -->
<div class="bg-white rounded-xl shadow-lg overflow-hidden">
<div class="analyzer-bg px-4 py-3">
<h2 class="text-lg font-semibold text-white">
<i class="fas fa-keyboard mr-2"></i> AI Text Input
</h2>
</div>
<div class="p-4 textarea-container">
<textarea
id="aiInput"
class="w-full h-64 p-4 border border-gray-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-300 resize-none"
placeholder="Paste your AI-generated text here..."></textarea>
<div id="inputWordCount" class="word-count">0 words</div>
</div>
<div class="px-4 pb-4">
<button
id="analyzeBtn"
class="w-full analyzer-bg hover:opacity-90 text-white font-bold py-3 px-6 rounded-lg shadow-lg transform transition-all duration-200 hover:scale-[1.01] focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-opacity-50">
<i class="fas fa-search mr-2"></i> Analyze Content
</button>
</div>
</div>
<!-- Analysis Results -->
<div class="bg-white rounded-xl shadow-lg overflow-hidden">
<div class="analyzer-bg px-4 py-3">
<h2 class="text-lg font-semibold text-white">
<i class="fas fa-chart-pie mr-2"></i> Analysis Results
</h2>
</div>
<div class="p-4">
<div id="analysisPlaceholder" class="h-64 flex flex-col items-center justify-center text-gray-400">
<i class="fas fa-chart-bar text-4xl mb-4"></i>
<p>Your analysis results will appear here</p>
</div>
<div id="analysisResults" class="hidden">
<!-- Overall Scores -->
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6">
<div class="metric-card bg-white p-4 rounded-lg border border-gray-200 shadow-sm">
<h3 class="font-semibold text-gray-700 mb-2 flex items-center">
<i class="fas fa-robot text-red-500 mr-2"></i> AI Detection Score
</h3>
<div class="flex items-center mb-1">
<div class="w-full progress-bar">
<div id="aiScoreBar" class="progress-fill bg-red-500" style="width: 0%"></div>
</div>
<span id="aiScoreText" class="ml-3 font-bold text-gray-700">0%</span>
</div>
<p class="text-sm text-gray-500">Higher score indicates more detectable AI patterns</p>
</div>
<div class="metric-card bg-white p-4 rounded-lg border border-gray-200 shadow-sm">
<h3 class="font-semibold text-gray-700 mb-2 flex items-center">
<i class="fas fa-user text-green-500 mr-2"></i> Human Likeness Score
</h3>
<div class="flex items-center mb-1">
<div class="w-full progress-bar">
<div id="humanScoreBar" class="progress-fill bg-green-500" style="width: 0%"></div>
</div>
<span id="humanScoreText" class="ml-3 font-bold text-gray-700">0%</span>
</div>
<p class="text-sm text-gray-500">Higher score indicates more human-like qualities</p>
</div>
</div>
<!-- Detailed Metrics -->
<div class="mb-6">
<h3 class="font-semibold text-gray-700 mb-3 flex items-center">
<i class="fas fa-tachometer-alt text-blue-500 mr-2"></i> Detailed Metrics
</h3>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-3">
<div class="metric-card bg-white p-3 rounded-lg border border-gray-200 shadow-sm">
<div class="flex justify-between items-start">
<div>
<h4 class="text-sm font-medium text-gray-600">Perplexity Score</h4>
<p id="perplexityScore" class="text-lg font-bold">--</p>
</div>
<div class="tooltip">
<i class="fas fa-info-circle text-gray-400"></i>
<span class="tooltiptext">Measures unpredictability of word choices. Higher values are more human-like.</span>
</div>
</div>
<div class="progress-bar mt-2">
<div id="perplexityBar" class="progress-fill bg-blue-500" style="width: 0%"></div>
</div>
</div>
<div class="metric-card bg-white p-3 rounded-lg border border-gray-200 shadow-sm">
<div class="flex justify-between items-start">
<div>
<h4 class="text-sm font-medium text-gray-600">Burstiness Score</h4>
<p id="burstinessScore" class="text-lg font-bold">--</p>
</div>
<div class="tooltip">
<i class="fas fa-info-circle text-gray-400"></i>
<span class="tooltiptext">Measures variation in sentence structure. Higher values are more human-like.</span>
</div>
</div>
<div class="progress-bar mt-2">
<div id="burstinessBar" class="progress-fill bg-purple-500" style="width: 0%"></div>
</div>
</div>
<div class="metric-card bg-white p-3 rounded-lg border border-gray-200 shadow-sm">
<div class="flex justify-between items-start">
<div>
<h4 class="text-sm font-medium text-gray-600">Formality Index</h4>
<p id="formalityScore" class="text-lg font-bold">--</p>
</div>
<div class="tooltip">
<i class="fas fa-info-circle text-gray-400"></i>
<span class="tooltiptext">Measures use of formal language. Higher values may indicate AI.</span>
</div>
</div>
<div class="progress-bar mt-2">
<div id="formalityBar" class="progress-fill bg-yellow-500" style="width: 0%"></div>
</div>
</div>
<div class="metric-card bg-white p-3 rounded-lg border border-gray-200 shadow-sm">
<div class="flex justify-between items-start">
<div>
<h4 class="text-sm font-medium text-gray-600">Passive Voice</h4>
<p id="passiveScore" class="text-lg font-bold">--</p>
</div>
<div class="tooltip">
<i class="fas fa-info-circle text-gray-400"></i>
<span class="tooltiptext">Percentage of passive voice constructions. Higher values may indicate AI.</span>
</div>
</div>
<div class="progress-bar mt-2">
<div id="passiveBar" class="progress-fill bg-orange-500" style="width: 0%"></div>
</div>
</div>
<div class="metric-card bg-white p-3 rounded-lg border border-gray-200 shadow-sm">
<div class="flex justify-between items-start">
<div>
<h4 class="text-sm font-medium text-gray-600">Sentence Variation</h4>
<p id="sentenceVarScore" class="text-lg font-bold">--</p>
</div>
<div class="tooltip">
<i class="fas fa-info-circle text-gray-400"></i>
<span class="tooltiptext">Measures diversity in sentence length and structure. Higher is better.</span>
</div>
</div>
<div class="progress-bar mt-2">
<div id="sentenceVarBar" class="progress-fill bg-teal-500" style="width: 0%"></div>
</div>
</div>
<div class="metric-card bg-white p-3 rounded-lg border border-gray-200 shadow-sm">
<div class="flex justify-between items-start">
<div>
<h4 class="text-sm font-medium text-gray-600">Personalization</h4>
<p id="personalScore" class="text-lg font-bold">--</p>
</div>
<div class="tooltip">
<i class="fas fa-info-circle text-gray-400"></i>
<span class="tooltiptext">Measures use of personal pronouns and anecdotes. Higher is better.</span>
</div>
</div>
<div class="progress-bar mt-2">
<div id="personalBar" class="progress-fill bg-pink-500" style="width: 0%"></div>
</div>
</div>
</div>
</div>
<!-- Text Analysis -->
<div class="mb-6">
<h3 class="font-semibold text-gray-700 mb-3 flex items-center">
<i class="fas fa-search text-blue-500 mr-2"></i> Text Analysis
</h3>
<div class="bg-gray-50 p-4 rounded-lg border border-gray-200 max-h-60 overflow-y-auto">
<div id="analyzedText" class="whitespace-pre-wrap"></div>
</div>
<div class="mt-2 flex flex-wrap">
<span class="text-xs mr-3"><span class="inline-block w-3 h-3 bg-red-100 border border-red-300 mr-1"></span> AI-like patterns</span>
<span class="text-xs mr-3"><span class="inline-block w-3 h-3 bg-green-100 border border-green-300 mr-1"></span> Human-like patterns</span>
<span class="text-xs"><span class="inline-block w-3 h-3 bg-yellow-100 border border-yellow-300 mr-1"></span> Neutral/Uncertain</span>
</div>
</div>
<!-- Key Findings -->
<div class="mb-4">
<h3 class="font-semibold text-gray-700 mb-3 flex items-center">
<i class="fas fa-lightbulb text-blue-500 mr-2"></i> Key Findings
</h3>
<div id="keyFindings" class="space-y-2">
<!-- Findings will be added here -->
</div>
</div>
<!-- Common AI Patterns Found -->
<div class="mb-4">
<h3 class="font-semibold text-gray-700 mb-2 flex items-center">
<i class="fas fa-exclamation-triangle text-orange-500 mr-2"></i> Common AI Patterns Detected
</h3>
<div id="aiPatterns" class="flex flex-wrap">
<!-- Patterns will be added here -->
</div>
</div>
<div class="mt-6 pt-4 border-t border-gray-200">
<button
id="proceedToHumanizeBtn"
class="w-full humanizer-bg hover:opacity-90 text-white font-bold py-3 px-6 rounded-lg shadow-lg transform transition-all duration-200 hover:scale-[1.01] focus:outline-none focus:ring-2 focus:ring-purple-500 focus:ring-opacity-50">
<i class="fas fa-magic mr-2"></i> Humanize This Content
</button>
</div>
</div>
</div>
</div>
</div>
<!-- Humanizer Panel -->
<div id="humanizerPanel" class="hidden grid grid-cols-1 lg:grid-cols-2 gap-6">
<!-- Input Section -->
<div class="bg-white rounded-xl shadow-lg overflow-hidden">
<div class="humanizer-bg px-4 py-3">
<h2 class="text-lg font-semibold text-white">
<i class="fas fa-keyboard mr-2"></i> Text to Humanize
</h2>
</div>
<div class="p-4 textarea-container">
<textarea
id="humanizerInput"
class="w-full h-64 p-4 border border-gray-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-purple-300 resize-none"
placeholder="Text to humanize will appear here..."></textarea>
<div id="humanizerWordCount" class="word-count">0 words</div>
</div>
<div class="px-4 pb-4">
<div class="grid grid-cols-2 gap-3 mb-3">
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">Humanization Level</label>
<select id="humanizeLevel" class="w-full border border-gray-300 rounded-md py-2 px-3 focus:outline-none focus:ring-2 focus:ring-purple-500">
<option value="light">Light (subtle changes)</option>
<option value="medium" selected>Medium (balanced)</option>
<option value="heavy">Heavy (complete rewrite)</option>
</select>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">Target Tone</label>
<select id="targetTone" class="w-full border border-gray-300 rounded-md py-2 px-3 focus:outline-none focus:ring-2 focus:ring-purple-500">
<option value="neutral">Neutral</option>
<option value="casual">Casual</option>
<option value="professional">Professional</option>
<option value="friendly">Friendly</option>
<option value="academic">Academic</option>
</select>
</div>
</div>
<button
id="humanizeBtn"
class="w-full humanizer-bg hover:opacity-90 text-white font-bold py-3 px-6 rounded-lg shadow-lg transform transition-all duration-200 hover:scale-[1.01] focus:outline-none focus:ring-2 focus:ring-purple-500 focus:ring-opacity-50">
<i class="fas fa-magic mr-2"></i> Humanize Text
</button>
</div>
</div>
<!-- Output Section -->
<div class="bg-white rounded-xl shadow-lg overflow-hidden">
<div class="humanizer-bg px-4 py-3">
<h2 class="text-lg font-semibold text-white">
<i class="fas fa-user mr-2"></i> Humanized Output
</h2>
</div>
<div class="p-4 textarea-container">
<textarea
id="humanOutput"
class="w-full h-64 p-4 border border-gray-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-purple-300 resize-none bg-gray-50"
placeholder="Your humanized text will appear here..."
readonly></textarea>
<div id="outputWordCount" class="word-count">0 words</div>
</div>
<div class="px-4 pb-4 grid grid-cols-2 gap-3">
<button
id="copyBtn"
class="bg-gray-700 hover:bg-gray-800 text-white font-bold py-3 px-6 rounded-lg shadow-lg transform transition-all duration-200 hover:scale-[1.01] focus:outline-none focus:ring-2 focus:ring-gray-500 focus:ring-opacity-50">
<i class="fas fa-copy mr-2"></i> Copy
</button>
<button
id="analyzeAgainBtn"
class="bg-blue-600 hover:bg-blue-700 text-white font-bold py-3 px-6 rounded-lg shadow-lg transform transition-all duration-200 hover:scale-[1.01] focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-opacity-50">
<i class="fas fa-redo mr-2"></i> Re-analyze
</button>
</div>
</div>
</div>
<!-- Loading and Error Indicators -->
<div class="mt-4 text-center">
<div id="analyzerLoading" class="hidden">
<div class="inline-flex items-center analyzer-bg text-white py-2 px-4 rounded-full">
<div class="pulse">
<i class="fas fa-spinner fa-spin mr-2"></i>
</div>
<span>Analyzing content with advanced metrics...</span>
</div>
</div>
<div id="humanizerLoading" class="hidden">
<div class="inline-flex items-center humanizer-bg text-white py-2 px-4 rounded-full">
<div class="pulse">
<i class="fas fa-spinner fa-spin mr-2"></i>
</div>
<span>Humanizing content (this may take a moment)...</span>
</div>
</div>
<div id="errorMessage" class="mt-2 hidden">
<div class="inline-flex items-center bg-red-100 border border-red-400 text-red-700 px-3 py-2 rounded">
<i class="fas fa-exclamation-circle mr-2"></i>
<span id="errorText">Something went wrong. Please try again.</span>
</div>
</div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
// DOM Elements
const aiInput = document.getElementById('aiInput');
const humanizerInput = document.getElementById('humanizerInput');
const humanOutput = document.getElementById('humanOutput');
const analyzeBtn = document.getElementById('analyzeBtn');
const proceedToHumanizeBtn = document.getElementById('proceedToHumanizeBtn');
const humanizeBtn = document.getElementById('humanizeBtn');
const copyBtn = document.getElementById('copyBtn');
const analyzeAgainBtn = document.getElementById('analyzeAgainBtn');
const analyzerLoading = document.getElementById('analyzerLoading');
const humanizerLoading = document.getElementById('humanizerLoading');
const errorMessage = document.getElementById('errorMessage');
const inputWordCount = document.getElementById('inputWordCount');
const humanizerWordCount = document.getElementById('humanizerWordCount');
const outputWordCount = document.getElementById('outputWordCount');
const analysisPlaceholder = document.getElementById('analysisPlaceholder');
const analysisResults = document.getElementById('analysisResults');
const aiScoreBar = document.getElementById('aiScoreBar');
const aiScoreText = document.getElementById('aiScoreText');
const humanScoreBar = document.getElementById('humanScoreBar');
const humanScoreText = document.getElementById('humanScoreText');
const keyFindings = document.getElementById('keyFindings');
const aiPatterns = document.getElementById('aiPatterns');
const analyzedText = document.getElementById('analyzedText');
const analyzerTab = document.getElementById('analyzerTab');
const humanizerTab = document.getElementById('humanizerTab');
const analyzerPanel = document.getElementById('analyzerPanel');
const humanizerPanel = document.getElementById('humanizerPanel');
const perplexityScore = document.getElementById('perplexityScore');
const perplexityBar = document.getElementById('perplexityBar');
const burstinessScore = document.getElementById('burstinessScore');
const burstinessBar = document.getElementById('burstinessBar');
const formalityScore = document.getElementById('formalityScore');
const formalityBar = document.getElementById('formalityBar');
const passiveScore = document.getElementById('passiveScore');
const passiveBar = document.getElementById('passiveBar');
const sentenceVarScore = document.getElementById('sentenceVarScore');
const sentenceVarBar = document.getElementById('sentenceVarBar');
const personalScore = document.getElementById('personalScore');
const personalBar = document.getElementById('personalBar');
const humanizeLevel = document.getElementById('humanizeLevel');
const targetTone = document.getElementById('targetTone');
const settingsToggle = document.getElementById('settingsToggle');
const settingsPanel = document.getElementById('settingsPanel');
const settingsIcon = document.getElementById('settingsIcon');
const apiKeyInput = document.getElementById('apiKeyInput');
const apiEndpointInput = document.getElementById('apiEndpointInput');
const saveSettingsCheckbox = document.getElementById('saveSettingsCheckbox');
const saveSettingsBtn = document.getElementById('saveSettingsBtn');
// Settings panel toggle
settingsToggle.addEventListener('click', function() {
settingsPanel.classList.toggle('open');
settingsIcon.classList.toggle('rotate-180');
});
// Load saved settings
function loadSettings() {
const savedSettings = localStorage.getItem('deepseekSettings');
if (savedSettings) {
const settings = JSON.parse(savedSettings);
apiKeyInput.value = settings.apiKey || '';
apiEndpointInput.value = settings.apiEndpoint || 'https://api.deepseek.com/v1';
saveSettingsCheckbox.checked = settings.saveSettings !== false;
}
}
// Save settings
saveSettingsBtn.addEventListener('click', function() {
const settings = {
apiKey: apiKeyInput.value,
apiEndpoint: apiEndpointInput.value,
saveSettings: saveSettingsCheckbox.checked
};
if (saveSettingsCheckbox.checked) {
localStorage.setItem('deepseekSettings', JSON.stringify(settings));
} else {
localStorage.removeItem('deepseekSettings');
}
showSuccess("Settings saved successfully!");
});
// Load settings on page load
loadSettings();
// Tab Switching
analyzerTab.addEventListener('click', function() {
analyzerTab.classList.add('active');
humanizerTab.classList.remove('active');
analyzerPanel.classList.remove('hidden');
humanizerPanel.classList.add('hidden');
});
humanizerTab.addEventListener('click', function() {
if (humanizerInput.value.trim() === '') {
showError("Please analyze content first before humanizing");
return;
}
humanizerTab.classList.add('active');
analyzerTab.classList.remove('active');
analyzerPanel.classList.add('hidden');
humanizerPanel.classList.remove('hidden');
});
// Update word count for input
aiInput.addEventListener('input', function() {
const text = aiInput.value.trim();
const words = text ? text.split(/\s+/).length : 0;
inputWordCount.textContent = `${words} words`;
});
humanizerInput.addEventListener('input', function() {
const text = humanizerInput.value.trim();
const words = text ? text.split(/\s+/).length : 0;
humanizerWordCount.textContent = `${words} words`;
});
// Analyze button click handler
analyzeBtn.addEventListener('click', async function() {
const inputText = aiInput.value.trim();
if (!inputText) {
showError("Please enter some text to analyze.");
return;
}
// Show loading, hide error
analyzerLoading.classList.remove('hidden');
errorMessage.classList.add('hidden');
analyzeBtn.disabled = true;
analyzeBtn.classList.add('opacity-75');
try {
// Simulate API call with comprehensive analysis
const analysis = await simulateComprehensiveAnalysis(inputText);
// Display results
displayAnalysisResults(analysis);
// Populate humanizer input
humanizerInput.value = inputText;
const words = inputText ? inputText.split(/\s+/).length : 0;
humanizerWordCount.textContent = `${words} words`;
} catch (error) {
console.error("Error:", error);
showError("Failed to analyze text. Please try again later.");
} finally {
analyzerLoading.classList.add('hidden');
analyzeBtn.disabled = false;
analyzeBtn.classList.remove('opacity-75');
}
});
// Proceed to humanize button
proceedToHumanizeBtn.addEventListener('click', function() {
humanizerTab.click();
});
// Humanize button click handler
humanizeBtn.addEventListener('click', async function() {
const inputText = humanizerInput.value.trim();
const level = humanizeLevel.value;
const tone = targetTone.value;
if (!inputText) {
showError("Please enter some text to humanize.");
return;
}
// Check if API key is provided
const apiKey = apiKeyInput.value.trim();
if (!apiKey) {
showError("Please enter your DeepSeek API key in the settings panel.");
return;
}
// Show loading, hide error
humanizerLoading.classList.remove('hidden');
errorMessage.classList.add('hidden');
humanizeBtn.disabled = true;
humanizeBtn.classList.add('opacity-75');
try {
// Call DeepSeek API to humanize text
const humanizedText = await callDeepSeekApi(inputText, level, tone, apiKey);
if (humanizedText) {
humanOutput.value = humanizedText;
// Update output word count
const words = humanizedText ? humanizedText.split(/\s+/).length : 0;
outputWordCount.textContent = `${words} words`;
} else {
showError("Failed to humanize text. No response from API.");
}
} catch (error) {
console.error("Error:", error);
showError("Failed to humanize text. Please check your API key and try again.");
} finally {
humanizerLoading.classList.add('hidden');
humanizeBtn.disabled = false;
humanizeBtn.classList.remove('opacity-75');
}
});
// Copy button click handler
copyBtn.addEventListener('click', function() {
if (humanOutput.value) {
humanOutput.select();
document.execCommand('copy');
// Show temporary tooltip
const tooltip = document.createElement('div');
tooltip.className = 'fixed bg-gray-800 text-white px-3 py-1 rounded text-sm';
tooltip.textContent = 'Copied!';
tooltip.style.top = (event.pageY - 40) + 'px';
tooltip.style.left = (event.pageX - 30) + 'px';
document.body.appendChild(tooltip);
setTimeout(() => {
document.body.removeChild(tooltip);
}, 1000);
}
});
// Analyze again button
analyzeAgainBtn.addEventListener('click', function() {
if (humanOutput.value.trim()) {
aiInput.value = humanOutput.value;
humanizerInput.value = humanOutput.value;
const words = humanOutput.value ? humanOutput.value.split(/\s+/).length : 0;
inputWordCount.textContent = `${words} words`;
humanizerWordCount.textContent = `${words} words`;
analyzerTab.click();
analyzeBtn.click();
}
});
// Function to call DeepSeek API
async function callDeepSeekApi(text, level, tone, apiKey) {
const endpoint = apiEndpointInput.value.trim() || 'https://api.deepseek.com/v1';
// Prepare the prompt based on level and tone
let prompt = `Please humanize the following text to make it sound more natural and less like AI-generated content. `;
if (level === 'light') {
prompt += `Make subtle changes only, keeping most of the original structure intact. `;
} else if (level === 'medium') {
prompt += `Make balanced changes, improving flow and naturalness while preserving the core meaning. `;
} else if (level === 'heavy') {
prompt += `Completely rewrite the text to make it sound entirely human-written, using more varied sentence structures and natural phrasing. `;
}
if (tone === 'casual') {
prompt += `Use a casual, conversational tone. `;
} else if (tone === 'professional') {
prompt += `Use a professional, formal tone. `;
} else if (tone === 'friendly') {
prompt += `Use a friendly, approachable tone. `;
} else if (tone === 'academic') {
prompt += `Use an academic, scholarly tone. `;
} else {
prompt += `Use a neutral tone. `;
}
prompt += `Here's the text to humanize:\n\n${text}`;
const requestBody = {
model: "deepseek-chat",
messages: [
{
role: "user",
content: prompt
}
],
temperature: 0.7,
max_tokens: 2000
};
const response = await fetch(`${endpoint}/chat/completions`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${apiKey}`
},
body: JSON.stringify(requestBody)
});
if (!response.ok) {
const errorData = await response.json();
throw new Error(errorData.error?.message || 'API request failed');
}
const data = await response.json();
return data.choices?.[0]?.message?.content || '';
}
// Function to display analysis results
function displayAnalysisResults(analysis) {
analysisPlaceholder.classList.add('hidden');
analysisResults.classList.remove('hidden');
// Animate progress bars
setTimeout(() => {
aiScoreBar.style.width = `${analysis.aiScore}%`;
humanScoreBar.style.width = `${analysis.humanScore}%`;
aiScoreText.textContent = `${analysis.aiScore}%`;
humanScoreText.textContent = `${analysis.humanScore}%`;
// Detailed metrics
perplexityScore.textContent = analysis.perplexity;
perplexityBar.style.width = `${analysis.perplexity}%`;
burstinessScore.textContent = analysis.burstiness;
burstinessBar.style.width = `${analysis.burstiness}%`;
formalityScore.textContent = analysis.formality;
formalityBar.style.width = `${analysis.formality}%`;
passiveScore.textContent = `${analysis.passiveVoice}%`;
passiveBar.style.width = `${analysis.passiveVoice}%`;
sentenceVarScore.textContent = analysis.sentenceVariation;
sentenceVarBar.style.width = `${analysis.sentenceVariation}%`;
personalScore.textContent = analysis.personalization;
personalBar.style.width = `${analysis.personalization}%`;
}, 100);
// Add key findings
keyFindings.innerHTML = '';
analysis.findings.forEach(finding => {
const div = document.createElement('div');
div.className = 'flex items-start';
div.innerHTML = `
<div class="flex-shrink-0 mt-1 mr-2">
<i class="fas ${finding.severity === 'high' ? 'fa-exclamation-circle text-red-500' : finding.severity === 'medium' ? 'fa-info-circle text-yellow-500' : 'fa-check-circle text-green-500'}"></i>
</div>
<div>
<p class="text-gray-700">${finding.text}</p>
${finding.suggestion ? `<p class="text-sm text-gray-500 mt-1">${finding.suggestion}</p>` : ''}
</div>
`;
keyFindings.appendChild(div);
});
// Add AI patterns
aiPatterns.innerHTML = '';
analysis.patterns.forEach(pattern => {
const span = document.createElement('span');
span.className = `analysis-tag ${pattern.type === 'ai' ? 'tag-ai' : pattern.type === 'human' ? 'tag-human' : 'tag-neutral'}`;
span.textContent = pattern.text;
aiPatterns.appendChild(span);
});
// Display analyzed text with highlights
analyzedText.innerHTML = '';
const textSegments = analysis.textSegments;
textSegments.forEach(segment => {
const span = document.createElement('span');
span.className = segment.class;
span.textContent = segment.text;
if (segment.tooltip) {
span.classList.add('tooltip');
const tooltipSpan = document.createElement('span');
tooltipSpan.className = 'tooltiptext';
tooltipSpan.textContent = segment.tooltip;
span.appendChild(tooltipSpan);
}
analyzedText.appendChild(span);
});
}
// Function to simulate comprehensive analysis API call
async function simulateComprehensiveAnalysis(text) {
// Simulate network delay
await new Promise(resolve => setTimeout(resolve, 2000));
// Calculate metrics based on text characteristics
const wordCount = text.split(/\s+/).length;
const sentenceCount = text.split(/[.!?]+/).filter(s => s.trim().length > 0).length;
const avgSentenceLength = wordCount / sentenceCount;
const aiKeywords = ['artificial intelligence', 'machine learning', 'algorithm', 'neural network', 'AI model', 'deep learning', 'language model'];
const formalWords = ['utilize', 'commence', 'terminate', 'optimal', 'endeavor', 'ascertain', 'ameliorate', 'furthermore', 'moreover', 'however'];
const passiveVoiceRegex = /\b(am|is|are|was|were|be|being|been)\s+[a-z]+\b/gi;
// Calculate AI score (0-100)
let aiScore = 0;
let patterns = [];
let textSegments = [];
let findings = [];
// 1. Check for AI keywords
aiKeywords.forEach(keyword => {
const regex = new RegExp(keyword, 'gi');
const matches = text.match(regex);
if (matches) {
aiScore += matches.length * 5;
patterns.push({ type: 'ai', text: `AI keyword: ${keyword}` });
// Add to text segments
let lastIndex = 0;
let match;
while ((match = regex.exec(text)) !== null) {
// Add text before match
if (match.index > lastIndex) {
textSegments.push({
text: text.substring(lastIndex, match.index),
class: ''
});
}
// Add highlighted match
textSegments.push({
text: match[0],
class: 'highlight-ai',
tooltip: `AI-related keyword detected`
});
lastIndex = regex.lastIndex;
}
// Add remaining text
if (lastIndex < text.length) {
textSegments.push({
text: text.substring(lastIndex),
class: ''
});
}
}
});
// 2. Check for formal words
let formalWordCount = 0;
formalWords.forEach(word => {
const regex = new RegExp(`\\b${word}\\b`, 'gi');
const matches = text.match(regex);
if (matches) {
formalWordCount += matches.length;
patterns.push({ type: 'ai', text: `Formal word: ${word}` });
}
});
if (formalWordCount > 0) {
aiScore += Math.min(30, formalWordCount * 3);
findings.push({
text: `Found ${formalWordCount} overly formal word${formalWordCount > 1 ? 's' : ''} (e.g., ${formalWords.find(w => text.toLowerCase().includes(w)) || 'utilize'})`,
severity: 'medium',
suggestion: 'Consider replacing with more natural alternatives'
});
}
// 3. Check for passive voice
const passiveMatches = text.match(passiveVoiceRegex) || [];
const passiveVoicePercentage = Math.round((passiveMatches.length / sentenceCount) * 100);
if (passiveVoicePercentage > 20) {
aiScore += Math.min(20, (passiveVoicePercentage - 20));
findings.push({
text: `High passive voice usage (${passiveVoicePercentage}% of sentences)`,
severity: 'medium',
suggestion: 'Try to use more active voice constructions'
});
patterns.push({ type: 'ai', text: `Passive voice overuse` });
}
// 4. Check sentence length variation
const sentences = text.split(/[.!?]+/).filter(s => s.trim().length > 0);
const sentenceLengths = sentences.map(s => s.split(/\s+/).length);
const lengthVariation = calculateVariation(sentenceLengths);
if (lengthVariation < 0.4) {
aiScore += 15;
findings.push({
text: 'Low sentence length variation detected',
severity: 'medium',
suggestion: 'Try mixing short, medium and long sentences'
});
patterns.push({ type: 'ai', text: `Uniform sentence length` });
}
// 5. Check for repetitive phrasing
const phraseRepetition = checkPhraseRepetition(text);
if (phraseRepetition.count > 0) {
aiScore += Math.min(20, phraseRepetition.count * 5);
findings.push({
text: `Repetitive phrasing detected (e.g., "${phraseRepetition.example}")`,
severity: 'high',
suggestion: 'Try to vary your phrasing and word choice'
});
patterns.push({ type: 'ai', text: `Repetitive phrasing` });
}
// 6. Check for personalization
const personalPronouns = (text.match(/\b(I|me|my|mine|we|us|our|ours)\b/gi) || []).length;
const personalizationScore = Math.min(100, Math.round((personalPronouns / wordCount) * 10000));
if (personalizationScore < 5) {
aiScore += 10;
findings.push({
text: 'Lack of personal pronouns or subjective perspective',
severity: 'low',
suggestion: 'Consider adding personal perspective where appropriate'
});
patterns.push({ type: 'ai', text: `Lacks personalization` });
}
// 7. Check for vague generalizations
const vaguePhrases = ['many ways', 'various aspects', 'numerous factors', 'multiple benefits', 'revolutionizing', 'transformative impact'];
let vagueCount = 0;
vaguePhrases.forEach(phrase => {
if (text.toLowerCase().includes(phrase)) {
vagueCount++;
}
});
if (vagueCount > 0) {
aiScore += Math.min(15, vagueCount * 3);
findings.push({
text: `Found ${vagueCount} vague generalization${vagueCount > 1 ? 's' : ''}`,
severity: 'medium',
suggestion: 'Try to be more specific with examples or data'
});
patterns.push({ type: 'ai', text: `Vague generalizations` });
}
// 8. Check for perfect grammar (lack of colloquialisms)
const grammarErrors = (text.match(/\b(ain't|gonna|wanna|gotta|kinda|sorta)\b/gi) || []).length;
if (grammarErrors === 0 && wordCount > 100) {
aiScore += 5;
findings.push({
text: 'No colloquialisms or informal grammar detected',
severity: 'low',
suggestion: 'In casual contexts, some informal language can sound more natural'
});
}
// Cap at 100
aiScore = Math.min(100, Math.max(0, aiScore));
// Human score is inverse of AI score with some randomness
const humanScore = Math.min(100, Math.max(0, 100 - aiScore + (Math.random() * 20 - 10)));
// Calculate perplexity (simulated)
const perplexity = Math.min(100, Math.max(0,
70 - (aiScore * 0.6) + (Math.random() * 20 - 10)
));
// Calculate burstiness (simulated)
const burstiness = Math.min(100, Math.max(0,
60 - (aiScore * 0.5) + (Math.random() * 20 - 10)
));
// Calculate formality index
const formality = Math.min(100, Math.max(0,
20 + (aiScore * 0.4) + (Math.random() * 10 - 5)
));
// Sentence variation score
const sentenceVariation = Math.min(100, Math.max(0,
40 + (lengthVariation * 60) + (Math.random() * 10 - 5)
));
// Add positive findings for human-like aspects
if (humanScore > 70) {
findings.unshift({
text: 'Content shows strong human-like qualities',
severity: 'low'
});
patterns.push({ type: 'human', text: `Human-like qualities` });
}
if (personalizationScore > 10) {
findings.unshift({
text: 'Contains personal perspective or subjective elements',
severity: 'low'
});
patterns.push({ type: 'human', text: `Personal perspective` });
}
if (lengthVariation > 0.6) {
findings.unshift({
text: 'Good variation in sentence length and structure',
severity: 'low'
});
patterns.push({ type: 'human', text: `Sentence variation` });
}
return {
aiScore: Math.round(aiScore),
humanScore: Math.round(humanScore),
perplexity: Math.round(perplexity),
burstiness: Math.round(burstiness),
formality: Math.round(formality),
passiveVoice: passiveVoicePercentage,
sentenceVariation: Math.round(sentenceVariation),
personalization: personalizationScore,
findings: findings,
patterns: patterns,
textSegments: textSegments.length > 0 ? textSegments : [{ text: text, class: '' }]
};
}
// Helper function to calculate variation coefficient
function calculateVariation(values) {
if (values.length < 2) return 0;
const mean = values.reduce((a, b) => a + b) / values.length;
const variance = values.reduce((a, b) => a + Math.pow(b - mean, 2), 0) / values.length;
const stdDev = Math.sqrt(variance);
return stdDev / mean;
}
// Helper function to check for repetitive phrasing
function checkPhraseRepetition(text) {
const phrases = [
'it is important to note',
'in conclusion',
'as a result',
'in other words',
'on the other hand',
'in addition',
'for example',
'this means that',
'it should be noted',
'as mentioned earlier'
];
let maxCount = 0;
let maxPhrase = '';
phrases.forEach(phrase => {
const regex = new RegExp(phrase, 'gi');
const matches = text.match(regex) || [];
if (matches.length > maxCount) {
maxCount = matches.length;
maxPhrase = phrase;
}
});
return { count: maxCount, example: maxPhrase };
}
function showError(message) {
errorText.textContent = message;
errorMessage.classList.remove('hidden');
}
function showSuccess(message) {
const successDiv = document.createElement('div');
successDiv.className = 'fixed bottom-4 right-4 bg-green-500 text-white px-4 py-2 rounded-md shadow-lg flex items-center';
successDiv.innerHTML = `
<i class="fas fa-check-circle mr-2"></i>
<span>${message}</span>
`;
document.body.appendChild(successDiv);
setTimeout(() => {
document.body.removeChild(successDiv);
}, 3000);
}
});
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=sqibhe/humanizer" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>