// InsightFlow Chrome Extension - Content Script // 在网页上下文中运行,负责提取页面内容 (function() { 'use strict'; // 避免重复注入 if (window.insightFlowInjected) return; window.insightFlowInjected = true; // 提取页面主要内容 function extractContent() { const result = { url: window.location.href, title: document.title, content: '', html: document.documentElement.outerHTML, meta: { author: getMetaContent('author'), description: getMetaContent('description'), keywords: getMetaContent('keywords'), publishedTime: getMetaContent('article:published_time') || getMetaContent('publishedDate'), siteName: getMetaContent('og:site_name') || getMetaContent('application-name'), language: document.documentElement.lang || 'unknown' }, extractedAt: new Date().toISOString() }; // 尝试提取正文内容 const article = extractArticleContent(); result.content = article.text; result.contentHtml = article.html; result.wordCount = article.text.split(/\s+/).length; return result; } // 获取 meta 标签内容 function getMetaContent(name) { const meta = document.querySelector(`meta[name="${name}"], meta[property="${name}"]`); return meta ? meta.getAttribute('content') : ''; } // 提取文章正文(使用多种策略) function extractArticleContent() { // 策略1:使用 Readability 算法(简化版) let bestElement = findBestElement(); if (bestElement) { return { text: cleanText(bestElement.innerText), html: bestElement.innerHTML }; } // 策略2:回退到 body 内容 const body = document.body; return { text: cleanText(body.innerText), html: body.innerHTML }; } // 查找最佳内容元素(基于文本密度) function findBestElement() { const candidates = []; const elements = document.querySelectorAll('article, [role="main"], .post-content, .entry-content, .article-content, #content, .content'); elements.forEach(el => { const text = el.innerText || ''; const linkDensity = calculateLinkDensity(el); const textDensity = text.length / (el.innerHTML.length || 1); candidates.push({ element: el, score: text.length * textDensity * (1 - linkDensity), textLength: text.length }); }); // 按分数排序 candidates.sort((a, b) => b.score - a.score); return candidates.length > 0 ? candidates[0].element : null; } // 计算链接密度 function calculateLinkDensity(element) { const links = element.getElementsByTagName('a'); let linkLength = 0; for (let link of links) { linkLength += link.innerText.length; } const textLength = element.innerText.length || 1; return linkLength / textLength; } // 清理文本 function cleanText(text) { return text .replace(/\s+/g, ' ') .replace(/\n\s*\n/g, '\n\n') .trim(); } // 高亮选中的文本 function highlightSelection() { const selection = window.getSelection(); if (selection.rangeCount > 0) { const range = selection.getRangeAt(0); const selectedText = selection.toString().trim(); if (selectedText.length > 0) { return { text: selectedText, context: getSelectionContext(range) }; } } return null; } // 获取选中内容的上下文 function getSelectionContext(range) { const container = range.commonAncestorContainer; const element = container.nodeType === Node.TEXT_NODE ? container.parentElement : container; return { tagName: element.tagName, className: element.className, id: element.id, surroundingText: element.innerText.substring(0, 200) }; } // 监听来自 background 的消息 chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { if (request.action === 'extractContent') { const content = extractContent(); sendResponse({ success: true, data: content }); } else if (request.action === 'getSelection') { const selection = highlightSelection(); sendResponse({ success: true, data: selection }); } else if (request.action === 'ping') { sendResponse({ success: true, pong: true }); } return true; }); // 添加浮动按钮(可选) function addFloatingButton() { const button = document.createElement('div'); button.id = 'insightflow-clipper-btn'; button.innerHTML = '📎'; button.title = 'Clip to InsightFlow'; button.style.cssText = ` position: fixed; bottom: 20px; right: 20px; width: 50px; height: 50px; background: #4CAF50; border-radius: 50%; display: flex; align-items: center; justify-content: center; cursor: pointer; box-shadow: 0 2px 10px rgba(0,0,0,0.3); z-index: 999999; font-size: 24px; transition: transform 0.2s; `; button.addEventListener('mouseenter', () => { button.style.transform = 'scale(1.1)'; }); button.addEventListener('mouseleave', () => { button.style.transform = 'scale(1)'; }); button.addEventListener('click', () => { chrome.runtime.sendMessage({ action: 'openClipper' }); }); document.body.appendChild(button); } // 如果启用,添加浮动按钮 chrome.storage.sync.get(['showFloatingButton'], (result) => { if (result.showFloatingButton !== false) { addFloatingButton(); } }); console.log('[InsightFlow] Content script loaded'); })();