Defamation Risk Analyzer

Defamation Risk Analyzer

Analyze statements for potential defamation risks based on configurable factors.

Analysis Results

Your risk analysis will appear here.

Detailed Risk Report

Add New Risk Factor

Configured Factors

Level: ${levelMap[factor.level]}

`; configList.appendChild(div); }); }; const renderResults = (results) => { lastResults = results; const { score, findings, highlightedHtml } = results; let scoreText, scoreColor; if (score >= 75) { scoreText = 'High Risk'; scoreColor = 'text-red-600'; } else if (score >= 40) { scoreText = 'Medium Risk'; scoreColor = 'text-yellow-600'; } else if (score > 0) { scoreText = 'Low Risk'; scoreColor = 'text-green-600'; } else { scoreText = 'No Specific Risks Detected'; scoreColor = 'text-slate-600'; } riskScoreContainer.innerHTML = `

${scoreText}

Overall Score: ${score.toFixed(0)} / 100

`; highlightedTextContainer.innerHTML = highlightedHtml; resultsPlaceholder.classList.add('hidden'); resultsContent.classList.remove('hidden'); downloadPdfBtn.disabled = false; renderDetailedReport(findings); }; const renderDetailedReport = (findings) => { reportView.innerHTML = ''; if(findings.length === 0) { reportView.innerHTML = `
No risks were identified in the provided text.
`; return; } findings.forEach(finding => { const levelMap = {1: 'Low', 3: 'Medium', 5: 'High'}; const colorMap = {1: 'text-green-700 bg-green-100', 3: 'text-yellow-700 bg-yellow-100', 5: 'text-red-700 bg-red-100'}; const card = document.createElement('div'); card.className = 'p-4 border border-slate-200 rounded-lg bg-slate-50'; card.innerHTML = `

${finding.factor.description}

${levelMap[finding.factor.level]} Risk

Triggered by keyword: "${finding.keyword}"

...${finding.context}...
`; reportView.appendChild(card); }); }; // --- UI & TAB LOGIC --- const updateTabUI = () => { tabs.forEach(tab => tab.classList.toggle('active', tab.dataset.tab === currentTab)); tabContents.forEach(content => content.classList.toggle('active', content.id === `tab-${currentTab}`)); const currentIndex = tabOrder.indexOf(currentTab); prevBtn.disabled = currentIndex === 0; nextBtn.disabled = currentIndex === tabOrder.length - 1; if (currentTab === 'config') renderConfigList(); }; const changeTab = (direction) => { const currentIndex = tabOrder.indexOf(currentTab); const newIndex = currentIndex + direction; if (newIndex >= 0 && newIndex < tabOrder.length) { currentTab = tabOrder[newIndex]; updateTabUI(); } }; // --- CORE LOGIC --- const analyzeDefamationRisk = () => { const text = statementText.value; if (!text.trim()) { alert("Please paste some text to analyze."); return; } let findings = []; let totalRiskPoints = 0; let maxPossiblePoints = 0; const lowerCaseText = text.toLowerCase(); let highlightedText = text; riskFactors.forEach(factor => { const keywords = factor.keywords.split(',').map(k => k.trim().toLowerCase()).filter(Boolean); let factorFound = false; keywords.forEach(keyword => { if (lowerCaseText.includes(keyword)) { factorFound = true; const regex = new RegExp(`\\b${keyword}\\b`, 'gi'); let match; while((match = regex.exec(text)) !== null) { const startIndex = Math.max(0, match.index - 20); const endIndex = Math.min(text.length, match.index + keyword.length + 20); findings.push({ factor, keyword, context: text.substring(startIndex, endIndex).replace(match[0], `${match[0]}`) }); } highlightedText = highlightedText.replace(regex, `${keyword}${factor.description}`); } }); if (factorFound) { totalRiskPoints += factor.level; } maxPossiblePoints += factor.level; }); const score = maxPossiblePoints > 0 ? (totalRiskPoints / maxPossiblePoints) * 100 : 0; renderResults({ score, findings, highlightedHtml: highlightedText.replace(/\n/g, '
') }); }; // --- EVENT LISTENERS --- tabs.forEach(tab => tab.addEventListener('click', () => { currentTab = tab.dataset.tab; updateTabUI(); })); prevBtn.addEventListener('click', () => changeTab(-1)); nextBtn.addEventListener('click', () => changeTab(1)); analyzeRiskBtn.addEventListener('click', analyzeDefamationRisk); riskForm.addEventListener('submit', (e) => { e.preventDefault(); const id = document.getElementById('risk-id').value; const newItem = { id: id ? parseInt(id) : Date.now(), description: document.getElementById('risk-description').value, keywords: document.getElementById('risk-keywords').value, level: parseInt(document.getElementById('risk-level').value), }; if (id) { riskFactors = riskFactors.map(item => item.id === newItem.id ? newItem : item); } else { riskFactors.push(newItem); } resetForm(); renderConfigList(); }); cancelEditBtn.addEventListener('click', resetForm); configList.addEventListener('click', (e) => { const target = e.target; const id = parseInt(target.dataset.id); if (target.classList.contains('edit-btn')) { const itemToEdit = riskFactors.find(item => item.id === id); if (itemToEdit) populateForm(itemToEdit); } if (target.classList.contains('delete-btn')) { riskFactors = riskFactors.filter(item => item.id !== id); renderConfigList(); } }); // --- FORM & DATA HANDLING --- function populateForm(item) { formTitle.textContent = 'Edit Risk Factor'; document.getElementById('risk-id').value = item.id; document.getElementById('risk-description').value = item.description; document.getElementById('risk-keywords').value = item.keywords; document.getElementById('risk-level').value = item.level; cancelEditBtn.classList.remove('hidden'); } function resetForm() { formTitle.textContent = 'Add New Risk Factor'; riskForm.reset(); document.getElementById('risk-id').value = ''; cancelEditBtn.classList.add('hidden'); } // --- PDF DOWNLOAD --- downloadPdfBtn.addEventListener('click', () => { if (!lastResults) { console.error("No results to download."); return; } if (typeof window.jspdf === 'undefined') { console.error('jsPDF library is not available.'); return; } const { jsPDF } = window.jspdf; const doc = new jsPDF({ unit: 'pt', format: 'a4' }); if (typeof doc.autoTable === 'undefined') { console.error('jsPDF autotable plugin is not available.'); return; } const { score, findings } = lastResults; const levelMap = {1: 'Low', 3: 'Medium', 5: 'High'}; doc.setFont('helvetica', 'bold'); doc.setFontSize(22); doc.setTextColor('#1e293b'); doc.text('Defamation Risk Analysis Report', doc.internal.pageSize.getWidth() / 2, 60, { align: 'center' }); doc.setFontSize(14); doc.text(`Overall Risk Score: ${score.toFixed(0)} / 100`, 40, 100); doc.setFont('helvetica', 'normal'); doc.setFontSize(10); doc.text(`Source Text: "${statementText.value.substring(0, 70)}..."`, 40, 120); const tableData = findings.map(f => [ f.factor.description, levelMap[f.factor.level], f.keyword, f.context.replace(/<[^>]*>/g, '') // strip html from context for pdf ]); doc.autoTable({ startY: 150, head: [['Risk Factor', 'Level', 'Trigger Keyword', 'Context']], body: tableData, theme: 'grid', headStyles: { fillColor: '#1e293b', textColor: '#ffffff', fontStyle: 'bold' }, columnStyles: { 3: { cellWidth: 200 } } }); doc.save('Defamation-Risk-Report.pdf'); }); // --- INITIALIZATION --- updateTabUI(); });
Scroll to Top