diff --git a/web-to-ppt/background.js b/web-to-ppt/background.js index fc8e77b..43e1600 100644 --- a/web-to-ppt/background.js +++ b/web-to-ppt/background.js @@ -1,6 +1,6 @@ const CAPTURE_FILE = "capture.js"; const RUNNER_FILE = "runner.js"; -const SETTINGS_KEY = "webToPPTSettings"; +const SETTINGS_KEY = "webToPixsoSettings"; const DEFAULT_SETTINGS = { useProxy: false, concurrency: "8", @@ -10,7 +10,6 @@ const DEFAULT_SETTINGS = { const MIN_CAPTURE_WIDTH = 320; const MAX_CAPTURE_WIDTH = 3840; -// 缓存最近一次采集数据,供 popup 获取 let lastCaptureData = null; const delay = ms => new Promise(resolve => setTimeout(resolve, ms)); @@ -56,22 +55,14 @@ async function getActiveTab() { } async function runCapture(tabId, options) { - await chrome.scripting.executeScript({ - target: { tabId }, - files: [CAPTURE_FILE] - }); - await chrome.scripting.executeScript({ - target: { tabId }, - files: [RUNNER_FILE] - }); + await chrome.scripting.executeScript({ target: { tabId }, files: [CAPTURE_FILE] }); + await chrome.scripting.executeScript({ target: { tabId }, files: [RUNNER_FILE] }); const [{ result }] = await chrome.scripting.executeScript({ target: { tabId }, func: captureOptions => window.__webToPPTRunCapture(captureOptions), args: [options] }); - if (!result) { - throw new Error("页面没有返回采集结果"); - } + if (!result) throw new Error("页面没有返回采集结果"); return result; } @@ -82,9 +73,7 @@ async function getTabViewportWidth(tabId) { func: () => Math.round(window.innerWidth || document.documentElement.clientWidth || 0) }); return normalizeCaptureWidth(result, null); - } catch { - return null; - } + } catch { return null; } } async function prepareCaptureViewport(tab, requestedWidth) { @@ -92,52 +81,25 @@ async function prepareCaptureViewport(tab, requestedWidth) { const beforeViewportWidth = await getTabViewportWidth(tab.id); const noop = async () => {}; if (!targetWidth || !beforeViewportWidth || Math.abs(beforeViewportWidth - targetWidth) <= 2) { - return { - restore: noop, - requestedWidth: targetWidth || beforeViewportWidth, - beforeViewportWidth, - actualViewportWidth: beforeViewportWidth, - resizedWindow: false - }; + return { restore: noop, requestedWidth: targetWidth || beforeViewportWidth, beforeViewportWidth, actualViewportWidth: beforeViewportWidth, resizedWindow: false }; } - if (!tab.windowId || !chrome.windows?.get || !chrome.windows?.update) { throw new Error("当前浏览器不支持临时调整采集视口宽度"); } - const originalWindow = await chrome.windows.get(tab.windowId); const originalState = originalWindow.state || "normal"; - const originalBounds = { - left: originalWindow.left, - top: originalWindow.top, - width: originalWindow.width, - height: originalWindow.height - }; - + const originalBounds = { left: originalWindow.left, top: originalWindow.top, width: originalWindow.width, height: originalWindow.height }; const restore = async () => { try { - if (originalState !== "normal") { - await chrome.windows.update(tab.windowId, { state: "normal" }); - await delay(120); - } + if (originalState !== "normal") { await chrome.windows.update(tab.windowId, { state: "normal" }); await delay(120); } const restoreBounds = definedWindowBounds(originalBounds); - if (Object.keys(restoreBounds).length) { - await chrome.windows.update(tab.windowId, restoreBounds); - } - if (originalState !== "normal") { - await delay(120); - await chrome.windows.update(tab.windowId, { state: originalState }); - } + if (Object.keys(restoreBounds).length) await chrome.windows.update(tab.windowId, restoreBounds); + if (originalState !== "normal") { await delay(120); await chrome.windows.update(tab.windowId, { state: originalState }); } await delay(250); } catch {} }; - try { - if (originalState !== "normal") { - await chrome.windows.update(tab.windowId, { state: "normal" }); - await delay(250); - } - + if (originalState !== "normal") { await chrome.windows.update(tab.windowId, { state: "normal" }); await delay(250); } let currentViewportWidth = beforeViewportWidth; let currentWindow = await chrome.windows.get(tab.windowId); for (let attempt = 0; attempt < 2; attempt += 1) { @@ -149,63 +111,18 @@ async function prepareCaptureViewport(tab, requestedWidth) { if (Math.abs(currentViewportWidth - targetWidth) <= 2) break; currentWindow = await chrome.windows.get(tab.windowId); } - - if (Math.abs(currentViewportWidth - targetWidth) > 2) { - throw new Error(`采集视口未生效:目标 ${targetWidth}px,实际 ${currentViewportWidth}px`); - } - - return { - restore, - requestedWidth: targetWidth, - beforeViewportWidth, - actualViewportWidth: currentViewportWidth, - resizedWindow: true - }; - } catch (error) { - await restore(); - throw error; - } + if (Math.abs(currentViewportWidth - targetWidth) > 2) throw new Error(`采集视口未生效:目标 ${targetWidth}px,实际 ${currentViewportWidth}px`); + return { restore, requestedWidth: targetWidth, beforeViewportWidth, actualViewportWidth: currentViewportWidth, resizedWindow: true }; + } catch (error) { await restore(); throw error; } } async function captureCurrentTab(tab, settings) { const viewport = await prepareCaptureViewport(tab, settings.captureWidth); try { - const data = await runCapture(tab.id, { - ...settings, - captureWidth: viewport.requestedWidth - }); - data.capture = { - ...(data.capture || {}), - resizedWindow: viewport.resizedWindow, - usedTemporaryWindow: viewport.resizedWindow, - requestedWidth: viewport.requestedWidth || data.source?.actualViewportWidth || data.canvas?.width, - beforeViewportWidth: viewport.beforeViewportWidth, - actualViewportWidth: data.source?.actualViewportWidth || viewport.actualViewportWidth - }; + const data = await runCapture(tab.id, { ...settings, captureWidth: viewport.requestedWidth }); + data.capture = { ...(data.capture || {}), resizedWindow: viewport.resizedWindow, usedTemporaryWindow: viewport.resizedWindow, requestedWidth: viewport.requestedWidth || data.source?.actualViewportWidth || data.canvas?.width, beforeViewportWidth: viewport.beforeViewportWidth, actualViewportWidth: data.source?.actualViewportWidth || viewport.actualViewportWidth }; return data; - } finally { - await viewport.restore(); - } -} - -async function downloadCapture(data) { - const json = JSON.stringify(data, null, 2); - const encodedJson = arrayBufferToBase64(new TextEncoder().encode(json)); - const url = `data:application/json;charset=utf-8;base64,${encodedJson}`; - const title = data.source?.title || "webpage"; - const safeTitle = title - .replace(/[\\/:*?"<>|]+/g, "-") - .replace(/\s+/g, "-") - .slice(0, 64) || "webpage"; - const filename = `web-to-ppt/${safeTitle}-${Date.now()}.json`; - - await chrome.downloads.download({ - url, - filename, - saveAs: true - }); - - return filename; + } finally { await viewport.restore(); } } function arrayBufferToBase64(buffer) { @@ -220,7 +137,7 @@ function arrayBufferToBase64(buffer) { // 消息处理 chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { - // 采集并缓存数据(不下载 JSON,由 popup 直接转化下载 PPTX) + // 采集并缓存数据 if (message?.type === "WEB_TO_PPT_CAPTURE_START") { (async () => { const settings = normalizeSettings(message.options); @@ -228,24 +145,19 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { const tab = sender?.tab || await getActiveTab(); assertCaptureableTab(tab); const data = await captureCurrentTab(tab, settings); - lastCaptureData = data; // 缓存数据 - return { - ok: true, - actualViewportWidth: data.source?.actualViewportWidth, - requestedViewportWidth: data.source?.requestedViewportWidth - }; + lastCaptureData = data; + return { ok: true, actualViewportWidth: data.source?.actualViewportWidth }; })() .then(sendResponse) .catch(error => sendResponse({ ok: false, error: error.message || String(error) })); return true; } - // 获取最近一次采集数据(供 popup 转化用) + // 获取缓存数据 if (message?.type === "WEB_TO_PPT_GET_DATA") { if (lastCaptureData) { sendResponse({ ok: true, data: lastCaptureData }); } else { - // 如果没有缓存,重新采集 (async () => { const settings = normalizeSettings({}); const tab = await getActiveTab(); @@ -259,7 +171,7 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { return true; } - // 下载 PPTX(由 popup 调用,background 执行下载) + // 下载 PPTX(base64 data URL) if (message?.type === "WEB_TO_PPT_DOWNLOAD") { (async () => { const dataUrl = 'data:application/vnd.openxmlformats-officedocument.presentationml.presentation;base64,' + message.base64; @@ -274,11 +186,8 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { return false; }); -// 安装时初始化设置 chrome.runtime.onInstalled.addListener(() => { chrome.storage.local.get({ [SETTINGS_KEY]: DEFAULT_SETTINGS }).then(result => { chrome.storage.local.set({ [SETTINGS_KEY]: normalizeSettings(result[SETTINGS_KEY]) }); }); }); - -// 点击图标打开 popup(MV3 默认行为)