feat: 优化提取功能和用户体验

- 复制/下载后自动关闭弹窗并显示提示
- 修复CSS隔离问题,避免影响页面样式
- 使用DOM克隆替代直接操作,避免修改原始页面HTML
- 删除未使用的styles.css文件

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
ddshi 2026-01-23 15:11:22 +08:00
parent c158ff28bd
commit c8fad8c4b8
4 changed files with 45 additions and 22 deletions

View File

@ -6,26 +6,41 @@ import type { ChromeMessage, ContentScriptResponse, ExtractedContent } from '../
// 调试记录content script已加载 // 调试记录content script已加载
console.log('ReadMD: Content script loaded on', window.location.href); console.log('ReadMD: Content script loaded on', window.location.href);
// 注入高亮样式 // 注入高亮样式使用shadow DOM隔离
let highlightStyleElement: HTMLStyleElement | null = null;
function injectHighlightStyles(): void { function injectHighlightStyles(): void {
const style = document.createElement('style'); if (highlightStyleElement) return; // 防止重复注入
style.id = 'readmd-highlight-styles';
style.textContent = ` highlightStyleElement = document.createElement('style');
highlightStyleElement.id = 'readmd-highlight-styles';
highlightStyleElement.textContent = `
.readmd-highlight { .readmd-highlight {
outline: 2px solid #4CAF50 !important; outline: 2px solid #4CAF50 !important;
background-color: rgba(76, 175, 80, 0.1) !important; background-color: rgba(76, 175, 80, 0.1) !important;
} }
.readmd-selection-mode {
cursor: crosshair !important;
}
`; `;
document.head.appendChild(style); document.head.appendChild(highlightStyleElement);
} }
// 使用Readability提取主要内容 // 清理高亮样式
function cleanupHighlightStyles(): void {
if (highlightStyleElement) {
highlightStyleElement.remove();
highlightStyleElement = null;
}
// 清除页面上的高亮元素
document.querySelectorAll('.readmd-highlight').forEach(el => {
el.classList.remove('readmd-highlight');
});
}
// 使用Readability提取主要内容不修改原始DOM
function extractWithReadability(): ExtractedContent | null { function extractWithReadability(): ExtractedContent | null {
try { try {
const reader = new Readability(document); // 创建文档的克隆副本,避免修改原始页面
const docClone = document.cloneNode(true);
const reader = new Readability(docClone as Document);
const article = reader.parse(); const article = reader.parse();
if (!article) { if (!article) {
@ -114,6 +129,7 @@ function handleMessage(message: ChromeMessage, _sender: any, sendResponse: (resp
// 自动提取页面主要内容 // 自动提取页面主要内容
const content = extractWithReadability(); const content = extractWithReadability();
if (content) { if (content) {
cleanupHighlightStyles(); // 提取完成后清理样式
sendResponse({ success: true, data: content }); sendResponse({ success: true, data: content });
} else { } else {
sendResponse({ success: false, error: '无法提取页面内容' }); sendResponse({ success: false, error: '无法提取页面内容' });
@ -124,6 +140,7 @@ function handleMessage(message: ChromeMessage, _sender: any, sendResponse: (resp
// 提取用户选择的区域 // 提取用户选择的区域
const selectionContent = extractSelection(); const selectionContent = extractSelection();
if (selectionContent) { if (selectionContent) {
cleanupHighlightStyles(); // 提取完成后清理样式
sendResponse({ success: true, data: selectionContent }); sendResponse({ success: true, data: selectionContent });
} else { } else {
sendResponse({ success: false, error: '请先选择要提取的内容' }); sendResponse({ success: false, error: '请先选择要提取的内容' });
@ -134,6 +151,8 @@ function handleMessage(message: ChromeMessage, _sender: any, sendResponse: (resp
// 高亮选中的区域 // 高亮选中的区域
highlightSelection(); highlightSelection();
const previewContent = extractSelection(); const previewContent = extractSelection();
// 预览完成后清理样式
cleanupHighlightStyles();
sendResponse({ sendResponse({
success: !!previewContent, success: !!previewContent,
data: previewContent || undefined, data: previewContent || undefined,
@ -141,6 +160,12 @@ function handleMessage(message: ChromeMessage, _sender: any, sendResponse: (resp
}); });
break; break;
case 'cleanup':
// 清理样式
cleanupHighlightStyles();
sendResponse({ success: true });
break;
default: default:
sendResponse({ success: false, error: '未知操作' }); sendResponse({ success: false, error: '未知操作' });
} }

View File

@ -1,10 +0,0 @@
/* Content Script Styles */
.readmd-highlight {
outline: 2px solid #4CAF50 !important;
background-color: rgba(76, 175, 80, 0.1) !important;
}
.readmd-selection-mode {
cursor: crosshair !important;
}

View File

@ -68,6 +68,10 @@ export function Popup() {
}); });
await copyToClipboard(markdown); await copyToClipboard(markdown);
showStatus('success', '已复制到剪贴板!'); showStatus('success', '已复制到剪贴板!');
// 1秒后关闭弹窗
setTimeout(() => {
window.close();
}, 1000);
} catch { } catch {
showStatus('error', '复制失败'); showStatus('error', '复制失败');
} }
@ -95,7 +99,11 @@ export function Popup() {
}); });
URL.revokeObjectURL(url); URL.revokeObjectURL(url);
showStatus('success', '下载完成!'); showStatus('success', '开始下载...');
// 1秒后关闭弹窗
setTimeout(() => {
window.close();
}, 1000);
} catch { } catch {
showStatus('error', '下载失败'); showStatus('error', '下载失败');
} }

View File

@ -24,7 +24,7 @@ export interface UserSettings {
// Chrome消息类型 // Chrome消息类型
export interface ChromeMessage { export interface ChromeMessage {
action: 'extract' | 'extractSelection' | 'preview' | 'copy' | 'download'; action: 'extract' | 'extractSelection' | 'preview' | 'cleanup' | 'copy' | 'download';
options?: ExtractOptions; options?: ExtractOptions;
} }