gemini_watermark_cleaner/build.js

127 lines
3.7 KiB
JavaScript

import * as esbuild from 'esbuild';
import { cpSync, rmSync, existsSync, mkdirSync, watch } from 'node:fs';
import { createRequire } from 'node:module';
import { execSync } from 'child_process';
const require = createRequire(import.meta.url);
const pkg = require('./package.json');
const isProd = process.env.NODE_ENV === 'production';
let _commitHash = null;
const getCommitHash = () => {
if (_commitHash) return _commitHash;
try {
_commitHash = execSync('git rev-parse --short HEAD').toString().trim();
} catch {
_commitHash = 'unknown';
}
return _commitHash;
};
const jsBanner = `/*!
* ${pkg.name} v${pkg.version}+${getCommitHash()}
* ${pkg.description}
* (c) ${new Date().getFullYear()} ${pkg.author}
* ${pkg.repository.url?.replace(/\.git$/, '')}
* Released under the ${pkg.license} License.
*/`;
const userscriptBanner = `// ==UserScript==
// @name Gemini NanoBanana Watermark Remover
// @name:zh-CN Gemini NanoBanana 图片水印移除
// @namespace https://github.com/journey-ad
// @version 0.1.4
// @description Automatically removes watermarks from Gemini AI generated images
// @description:zh-CN 自动移除 Gemini AI 生成图像中的水印
// @icon https://www.google.com/s2/favicons?domain=gemini.google.com
// @author journey-ad
// @license MIT
// @match https://gemini.google.com/app
// @match https://gemini.google.com/app/*
// @match https://gemini.google.com/u/*/app
// @match https://gemini.google.com/u/*/app/*
// @grant GM_xmlhttpRequest
// @run-at document-end
// ==/UserScript==
`;
const copyAssetsPlugin = {
name: 'copy-assets',
setup(build) {
build.onEnd(() => {
console.log('📂 Syncing static assets...');
try {
if (!existsSync('dist/i18n')) mkdirSync('dist/i18n', { recursive: true });
cpSync('src/i18n', 'dist/i18n', { recursive: true });
cpSync('public', 'dist', { recursive: true });
} catch (err) {
console.error('❌ Asset copy failed:', err);
}
});
},
};
const commonConfig = {
bundle: true,
loader: { '.png': 'dataurl' },
minify: isProd,
logLevel: 'info',
};
// Build website - app.js
const websiteCtx = await esbuild.context({
...commonConfig,
entryPoints: ['src/app.js'],
outfile: 'dist/app.js',
platform: 'browser',
target: ['es2020'],
banner: { js: jsBanner },
sourcemap: !isProd,
plugins: [copyAssetsPlugin],
});
// Build userscript
const userscriptCtx = await esbuild.context({
...commonConfig,
entryPoints: ['src/userscript/index.js'],
format: 'iife',
outfile: 'dist/userscript/gemini-watermark-remover.user.js',
banner: { js: userscriptBanner },
minify: false
});
console.log(`🚀 Starting build process... [${isProd ? 'PRODUCTION' : 'DEVELOPMENT'}]`);
if (existsSync('dist')) rmSync('dist', { recursive: true });
mkdirSync('dist/userscript', { recursive: true });
if (isProd) {
await Promise.all([websiteCtx.rebuild(), userscriptCtx.rebuild()]);
console.log('✅ Build complete!');
process.exit(0);
} else {
await Promise.all([websiteCtx.watch(), userscriptCtx.watch()]);
const watchDir = (dir, dest) => {
let debounceTimer = null;
watch(dir, { recursive: true }, (eventType, filename) => {
if (!filename) return;
if (debounceTimer) clearTimeout(debounceTimer);
debounceTimer = setTimeout(() => {
console.log(`📂 Asset changed: ${filename}`);
try {
cpSync(dir, dest, { recursive: true });
} catch (e) {
console.error('Sync failed:', e);
}
}, 100);
});
};
watchDir('src/i18n', 'dist/i18n');
watchDir('public', 'dist');
console.log('👀 Watching for changes...');
}