|
@@ -0,0 +1,150 @@
|
|
|
|
|
+export default defineContentScript({
|
|
|
|
|
+ matches: ["<all_urls>"],
|
|
|
|
|
+
|
|
|
|
|
+ main() {
|
|
|
|
|
+ // 辅助函数:提取背景图片URL
|
|
|
|
|
+ const extractBackgroundUrl = (element: Element): string | null => {
|
|
|
|
|
+ const computedStyle = window.getComputedStyle(element);
|
|
|
|
|
+ const backgroundImage = computedStyle.backgroundImage;
|
|
|
|
|
+
|
|
|
|
|
+ if (backgroundImage && backgroundImage !== 'none' && backgroundImage.includes('url')) {
|
|
|
|
|
+ // 处理包含转义字符的URL
|
|
|
|
|
+ const urlMatch = backgroundImage.match(/url\(["']?(.*?)["']?\)/);
|
|
|
|
|
+ if (urlMatch && urlMatch[1]) {
|
|
|
|
|
+ // 解码HTML实体
|
|
|
|
|
+ let url = urlMatch[1];
|
|
|
|
|
+ const textarea = document.createElement('textarea');
|
|
|
|
|
+ textarea.innerHTML = url;
|
|
|
|
|
+ return textarea.value;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return null;
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ // 监听来自popup的消息
|
|
|
|
|
+ browser.runtime.onMessage.addListener((request, sender, sendResponse) => {
|
|
|
|
|
+ if (request.action === "getImages") {
|
|
|
|
|
+ // 获取页面上所有图片元素
|
|
|
|
|
+ const images = Array.from(document.querySelectorAll('img'))
|
|
|
|
|
+ .map(img => ({
|
|
|
|
|
+ src: img.src,
|
|
|
|
|
+ alt: img.alt,
|
|
|
|
|
+ width: img.width,
|
|
|
|
|
+ height: img.height
|
|
|
|
|
+ }))
|
|
|
|
|
+ .filter(img => img.src);
|
|
|
|
|
+
|
|
|
|
|
+ sendResponse({ images });
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (request.action === "getImageById") {
|
|
|
|
|
+ // 根据ID获取特定图片元素
|
|
|
|
|
+ const imageElement = document.getElementById(request.imageId);
|
|
|
|
|
+
|
|
|
|
|
+ if (imageElement && imageElement.tagName.toLowerCase() === 'img') {
|
|
|
|
|
+ const image = {
|
|
|
|
|
+ src: (imageElement as HTMLImageElement).src,
|
|
|
|
|
+ alt: (imageElement as HTMLImageElement).alt,
|
|
|
|
|
+ width: (imageElement as HTMLImageElement).width,
|
|
|
|
|
+ height: (imageElement as HTMLImageElement).height
|
|
|
|
|
+ };
|
|
|
|
|
+ sendResponse({ image });
|
|
|
|
|
+ } else {
|
|
|
|
|
+ sendResponse({ image: null });
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (request.action === "getTbodyData") {
|
|
|
|
|
+ // 获取所有tbody中的数据,包括背景图片
|
|
|
|
|
+ const tables = Array.from(document.querySelectorAll('table')).map((table, tableIndex) => {
|
|
|
|
|
+ const tbodies = Array.from(table.querySelectorAll('tbody'));
|
|
|
|
|
+
|
|
|
|
|
+ return tbodies.map(tbody => {
|
|
|
|
|
+ const rows = Array.from(tbody.querySelectorAll('tr'));
|
|
|
|
|
+
|
|
|
|
|
+ return rows.map((row, rowIndex) => {
|
|
|
|
|
+ const cells = Array.from(row.querySelectorAll('td, th'));
|
|
|
|
|
+ return cells.map((cell, cellIndex) => {
|
|
|
|
|
+ // 获取单元格文本内容
|
|
|
|
|
+ const textContent = cell.textContent?.trim() || '';
|
|
|
|
|
+
|
|
|
|
|
+ // 查找单元格内所有带有背景图片的div元素
|
|
|
|
|
+ const divsWithBackground = Array.from(cell.querySelectorAll('div[style*="background-image"]'))
|
|
|
|
|
+ .map((div, divIndex) => {
|
|
|
|
|
+ const backgroundUrl = extractBackgroundUrl(div);
|
|
|
|
|
+ if (backgroundUrl) {
|
|
|
|
|
+ return {
|
|
|
|
|
+ url: backgroundUrl,
|
|
|
|
|
+ className: div.className || '',
|
|
|
|
|
+ style: div.getAttribute('style') || ''
|
|
|
|
|
+ };
|
|
|
|
|
+ }
|
|
|
|
|
+ return null;
|
|
|
|
|
+ })
|
|
|
|
|
+ .filter(item => item !== null);
|
|
|
|
|
+
|
|
|
|
|
+ // 如果找到带背景图片的div,返回包含这些信息的对象
|
|
|
|
|
+ if (divsWithBackground.length > 0) {
|
|
|
|
|
+ return {
|
|
|
|
|
+ text: textContent,
|
|
|
|
|
+ backgroundImages: divsWithBackground
|
|
|
|
|
+ };
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 检查单元格本身是否有背景图片
|
|
|
|
|
+ const cellBackgroundUrl = extractBackgroundUrl(cell);
|
|
|
|
|
+ if (cellBackgroundUrl) {
|
|
|
|
|
+ return {
|
|
|
|
|
+ text: textContent,
|
|
|
|
|
+ cellBackgroundUrl: cellBackgroundUrl
|
|
|
|
|
+ };
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 否则返回文本内容
|
|
|
|
|
+ return textContent;
|
|
|
|
|
+ });
|
|
|
|
|
+ });
|
|
|
|
|
+ }).flat();
|
|
|
|
|
+ }).flat();
|
|
|
|
|
+
|
|
|
|
|
+ // 过滤掉空表格
|
|
|
|
|
+ const nonEmptyTables = tables.filter(table => table.length > 0);
|
|
|
|
|
+
|
|
|
|
|
+ sendResponse({ tables: nonEmptyTables });
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (request.action === "getBackgroundImages") {
|
|
|
|
|
+ // 获取所有带有background-image的元素
|
|
|
|
|
+ const allElements = Array.from(document.querySelectorAll('*'));
|
|
|
|
|
+ const backgroundImages: Array<{url: string, element: string, class: string, id: string}> = [];
|
|
|
|
|
+
|
|
|
|
|
+ allElements.forEach(element => {
|
|
|
|
|
+ const computedStyle = window.getComputedStyle(element);
|
|
|
|
|
+ const backgroundImage = computedStyle.backgroundImage;
|
|
|
|
|
+
|
|
|
|
|
+ // 检查是否有background-image
|
|
|
|
|
+ if (backgroundImage && backgroundImage !== 'none' && backgroundImage.includes('url')) {
|
|
|
|
|
+ // 提取URL
|
|
|
|
|
+ const urlMatch = backgroundImage.match(/url\(["']?(.*?)["']?\)/);
|
|
|
|
|
+ if (urlMatch && urlMatch[1]) {
|
|
|
|
|
+ // 解码HTML实体
|
|
|
|
|
+ const textarea = document.createElement('textarea');
|
|
|
|
|
+ textarea.innerHTML = urlMatch[1];
|
|
|
|
|
+ const decodedUrl = textarea.value;
|
|
|
|
|
+
|
|
|
|
|
+ backgroundImages.push({
|
|
|
|
|
+ url: decodedUrl,
|
|
|
|
|
+ element: element.tagName.toLowerCase(),
|
|
|
|
|
+ class: element.className || '',
|
|
|
|
|
+ id: element.id || ''
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ sendResponse({ backgroundImages });
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+});
|