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:
1 parent
3019487608
commit
95bb7d56f9
8 files changed
+335
-112
No files matched your search
@@ -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
@@ -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: {
|
||||||
|
|||||||
@@ -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
@@ -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: {
|
||||||
|
|||||||
@@ -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
@@ -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);
|
||||||
|
|||||||
@@ -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
@@ -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();
|
||||||
|
|||||||
Reference in new issue
Block a user