Compare commits
4 Commits
f6f3fca1c4
...
23a0e55979
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
23a0e55979 | ||
|
|
5e7bde1879 | ||
|
|
1f1b0a440f | ||
|
|
0995811155 |
10
README.md
Normal file
10
README.md
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
|
||||||
|
### ai对话常用语句
|
||||||
|
|
||||||
|
继续任务M1.3,必须严格遵守docs/README.md开发流程规范,等我验收通过后才能提交代码。如果你的上下文不够了,需要提醒我新开对话。
|
||||||
|
|
||||||
|
M1.2验收通过,提交代码。
|
||||||
|
|
||||||
|
继续开发沙拉查词项目,请先阅读 docs/README.md要求。
|
||||||
|
|
||||||
|
实现 M3.3,遵循 docs/README.md 要求。
|
||||||
12
assets/icons/icon16.png
Normal file
12
assets/icons/icon16.png
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz
|
||||||
|
AAAAdgAAAHYBTnsmCAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAFUSURB
|
||||||
|
VDiNpZM9SwNBEIafJQQLwcJCG1sLwcJCG8HKQhArwU5tf4C1v2AbtbHQylZ8rCxsLPwAg+AD+oFg
|
||||||
|
YyM2IigY8XnPze1eEg58zM7MPsy53J1zROQqUAtwTlVrHnADjAGbQNPdR8BGwG9APdAGToGJmS2a
|
||||||
|
2V1cN7NTd78OfAI3ZvZsZqOJGFR1DpgG3oGHAPeBqruvuXuzG1DVJ+AGmAcO3X0tBvLANXALjLj7
|
||||||
|
cgyo6jFwAMwDT+6+GQO5DlwCL8C4u5/EgKoeArPAs7tvxEAGwAVwBoy6+30M5Pp/Ap4E3tw9D+SB
|
||||||
|
C+AIGHH3hxjI9T8DXgJn7r6ZB3L9T4FTYOi3XyLyD7X/LyLyD7X/LyLyD7X/LyLyD7X/LyLyD7X/
|
||||||
|
LyLyD7X/LyLyD7X/LyLyD7X/LyLyD7X/LyLyD7X/LyLyD7X/LyLyD7X/LyLyD7X/LyLyD7X/LyLy
|
||||||
|
D7X/LyLyD7X/LyLyD7X/LyLyD7X/LyLyD7X/LyLyD7X/LyLyD7X/LyLyD7X/LyLyD7X/LyLyD7X/
|
||||||
|
LyLyD7X/LyLyD7X/LyLyD7X/LyLyD7X/LyLyD7X/LyLyD7X/LyLyD7X/LyLyD7X/LyLyD7X/LyLy
|
||||||
|
D7X/LyLyD7X/LyLyD7X/LyLyD7X/LyLyD7X/LyLyD7X/LyLyD7X/LyLyD7X/LyLyD7X/LyLyD7X/
|
||||||
|
LyLyD7X/LyLyD7X/LyLyD7X/LyLyD7X/LyLyD7X/LyLyD7X/LyLyD7X/LyLyD7X/LyLyD7X/LyLy
|
||||||
@ -7,7 +7,7 @@
|
|||||||
## 版本速查
|
## 版本速查
|
||||||
|
|
||||||
### 当前版本
|
### 当前版本
|
||||||
`0.0.2` → 下一目标 `0.0.3` ([M1.3](./M1.md))
|
`0.0.5` → 下一目标 `0.1.1` ([M2.1](./M2.md))
|
||||||
|
|
||||||
### 模块版本范围
|
### 模块版本范围
|
||||||
|
|
||||||
|
|||||||
@ -17,6 +17,7 @@
|
|||||||
- Vue.js ^3.4.0 (Popup/Options)
|
- Vue.js ^3.4.0 (Popup/Options)
|
||||||
- Vite ^5.0.0
|
- Vite ^5.0.0
|
||||||
- Node.js >= 18.0.0
|
- Node.js >= 18.0.0
|
||||||
|
- pnpm >= 9.0.0 (包管理器)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -64,9 +65,9 @@ M11.10完成 → 1.0.0 (正式发布)
|
|||||||
|
|
||||||
## 当前状态
|
## 当前状态
|
||||||
|
|
||||||
**当前版本**: `0.0.2`
|
**当前版本**: `0.0.5`
|
||||||
**当前进度**: 2/97 (2%)
|
**当前进度**: 5/97 (5%)
|
||||||
**下一任务**: [M1.3 构建工具配置](./M1.md#m13-构建工具配置--目标版本-0003)
|
**下一任务**: [M2.1 文本选择检测](./M2.md#m21-文本选择检测--目标版本-011)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@ -19,9 +19,9 @@
|
|||||||
|------|------|------|------|------|
|
|------|------|------|------|------|
|
||||||
| M1.1 | 0.0.1 | 项目初始化 | ✅ | 2026-02-09 |
|
| M1.1 | 0.0.1 | 项目初始化 | ✅ | 2026-02-09 |
|
||||||
| M1.2 | 0.0.2 | Manifest V3 配置 | ✅ | 2026-02-09 |
|
| M1.2 | 0.0.2 | Manifest V3 配置 | ✅ | 2026-02-09 |
|
||||||
| M1.3 | 0.0.3 | 构建工具配置 | ⬜ | - |
|
| M1.3 | 0.0.3 | 构建工具配置 | ✅ | 2026-02-09 |
|
||||||
| M1.4 | 0.0.4 | 模块间通信工具 | ⬜ | - |
|
| M1.4 | 0.0.4 | 模块间通信工具 | ✅ | 2026-02-09 |
|
||||||
| M1.5 | 0.0.5 | 开发环境验证 | ⬜ | - |
|
| M1.5 | 0.0.5 | 开发环境验证 | ✅ | 2026-02-09 |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"manifest_version": 3,
|
"manifest_version": 3,
|
||||||
"name": "沙拉查词",
|
"name": "沙拉查词",
|
||||||
"version": "0.0.2",
|
"version": "0.0.5",
|
||||||
"description": "聚合词典划词翻译",
|
"description": "聚合词典划词翻译",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
"storage",
|
"storage",
|
||||||
@ -29,15 +29,15 @@
|
|||||||
"default_popup": "src/popup/index.html",
|
"default_popup": "src/popup/index.html",
|
||||||
"default_title": "沙拉查词",
|
"default_title": "沙拉查词",
|
||||||
"default_icon": {
|
"default_icon": {
|
||||||
"16": "assets/icons/icon16.png",
|
"16": "icons/icon16.png",
|
||||||
"48": "assets/icons/icon48.png",
|
"48": "icons/icon48.png",
|
||||||
"128": "assets/icons/icon128.png"
|
"128": "icons/icon128.png"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"icons": {
|
"icons": {
|
||||||
"16": "assets/icons/icon16.png",
|
"16": "icons/icon16.png",
|
||||||
"48": "assets/icons/icon48.png",
|
"48": "icons/icon48.png",
|
||||||
"128": "assets/icons/icon128.png"
|
"128": "icons/icon128.png"
|
||||||
},
|
},
|
||||||
"options_page": "src/options/index.html"
|
"options_page": "src/options/index.html"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,9 +1,10 @@
|
|||||||
{
|
{
|
||||||
"name": "salad-dict",
|
"name": "salad-dict",
|
||||||
"version": "0.0.2",
|
"version": "0.0.5",
|
||||||
"description": "聚合词典划词翻译",
|
"description": "聚合词典划词翻译",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
"packageManager": "pnpm@9.1.2",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
@ -23,6 +24,10 @@
|
|||||||
"eslint": "^8.56.0",
|
"eslint": "^8.56.0",
|
||||||
"eslint-plugin-vue": "^9.19.0"
|
"eslint-plugin-vue": "^9.19.0"
|
||||||
},
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18.0.0",
|
||||||
|
"pnpm": ">=9.0.0"
|
||||||
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"chrome-extension",
|
"chrome-extension",
|
||||||
"dictionary",
|
"dictionary",
|
||||||
|
|||||||
2046
pnpm-lock.yaml
generated
Normal file
2046
pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
BIN
public/icons/icon128.png
Normal file
BIN
public/icons/icon128.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 411 B |
BIN
public/icons/icon16.png
Normal file
BIN
public/icons/icon16.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 411 B |
BIN
public/icons/icon48.png
Normal file
BIN
public/icons/icon48.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 411 B |
17
src/background/index.js
Normal file
17
src/background/index.js
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
// Background Service Worker
|
||||||
|
import { backgroundHandler } from '../shared/messaging.js';
|
||||||
|
|
||||||
|
console.log('[SaladDict] Background service worker started');
|
||||||
|
|
||||||
|
// 监听安装事件
|
||||||
|
chrome.runtime.onInstalled.addListener((details) => {
|
||||||
|
console.log('[SaladDict] Extension installed:', details.reason);
|
||||||
|
});
|
||||||
|
|
||||||
|
// BackgroundHandler 自动初始化消息监听
|
||||||
|
console.log('[SaladDict] Message handler initialized');
|
||||||
|
|
||||||
|
// 注册自定义消息处理器示例
|
||||||
|
backgroundHandler.register('ECHO', async (payload) => {
|
||||||
|
return { echo: payload };
|
||||||
|
});
|
||||||
31
src/content/index.js
Normal file
31
src/content/index.js
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
// Content Script
|
||||||
|
import { messaging, ping } from '../shared/messaging.js';
|
||||||
|
|
||||||
|
console.log('[SaladDict] Content script loaded');
|
||||||
|
|
||||||
|
// Ping 测试 - 验证通信链路
|
||||||
|
async function testCommunication() {
|
||||||
|
console.log('[SaladDict] Testing communication...');
|
||||||
|
|
||||||
|
// 测试 1: 简单 Ping
|
||||||
|
const pingResult = await ping();
|
||||||
|
console.log('[SaladDict] Ping test:', pingResult ? '✅ OK' : '❌ Failed');
|
||||||
|
|
||||||
|
// 测试 2: Echo 消息
|
||||||
|
try {
|
||||||
|
const echoResult = await messaging.sendToBackground('ECHO', { message: 'Hello from content' });
|
||||||
|
console.log('[SaladDict] Echo test:', echoResult);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[SaladDict] Echo test failed:', error.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 延迟执行测试,确保 background 已就绪
|
||||||
|
setTimeout(testCommunication, 1000);
|
||||||
|
|
||||||
|
// 监听来自 Background 的消息
|
||||||
|
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
||||||
|
console.log('[SaladDict] Content received message:', message);
|
||||||
|
sendResponse({ received: true });
|
||||||
|
return true;
|
||||||
|
});
|
||||||
25
src/options/index.html
Normal file
25
src/options/index.html
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>沙拉查词设置</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 24px;
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
margin: 0 0 24px 0;
|
||||||
|
font-size: 24px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>沙拉查词设置</h1>
|
||||||
|
<p>设置页面占位</p>
|
||||||
|
<script type="module" src="./index.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
6
src/options/index.js
Normal file
6
src/options/index.js
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
// Options entry
|
||||||
|
console.log('[SaladDict] Options page loaded')
|
||||||
|
|
||||||
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
console.log('[SaladDict] Options DOM ready')
|
||||||
|
})
|
||||||
27
src/popup/index.html
Normal file
27
src/popup/index.html
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>沙拉查词</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 16px;
|
||||||
|
width: 400px;
|
||||||
|
min-height: 300px;
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
margin: 0 0 16px 0;
|
||||||
|
font-size: 18px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>沙拉查词</h1>
|
||||||
|
<p>Popup 页面占位</p>
|
||||||
|
<script type="module" src="./index.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
6
src/popup/index.js
Normal file
6
src/popup/index.js
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
// Popup entry
|
||||||
|
console.log('[SaladDict] Popup opened')
|
||||||
|
|
||||||
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
console.log('[SaladDict] Popup DOM ready')
|
||||||
|
})
|
||||||
219
src/shared/messaging.js
Normal file
219
src/shared/messaging.js
Normal file
@ -0,0 +1,219 @@
|
|||||||
|
/**
|
||||||
|
* @file 模块间通信工具
|
||||||
|
* @description 封装 Content Script、Background、Popup 之间的通信
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成唯一请求ID
|
||||||
|
* @returns {string} UUID
|
||||||
|
*/
|
||||||
|
function generateUUID() {
|
||||||
|
return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息客户端 - 用于 Content Script 和 Popup
|
||||||
|
*/
|
||||||
|
class MessageClient {
|
||||||
|
/**
|
||||||
|
* 向 Background 发送消息并等待响应
|
||||||
|
* @param {string} type - 消息类型
|
||||||
|
* @param {Object} payload - 消息数据
|
||||||
|
* @param {number} timeout - 超时时间(ms)
|
||||||
|
* @returns {Promise<any>} 响应数据
|
||||||
|
*/
|
||||||
|
async sendToBackground(type, payload = {}, timeout = 5000) {
|
||||||
|
const requestId = generateUUID();
|
||||||
|
const message = {
|
||||||
|
type,
|
||||||
|
payload,
|
||||||
|
meta: {
|
||||||
|
timestamp: Date.now(),
|
||||||
|
requestId
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const timer = setTimeout(() => {
|
||||||
|
reject(new Error(`Request timeout: ${type}`));
|
||||||
|
}, timeout);
|
||||||
|
|
||||||
|
chrome.runtime.sendMessage(message, (response) => {
|
||||||
|
clearTimeout(timer);
|
||||||
|
|
||||||
|
if (chrome.runtime.lastError) {
|
||||||
|
reject(new Error(chrome.runtime.lastError.message));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response?.error) {
|
||||||
|
reject(new Error(response.error.message));
|
||||||
|
} else {
|
||||||
|
resolve(response?.payload);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ping 测试
|
||||||
|
* @returns {Promise<boolean>}
|
||||||
|
*/
|
||||||
|
async ping() {
|
||||||
|
try {
|
||||||
|
const result = await this.sendToBackground('PING');
|
||||||
|
return result?.pong === true;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[Messaging] Ping failed:', error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Background 消息处理器 - 用于 Service Worker
|
||||||
|
*/
|
||||||
|
class BackgroundHandler {
|
||||||
|
constructor() {
|
||||||
|
this.handlers = new Map();
|
||||||
|
this.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注册消息处理器
|
||||||
|
* @param {string} type - 消息类型
|
||||||
|
* @param {Function} handler - 处理函数 (payload, sender) => Promise<any>
|
||||||
|
*/
|
||||||
|
register(type, handler) {
|
||||||
|
this.handlers.set(type, handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化监听
|
||||||
|
*/
|
||||||
|
init() {
|
||||||
|
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
||||||
|
this.handleMessage(message, sender, sendResponse);
|
||||||
|
return true; // 保持消息通道开放
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理消息
|
||||||
|
*/
|
||||||
|
handleMessage(message, sender, sendResponse) {
|
||||||
|
const { type, payload, meta } = message;
|
||||||
|
const requestId = meta?.requestId;
|
||||||
|
|
||||||
|
console.log('[Background] Received:', type, payload);
|
||||||
|
|
||||||
|
// 内置 PING 处理
|
||||||
|
if (type === 'PING') {
|
||||||
|
sendResponse({
|
||||||
|
type: 'PONG',
|
||||||
|
payload: { pong: true },
|
||||||
|
meta: { requestId }
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const handler = this.handlers.get(type);
|
||||||
|
if (!handler) {
|
||||||
|
sendResponse({
|
||||||
|
type: `${type}_RESPONSE`,
|
||||||
|
error: { message: `No handler for type: ${type}` },
|
||||||
|
meta: { requestId }
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 异步处理
|
||||||
|
handler(payload, sender)
|
||||||
|
.then(result => {
|
||||||
|
sendResponse({
|
||||||
|
type: `${type}_RESPONSE`,
|
||||||
|
payload: result,
|
||||||
|
meta: { requestId }
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('[Background] Handler error:', error);
|
||||||
|
sendResponse({
|
||||||
|
type: `${type}_RESPONSE`,
|
||||||
|
error: { message: error.message },
|
||||||
|
meta: { requestId }
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 向指定 Tab 的 Content Script 发送消息
|
||||||
|
* @param {number} tabId - Tab ID
|
||||||
|
* @param {string} type - 消息类型
|
||||||
|
* @param {Object} payload - 消息数据
|
||||||
|
*/
|
||||||
|
async sendToContent(tabId, type, payload = {}) {
|
||||||
|
const requestId = generateUUID();
|
||||||
|
const message = {
|
||||||
|
type,
|
||||||
|
payload,
|
||||||
|
meta: {
|
||||||
|
timestamp: Date.now(),
|
||||||
|
requestId
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const timer = setTimeout(() => {
|
||||||
|
reject(new Error(`Send to content timeout: ${type}`));
|
||||||
|
}, 5000);
|
||||||
|
|
||||||
|
chrome.tabs.sendMessage(tabId, message, (response) => {
|
||||||
|
clearTimeout(timer);
|
||||||
|
if (chrome.runtime.lastError) {
|
||||||
|
reject(new Error(chrome.runtime.lastError.message));
|
||||||
|
} else if (response?.error) {
|
||||||
|
reject(new Error(response.error.message));
|
||||||
|
} else {
|
||||||
|
resolve(response?.payload);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 向所有 Tab 广播消息
|
||||||
|
* @param {string} type - 消息类型
|
||||||
|
* @param {Object} payload - 消息数据
|
||||||
|
*/
|
||||||
|
async broadcastToAllContent(type, payload = {}) {
|
||||||
|
const tabs = await chrome.tabs.query({});
|
||||||
|
const results = [];
|
||||||
|
|
||||||
|
for (const tab of tabs) {
|
||||||
|
if (tab.id) {
|
||||||
|
try {
|
||||||
|
const result = await this.sendToContent(tab.id, type, payload);
|
||||||
|
results.push({ tabId: tab.id, success: true, result });
|
||||||
|
} catch (error) {
|
||||||
|
results.push({ tabId: tab.id, success: false, error: error.message });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 导出单例
|
||||||
|
export const messaging = new MessageClient();
|
||||||
|
export const backgroundHandler = new BackgroundHandler();
|
||||||
|
|
||||||
|
// 兼容性导出
|
||||||
|
export const sendToBackground = (type, payload, timeout) =>
|
||||||
|
messaging.sendToBackground(type, payload, timeout);
|
||||||
|
|
||||||
|
export const sendToContent = (tabId, type, payload) =>
|
||||||
|
backgroundHandler.sendToContent(tabId, type, payload);
|
||||||
|
|
||||||
|
export const ping = () => messaging.ping();
|
||||||
19
vite.config.js
Normal file
19
vite.config.js
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import { defineConfig } from 'vite'
|
||||||
|
import vue from '@vitejs/plugin-vue'
|
||||||
|
import { crx } from '@crxjs/vite-plugin'
|
||||||
|
import manifest from './manifest.json' with { type: 'json' }
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
plugins: [
|
||||||
|
vue(),
|
||||||
|
crx({ manifest })
|
||||||
|
],
|
||||||
|
build: {
|
||||||
|
rollupOptions: {
|
||||||
|
input: {
|
||||||
|
popup: 'src/popup/index.html',
|
||||||
|
options: 'src/options/index.html'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
Loading…
x
Reference in New Issue
Block a user