安全与权限: - 站点访问权限改为 optional_host_permissions,保存配置时逐域名授权;移除 host_permissions 与 tabs,安装提示不再出现全站数据访问与浏览记录 - 主口令不再写入 storage.session,改用 IndexedDB 中不可导出的 CryptoKey 句柄恢复解锁,锁定即丢弃 - content script 注入范围只注册已授权域名,并随权限变化即时收敛 自动登录: - 支持 iframe 内的登录表单:脚本注入所有帧,逐帧按自身地址匹配配置 - 手动填充改为逐帧探测,定向发送到真正含密码框的帧 - 限流修正:只在真正触发提交后计数;判定登录成功后立即清零;达到上限时页面给出可见提示;重置判断只看启用中的配置 - SPA 重试改为 DOM 变更门控 + 退避,并单独监听已发现的 Shadow Root 工程化与文档: - 引入 ESLint(扁平配置)与 Prettier,CI 增加 lint 与 format:check - 信息类日志改为 debugLog(默认静默,chrome.storage.local.debugLog 开关) - 测试 123 → 128 用例(新增权限、iframe、限流相关用例) - README / PRIVACY / CHANGELOG 同步
46 lines
1.8 KiB
JavaScript
46 lines
1.8 KiB
JavaScript
#!/usr/bin/env node
|
||
/**
|
||
* 打包:发布构建 + 打成可直接上传 Chrome / 用于自托管自更新的 zip。
|
||
*
|
||
* 只收运行时文件,源码、脚本、部署产物(updates.xml / install-policy.reg)不入包。
|
||
*
|
||
* 用法:
|
||
* node scripts/package.mjs 构建并打包
|
||
* node scripts/package.mjs --skip-build 仅打包(复用现有 dist)
|
||
*/
|
||
import { execFileSync } from "node:child_process";
|
||
import { mkdir, readFile, rm } from "node:fs/promises";
|
||
import path from "node:path";
|
||
import { fileURLToPath, pathToFileURL } from "node:url";
|
||
import { buildAll } from "./build.mjs";
|
||
|
||
const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
||
|
||
/** 扩展包内容:manifest 及其引用的所有运行时资源 */
|
||
const PACKAGE_FILES = ["manifest.json", "popup.html", "popup.css", "icons", "_locales", "dist"];
|
||
|
||
export async function packageExtension({ skipBuild = false } = {}) {
|
||
if (!skipBuild) await buildAll({ release: true });
|
||
|
||
const manifest = JSON.parse(await readFile(path.join(ROOT, "manifest.json"), "utf8"));
|
||
const outDir = path.join(ROOT, "release");
|
||
await mkdir(outDir, { recursive: true });
|
||
|
||
const zipPath = path.join(outDir, `auto-login-v${manifest.version}.zip`);
|
||
await rm(zipPath, { force: true });
|
||
|
||
try {
|
||
execFileSync("zip", ["-r", "-q", zipPath, ...PACKAGE_FILES], { cwd: ROOT, stdio: "inherit" });
|
||
} catch (err) {
|
||
throw new Error(`打包失败(需要系统 zip 命令):${err.message}`, { cause: err });
|
||
}
|
||
|
||
console.log(`[package] v${manifest.version} → ${path.relative(ROOT, zipPath)}`);
|
||
return { version: manifest.version, zipPath };
|
||
}
|
||
|
||
const isDirectRun = process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href;
|
||
if (isDirectRun) {
|
||
await packageExtension({ skipBuild: process.argv.includes("--skip-build") });
|
||
}
|