Wplace-BlueMarble/build/build.js
SwingTheVine 05893df35c
Update to 0.80.0 (#108)
* Create CONTRIBUTING.md

* Update CONTRIBUTING.md

* Update CONTRIBUTING.md

* Update CONTRIBUTING.md

* Added some install instructions

* Finished CONTRIBUTING.md

* Fixed CONTRIBUTING table

* Added SECURITY.md

* Added Computer Edge instructions

* Added Computer FireFox instructions

* Clarified where the userscript can be downloaded from

* Update to Wiki Docs

* Simplify installation instructions with one-click install links

This is because Tampermonkey automagically detect whether raw js files are being opened and redirect user to installation page. We might need a custom build action to update the links though.

- Replace manual download and drag process with direct install links
- Remove unnecessary screenshots and dashboard steps

* Fix stuff

* Fixed again. Sorry I was looking at the wrong branch T-T

* .

* Added color palette to src/utils.js

* Updated Shields to match HEAD of main

* Added build.yml RegEx for v0.0.0 version updating in README.md

* Branch sync

* Update CONTRIBUTING.md

* Added the quick guide

* Added wplace status shield

* Moved wiki to its own branch

* Added Shields from #61 and #58

* Fixed PR template

* Squashed commit of the following:

commit aca7df4189
Author: SwingTheVine <swingthevine@gmail.com>
Date:   Sat Aug 9 20:52:22 2025 -0400

    Added color palette to src/utils.js

commit 13ff8fbe33
Merge: 70eb0a2 f2d34d8
Author: SwingTheVine <swingthevine@gmail.com>
Date:   Sat Aug 9 20:49:26 2025 -0400

    Merge branch 'main' of https://github.com/SwingTheVine/Wplace-BlueMarble

commit 70eb0a26fa
Author: SwingTheVine <swingthevine@gmail.com>
Date:   Fri Aug 8 19:38:49 2025 -0400

    Update to Wiki Docs

* Fixed bug in JSDoc generation in build.js

* v0.79.0; Merge pull request #98 from SwingTheVine/documentation

Updated documentation

* Added missing dependency for minami

* Added brief description about what Blue Marble does

* v0.80.0; Added brief description about what Blue Marble does

* v0.81.0; Merge branch 'code' into main

---------

Co-authored-by: thatfrozenfrog <101154752+thatfrozenfrog@users.noreply.github.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-08-11 23:51:30 -04:00

142 lines
5.4 KiB
JavaScript

/** Builds the userscript using esbuild.
* This will:
* 1. Update the package version across the entire project
* 2. Bundle the JS files into one file (esbuild)
* 3. Bundle the CSS files into one file (esbuild)
* 4. Compress & obfuscate the bundled JS file (terner)
* 5. Runs the CSS selector mangler (cssMandler.js)
* @since 0.0.6
*/
// ES Module imports
import esbuild from 'esbuild';
import fs from 'fs';
import { execSync } from 'child_process';
import { consoleStyle } from './utils.js';
import mangleSelectors from './cssMangler.js';
import { createRequire } from 'module';
const require = createRequire(import.meta.url);
// CommonJS imports (require)
const terser = require('terser');
const isGitHub = !!process.env?.GITHUB_ACTIONS; // Is this running in a GitHub Action Workflow?'
console.log(`${consoleStyle.BLUE}Starting build...${consoleStyle.RESET}`);
// Tries to build the wiki if build.js is run in a GitHub Workflow
// if (isGitHub) {
// try {
// console.log(`Generating JSDoc...`);
// execSync(`npx jsdoc src/ -r -d docs -t node_modules/minami`, { stdio: "inherit" });
// console.log(`JSDoc built ${consoleStyle.GREEN}successfully${consoleStyle.RESET}`);
// } catch (error) {
// console.error(`${consoleStyle.RED + consoleStyle.BOLD}Failed to generate JSDoc${consoleStyle.RESET}:`, error);
// process.exit(1);
// }
// }
// Tries to bump the version
try {
const update = execSync('node build/update-version.js', { stdio: 'inherit' });
console.log(`Version updated in meta file ${consoleStyle.GREEN}successfully${consoleStyle.RESET}`);
} catch (error) {
console.error(`${consoleStyle.RED + consoleStyle.BOLD}Failed to update version number${consoleStyle.RESET}:`, error);
process.exit(1);
}
// Fetches the userscript metadata banner
const metaContent = fs.readFileSync('src/BlueMarble.meta.js', 'utf8');
// Compiles a string array of all CSS files
const cssFiles = fs.readdirSync('src/')
.filter(file => file.endsWith('.css'))
.map(file => `src/${file}`);
// Compiles the CSS files
esbuild.build({
entryPoints: cssFiles,
bundle: true,
outfile: 'dist/BlueMarble.user.css',
minify: true
});
// Compiles the JS files
const resultEsbuild = await esbuild.build({
entryPoints: ['src/main.js'], // "Infect" the files from this point (it spreads from this "patient 0")
bundle: true, // Should the code be bundled?
outfile: 'dist/BlueMarble.user.js', // The file the bundled code is exported to
format: 'iife', // What format the bundler bundles the code into
target: 'es2020', // What is the minimum version/year that should be supported? When omited, it attempts to support backwards compatability with legacy browsers
platform: 'browser', // The platform the bundled code will be operating on
legalComments: 'inline', // What level of legal comments are preserved? (Hard: none, Soft: inline)
minify: false, // Should the code be minified?
write: false, // Should we write the outfile to the disk?
}).catch(() => process.exit(1));
// Retrieves the JS file
const resultEsbuildJS = resultEsbuild.outputFiles.find(file => file.path.endsWith('.js'));
// Obfuscates the JS file
let resultTerser = await terser.minify(resultEsbuildJS.text, {
mangle: {
//toplevel: true, // Obfuscate top-level class/function names
keep_classnames: false, // Should class names be preserved?
keep_fnames: false, // Should function names be preserved?
reserved: [], // List of keywords to preserve
properties: {
// regex: /.*/, // Yes, I am aware I should be using a RegEx. Yes, like you, I am also suprised the userscript still functions
keep_quoted: true, // Should names in quotes be preserved?
reserved: [] // What properties should be preserved?
},
},
format: {
comments: 'some' // Save legal comments
},
compress: {
dead_code: isGitHub, // Should unreachable code be removed?
drop_console: isGitHub, // Should console code be removed?
drop_debugger: isGitHub, // SHould debugger code be removed?
passes: 2 // How many times terser will compress the code
}
});
// Writes the obfuscated/mangled JS code to a file
fs.writeFileSync('dist/BlueMarble.user.js', resultTerser.code, 'utf8');
let importedMapCSS = {}; // The imported CSS map
// Only import a CSS map if we are NOT in production (GitHub Workflow)
// Theoretically, if the previous map is always imported, the names would not scramble. However, the names would never decrease in number...
if (!isGitHub) {
try {
importedMapCSS = JSON.parse(fs.readFileSync('dist/BlueMarble.user.css.map.json', 'utf8'));
} catch {
console.log(`${consoleStyle.YELLOW}Warning! Could not find a CSS map to import. A 100% new CSS map will be generated...${consoleStyle.RESET}`);
}
}
// Mangles the CSS selectors
// If we are in production (GitHub Workflow), then generate the CSS mapping
const mapCSS = mangleSelectors({
inputPrefix: 'bm-',
outputPrefix: 'bm-',
pathJS: 'dist/BlueMarble.user.js',
pathCSS: 'dist/BlueMarble.user.css',
importMap: importedMapCSS,
returnMap: isGitHub
});
// If a map was returned, write it to the file
if (mapCSS) {
fs.writeFileSync('dist/BlueMarble.user.css.map.json', JSON.stringify(mapCSS, null, 2));
}
// Adds the banner
fs.writeFileSync(
'dist/BlueMarble.user.js',
metaContent + fs.readFileSync('dist/BlueMarble.user.js', 'utf8'),
'utf8'
);
console.log(`${consoleStyle.GREEN + consoleStyle.BOLD + consoleStyle.UNDERLINE}Building complete!${consoleStyle.RESET}`);