browser-plugin-creator
Version:
A modern scaffolding tool for creating browser extensions with ease
196 lines (166 loc) • 5.38 kB
JavaScript
// 内容脚本 - 在页面上下文中运行
// 检查是否已经注入
if (!window.contentScriptInjected) {
window.contentScriptInjected = true;
console.log('{{name}} content script loaded');
// 初始化扩展
initContentScript();
}
function initContentScript() {
// 添加扩展标识
const extensionIndicator = createExtensionIndicator();
document.body.appendChild(extensionIndicator);
// 监听来自popup的消息
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
console.log('Content script received message:', request);
switch (request.type) {
case 'GET_PAGE_INFO':
handleGetPageInfo(sendResponse);
break;
case 'HIGHLIGHT_TEXT':
handleHighlightText(request.data);
sendResponse({ success: true });
break;
case 'EXTRACT_LINKS':
handleExtractLinks(sendResponse);
break;
default:
sendResponse({ error: 'Unknown message type' });
}
return true; // 保持消息通道开放
});
// 监听键盘快捷键
document.addEventListener('keydown', handleKeyboardShortcut);
// 页面变化监听
observePageChanges();
}
function createExtensionIndicator() {
const indicator = document.createElement('div');
indicator.id = '{{name}}-indicator';
indicator.innerHTML = '🚀 {{name}} 已激活';
indicator.style.cssText = `
position: fixed;
top: 10px;
right: 10px;
background: #007bff;
color: white;
padding: 8px 12px;
border-radius: 4px;
font-size: 12px;
z-index: 9999;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
font-family: -apple-system, BlinkMacSystemFont, sans-serif;
`;
// 3秒后淡出
setTimeout(() => {
indicator.style.transition = 'opacity 0.5s';
indicator.style.opacity = '0';
setTimeout(() => indicator.remove(), 500);
}, 3000);
return indicator;
}
function handleGetPageInfo(sendResponse) {
const pageInfo = {
title: document.title,
url: window.location.href,
domain: window.location.hostname,
description: getMetaContent('description'),
keywords: getMetaContent('keywords'),
links: document.links.length,
images: document.images.length,
textLength: document.body.innerText.length
};
sendResponse(pageInfo);
}
function handleHighlightText(data) {
const { text, color = '#ffff00' } = data;
// 移除之前的高亮
removeHighlights();
if (!text) return;
// 创建正则表达式
const regex = new RegExp(text, 'gi');
// 遍历文本节点
const walker = document.createTreeWalker(
document.body,
NodeFilter.SHOW_TEXT,
{
acceptNode: (node) => {
// 跳过脚本和样式
if (node.parentNode.tagName === 'SCRIPT' ||
node.parentNode.tagName === 'STYLE' ||
node.parentNode.tagName === 'NOSCRIPT') {
return NodeFilter.FILTER_REJECT;
}
return regex.test(node.textContent) ?
NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP;
}
}
);
const textNodes = [];
let node;
while (node = walker.nextNode()) {
textNodes.push(node);
}
// 应用高亮
textNodes.forEach(textNode => {
const span = document.createElement('span');
span.className = '{{name}}-highlight';
span.style.backgroundColor = color;
span.style.padding = '2px 4px';
span.style.borderRadius = '3px';
const highlightedText = textNode.textContent.replace(
regex,
match => `<span class="{{name}}-highlight" style="background-color: ${color}; padding: 2px 4px; border-radius: 3px;">${match}</span>`
);
const wrapper = document.createElement('div');
wrapper.innerHTML = highlightedText;
const parent = textNode.parentNode;
while (wrapper.firstChild) {
parent.insertBefore(wrapper.firstChild, textNode);
}
parent.removeChild(textNode);
});
}
function handleExtractLinks(sendResponse) {
const links = Array.from(document.links).map(link => ({
text: link.textContent.trim(),
href: link.href,
external: !link.href.includes(window.location.hostname)
}));
sendResponse({ links });
}
function removeHighlights() {
const highlights = document.querySelectorAll('.{{name}}-highlight');
highlights.forEach(highlight => {
const parent = highlight.parentNode;
parent.replaceChild(document.createTextNode(highlight.textContent), highlight);
parent.normalize();
});
}
function getMetaContent(name) {
const meta = document.querySelector(`meta[name="${name}"], meta[property="og:${name}"]`);
return meta ? meta.getAttribute('content') : '';
}
function handleKeyboardShortcut(event) {
// Ctrl+Shift+H 高亮选中文本
if (event.ctrlKey && event.shiftKey && event.key === 'H') {
event.preventDefault();
const selection = window.getSelection().toString();
if (selection) {
handleHighlightText({ text: selection });
}
}
}
function observePageChanges() {
// 监听URL变化(单页应用)
let lastUrl = location.href;
new MutationObserver(() => {
const url = location.href;
if (url !== lastUrl) {
lastUrl = url;
console.log('URL changed to:', url);
// 重新初始化内容脚本功能
setTimeout(initContentScript, 1000);
}
}).observe(document, { subtree: true, childList: true });
}