最后更新日期:2024.8
28 | 29 |31 | 欢迎使用DeepSeek 32 | AI浏览器扩展(以下简称"扩展")。本隐私政策旨在说明我们如何收集、使用、存储和保护您的信息。我们深知隐私的重要性,并致力于保护您的个人数据。 33 |
34 | 35 |57 | 所有数据(包括API密钥)仅存储在您的本地浏览器中。我们不在任何远程服务器上存储您的个人数据。 58 |
59 | 60 |62 | 我们不与任何第三方共享您的个人数据。您选择的文本仅用于通过DeepSeek 63 | API生成响应。 64 |
65 | 66 |68 | 我们采取适当的技术措施来保护您的信息。然而,请注意,任何互联网传输都不能保证100%的安全性。 69 |
70 | 71 |73 | 您可以随时通过删除扩展来移除所有本地存储的数据。您也可以在扩展设置中更改或删除您的API密钥。 74 |
75 | 76 |我们可能会不时更新本隐私政策。任何重大变更都会通过扩展更新通知您。
78 | 79 |如果您对本隐私政策有任何问题或疑虑,请通过以下方式联系我们:
81 |82 | deeplifestudio@gmail.com 83 |
84 | 85 | 86 | -------------------------------------------------------------------------------- /src/content/utils/focusManager.js: -------------------------------------------------------------------------------- 1 | import { popupStateManager } from './popupStateManager'; 2 | import { getPopupElement } from '../components/ShadowContainer'; 3 | 4 | function isElementEditable(element) { 5 | if (!element) return false; 6 | const tag = element.tagName; 7 | if (!tag) return false; 8 | const editableTags = ['INPUT', 'TEXTAREA', 'SELECT']; 9 | return editableTags.includes(tag) || element.isContentEditable === true; 10 | } 11 | 12 | function isPopupRenderable(popup) { 13 | if (!popup || !popup.isConnected) return false; 14 | const style = window.getComputedStyle(popup); 15 | if (style.visibility === 'hidden' || style.display === 'none' || parseFloat(style.opacity || '1') === 0) { 16 | return false; 17 | } 18 | const rect = popup.getBoundingClientRect(); 19 | return rect.width > 0 && rect.height > 0; 20 | } 21 | 22 | export function focusInputIfSafe(popup) { 23 | const targetPopup = popup || getPopupElement(); 24 | 25 | if (document.visibilityState !== 'visible') return; 26 | if (typeof document.hasFocus === 'function' && !document.hasFocus()) return; 27 | if (!isPopupRenderable(targetPopup)) return; 28 | if (popupStateManager && typeof popupStateManager.isMinimized === 'function' && popupStateManager.isMinimized()) return; 29 | 30 | const active = document.activeElement; 31 | if (isElementEditable(active)) return; 32 | 33 | const textarea = targetPopup && targetPopup.querySelector && targetPopup.querySelector('.expandable-textarea'); 34 | if (!textarea) return; 35 | 36 | const tryFocus = () => { 37 | if (!textarea || textarea.disabled) return false; 38 | try { 39 | if (typeof textarea.focus === 'function') textarea.focus({ preventScroll: true }); 40 | const len = typeof textarea.value === 'string' ? textarea.value.length : 0; 41 | if (typeof textarea.setSelectionRange === 'function') textarea.setSelectionRange(len, len); 42 | } catch (_) { 43 | if (typeof textarea.focus === 'function') textarea.focus(); 44 | } 45 | return document.activeElement === textarea; 46 | }; 47 | 48 | if (!tryFocus()) { 49 | requestAnimationFrame(() => { setTimeout(tryFocus, 120); }); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require("path"); 2 | const CopyPlugin = require("copy-webpack-plugin"); 3 | const TerserPlugin = require("terser-webpack-plugin"); 4 | const CssMinimizerPlugin = require("css-minimizer-webpack-plugin"); 5 | 6 | module.exports = { 7 | entry: "./src/content/content.js", 8 | output: { 9 | filename: "content.js", 10 | path: path.resolve(__dirname, "dist"), 11 | clean: true, 12 | publicPath: "" 13 | }, 14 | module: { 15 | rules: [ 16 | { 17 | test: /\.js$/, 18 | use: { 19 | loader: 'babel-loader', 20 | options: { 21 | presets: ['@babel/preset-env'] 22 | } 23 | }, 24 | exclude: /node_modules/ 25 | }, 26 | { 27 | // 普通 CSS 导入(注入到页面) 28 | test: /\.css$/, 29 | resourceQuery: { not: [/raw/] }, 30 | use: ["style-loader", "css-loader"], 31 | }, 32 | { 33 | // CSS 字符串导入(用于 Shadow DOM) 34 | test: /\.css$/, 35 | resourceQuery: /raw/, 36 | type: 'asset/source', 37 | }, 38 | { 39 | test: /\.(woff|woff2|eot|ttf|otf)$/i, 40 | type: 'asset/resource', 41 | generator: { 42 | filename: 'fonts/[name][ext][query]' 43 | } 44 | } 45 | ], 46 | }, 47 | plugins: [ 48 | new CopyPlugin({ 49 | patterns: [ 50 | { 51 | from: "./src/manifest.json", 52 | to: "manifest.json", 53 | transform(content) { 54 | return Buffer.from(JSON.stringify(JSON.parse(content), null, 2), 'utf-8') 55 | } 56 | }, 57 | { from: "./src/icons", to: "icons" }, 58 | { from: "./src/content/styles/style.css", to: "style.css" }, 59 | { from: "./src/popup", to: "popup" }, 60 | { from: "./src/background.js", to: "background.js" }, 61 | { from: "./src/Instructions", to: "Instructions" }, 62 | { 63 | from: "node_modules/katex/dist/fonts", 64 | to: "fonts" 65 | } 66 | ], 67 | }), 68 | ], 69 | optimization: { 70 | minimize: true, 71 | minimizer: [ 72 | new TerserPlugin({ 73 | terserOptions: { 74 | compress: { 75 | drop_console: true, // 临时开启 console 以调试根号渲染问题 76 | drop_debugger: true, 77 | passes: 2, 78 | pure_getters: true, 79 | module: true 80 | }, 81 | mangle: true, 82 | format: { 83 | comments: false, 84 | ascii_only: true 85 | } 86 | }, 87 | extractComments: false, 88 | }), 89 | new CssMinimizerPlugin(), 90 | ], 91 | }, 92 | resolve: { 93 | extensions: [".js"], 94 | }, 95 | mode: "production", 96 | }; 97 | -------------------------------------------------------------------------------- /src/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "manifest_version": 3, 3 | "name": "DeepSeek AI", 4 | "description": "DeepSeek AI Assistant is a free and open-source browser extension tool (unrelated to DeepSeek official).", 5 | "version": "3.1.5", 6 | "permissions": ["storage", "contextMenus", "scripting", "commands", "tabs"], 7 | "content_scripts": [ 8 | { 9 | "matches": ["Let AI Assistant Enhance Your Web Browsing Experience
303 |Install the extension from the Chrome Web Store
311 | 312 | 313 |Install the extension from the Edge Web Store
315 | 316 | 317 |Get Your API Key on the DeepSeek Platform
319 | 320 |• Supports Multi-turn Dialogues
342 |• Real-time Streaming Response
343 |• Supports Regenerating Answers
344 |• Draggable Window
348 |• Markdown Support
349 |• LaTeX Math Rendering
350 |• One-click Copy
351 |• Custom Language Preference
355 |• Dark Mode Auto Adaptation
356 |• Configurable Shortcuts
357 |373 | Customizable shortcuts that work anywhere: 374 |
375 |392 | Customize at 393 | chrome://extensions/shortcuts 394 | 395 |
396 |405 | If you like the DeepSeek AI extension, please rate and review it on the Chrome Web Store. We look forward to your feedback! 406 |
407 | 417 |423 | We value your privacy. DeepSeek AI extension will only send the text you select to API when necessary, and will not collect or store any other personal information. Your API key is only stored in the local browser. 424 |
425 |