Refactor and document build, dev, and extension scripts

Added detailed docstrings and comments to Python build and dev scripts, improving maintainability and clarity. Enhanced JavaScript files (background.js, content.js, popup.js, platform-detector.js, webext-compat.js) with module-level and function-level documentation. Standardized package naming in build.py and updated the GitHub Actions workflow for simplified, platform-agnostic publishing, removing platform selection input and automating release steps for Chrome, Edge, and Firefox. Improved code quality checks and test coverage in dev.py.
This commit is contained in:
xixu-me committed 2025-08-10 18:43:32 +08:00
1 parent 3019487608
commit 95bb7d56f9
8 files changed
+335 -112

No files matched your search

+84 -80
View File
@@ -1,5 +1,6 @@
name: 发布扩展到多个应用商店 name: 发布扩展到多个应用商店
# 工作流触发条件:手动触发,允许指定版本号
on: on:
workflow_dispatch: workflow_dispatch:
inputs: inputs:
@@ -7,56 +8,54 @@ on:
description: "版本号 (例如: 1.0.0)" description: "版本号 (例如: 1.0.0)"
required: true required: true
type: string type: string
platforms:
description: "发布平台"
required: true
default: "all"
type: choice
options:
- all
- chrome
- firefox
# 工作流权限设置
permissions: permissions:
contents: write contents: write # 创建 GitHub Release 需要
packages: write packages: write # 发布包需要
jobs: jobs:
build-and-publish: build-and-publish:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
# 第一步:检出源代码
- name: 检出代码 - name: 检出代码
uses: actions/checkout@v4 uses: actions/checkout@v4
# 第二步:设置 Python 环境用于构建脚本
- name: 设置 Python - name: 设置 Python
uses: actions/setup-python@v4 uses: actions/setup-python@v4
with: with:
python-version: "3.11" python-version: "3.11"
# 第三步:设置 Node.js 环境用于 JSON 验证
- name: 设置 Node.js - name: 设置 Node.js
uses: actions/setup-node@v4 uses: actions/setup-node@v4
with: with:
node-version: "18" node-version: "18"
# 第四步:验证 manifest 文件格式
- name: 验证 manifest 文件 - name: 验证 manifest 文件
run: | run: |
# 验证 manifest.json 是否为有效的 JSON # 验证 Chrome manifest.json 是否为有效的 JSON
node -e "JSON.parse(require('fs').readFileSync('manifest.json', 'utf8'))" node -e "JSON.parse(require('fs').readFileSync('manifest.json', 'utf8'))"
echo "✅ Chrome manifest.json 格式有效" echo "✅ Chrome manifest.json 格式有效"
# 验证 Firefox manifest # 验证 Firefox manifest 是否为有效的 JSON
node -e "JSON.parse(require('fs').readFileSync('manifest-firefox.json', 'utf8'))" node -e "JSON.parse(require('fs').readFileSync('manifest-firefox.json', 'utf8'))"
echo "✅ Firefox manifest.json 格式有效" echo "✅ Firefox manifest.json 格式有效"
# 第五步:设置版本号
- name: 从输入设置版本 - name: 从输入设置版本
id: version id: version
run: | run: |
# 使用手动提供的版本 # 从工作流输入获取版本号
VERSION="${{ inputs.version }}" VERSION="${{ inputs.version }}"
echo "version=$VERSION" >> $GITHUB_OUTPUT echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "手动设置版本: $VERSION" echo "手动设置版本: $VERSION"
# 第六步:更新所有配置文件中的版本号
- name: 更新 manifest 版本 - name: 更新 manifest 版本
run: | run: |
# 更新 Chrome manifest.json 中的版本 # 更新 Chrome manifest.json 中的版本
@@ -77,9 +76,10 @@ jobs:
console.log('已更新 Firefox manifest.json 版本为:', manifest.version); console.log('已更新 Firefox manifest.json 版本为:', manifest.version);
" "
# 第七步:同步更新 package.json 版本
- name: 更新 package.json 版本 - name: 更新 package.json 版本
run: | run: |
# 更新 package.json 中的版本以匹配标签 # 更新 package.json 中的版本以保持一致性
node -e " node -e "
const fs = require('fs'); const fs = require('fs');
const pkg = JSON.parse(fs.readFileSync('package.json', 'utf8')); const pkg = JSON.parse(fs.readFileSync('package.json', 'utf8'));
@@ -88,9 +88,10 @@ jobs:
console.log('已更新 package.json 版本为:', pkg.version); console.log('已更新 package.json 版本为:', pkg.version);
" "
# 第八步:提交版本更改并创建 Git 标签
- name: 提交并推送版本更新 - name: 提交并推送版本更新
run: | run: |
# 配置 git 用户信息以进行提交 # 配置 Git 用户信息用于自动提交
git config --local user.email "action@github.com" git config --local user.email "action@github.com"
git config --local user.name "GitHub Action" git config --local user.name "GitHub Action"
@@ -118,68 +119,56 @@ jobs:
run: | run: |
echo "🏗️ 开始构建扩展包..." echo "🏗️ 开始构建扩展包..."
# 运行构建脚本 # 运行构建脚本构建所有平台
if [ "${{ inputs.platforms }}" = "all" ]; then python build.py --platform all --package
python build.py --platform all --package
elif [ "${{ inputs.platforms }}" = "chrome" ]; then
python build.py --platform chrome --package
elif [ "${{ inputs.platforms }}" = "firefox" ]; then
python build.py --platform firefox --package
fi
echo "📦 扩展包构建完成" echo "📦 扩展包构建完成"
ls -la packages/ || echo "packages 目录不存在" ls -la packages/ || echo "packages 目录不存在"
ls -la build/ || echo "build 目录不存在"
- name: 运行测试 - name: 运行测试
run: | run: |
echo "🧪 运行基础测试..." echo "🧪 运行基础测试..."
python dev.py test python dev.py test
echo "� 运行代码检查..." echo "🔍 运行代码检查..."
python dev.py lint python dev.py lint
- name: 发布到 Chrome 应用商店 - name: 发布到 Chrome 应用商店
if: inputs.platforms == 'all' || inputs.platforms == 'chrome'
continue-on-error: true continue-on-error: true
id: chrome-publish id: chrome-publish
uses: mnao305/chrome-extension-upload@v5.0.0 uses: mnao305/chrome-extension-upload@v5.0.0
with: with:
file-path: packages/xget-now-chrome-v${{ steps.version.outputs.version }}.zip file-path: packages/Xget-Now_${{ steps.version.outputs.version }}.chromium.zip
extension-id: ${{ secrets.CHROME_EXTENSION_ID }} extension-id: ${{ secrets.CHROME_EXTENSION_ID }}
client-id: ${{ secrets.CHROME_CLIENT_ID }} client-id: ${{ secrets.CHROME_CLIENT_ID }}
client-secret: ${{ secrets.CHROME_CLIENT_SECRET }} client-secret: ${{ secrets.CHROME_CLIENT_SECRET }}
refresh-token: ${{ secrets.CHROME_REFRESH_TOKEN }} refresh-token: ${{ secrets.CHROME_REFRESH_TOKEN }}
publish: true # 如果只想上传而不发布,设置为 false publish: true
- name: 发布到 Microsoft Edge 加载项 - name: 发布到 Microsoft Edge 加载项
if: inputs.platforms == 'all' || inputs.platforms == 'chrome'
continue-on-error: true continue-on-error: true
id: edge-publish id: edge-publish
uses: wdzeng/edge-addon@v2 uses: wdzeng/edge-addon@v2
with: with:
product-id: ${{ secrets.EDGE_PRODUCT_ID }} product-id: ${{ secrets.EDGE_PRODUCT_ID }}
zip-path: packages/xget-now-chrome-v${{ steps.version.outputs.version }}.zip zip-path: packages/Xget-Now_${{ steps.version.outputs.version }}.chromium.zip
api-key: ${{ secrets.EDGE_API_KEY }} api-key: ${{ secrets.EDGE_API_KEY }}
client-id: ${{ secrets.EDGE_CLIENT_ID }} client-id: ${{ secrets.EDGE_CLIENT_ID }}
notes-for-certification: "自动发布 v${{ steps.version.outputs.version }} - ${{ github.sha }}" notes-for-certification: "自动发布 v${{ steps.version.outputs.version }} - ${{ github.sha }}"
- name: 准备 Firefox 发布 - name: 发布到 Firefox 附加组件
if: inputs.platforms == 'all' || inputs.platforms == 'firefox'
continue-on-error: true continue-on-error: true
id: firefox-prepare id: firefox-publish
run: | uses: browser-actions/release-firefox-addon@latest
echo "🦊 准备 Firefox 扩展发布..." with:
addon-id: ${{ secrets.FIREFOX_ADDON_ID }}
# 检查 Firefox 扩展包是否存在 addon-path: packages/Xget-Now_${{ steps.version.outputs.version }}.firefox.xpi
if [ -f "packages/xget-now-firefox-v${{ steps.version.outputs.version }}.zip" ]; then auth-api-issuer: ${{ secrets.FIREFOX_AUTH_API_ISSUER }}
echo "✅ Firefox 扩展包存在" auth-api-secret: ${{ secrets.FIREFOX_AUTH_API_SECRET }}
echo "firefox-package-exists=true" >> $GITHUB_OUTPUT approval-note: |
echo "firefox-package-path=packages/xget-now-firefox-v${{ steps.version.outputs.version }}.zip" >> $GITHUB_OUTPUT 这是一个下载加速器扩展,支持多个平台的文件下载加速。
else 源代码位于 GitHub: https://github.com/xixu-me/Xget-Now
echo "❌ Firefox 扩展包不存在" 构建说明:直接从源代码打包,无需编译或转译。
echo "firefox-package-exists=false" >> $GITHUB_OUTPUT
fi
- name: 创建 GitHub 发布 - name: 创建 GitHub 发布
uses: softprops/action-gh-release@v2 uses: softprops/action-gh-release@v2
@@ -187,8 +176,29 @@ jobs:
tag_name: v${{ steps.version.outputs.version }} tag_name: v${{ steps.version.outputs.version }}
name: Xget Now ${{ steps.version.outputs.version }} name: Xget Now ${{ steps.version.outputs.version }}
files: | files: |
packages/*.zip packages/Xget-Now_${{ steps.version.outputs.version }}.chromium.zip
packages/Xget-Now_${{ steps.version.outputs.version }}.firefox.xpi
generate_release_notes: true generate_release_notes: true
body: |
## 📦 扩展包下载
### Chrome/Chromium
- **文件**: `Xget-Now_${{ steps.version.outputs.version }}.chromium.zip`
- **支持**: Chrome、Chromium、Microsoft Edge 等基于 Chromium 的浏览器
- **Manifest**: v3
### Firefox
- **文件**: `Xget-Now_${{ steps.version.outputs.version }}.firefox.xpi`
- **支持**: Firefox 或其他基于 Firefox 的浏览器
- **Manifest**: v2
## 🚀 安装方法
详细的安装说明请参考:[手动安装指南](https://github.com/xixu-me/Xget-Now?tab=readme-ov-file#%E6%89%8B%E5%8A%A8%E5%AE%89%E8%A3%85)
## 📝 更新日志
详细的更改内容请查看下方的自动生成的发布说明。
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -197,34 +207,31 @@ jobs:
run: | run: |
echo "📊 发布结果摘要:" echo "📊 发布结果摘要:"
echo "================================" echo "================================"
echo "🏗️ 构建平台: ${{ inputs.platforms }}"
echo "📦 版本: ${{ steps.version.outputs.version }}" echo "📦 版本: ${{ steps.version.outputs.version }}"
echo "" echo ""
if [ "${{ inputs.platforms }}" = "all" ] || [ "${{ inputs.platforms }}" = "chrome" ]; then if [ "${{ steps.chrome-publish.outcome }}" = "success" ]; then
if [ "${{ steps.chrome-publish.outcome }}" = "success" ]; then echo "✅ Chrome 应用商店: 发布成功"
echo "✅ Chrome 应用商店: 发布成功" elif [ "${{ steps.chrome-publish.outcome }}" = "failure" ]; then
elif [ "${{ steps.chrome-publish.outcome }}" = "failure" ]; then echo "❌ Chrome 应用商店: 发布失败"
echo "❌ Chrome 应用商店: 发布失败" else
else echo "⚠️ Chrome 应用商店: 已跳过(缺少密钥或其他原因)"
echo "⚠️ Chrome 应用商店: 已跳过(缺少密钥)"
fi
if [ "${{ steps.edge-publish.outcome }}" = "success" ]; then
echo "✅ Microsoft Edge 加载项: 发布成功"
elif [ "${{ steps.edge-publish.outcome }}" = "failure" ]; then
echo "❌ Microsoft Edge 加载项: 发布失败"
else
echo "⚠️ Microsoft Edge 加载项: 已跳过(缺少密钥)"
fi
fi fi
if [ "${{ inputs.platforms }}" = "all" ] || [ "${{ inputs.platforms }}" = "firefox" ]; then if [ "${{ steps.edge-publish.outcome }}" = "success" ]; then
if [ "${{ steps.firefox-prepare.outputs.firefox-package-exists }}" = "true" ]; then echo "✅ Microsoft Edge 加载项: 发布成功"
echo "✅ Firefox 扩展包: 已准备就绪,需要手动提交到 Mozilla" elif [ "${{ steps.edge-publish.outcome }}" = "failure" ]; then
else echo "❌ Microsoft Edge 加载项: 发布失败"
echo "❌ Firefox 扩展包: 构建失败" else
fi echo "⚠️ Microsoft Edge 加载项: 已跳过(缺少密钥或其他原因)"
fi
if [ "${{ steps.firefox-publish.outcome }}" = "success" ]; then
echo "✅ Firefox 附加组件: 发布成功"
elif [ "${{ steps.firefox-publish.outcome }}" = "failure" ]; then
echo "❌ Firefox 附加组件: 发布失败"
else
echo "⚠️ Firefox 附加组件: 已跳过(缺少密钥或其他原因)"
fi fi
echo "" echo ""
@@ -236,16 +243,13 @@ jobs:
echo "" echo ""
echo "🎉 成功发布 Xget Now ${{ steps.version.outputs.version }}!" echo "🎉 成功发布 Xget Now ${{ steps.version.outputs.version }}!"
echo "================================" echo "================================"
echo "🔗 Chrome 应用商店: https://chrome.google.com/webstore/detail/${{ secrets.CHROME_EXTENSION_ID }}"
if [ "${{ inputs.platforms }}" = "all" ] || [ "${{ inputs.platforms }}" = "chrome" ]; then echo "🔗 Microsoft Edge 加载项: 查看发布页面获取最新信息"
echo "🔗 Chrome 应用商店: https://chrome.google.com/webstore/detail/${{ secrets.CHROME_EXTENSION_ID }}" echo "🦊 Firefox 附加组件: 查看 Mozilla Add-ons 获取最新信息"
echo "🔗 Microsoft Edge 加载项: 查看发布页面获取最新信息"
fi
if [ "${{ inputs.platforms }}" = "all" ] || [ "${{ inputs.platforms }}" = "firefox" ]; then
echo "🦊 Firefox: 手动提交到 Mozilla Add-ons(文件已准备就绪)"
fi
echo "📦 GitHub 发布: https://github.com/${{ github.repository }}/releases/tag/v${{ steps.version.outputs.version }}" echo "📦 GitHub 发布: https://github.com/${{ github.repository }}/releases/tag/v${{ steps.version.outputs.version }}"
echo "📖 安装指南: https://github.com/${{ github.repository }}#installation" echo "📖 安装指南: https://github.com/${{ github.repository }}#installation"
echo ""
echo "📁 发布的文件:"
echo " - Xget-Now_${{ steps.version.outputs.version }}.chromium.zip (Chrome/Chromium/Edge)"
echo " - Xget-Now_${{ steps.version.outputs.version }}.firefox.xpi (Firefox)"
echo "================================" echo "================================"
+14 -1
View File
@@ -1,3 +1,13 @@
/**
* Xget Now - 扩展后台脚本
*
* 功能:
* - 处理扩展设置管理
* - 监听标签页更新事件
* - 处理来自内容脚本的消息
* - 管理扩展状态和配置
*/
// 导入兼容层 // 导入兼容层
importScripts("webext-compat.js"); importScripts("webext-compat.js");
@@ -7,7 +17,10 @@ if (typeof webext === "undefined") {
console.error("WebExt compatibility layer not found"); console.error("WebExt compatibility layer not found");
} }
// 平台配置 /**
* 平台配置定义
* 支持的下载加速平台列表
*/
const PLATFORMS = { const PLATFORMS = {
// 代码托管平台 // 代码托管平台
gh: { gh: {
+85 -14
View File
@@ -1,7 +1,13 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
""" """
构建脚本,用于生成不同浏览器版本的扩展包 构建脚本,用于生成不同浏览器版本的扩展包
支持 Chrome/Chromium(Manifest V3)和 Firefox(Manifest V2)
支持平台:
- Chrome/Chromium(Manifest V3)
- Firefox(Manifest V2)
使用方法:
python build.py --platform all --package
""" """
import argparse import argparse
@@ -13,7 +19,16 @@ from pathlib import Path
def create_build_directory(platform, clean=True): def create_build_directory(platform, clean=True):
"""创建构建目录""" """
创建构建目录
Args:
platform (str): 目标平台名称 (chrome/firefox)
clean (bool): 是否清理已存在的目录
Returns:
Path: 构建目录路径
"""
build_dir = Path(f"build/{platform}") build_dir = Path(f"build/{platform}")
if clean and build_dir.exists(): if clean and build_dir.exists():
shutil.rmtree(build_dir) shutil.rmtree(build_dir)
@@ -22,7 +37,12 @@ def create_build_directory(platform, clean=True):
def copy_common_files(build_dir): def copy_common_files(build_dir):
"""复制通用文件""" """
复制通用文件到构建目录
Args:
build_dir (Path): 目标构建目录
"""
common_files = [ common_files = [
"webext-compat.js", "webext-compat.js",
"background.js", "background.js",
@@ -40,13 +60,18 @@ def copy_common_files(build_dir):
if os.path.exists(file): if os.path.exists(file):
shutil.copy2(file, build_dir) shutil.copy2(file, build_dir)
# 复制 icons 目录 # 复制图标目录
if os.path.exists("icons"): if os.path.exists("icons"):
shutil.copytree("icons", build_dir / "icons", dirs_exist_ok=True) shutil.copytree("icons", build_dir / "icons", dirs_exist_ok=True)
def build_chrome(): def build_chrome():
"""构建 Chrome 版本""" """
构建 Chrome/Chromium 版本
Returns:
Path: 构建目录路径
"""
print("构建 Chrome 版本...") print("构建 Chrome 版本...")
build_dir = create_build_directory("chrome") build_dir = create_build_directory("chrome")
@@ -64,7 +89,12 @@ def build_chrome():
def build_firefox(): def build_firefox():
"""构建 Firefox 版本""" """
构建 Firefox 版本
Returns:
Path: 构建目录路径
"""
print("构建 Firefox 版本...") print("构建 Firefox 版本...")
build_dir = create_build_directory("firefox") build_dir = create_build_directory("firefox")
@@ -74,7 +104,7 @@ def build_firefox():
# 复制 Firefox manifest # 复制 Firefox manifest
shutil.copy2("manifest-firefox.json", build_dir / "manifest.json") shutil.copy2("manifest-firefox.json", build_dir / "manifest.json")
# 修改文件为 Firefox 优化 # 优化文件以适配 Firefox
optimize_for_firefox(build_dir) optimize_for_firefox(build_dir)
print(f"Firefox 版本构建完成: {build_dir}") print(f"Firefox 版本构建完成: {build_dir}")
@@ -82,7 +112,12 @@ def build_firefox():
def optimize_for_chrome(build_dir): def optimize_for_chrome(build_dir):
"""为 Chrome 优化文件""" """
为 Chrome 优化文件
Args:
build_dir (Path): 构建目录路径
"""
# 移除 background.js 中的 importScripts 调用,因为在 Manifest V3 中不需要 # 移除 background.js 中的 importScripts 调用,因为在 Manifest V3 中不需要
bg_file = build_dir / "background.js" bg_file = build_dir / "background.js"
if bg_file.exists(): if bg_file.exists():
@@ -96,13 +131,27 @@ def optimize_for_chrome(build_dir):
def optimize_for_firefox(build_dir): def optimize_for_firefox(build_dir):
"""为 Firefox 优化文件""" """
为 Firefox 优化文件
Args:
build_dir (Path): 构建目录路径
"""
# Firefox 特有的优化可以在这里添加 # Firefox 特有的优化可以在这里添加
pass pass
def create_package(build_dir, platform): def create_package(build_dir, platform):
"""创建扩展包""" """
创建扩展包
Args:
build_dir (Path): 构建目录路径
platform (str): 目标平台名称 (chrome/firefox)
Returns:
Path: 扩展包文件路径
"""
package_dir = Path("packages") package_dir = Path("packages")
package_dir.mkdir(exist_ok=True) package_dir.mkdir(exist_ok=True)
@@ -112,11 +161,24 @@ def create_package(build_dir, platform):
manifest = json.load(f) manifest = json.load(f)
version = manifest["version"] version = manifest["version"]
package_name = f"xget-now-{platform}-v{version}.zip"
# 根据平台设置文件扩展名和命名
if platform == "chrome":
file_ext = "zip"
platform_name = "chromium"
elif platform == "firefox":
file_ext = "xpi"
platform_name = "firefox"
else:
file_ext = "zip"
platform_name = platform
package_name = f"Xget-Now_{version}.{platform_name}.{file_ext}"
package_path = package_dir / package_name package_path = package_dir / package_name
# 创建 ZIP 包 # 创建扩展包
with zipfile.ZipFile(package_path, "w", zipfile.ZIP_DEFLATED) as zipf: compression = zipfile.ZIP_DEFLATED
with zipfile.ZipFile(package_path, "w", compression) as zipf:
for file_path in build_dir.rglob("*"): for file_path in build_dir.rglob("*"):
if file_path.is_file(): if file_path.is_file():
arcname = file_path.relative_to(build_dir) arcname = file_path.relative_to(build_dir)
@@ -127,7 +189,16 @@ def create_package(build_dir, platform):
def validate_manifest(manifest_path, platform): def validate_manifest(manifest_path, platform):
"""验证 manifest 文件""" """
验证 manifest 文件格式和内容
Args:
manifest_path (str): manifest 文件路径
platform (str): 目标平台名称 (chrome/firefox)
Returns:
bool: 验证是否通过
"""
try: try:
with open(manifest_path, encoding="utf-8") as f: with open(manifest_path, encoding="utf-8") as f:
manifest = json.load(f) manifest = json.load(f)
+13 -2
View File
@@ -1,11 +1,22 @@
// 内容脚本,在支持的平台上注入下载拦截功能 /**
* Xget Now - 内容脚本
*
* 功能:
* - 在支持的平台页面上注入下载拦截功能
* - 监听页面上的下载链接点击事件
* - 将下载请求重定向到加速服务
* - 处理不同平台的特殊下载逻辑
*/
// 确保兼容层可用 // 确保兼容层可用
if (typeof webext === "undefined") { if (typeof webext === "undefined") {
console.error("WebExt compatibility layer not found in content script"); console.error("WebExt compatibility layer not found in content script");
} }
// 平台配置 /**
* 平台配置定义
* 与后台脚本保持同步的平台列表
*/
const PLATFORMS = { const PLATFORMS = {
// 代码托管平台 // 代码托管平台
gh: { gh: {
+89 -11
View File
@@ -1,6 +1,18 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
""" """
开发和测试脚本 开发和测试脚本
提供功能:
- 启动开发服务器
- 文件变化监控
- 代码质量检查
- 自动化测试
使用方法:
python dev.py test # 运行测试
python dev.py lint # 代码检查
python dev.py watch # 监控文件变化
python dev.py serve # 启动开发服务器
""" """
import http.server import http.server
@@ -12,14 +24,19 @@ import time
def start_dev_server(port=8000): def start_dev_server(port=8000):
"""启动开发服务器用于测试""" """
启动开发服务器用于测试扩展
Args:
port (int): 服务器端口号,默认 8000
"""
class Handler(http.server.SimpleHTTPRequestHandler): class Handler(http.server.SimpleHTTPRequestHandler):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, directory=os.getcwd(), **kwargs) super().__init__(*args, directory=os.getcwd(), **kwargs)
def log_message(self, format, *args): def log_message(self, format, *args):
# 简化日志输出 # 简化日志输出格式
print(f"[DEV] {format % args}") print(f"[DEV] {format % args}")
with socketserver.TCPServer(("", port), Handler) as httpd: with socketserver.TCPServer(("", port), Handler) as httpd:
@@ -32,7 +49,15 @@ def start_dev_server(port=8000):
def watch_files(): def watch_files():
"""监控文件变化并自动重新构建""" """
监控文件变化并自动重新构建
监控的文件包括:
- manifest.json / manifest-firefox.json
- JavaScript 文件 (background.js, content.js, popup.js)
- HTML 文件 (popup.html)
- 兼容层文件 (webext-compat.js)
"""
import os import os
watch_files = [ watch_files = [
@@ -84,11 +109,30 @@ def watch_files():
def run_tests(): def run_tests():
"""运行测试""" """
运行基础测试套件
测试内容:
- 必需文件存在性检查
- Manifest 文件格式和内容验证
- 平台特定配置检查
Returns:
bool: 所有测试是否通过
"""
print("运行基础测试...") print("运行基础测试...")
# 测试 manifest 文件
def test_manifest(file_path, platform): def test_manifest(file_path, platform):
"""
测试 manifest 文件
Args:
file_path (str): manifest 文件路径
platform (str): 目标平台 (chrome/firefox)
Returns:
bool: 测试是否通过
"""
try: try:
with open(file_path, encoding="utf-8") as f: with open(file_path, encoding="utf-8") as f:
manifest = json.load(f) manifest = json.load(f)
@@ -150,27 +194,61 @@ def run_tests():
def lint_code(): def lint_code():
"""代码检查""" """
执行代码质量检查
检查内容:
- API 使用规范性 (优先使用 webext 兼容层)
- 错误处理最佳实践
- 接口导出规范性
特殊处理:
- webext-compat.js: 允许直接使用原生 API
- platform-detector.js: 允许直接使用原生 API
"""
print("运行代码检查...") print("运行代码检查...")
js_files = ["background.js", "content.js", "popup.js", "webext-compat.js"] js_files = [
"background.js",
"content.js",
"popup.js",
"webext-compat.js",
"platform-detector.js",
]
for file in js_files: for file in js_files:
if os.path.exists(file): if os.path.exists(file):
print(f"检查 {file}...") print(f"检查 {file}...")
# 简单的语法检查 # 读取文件内容进行检查
with open(file, encoding="utf-8") as f: with open(file, encoding="utf-8") as f:
content = f.read() content = f.read()
# 检查常见问题 # 检查常见问题
issues = [] issues = []
if "chrome." in content and "webext." not in content: # 底层文件允许直接使用原生 API
issues.append("发现直接使用 chrome API,应使用 webext 兼容层") bottom_layer_files = ["webext-compat.js", "platform-detector.js"]
if file not in bottom_layer_files:
if "chrome." in content and "webext." not in content:
issues.append("发现直接使用 chrome API,应使用 webext 兼容层")
elif file == "webext-compat.js":
# 对于 webext-compat.js,检查是否正确导出了 webext 接口
if "window.webext" not in content and "module.exports" not in content:
issues.append("兼容层未正确导出 webext 接口")
elif file == "platform-detector.js":
# 对于 platform-detector.js,检查是否正确导出了平台检测接口
if "platformDetector" not in content:
issues.append("平台检测器未正确定义 platformDetector 接口")
# 检查错误处理
if "console.log(" in content and "console.error(" not in content: if "console.log(" in content and "console.error(" not in content:
issues.append("建议使用 console.error 处理错误") # 对于底层文件,console.warn 也是可以接受的
if file in bottom_layer_files and "console.warn(" in content:
pass # 底层文件使用 console.warn 是合理的
else:
issues.append("建议使用 console.error 处理错误")
if issues: if issues:
print(f" ⚠ {file} 发现问题:") print(f" ⚠ {file} 发现问题:")
+18 -1
View File
@@ -1,11 +1,27 @@
/** /**
* 平台特定的配置和检测 * 平台特定的配置和检测
*
* 提供浏览器平台检测和特性识别功能:
* - 检测当前运行的浏览器类型和版本
* - 识别 Manifest 版本 (V2/V3)
* - 检测移动端环境
* - 识别开发版本
*/ */
// 检测当前平台和环境 /**
* 平台检测器
* 提供浏览器环境检测的核心功能
*/
const platformDetector = { const platformDetector = {
/** /**
* 检测当前浏览器平台 * 检测当前浏览器平台
*
* @returns {Object} 平台检测结果
* @property {string} platform - 浏览器类型 (firefox/chrome/edge/opera/safari/unknown)
* @property {number} version - 浏览器主版本号
* @property {number} manifestVersion - Manifest 版本号
* @property {boolean} isMobile - 是否为移动端
* @property {boolean} isDevBuild - 是否为开发版本
*/ */
detect() { detect() {
const manifest = const manifest =
@@ -22,6 +38,7 @@ const platformDetector = {
let platform = "unknown"; let platform = "unknown";
let version = 0; let version = 0;
// 根据扩展 URL 前缀检测浏览器类型
if (extURL.startsWith("moz-extension://")) { if (extURL.startsWith("moz-extension://")) {
platform = "firefox"; platform = "firefox";
const match = /Firefox\/(\d+)/.exec(ua); const match = /Firefox\/(\d+)/.exec(ua);
+14 -1
View File
@@ -1,3 +1,13 @@
/**
* Xget Now - 弹窗脚本
*
* 功能:
* - 管理扩展设置界面
* - 处理用户交互事件
* - 同步设置到后台脚本
* - 提供平台开关控制
*/
document.addEventListener("DOMContentLoaded", async () => { document.addEventListener("DOMContentLoaded", async () => {
// 确保兼容层可用 // 确保兼容层可用
if (typeof webext === "undefined") { if (typeof webext === "undefined") {
@@ -12,6 +22,9 @@ document.addEventListener("DOMContentLoaded", async () => {
setupEventListeners(); setupEventListeners();
}); });
/**
* 加载并应用当前设置到 UI
*/
async function loadSettings() { async function loadSettings() {
try { try {
const settings = await webext.runtime.sendMessage({ const settings = await webext.runtime.sendMessage({
@@ -26,7 +39,7 @@ async function loadSettings() {
const enabledValue = settings.enabled && domainValue.trim() !== ""; const enabledValue = settings.enabled && domainValue.trim() !== "";
document.getElementById("enabledToggle").checked = enabledValue; document.getElementById("enabledToggle").checked = enabledValue;
// 更新平台切换 // 更新平台切换状态
const platformToggles = { const platformToggles = {
// 代码托管平台 // 代码托管平台
gh: document.getElementById("ghToggle"), gh: document.getElementById("ghToggle"),
+18 -2
View File
@@ -1,9 +1,25 @@
/** /**
* WebExtension API 兼容层 * WebExtension API 兼容层
* 提供跨浏览器的统一API接口 *
* 提供跨浏览器的统一 API 接口,解决不同浏览器间的差异:
* - Firefox 使用 browser API,返回 Promise
* - Chrome/Chromium 使用 chrome API,使用回调函数
* - 不同版本的 Manifest API 差异 (V2 vs V3)
*
* 功能:
* - 自动检测当前浏览器环境
* - 提供统一的 Promise 化 API 接口
* - 处理 API 调用失败的情况
* - 兼容不同浏览器的特性差异
*/ */
// 检测当前浏览器环境 /**
* 检测当前浏览器环境
*
* @returns {Object} 浏览器特性信息
* @property {number} major - 浏览器主版本号
* @property {Set<string>} soup - 浏览器特性标识集合
*/
const detectBrowser = () => { const detectBrowser = () => {
const ua = navigator.userAgent; const ua = navigator.userAgent;
const manifest = chrome.runtime.getManifest(); const manifest = chrome.runtime.getManifest();