if (results.seo) scores.push(results.seo.overallScore);
const overallScore = scores.length > 0 ? Math.round(scores.reduce((a, b) => a + b, 0) / scores.length) : 0;
const scoreClass = getScoreClass(overallScore);
card.innerHTML = `
${results.plagiarism ? `
${results.plagiarism.originalityScore}%
Originality
` : ''}
${results.aiDetection ? `
${Math.round((1 - results.aiDetection.aiProbability) * 100)}%
Human-like
` : ''}
${results.grammar ? `
${results.grammar.score}/100
Grammar
` : ''}
${results.readability ? `
${results.readability.gradeLevel}
Grade Level
` : ''}
`;
return card;
}
function createPlagiarismCard(plagiarism) {
const card = document.createElement('div');
card.className = 'result-card';
card.innerHTML = `
${plagiarism.matches.length}
Matches Found
${plagiarism.sourcesChecked.toLocaleString()}
Sources Checked
${plagiarism.highestMatch}%
Highest Match
${plagiarism.matches.length > 0 ? `
🚨 Potential Matches
${plagiarism.matches.map(match => `
`).join('')}
` : ''}
`;
return card;
}
function createAIDetectionCard(aiDetection) {
const card = document.createElement('div');
card.className = 'result-card';
const humanProbability = (1 - aiDetection.aiProbability) * 100;
const aiProbability = aiDetection.aiProbability * 100;
card.innerHTML = `
Human Content
${Math.round(humanProbability)}%
AI Generated
${Math.round(aiProbability)}%
${aiDetection.confidence}%
Confidence
${aiDetection.flaggedSentences}
Flagged Sentences
${aiDetection.patterns.length > 0 ? `
🔍 AI Patterns Detected
${aiDetection.patterns.map(pattern => `
${pattern.description}
`).join('')}
` : ''}
`;
return card;
}
function createGrammarCard(grammar) {
const card = document.createElement('div');
card.className = 'result-card';
card.innerHTML = `
${grammar.errors.length}
Total Issues
${grammar.errors.filter(e => e.severity === 'high').length}
Critical
${grammar.errors.filter(e => e.severity === 'medium').length}
Medium
${grammar.errors.filter(e => e.severity === 'low').length}
Minor
${grammar.errors.length > 0 ? `
📝 Issues Found
${grammar.errors.length > 5 ? `
+${grammar.errors.length - 5} more issues found
` : ''}
` : ''}
`;
return card;
}
function createReadabilityCard(readability) {
const card = document.createElement('div');
card.className = 'result-card';
card.innerHTML = `
${readability.fleschScore}
Flesch Score
${readability.avgSentenceLength}
Avg Sentence
${readability.avgWordsPerSentence}
Words/Sentence
${readability.complexWords}
Complex Words
📖 Reading Level Assessment
${readability.assessment}
`;
return card;
}
function createToneCard(tone) {
const card = document.createElement('div');
card.className = 'result-card';
card.innerHTML = `
${Object.entries(tone.toneBreakdown).map(([toneType, confidence]) => `
${toneType}
${Math.round(confidence * 100)}%
`).join('')}
💡 Tone Insights
${tone.insights}
`;
return card;
}
function createSEOCard(seo) {
const card = document.createElement('div');
card.className = 'result-card';
card.innerHTML = `
${seo.keywordDensity}%
Keyword Density
${seo.internalLinks}
Internal Links
${seo.metaScore}
Meta Score
${seo.recommendations.length > 0 ? `
🎯 SEO Recommendations
${seo.recommendations.map(rec => `
${rec.description}
`).join('')}
` : ''}
`;
return card;
}
function createSuggestionsPanel(results) {
const panel = document.createElement('div');
panel.className = 'suggestions-panel';
const suggestions = generateSuggestions(results);
panel.innerHTML = `
💡 Improvement Suggestions
${suggestions.map(suggestion => `
${suggestion.title}
${suggestion.description}
${suggestion.action ? `
${suggestion.actionText}
` : ''}
`).join('')}
`;
return panel;
}
function generateSuggestions(results) {
const suggestions = [];
if (results.plagiarism && results.plagiarism.originalityScore < 85) {
suggestions.push({
title: '🔄 Improve Originality',
description: 'Rewrite flagged sections to increase originality score.',
action: 'rewriteContent()',
actionText: 'Auto-Rewrite'
});
}
if (results.aiDetection && results.aiDetection.aiProbability > 0.6) {
suggestions.push({
title: '👤 Humanize Content',
description: 'Add personal touches, varied sentence structure, and natural flow.',
action: 'humanizeContent()',
actionText: 'Humanize'
});
}
if (results.grammar && results.grammar.score < 80) {
suggestions.push({
title: '✏️ Fix Grammar Issues',
description: 'Address identified grammar and style issues.',
action: 'fixGrammar()',
actionText: 'Auto-Fix'
});
}
if (results.readability && results.readability.fleschScore < 60) {
suggestions.push({
title: '📚 Improve Readability',
description: 'Simplify complex sentences and use clearer language.',
action: 'improveReadability()',
actionText: 'Simplify'
});
}
return suggestions;
}
function getScoreClass(score) {
if (score >= 90) return 'score-excellent';
if (score >= 75) return 'score-good';
if (score >= 60) return 'score-warning';
return 'score-poor';
}
// Action functions
function exportReport() {
const report = {
title: 'Content Analysis Report',
timestamp: new Date().toISOString(),
content: {
length: contentText.length,
wordCount: contentText.trim().split(/\s+/).length
},
results: analysisResults,
summary: analysisResults.summary
};
const blob = new Blob([JSON.stringify(report, null, 2)], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `content-analysis-${Date.now()}.json`;
a.click();
URL.revokeObjectURL(url);
sendContentWebhook('report_exported', { format: 'json' });
}
function saveResults() {
const saved = localStorage.getItem('contentAnalysisHistory') || '[]';
const history = JSON.parse(saved);
const entry = {
id: Date.now(),
timestamp: new Date().toISOString(),
contentPreview: contentText.substring(0, 100) + '...',
results: analysisResults.summary
};
history.unshift(entry);
if (history.length > 50) history.pop(); // Keep last 50
localStorage.setItem('contentAnalysisHistory', JSON.stringify(history));
alert('Results saved to history!');
sendContentWebhook('results_saved', { entryId: entry.id });
}
function shareResults() {
const shareText = `Content Analysis Results:\n\n`;
const summary = analysisResults.summary;
let shareContent = shareText;
if (summary.plagiarismScore) shareContent += `✅ Originality: ${summary.plagiarismScore}%\n`;
if (summary.aiProbability) shareContent += `👤 Human-like: ${Math.round((1-summary.aiProbability)*100)}%\n`;
if (summary.grammarScore) shareContent += `✏️ Grammar: ${summary.grammarScore}/100\n`;
if (summary.readabilityScore) shareContent += `📚 Readability: ${summary.readabilityScore}\n`;
shareContent += `\nAnalyzed with Cloud Connect Content Checker`;
if (navigator.share) {
navigator.share({
title: 'Content Analysis Results',
text: shareContent
});
} else {
navigator.clipboard.writeText(shareContent);
alert('Results copied to clipboard!');
}
sendContentWebhook('results_shared', { method: navigator.share ? 'native' : 'clipboard' });
}
function improveContent() {
// This would integrate with AI rewriting services
alert('AI Content Improvement feature coming soon! This will automatically rewrite content to improve all scores.');
sendContentWebhook('improvement_requested', {});
}
// Content improvement functions
function rewriteContent() {
alert('Auto-rewrite feature will paraphrase flagged sections to improve originality.');
}
function humanizeContent() {
alert('Humanization feature will add personal touches and natural language patterns.');
}
function fixGrammar() {
alert('Auto-fix will correct identified grammar and style issues.');
}
function improveReadability() {
alert('Readability improvement will simplify complex sentences and terminology.');
}
// Analysis engine implementations
class PlagiarismChecker {
check(content) {
// Simulate plagiarism check
const sentences = content.split('.').filter(s => s.trim().length > 10);
const matches = [];
// Simulate some matches for demo
if (content.toLowerCase().includes('artificial intelligence')) {
matches.push({
text: content.substring(content.toLowerCase().indexOf('artificial intelligence'), content.toLowerCase().indexOf('artificial intelligence') + 50),
source: 'Wikipedia - Artificial Intelligence',
url: 'https://en.wikipedia.org/wiki/Artificial_intelligence',
similarity: 78
});
}
if (content.toLowerCase().includes('machine learning')) {
matches.push({
text: content.substring(content.toLowerCase().indexOf('machine learning'), content.toLowerCase().indexOf('machine learning') + 60),
source: 'MIT Technology Review',
url: 'https://www.technologyreview.com',
similarity: 65
});
}
const originalityScore = Math.max(50, 100 - (matches.length * 15) - Math.random() * 20);
return {
originalityScore: Math.round(originalityScore),
matches: matches,
sourcesChecked: Math.floor(Math.random() * 1000000) + 500000,
highestMatch: matches.length > 0 ? Math.max(...matches.map(m => m.similarity)) : 0
};
}
}
class AIDetector {
analyze(content) {
// Simulate AI detection based on patterns
const sentences = content.split('.').filter(s => s.trim().length > 5);
const patterns = [];
// Check for AI patterns
const aiIndicators = [
'furthermore', 'moreover', 'additionally', 'consequently',
'it is important to note', 'in conclusion', 'to summarize'
];
let aiScore = 0;
let flaggedSentences = 0;
sentences.forEach(sentence => {
const lowerSentence = sentence.toLowerCase();
const hasAiIndicators = aiIndicators.some(indicator => lowerSentence.includes(indicator));
if (hasAiIndicators) {
aiScore += 0.1;
flaggedSentences++;
}
// Check sentence structure patterns
if (sentence.split(',').length > 3) {
aiScore += 0.05; // Complex comma usage
}
if (sentence.length > 100) {
aiScore += 0.03; // Very long sentences
}
});
// Normalize score
aiScore = Math.min(aiScore, 0.95);
if (aiScore > 0.5) {
patterns.push({
type: 'Formal Language Patterns',
description: 'High use of transitional phrases typical of AI writing'
});
}
if (flaggedSentences > sentences.length * 0.3) {
patterns.push({
type: 'Repetitive Structure',
description: 'Consistent sentence patterns that may indicate AI generation'
});
}
return {
aiProbability: aiScore,
confidence: Math.round((1 - Math.abs(aiScore - 0.5)) * 100),
flaggedSentences: flaggedSentences,
patterns: patterns
};
}
}
class GrammarChecker {
check(content) {
const errors = [];
const sentences = content.split('.').filter(s => s.trim().length > 0);
// Simulate grammar checking
sentences.forEach((sentence, index) => {
// Check for basic issues
if (!sentence.trim().match(/^[A-Z]/)) {
errors.push({
type: 'Capitalization',
text: sentence.trim().substring(0, 30) + '...',
suggestion: 'Start sentence with capital letter',
severity: 'medium',
position: index
});
}
if (sentence.includes(' i ')) {
errors.push({
type: 'Pronoun Case',
text: sentence.trim().substring(0, 30) + '...',
suggestion: 'Use "I" instead of "i"',
severity: 'high',
position: index
});
}
if (sentence.length > 150) {
errors.push({
type: 'Sentence Length',
text: sentence.trim().substring(0, 50) + '...',
suggestion: 'Consider breaking into shorter sentences',
severity: 'low',
position: index
});
}
});
// Add some random errors for demo
if (Math.random() > 0.7) {
errors.push({
type: 'Subject-Verb Agreement',
text: 'The data shows that...',
suggestion: 'Use "show" instead of "shows" with plural subject',
severity: 'high',
position: 0
});
}
const score = Math.max(20, 100 - (errors.length * 5));
return {
score: Math.round(score),
errors: errors.slice(0, 10), // Limit for display
totalErrors: errors.length
};
}
}
class ReadabilityAnalyzer {
analyze(content) {
const sentences = content.split(/[.!?]+/).filter(s => s.trim().length > 0);
const words = content.trim().split(/\s+/);
const syllables = this.countSyllables(content);
// Flesch Reading Ease
const avgSentenceLength = words.length / sentences.length;
const avgSyllablesPerWord = syllables / words.length;
const fleschScore = 206.835 - (1.015 * avgSentenceLength) - (84.6 * avgSyllablesPerWord);
const normalizedFlesch = Math.max(0, Math.min(100, Math.round(fleschScore)));
// Grade level estimation
const gradeLevel = Math.max(1, Math.round(0.39 * avgSentenceLength + 11.8 * avgSyllablesPerWord - 15.59));
let assessment = '';
if (normalizedFlesch >= 90) assessment = 'Very easy to read (5th grade level)';
else if (normalizedFlesch >= 50) assessment = 'Fairly difficult to read (10th-12th grade)';
else if (normalizedFlesch >= 30) assessment = 'Difficult to read (college level)';
else assessment = 'Very difficult to read (graduate level)';
// Complex words (3+ syllables)
const complexWords = words.filter(word => this.countWordSyllables(word) >= 3).length;
return {
fleschScore: normalizedFlesch,
gradeLevel: gradeLevel,
avgSentenceLength: Math.round(avgSentenceLength),
avgWordsPerSentence: Math.round(avgSentenceLength),
complexWords: complexWords,
assessment: assessment
};
}
countSyllables(text) {
const words = text.toLowerCase().match(/\b[a-z]+\b/g) || [];
return words.reduce((total, word) => total + this.countWordSyllables(word), 0);
}
countWordSyllables(word) {
word = word.toLowerCase();
if (word.length <= 3) return 1;
const vowels = 'aeiouy';
let syllableCount = 0;
let previousWasVowel = false;
for (let i = 0; i < word.length; i++) {
const isVowel = vowels.includes(word[i]);
if (isVowel && !previousWasVowel) {
syllableCount++;
}
previousWasVowel = isVowel;
}
// Handle silent e
if (word.endsWith('e')) {
syllableCount--;
}
return Math.max(1, syllableCount);
}
}
class ToneAnalyzer {
analyze(content) {
const text = content.toLowerCase();
const tonePatterns = {
formal: ['furthermore', 'moreover', 'consequently', 'therefore', 'additionally'],
casual: ['hey', 'cool', 'awesome', 'yeah', 'stuff', 'thing'],
confident: ['certainly', 'definitely', 'absolutely', 'clearly', 'obviously'],
analytical: ['analyze', 'examine', 'consider', 'evaluate', 'assess'],
emotional: ['feel', 'love', 'hate', 'amazing', 'terrible', 'wonderful'],
persuasive: ['should', 'must', 'need to', 'important', 'essential', 'crucial']
};
const toneScores = {};
Object.entries(tonePatterns).forEach(([tone, patterns]) => {
let score = 0;
patterns.forEach(pattern => {
const matches = (text.match(new RegExp(pattern, 'g')) || []).length;
score += matches;
});
toneScores[tone] = score / patterns.length;
});
// Normalize scores
const maxScore = Math.max(...Object.values(toneScores));
if (maxScore > 0) {
Object.keys(toneScores).forEach(tone => {
toneScores[tone] = toneScores[tone] / maxScore;
});
}
const primaryTone = Object.entries(toneScores).reduce((a, b) =>
toneScores[a[0]] > toneScores[b[0]] ? a : b
)[0];
let insights = '';
if (primaryTone === 'formal') {
insights = 'Content uses formal, academic language suitable for professional contexts.';
} else if (primaryTone === 'casual') {
insights = 'Content has a relaxed, conversational tone that connects well with readers.';
} else if (primaryTone === 'confident') {
insights = 'Content demonstrates authority and confidence in the subject matter.';
} else if (primaryTone === 'analytical') {
insights = 'Content takes an analytical approach, examining topics systematically.';
} else if (primaryTone === 'emotional') {
insights = 'Content uses emotional language to connect with readers on a personal level.';
} else if (primaryTone === 'persuasive') {
insights = 'Content aims to convince readers and drive specific actions.';
} else {
insights = 'Content maintains a balanced, neutral tone throughout.';
}
return {
primaryTone: primaryTone.charAt(0).toUpperCase() + primaryTone.slice(1),
toneBreakdown: toneScores,
insights: insights
};
}
}
class SEOAnalyzer {
analyze(content) {
const words = content.toLowerCase().match(/\b[a-z]+\b/g) || [];
const sentences = content.split(/[.!?]+/).filter(s => s.trim().length > 0);
// Keyword density (simplified)
const wordCount = words.length;
const wordFreq = {};
words.forEach(word => {
if (word.length > 3) {
wordFreq[word] = (wordFreq[word] || 0) + 1;
}
});
const topKeywords = Object.entries(wordFreq)
.sort(([,a], [,b]) => b - a)
.slice(0, 5);
const keywordDensity = topKeywords.length > 0 ?
Math.round((topKeywords[0][1] / wordCount) * 100 * 10) / 10 : 0;
// Simulate other SEO metrics
const headings = (content.match(/^#{1,6}\s/gm) || []).length;
const internalLinks = (content.match(/\[.*?\]\(.*?\)/g) || []).length;
const recommendations = [];
if (keywordDensity > 3) {
recommendations.push({
title: 'Keyword Density Too High',
description: 'Reduce keyword usage to avoid over-optimization',
priority: 'high'
});
} else if (keywordDensity < 0.5) {
recommendations.push({
title: 'Low Keyword Density',
description: 'Include target keywords more naturally in content',
priority: 'medium'
});
}
if (headings === 0) {
recommendations.push({
title: 'Missing Headings',
description: 'Add H1, H2, H3 headings to improve structure',
priority: 'high'
});
}
if (wordCount < 300) {
recommendations.push({
title: 'Content Too Short',
description: 'Expand content to at least 300 words for better SEO',
priority: 'medium'
});
}
if (sentences.some(s => s.length > 150)) {
recommendations.push({
title: 'Long Sentences',
description: 'Break up sentences longer than 20 words',
priority: 'low'
});
}
// Calculate overall SEO score
let score = 50;
if (keywordDensity >= 0.5 && keywordDensity <= 3) score += 20;
if (headings > 0) score += 15;
if (wordCount >= 300) score += 15;
if (internalLinks > 0) score += 10;
return {
overallScore: Math.min(100, score),
keywordDensity: keywordDensity,
headings: headings,
internalLinks: internalLinks,
metaScore: Math.floor(Math.random() * 30) + 70,
topKeywords: topKeywords.map(([word, freq]) => ({ word, frequency: freq })),
recommendations: recommendations
};
}
}
// Enhanced webhook function for content checker
function sendContentWebhook(action, data) {
const webhookData = {
tool: 'content_checker',
action: action,
data: data,
timestamp: new Date().toISOString(),
sessionId: getSessionId() || 'anonymous',
contentLength: contentText ? contentText.length : 0,
checkType: currentCheckType
};
// Use safe webhook call if available, otherwise fallback
if (typeof safeWebhookCall === 'function') {
safeWebhookCall('contentChecker', webhookData);
} else {
// Fallback for standalone use
fetch('https://hooks.zapier.com/hooks/catch/12345/content-checker/', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(webhookData)
}).catch(() => {
// Silently handle errors in fallback mode
console.log('Webhook call completed (fallback mode)');
});
}
}
function getSessionId() {
return sessionStorage.getItem('ccSessionId') ||
sessionStorage.getItem('sessionId') ||
'cc_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
}
// Drag and drop functionality
function setupDragAndDrop() {
const uploadArea = document.querySelector('.upload-area');
['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
uploadArea.addEventListener(eventName, preventDefaults, false);
});
function preventDefaults(e) {
e.preventDefault();
e.stopPropagation();
}
['dragenter', 'dragover'].forEach(eventName => {
uploadArea.addEventListener(eventName, highlight, false);
});
['dragleave', 'drop'].forEach(eventName => {
uploadArea.addEventListener(eventName, unhighlight, false);
});
function highlight() {
uploadArea.classList.add('dragover');
}
function unhighlight() {
uploadArea.classList.remove('dragover');
}
uploadArea.addEventListener('drop', handleDrop, false);
function handleDrop(e) {
const files = e.dataTransfer.files;
if (files.length > 0) {
handleDroppedFile(files[0]);
}
}
}
function handleDroppedFile(file) {
const fileInput = document.getElementById('fileInput');
const dataTransfer = new DataTransfer();
dataTransfer.items.add(file);
fileInput.files = dataTransfer.files;
handleFileUpload();
}
// Initialize on page load
document.addEventListener('DOMContentLoaded', function() {
// Initialize drag and drop
setupDragAndDrop();
// Set up auto-save
const contentInput = document.getElementById('contentInput');
let saveTimeout;
contentInput.addEventListener('input', function() {
clearTimeout(saveTimeout);
saveTimeout = setTimeout(() => {
const content = contentInput.value;
if (content.length > 100) {
sessionStorage.setItem('draftContent', content);
}
}, 2000);
});
// Restore draft content
const draftContent = sessionStorage.getItem('draftContent');
if (draftContent && !contentInput.value) {
if (confirm('Restore your previous draft?')) {
contentInput.value = draftContent;
updateWordCount();
}
}
// Track page load
sendContentWebhook('page_loaded', {
userAgent: navigator.userAgent,
viewport: { width: window.innerWidth, height: window.innerHeight }
});
});
// Keyboard shortcuts
document.addEventListener('keydown', function(e) {
// Ctrl/Cmd + Enter to analyze
if ((e.ctrlKey || e.metaKey) && e.key === 'Enter') {
e.preventDefault();
analyzeContent();
}
// Ctrl/Cmd + S to save
if ((e.ctrlKey || e.metaKey) && e.key === 's') {
e.preventDefault();
saveResults();
}
});