feat: Add development scripts for building UserScript header

This commit is contained in:
JonasPfalzgraf 2025-07-11 18:02:09 +02:00
parent 88aeab8f29
commit ca60f67d37
3 changed files with 52 additions and 27 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 110 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

Before After
Before After

View file

@ -6,6 +6,8 @@
"module": "node", "module": "node",
"scripts": { "scripts": {
"dev": "vite build --watch --mode development", "dev": "vite build --watch --mode development",
"dev:header": "npm run build-userScriptHeader",
"dev:build": "vite build --mode development && npm run build-userScriptHeader",
"build": "vite build && npm run build-userScriptHeader", "build": "vite build && npm run build-userScriptHeader",
"build:prod": "vite build --mode production && npm run build-userScriptHeader", "build:prod": "vite build --mode production && npm run build-userScriptHeader",
"build-tooling": "tsc ./tools/userScriptHeader.ts --resolveJsonModule --esModuleInterop", "build-tooling": "tsc ./tools/userScriptHeader.ts --resolveJsonModule --esModuleInterop",

View file

@ -1,15 +1,34 @@
import * as fs from "fs"; import * as fs from 'fs';
import config from "../header.config.json"; import config from '../header.config.json';
import pkg from "../package.json"; import pkg from '../package.json';
const targetFile = "./dist/" + pkg.name + ".user.js"; // Check which file exists to determine the environment
const prodFile = `./dist/${pkg.name}.user.js`;
const devFile = `./dist/${pkg.name}.dev.user.js`;
let targetFile: string;
let environment: 'production' | 'development';
if (fs.existsSync(prodFile)) {
targetFile = prodFile;
environment = 'production';
} else if (fs.existsSync(devFile)) {
targetFile = devFile;
environment = 'development';
} else {
console.error('❌ No UserScript file found in dist/');
console.error(`Expected either: ${prodFile} or ${devFile}`);
process.exit(1);
}
console.log(`🔧 Building UserScript header for ${environment} (${targetFile})`);
/** /**
* Appends header * Appends header
* @param header * @param header
*/ */
function appendHeader(header: string) { function appendHeader(header: string) {
fs.readFile(targetFile, "utf8", (err: NodeJS.ErrnoException | null, data: string) => { fs.readFile(targetFile, 'utf8', (err: NodeJS.ErrnoException | null, data: string) => {
if (err) { if (err) {
throw err; throw err;
} }
@ -28,7 +47,7 @@ function appendHeader(header: string) {
*/ */
async function buildBase64UrlFromFile(filePath: string): Promise<string> { async function buildBase64UrlFromFile(filePath: string): Promise<string> {
const file = await fs.promises.readFile(filePath); const file = await fs.promises.readFile(filePath);
return "data:image/png;base64," + file.toString("base64"); return 'data:image/png;base64,' + file.toString('base64');
} }
/** /**
@ -38,7 +57,7 @@ async function buildBase64UrlFromFile(filePath: string): Promise<string> {
* @returns multiple entries * @returns multiple entries
*/ */
function generateMultipleEntries(type: string, array: string[]): string { function generateMultipleEntries(type: string, array: string[]): string {
let result: string = ""; let result: string = '';
if (array) { if (array) {
array.forEach((item: string) => { array.forEach((item: string) => {
result += `// ${type} ${item}\n`; result += `// ${type} ${item}\n`;
@ -53,7 +72,7 @@ function generateMultipleEntries(type: string, array: string[]): string {
* @returns string without empty lines * @returns string without empty lines
*/ */
function removeEmptyLinesFromString(string: string): string { function removeEmptyLinesFromString(string: string): string {
return string.replace(/\n\s*\n/g, "\n"); return string.replace(/\n\s*\n/g, '\n');
} }
/** /**
@ -62,30 +81,34 @@ function removeEmptyLinesFromString(string: string): string {
async function generateUserScriptHeader() { async function generateUserScriptHeader() {
// Determine environment from NODE_ENV or default to production // Determine environment from NODE_ENV or default to production
const environment = process.env.NODE_ENV === 'development' ? 'development' : 'production'; const environment = process.env.NODE_ENV === 'development' ? 'development' : 'production';
console.log(`🔧 Building UserScript header for environment: ${environment}`);
// Get environment-specific config or fallback to empty arrays // Get environment-specific config or fallback to empty arrays
const envConfig = config.environments?.[environment] || { const envConfig = config.environments?.[environment] || {
includes: [], includes: [],
excludes: [], excludes: [],
grants: [] grants: [],
}; };
const excludes = generateMultipleEntries("@exclude", envConfig.excludes); const excludes = generateMultipleEntries('@exclude', envConfig.excludes);
const requires = generateMultipleEntries("@require", config.requires); const requires = generateMultipleEntries('@require', config.requires);
const resources = generateMultipleEntries("@resource", config.resources); const resources = generateMultipleEntries('@resource', config.resources);
const connecters = generateMultipleEntries("@connect", config.connecters); const connecters = generateMultipleEntries('@connect', config.connecters);
const grants = generateMultipleEntries("@grant", envConfig.grants); const grants = generateMultipleEntries('@grant', envConfig.grants);
const matches = generateMultipleEntries("@match", config.matches);
const includes = generateMultipleEntries("@match", envConfig.includes); // Use environment-specific includes as matches, fallback to root matches if available
const antifeatures = generateMultipleEntries("@antifeature", config.antifeatures); const allMatches = envConfig.includes.length > 0 ? envConfig.includes : config.matches;
const matches = generateMultipleEntries('@match', allMatches);
// No includes needed as we use matches
const includes = '';
const antifeatures = generateMultipleEntries('@antifeature', config.antifeatures);
const base64url = await buildBase64UrlFromFile(config.iconUrl); const base64url = await buildBase64UrlFromFile(config.iconUrl);
let noframes = ""; let noframes = '';
let matchAllFrames = ""; let matchAllFrames = '';
let updateUrl = ""; let updateUrl = '';
let downloadUrl = ""; let downloadUrl = '';
let supportUrl = ""; let supportUrl = '';
if (config.noframes) { if (config.noframes) {
noframes = `// @noframes\n`; noframes = `// @noframes\n`;
@ -93,13 +116,13 @@ async function generateUserScriptHeader() {
if (config.matchAllFrames) { if (config.matchAllFrames) {
matchAllFrames = `// @matchAllFrames\n`; matchAllFrames = `// @matchAllFrames\n`;
} }
if (config.updateUrl !== "") { if (config.updateUrl !== '') {
updateUrl = `// @updateURL ${config.updateUrl}\n`; updateUrl = `// @updateURL ${config.updateUrl}\n`;
} }
if (config.downloadUrl !== "") { if (config.downloadUrl !== '') {
downloadUrl = `// @downloadURL ${config.downloadUrl}\n`; downloadUrl = `// @downloadURL ${config.downloadUrl}\n`;
} }
if (config.supportUrl !== "") { if (config.supportUrl !== '') {
supportUrl = `// @supportURL ${config.supportUrl}\n`; supportUrl = `// @supportURL ${config.supportUrl}\n`;
} }
@ -128,7 +151,7 @@ ${matchAllFrames}
`; `;
header = removeEmptyLinesFromString(header); header = removeEmptyLinesFromString(header);
header += "\n"; header += '\n';
appendHeader(header); appendHeader(header);
} }