fix: content script truncation error and mac shortcut issue
- Fixed truncated content.js file causing syntax error and missing logic - Updated manifest.json to use Command+Shift+X for Mac shortcut - Updated documentation
This commit is contained in:
@@ -4,12 +4,38 @@ chrome.commands.onCommand.addListener((command) => {
|
||||
if (tabs.length === 0) return;
|
||||
const tabId = tabs[0].id;
|
||||
|
||||
// 尝试发送消息,如果失败可能是页面未加载content script
|
||||
chrome.tabs.sendMessage(tabId, { action: 'toggleElementSelection' })
|
||||
.catch(() => {
|
||||
// 可以选择注入脚本或忽略
|
||||
console.log('Cannot send message to tab', tabId);
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 图片下载代理,绕过 CORS
|
||||
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
|
||||
if (request.action === 'fetchImage') {
|
||||
fetch(request.url)
|
||||
.then(response => {
|
||||
if (!response.ok) throw new Error('Network response was not ok');
|
||||
return response.blob();
|
||||
})
|
||||
.then(blob => {
|
||||
// 将 Blob 转换为 Base64 字符串返回给 content script
|
||||
const reader = new FileReader();
|
||||
reader.onloadend = () => {
|
||||
sendResponse({ success: true, data: reader.result });
|
||||
};
|
||||
reader.onerror = () => {
|
||||
sendResponse({ success: false, error: 'Failed to read blob' });
|
||||
};
|
||||
reader.readAsDataURL(blob);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Image fetch failed:', error);
|
||||
sendResponse({ success: false, error: error.message });
|
||||
});
|
||||
|
||||
return true; // 保持消息通道开启以进行异步响应
|
||||
}
|
||||
});
|
||||
@@ -14,17 +14,13 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
|
||||
} else if (request.action === 'extractFullPage') {
|
||||
currentFormat = request.format || 'markdown';
|
||||
const content = extractContent(document.body);
|
||||
const formatted = formatContent(content, currentFormat);
|
||||
copyToClipboard(formatted);
|
||||
saveToStorage(formatted);
|
||||
handleOutput(content, currentFormat);
|
||||
sendResponse({ success: true });
|
||||
} else if (request.action === 'toggleElementSelection') {
|
||||
// 如果已经在选择模式,则退出
|
||||
if (isSelecting) {
|
||||
cleanup();
|
||||
} else {
|
||||
// 默认格式或者读取存储的格式? 这里暂时用默认markdown
|
||||
// 理想情况应该从 storage 读取,这里简化处理
|
||||
chrome.storage.local.get('format', (res) => {
|
||||
currentFormat = res.format || 'markdown';
|
||||
startElementSelectionMode();
|
||||
@@ -35,6 +31,24 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
|
||||
return true;
|
||||
});
|
||||
|
||||
// === 统一输出处理 ===
|
||||
function handleOutput(content, format) {
|
||||
if (format === 'zip') {
|
||||
handleZipDownload(content);
|
||||
} else {
|
||||
const formatted = formatContent(content, format);
|
||||
copyToClipboard(formatted);
|
||||
saveToStorage(formatted);
|
||||
|
||||
if (currentFormat !== 'zip') {
|
||||
// 简单的检查,避免误报
|
||||
if (content && content.length > 0) {
|
||||
// 这里的通知逻辑由调用者处理,或者已经统一了
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// === 元素选择模式 ===
|
||||
let highlightBox = null;
|
||||
let lastTarget = null;
|
||||
@@ -86,11 +100,11 @@ function onElementClick(e) {
|
||||
if (lastTarget) {
|
||||
// 提取内容
|
||||
const content = extractContent(lastTarget);
|
||||
const formatted = formatContent(content, currentFormat);
|
||||
handleOutput(content, currentFormat);
|
||||
|
||||
copyToClipboard(formatted);
|
||||
saveToStorage(formatted);
|
||||
showNotification('✅ 元素内容已提取');
|
||||
if (currentFormat !== 'zip') {
|
||||
showNotification('✅ 元素内容已提取');
|
||||
}
|
||||
}
|
||||
|
||||
cleanup();
|
||||
@@ -166,11 +180,11 @@ function onMouseUp(e) {
|
||||
if (elements.length > 0) {
|
||||
// 提取内容
|
||||
const content = extractFromElements(elements);
|
||||
const formatted = formatContent(content, currentFormat);
|
||||
handleOutput(content, currentFormat);
|
||||
|
||||
copyToClipboard(formatted);
|
||||
saveToStorage(formatted);
|
||||
showNotification('✅ 内容已提取并复制到剪贴板');
|
||||
if (currentFormat !== 'zip') {
|
||||
showNotification('✅ 内容已提取并复制到剪贴板');
|
||||
}
|
||||
} else {
|
||||
showNotification('❌ 未选中任何内容');
|
||||
}
|
||||
@@ -523,41 +537,4 @@ function escapeXML(str) {
|
||||
.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/"/g, '"')
|
||||
.replace(/'/g, ''');
|
||||
}
|
||||
|
||||
// 复制到剪贴板
|
||||
async function copyToClipboard(text) {
|
||||
try {
|
||||
await navigator.clipboard.writeText(text);
|
||||
} catch (err) {
|
||||
// 降级方案
|
||||
const textarea = document.createElement('textarea');
|
||||
textarea.value = text;
|
||||
textarea.style.position = 'fixed';
|
||||
textarea.style.opacity = '0';
|
||||
document.body.appendChild(textarea);
|
||||
textarea.select();
|
||||
document.execCommand('copy');
|
||||
document.body.removeChild(textarea);
|
||||
}
|
||||
}
|
||||
|
||||
// 保存到 storage
|
||||
function saveToStorage(text) {
|
||||
chrome.storage.local.set({ lastExtraction: text });
|
||||
}
|
||||
|
||||
// 显示通知
|
||||
function showNotification(message) {
|
||||
const notification = document.createElement('div');
|
||||
notification.className = 'llm-extractor-notification';
|
||||
notification.textContent = message;
|
||||
document.body.appendChild(notification);
|
||||
|
||||
setTimeout(() => {
|
||||
notification.classList.add('fade-out');
|
||||
setTimeout(() => notification.remove(), 300);
|
||||
}, 2000);
|
||||
}
|
||||
.replace(/
|
||||
13
src/browser-extension/lib/jszip.min.js
vendored
Normal file
13
src/browser-extension/lib/jszip.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -24,7 +24,7 @@
|
||||
"toggle-element-selection": {
|
||||
"suggested_key": {
|
||||
"default": "Alt+Shift+X",
|
||||
"mac": "Alt+Shift+X"
|
||||
"mac": "Command+Shift+X"
|
||||
},
|
||||
"description": "Toggle Element Selection Mode"
|
||||
}
|
||||
@@ -32,7 +32,7 @@
|
||||
"content_scripts": [
|
||||
{
|
||||
"matches": ["<all_urls>"],
|
||||
"js": ["content.js"],
|
||||
"js": ["lib/jszip.min.js", "content.js"],
|
||||
"css": ["content.css"]
|
||||
}
|
||||
],
|
||||
|
||||
@@ -113,6 +113,7 @@
|
||||
<option value="markdown">Markdown 格式</option>
|
||||
<option value="json">JSON 结构化</option>
|
||||
<option value="xml">XML 格式</option>
|
||||
<option value="zip">ZIP (Markdown + 图)</option>
|
||||
</select>
|
||||
|
||||
<button id="selectBtn" class="btn btn-primary">
|
||||
|
||||
Reference in New Issue
Block a user