Grunt formatting restore

This commit is contained in:
C85297 2026-02-03 11:55:08 +00:00
parent 8a504e7d75
commit 75650dc9b2
No known key found for this signature in database

View File

@ -2,13 +2,11 @@
const webpack = require("webpack"); const webpack = require("webpack");
const HtmlWebpackPlugin = require("html-webpack-plugin"); const HtmlWebpackPlugin = require("html-webpack-plugin");
const BundleAnalyzerPlugin = const BundleAnalyzerPlugin = require("webpack-bundle-analyzer").BundleAnalyzerPlugin;
require("webpack-bundle-analyzer").BundleAnalyzerPlugin;
const glob = require("glob"); const glob = require("glob");
const path = require("path"); const path = require("path");
const nodeFlags = const nodeFlags = "--experimental-modules --experimental-json-modules --experimental-specifier-resolution=node --no-warnings --no-deprecation";
"--experimental-modules --experimental-json-modules --experimental-specifier-resolution=node --no-warnings --no-deprecation";
/** /**
* Grunt configuration for building the app in various formats. * Grunt configuration for building the app in various formats.
@ -23,98 +21,56 @@ module.exports = function (grunt) {
grunt.file.preserveBOM = false; grunt.file.preserveBOM = false;
// Tasks // Tasks
grunt.registerTask( grunt.registerTask("dev",
"dev",
"A persistent task which creates a development build whenever source files are modified.", "A persistent task which creates a development build whenever source files are modified.",
["clean:dev", "clean:config", "exec:generateConfig", "concurrent:dev"], ["clean:dev", "clean:config", "exec:generateConfig", "concurrent:dev"]);
);
grunt.registerTask( grunt.registerTask("prod",
"prod",
"Creates a production-ready build. Use the --msg flag to add a compile message.", "Creates a production-ready build. Use the --msg flag to add a compile message.",
[ [
"eslint", "eslint", "clean:prod", "clean:config", "exec:generateConfig", "findModules", "webpack:web",
"clean:prod", "copy:standalone", "zip:standalone", "clean:standalone", "exec:calcDownloadHash", "chmod"
"clean:config", ]);
"exec:generateConfig",
"findModules",
"webpack:web",
"copy:standalone",
"zip:standalone",
"clean:standalone",
"exec:calcDownloadHash",
"chmod",
],
);
grunt.registerTask( grunt.registerTask("node",
"node",
"Compiles CyberChef into a single NodeJS module.", "Compiles CyberChef into a single NodeJS module.",
[ [
"clean:node", "clean:node", "clean:config", "clean:nodeConfig", "exec:generateConfig", "exec:generateNodeIndex"
"clean:config", ]);
"clean:nodeConfig",
"exec:generateConfig",
"exec:generateNodeIndex",
],
);
grunt.registerTask( grunt.registerTask("configTests",
"configTests",
"A task which configures config files in preparation for tests to be run. Use `npm test` to run tests.", "A task which configures config files in preparation for tests to be run. Use `npm test` to run tests.",
[ [
"clean:config", "clean:config", "clean:nodeConfig", "exec:generateConfig", "exec:generateNodeIndex"
"clean:nodeConfig", ]);
"exec:generateConfig",
"exec:generateNodeIndex",
],
);
grunt.registerTask( grunt.registerTask("testui",
"testui",
"A task which runs all the UI tests in the tests directory. The prod task must already have been run.", "A task which runs all the UI tests in the tests directory. The prod task must already have been run.",
["connect:prod", "exec:browserTests"], ["connect:prod", "exec:browserTests"]);
);
grunt.registerTask( grunt.registerTask("testnodeconsumer",
"testnodeconsumer",
"A task which checks whether consuming CJS and ESM apps work with the CyberChef build", "A task which checks whether consuming CJS and ESM apps work with the CyberChef build",
[ ["exec:setupNodeConsumers", "exec:testCJSNodeConsumer", "exec:testESMNodeConsumer", "exec:teardownNodeConsumers"]);
"exec:setupNodeConsumers",
"exec:testCJSNodeConsumer",
"exec:testESMNodeConsumer",
"exec:teardownNodeConsumers",
],
);
grunt.registerTask("default", "Lints the code base", [ grunt.registerTask("default",
"eslint", "Lints the code base",
"exec:repoSize", ["eslint", "exec:repoSize"]);
]);
grunt.registerTask("lint", "eslint"); grunt.registerTask("lint", "eslint");
grunt.registerTask( grunt.registerTask("findModules",
"findModules",
"Finds all generated modules and updates the entry point list for Webpack", "Finds all generated modules and updates the entry point list for Webpack",
function (arg1, arg2) { function(arg1, arg2) {
const moduleEntryPoints = listEntryModules(); const moduleEntryPoints = listEntryModules();
grunt.log.writeln( grunt.log.writeln(`Found ${Object.keys(moduleEntryPoints).length} modules.`);
`Found ${Object.keys(moduleEntryPoints).length} modules.`,
); grunt.config.set("webpack.web.entry",
Object.assign({
main: "./src/web/index.js"
}, moduleEntryPoints));
});
grunt.config.set(
"webpack.web.entry",
Object.assign(
{
main: "./src/web/index.js",
},
moduleEntryPoints,
),
);
},
);
// Load tasks provided by each plugin // Load tasks provided by each plugin
grunt.loadNpmTasks("grunt-eslint"); grunt.loadNpmTasks("grunt-eslint");
@ -128,6 +84,7 @@ module.exports = function (grunt) {
grunt.loadNpmTasks("grunt-contrib-connect"); grunt.loadNpmTasks("grunt-contrib-connect");
grunt.loadNpmTasks("grunt-zip"); grunt.loadNpmTasks("grunt-zip");
// Project configuration // Project configuration
const compileYear = grunt.template.today("UTC:yyyy"), const compileYear = grunt.template.today("UTC:yyyy"),
compileTime = grunt.template.today("UTC:dd/mm/yyyy HH:MM:ss") + " UTC", compileTime = grunt.template.today("UTC:dd/mm/yyyy HH:MM:ss") + " UTC",
@ -136,9 +93,7 @@ module.exports = function (grunt) {
BUILD_CONSTANTS = { BUILD_CONSTANTS = {
COMPILE_YEAR: JSON.stringify(compileYear), COMPILE_YEAR: JSON.stringify(compileYear),
COMPILE_TIME: JSON.stringify(compileTime), COMPILE_TIME: JSON.stringify(compileTime),
COMPILE_MSG: JSON.stringify( COMPILE_MSG: JSON.stringify(grunt.option("compile-msg") || grunt.option("msg") || ""),
grunt.option("compile-msg") || grunt.option("msg") || "",
),
PKG_VERSION: JSON.stringify(pkg.version), PKG_VERSION: JSON.stringify(pkg.version),
}, },
moduleEntryPoints = listEntryModules(), moduleEntryPoints = listEntryModules(),
@ -151,26 +106,20 @@ module.exports = function (grunt) {
return { return {
mode: "production", mode: "production",
target: "web", target: "web",
entry: Object.assign( entry: Object.assign({
{ main: "./src/web/index.js"
main: "./src/web/index.js", }, moduleEntryPoints),
},
moduleEntryPoints,
),
output: { output: {
path: __dirname + "/build/prod", path: __dirname + "/build/prod",
filename: (chunkData) => { filename: chunkData => {
return chunkData.chunk.name === "main" return chunkData.chunk.name === "main" ? "assets/[name].js": "[name].js";
? "assets/[name].js"
: "[name].js";
}, },
globalObject: "this", globalObject: "this"
}, },
resolve: { resolve: {
alias: { alias: {
"./config/modules/OpModules.mjs": "./config/modules/OpModules.mjs": "./config/modules/Default.mjs"
"./config/modules/Default.mjs", }
},
}, },
plugins: [ plugins: [
new webpack.DefinePlugin(BUILD_CONSTANTS), new webpack.DefinePlugin(BUILD_CONSTANTS),
@ -185,29 +134,29 @@ module.exports = function (grunt) {
removeComments: true, removeComments: true,
collapseWhitespace: true, collapseWhitespace: true,
minifyJS: true, minifyJS: true,
minifyCSS: true, minifyCSS: true
}, }
}), }),
new BundleAnalyzerPlugin({ new BundleAnalyzerPlugin({
analyzerMode: "static", analyzerMode: "static",
reportFilename: "BundleAnalyzerReport.html", reportFilename: "BundleAnalyzerReport.html",
openAnalyzer: false, openAnalyzer: false
}), }),
], ]
}; };
}; };
/** /**
* Generates an entry list for all the modules. * Generates an entry list for all the modules.
*/ */
function listEntryModules() { function listEntryModules() {
const entryModules = {}; const entryModules = {};
glob.sync("./src/core/config/modules/*.mjs").forEach((file) => { glob.sync("./src/core/config/modules/*.mjs").forEach(file => {
const basename = path.basename(file); const basename = path.basename(file);
if (basename !== "Default.mjs" && basename !== "OpModules.mjs") if (basename !== "Default.mjs" && basename !== "OpModules.mjs")
entryModules["modules/" + basename.split(".mjs")[0]] = entryModules["modules/" + basename.split(".mjs")[0]] = path.resolve(file);
path.resolve(file);
}); });
return entryModules; return entryModules;
@ -225,14 +174,12 @@ module.exports = function (grunt) {
if (!win) { if (!win) {
return cmds.join(";"); return cmds.join(";");
} }
return ( return cmds
cmds // && means that subsequent commands will not be executed if the
// && means that subsequent commands will not be executed if the // previous one fails. & would coninue on a fail
// previous one fails. & would coninue on a fail .join("&&")
.join("&&") // Windows does not support \n properly
// Windows does not support \n properly .replace(/\n/g, "\\n");
.replace(/\n/g, "\\n")
);
} }
grunt.initConfig({ grunt.initConfig({
@ -240,24 +187,13 @@ module.exports = function (grunt) {
dev: ["build/dev/*"], dev: ["build/dev/*"],
prod: ["build/prod/*"], prod: ["build/prod/*"],
node: ["build/node/*"], node: ["build/node/*"],
config: [ config: ["src/core/config/OperationConfig.json", "src/core/config/modules/*", "src/code/operations/index.mjs"],
"src/core/config/OperationConfig.json", nodeConfig: ["src/node/index.mjs", "src/node/config/OperationConfig.json"],
"src/core/config/modules/*", standalone: ["build/prod/CyberChef*.html"]
"src/code/operations/index.mjs",
],
nodeConfig: [
"src/node/index.mjs",
"src/node/config/OperationConfig.json",
],
standalone: ["build/prod/CyberChef*.html"],
}, },
eslint: { eslint: {
configs: ["*.{js,mjs}"], configs: ["*.{js,mjs}"],
core: [ core: ["src/core/**/*.{js,mjs}", "!src/core/vendor/**/*", "!src/core/operations/legacy/**/*"],
"src/core/**/*.{js,mjs}",
"!src/core/vendor/**/*",
"!src/core/operations/legacy/**/*",
],
web: ["src/web/**/*.{js,mjs}", "!src/web/static/**/*"], web: ["src/web/**/*.{js,mjs}", "!src/web/static/**/*"],
node: ["src/node/**/*.{js,mjs}"], node: ["src/node/**/*.{js,mjs}"],
tests: ["tests/**/*.{js,mjs}"], tests: ["tests/**/*.{js,mjs}"],
@ -272,25 +208,21 @@ module.exports = function (grunt) {
start: { start: {
mode: "development", mode: "development",
target: "web", target: "web",
entry: Object.assign( entry: Object.assign({
{ main: "./src/web/index.js"
main: "./src/web/index.js", }, moduleEntryPoints),
},
moduleEntryPoints,
),
resolve: { resolve: {
alias: { alias: {
"./config/modules/OpModules.mjs": "./config/modules/OpModules.mjs": "./config/modules/Default.mjs"
"./config/modules/Default.mjs", }
},
}, },
devServer: { devServer: {
port: grunt.option("port") || 8080, port: grunt.option("port") || 8080,
client: { client: {
logging: "error", logging: "error",
overlay: true, overlay: true
}, },
hot: "only", hot: "only"
}, },
plugins: [ plugins: [
new webpack.DefinePlugin(BUILD_CONSTANTS), new webpack.DefinePlugin(BUILD_CONSTANTS),
@ -301,9 +233,9 @@ module.exports = function (grunt) {
compileYear: compileYear, compileYear: compileYear,
compileTime: compileTime, compileTime: compileTime,
version: pkg.version, version: pkg.version,
}), })
], ]
}, }
}, },
zip: { zip: {
standalone: { standalone: {
@ -313,16 +245,16 @@ module.exports = function (grunt) {
"!build/prod/index.html", "!build/prod/index.html",
"!build/prod/BundleAnalyzerReport.html", "!build/prod/BundleAnalyzerReport.html",
], ],
dest: `build/prod/CyberChef_v${pkg.version}.zip`, dest: `build/prod/CyberChef_v${pkg.version}.zip`
}, }
}, },
connect: { connect: {
prod: { prod: {
options: { options: {
port: grunt.option("port") || 8000, port: grunt.option("port") || 8000,
base: "build/prod/", base: "build/prod/"
}, }
}, }
}, },
copy: { copy: {
ghPages: { ghPages: {
@ -330,86 +262,70 @@ module.exports = function (grunt) {
process: function (content, srcpath) { process: function (content, srcpath) {
if (srcpath.indexOf("index.html") >= 0) { if (srcpath.indexOf("index.html") >= 0) {
// Add Google Analytics code to index.html // Add Google Analytics code to index.html
content = content.replace( content = content.replace("</body></html>",
"</body></html>", grunt.file.read("src/web/static/ga.html") + "</body></html>");
grunt.file.read("src/web/static/ga.html") +
"</body></html>",
);
// Add Structured Data for SEO // Add Structured Data for SEO
content = content.replace( content = content.replace("</head>",
"</head>",
"<script type='application/ld+json'>" + "<script type='application/ld+json'>" +
JSON.stringify( JSON.stringify(JSON.parse(grunt.file.read("src/web/static/structuredData.json"))) +
JSON.parse( "</script></head>");
grunt.file.read(
"src/web/static/structuredData.json",
),
),
) +
"</script></head>",
);
return grunt.template.process(content, srcpath); return grunt.template.process(content, srcpath);
} else { } else {
return content; return content;
} }
}, },
noProcess: ["**", "!**/*.html"], noProcess: ["**", "!**/*.html"]
}, },
files: [ files: [
{ {
src: ["build/prod/index.html"], src: ["build/prod/index.html"],
dest: "build/prod/index.html", dest: "build/prod/index.html"
}, }
], ]
}, },
standalone: { standalone: {
options: { options: {
process: function (content, srcpath) { process: function (content, srcpath) {
if (srcpath.indexOf("index.html") >= 0) { if (srcpath.indexOf("index.html") >= 0) {
// Replace download link with version number // Replace download link with version number
content = content.replace( content = content.replace(/<a [^>]+>Download CyberChef.+?<\/a>/,
/<a [^>]+>Download CyberChef.+?<\/a>/, `<span>Version ${pkg.version}</span>`);
`<span>Version ${pkg.version}</span>`,
);
return grunt.template.process(content, srcpath); return grunt.template.process(content, srcpath);
} else { } else {
return content; return content;
} }
}, },
noProcess: ["**", "!**/*.html"], noProcess: ["**", "!**/*.html"]
}, },
files: [ files: [
{ {
src: ["build/prod/index.html"], src: ["build/prod/index.html"],
dest: `build/prod/CyberChef_v${pkg.version}.html`, dest: `build/prod/CyberChef_v${pkg.version}.html`
}, }
], ]
}, }
}, },
chmod: { chmod: {
build: { build: {
options: { options: {
mode: "755", mode: "755",
}, },
src: ["build/**/*", "build/"], src: ["build/**/*", "build/"]
}, }
}, },
watch: { watch: {
config: { config: {
files: [ files: ["src/core/operations/**/*", "!src/core/operations/index.mjs"],
"src/core/operations/**/*", tasks: ["exec:generateNodeIndex", "exec:generateConfig"]
"!src/core/operations/index.mjs", }
],
tasks: ["exec:generateNodeIndex", "exec:generateConfig"],
},
}, },
concurrent: { concurrent: {
dev: ["watch:config", "webpack-dev-server:start"], dev: ["watch:config", "webpack-dev-server:start"],
options: { options: {
logConcurrentOutput: true, logConcurrentOutput: true
}, }
}, },
exec: { exec: {
calcDownloadHash: { calcDownloadHash: {
@ -418,12 +334,12 @@ module.exports = function (grunt) {
case "darwin": case "darwin":
return chainCommands([ return chainCommands([
`shasum -a 256 build/prod/CyberChef_v${pkg.version}.zip | awk '{print $1;}' > build/prod/sha256digest.txt`, `shasum -a 256 build/prod/CyberChef_v${pkg.version}.zip | awk '{print $1;}' > build/prod/sha256digest.txt`,
`sed -i '' -e "s/DOWNLOAD_HASH_PLACEHOLDER/$(cat build/prod/sha256digest.txt)/" build/prod/index.html`, `sed -i '' -e "s/DOWNLOAD_HASH_PLACEHOLDER/$(cat build/prod/sha256digest.txt)/" build/prod/index.html`
]); ]);
default: default:
return chainCommands([ return chainCommands([
`sha256sum build/prod/CyberChef_v${pkg.version}.zip | awk '{print $1;}' > build/prod/sha256digest.txt`, `sha256sum build/prod/CyberChef_v${pkg.version}.zip | awk '{print $1;}' > build/prod/sha256digest.txt`,
`sed -i -e "s/DOWNLOAD_HASH_PLACEHOLDER/$(cat build/prod/sha256digest.txt)/" build/prod/index.html`, `sed -i -e "s/DOWNLOAD_HASH_PLACEHOLDER/$(cat build/prod/sha256digest.txt)/" build/prod/index.html`
]); ]);
} }
}, },
@ -431,16 +347,16 @@ module.exports = function (grunt) {
repoSize: { repoSize: {
command: chainCommands([ command: chainCommands([
"git ls-files | wc -l | xargs printf '\n%b\ttracked files\n'", "git ls-files | wc -l | xargs printf '\n%b\ttracked files\n'",
"du -hs | egrep -o '^[^\t]*' | xargs printf '%b\trepository size\n'", "du -hs | egrep -o '^[^\t]*' | xargs printf '%b\trepository size\n'"
]), ]),
stderr: false, stderr: false
}, },
cleanGit: { cleanGit: {
command: "git gc --prune=now --aggressive", command: "git gc --prune=now --aggressive"
}, },
sitemap: { sitemap: {
command: `node ${nodeFlags} src/web/static/sitemap.mjs > build/prod/sitemap.xml`, command: `node ${nodeFlags} src/web/static/sitemap.mjs > build/prod/sitemap.xml`,
sync: true, sync: true
}, },
generateConfig: { generateConfig: {
command: chainCommands([ command: chainCommands([
@ -448,20 +364,20 @@ module.exports = function (grunt) {
"echo [] > src/core/config/OperationConfig.json", "echo [] > src/core/config/OperationConfig.json",
`node ${nodeFlags} src/core/config/scripts/generateOpsIndex.mjs`, `node ${nodeFlags} src/core/config/scripts/generateOpsIndex.mjs`,
`node ${nodeFlags} src/core/config/scripts/generateConfig.mjs`, `node ${nodeFlags} src/core/config/scripts/generateConfig.mjs`,
"echo '--- Config scripts finished. ---\n'", "echo '--- Config scripts finished. ---\n'"
]), ]),
sync: true, sync: true
}, },
generateNodeIndex: { generateNodeIndex: {
command: chainCommands([ command: chainCommands([
"echo '\n--- Regenerating node index ---'", "echo '\n--- Regenerating node index ---'",
`node ${nodeFlags} src/node/config/scripts/generateNodeIndex.mjs`, `node ${nodeFlags} src/node/config/scripts/generateNodeIndex.mjs`,
"echo '--- Node index generated. ---\n'", "echo '--- Node index generated. ---\n'"
]), ]),
sync: true, sync: true
}, },
browserTests: { browserTests: {
command: "./node_modules/.bin/nightwatch --env prod", command: "./node_modules/.bin/nightwatch --env prod"
}, },
setupNodeConsumers: { setupNodeConsumers: {
command: chainCommands([ command: chainCommands([
@ -470,14 +386,14 @@ module.exports = function (grunt) {
`mkdir ${nodeConsumerTestPath}`, `mkdir ${nodeConsumerTestPath}`,
`cp tests/node/consumers/* ${nodeConsumerTestPath}`, `cp tests/node/consumers/* ${nodeConsumerTestPath}`,
`cd ${nodeConsumerTestPath}`, `cd ${nodeConsumerTestPath}`,
"npm link cyberchef", "npm link cyberchef"
]), ]),
sync: true, sync: true
}, },
teardownNodeConsumers: { teardownNodeConsumers: {
command: chainCommands([ command: chainCommands([
`rm -rf ${nodeConsumerTestPath}`, `rm -rf ${nodeConsumerTestPath}`,
"echo '\n--- Node consumer tests complete ---'", "echo '\n--- Node consumer tests complete ---'"
]), ]),
}, },
testCJSNodeConsumer: { testCJSNodeConsumer: {
@ -503,7 +419,7 @@ module.exports = function (grunt) {
return `find ./node_modules/crypto-api/src/ \\( -type d -name .git -prune \\) -o -type f -print0 | xargs -0 sed -i -e '/\\.mjs/!s/\\(from "\\.[^"]*\\)";/\\1.mjs";/g'`; return `find ./node_modules/crypto-api/src/ \\( -type d -name .git -prune \\) -o -type f -print0 | xargs -0 sed -i -e '/\\.mjs/!s/\\(from "\\.[^"]*\\)";/\\1.mjs";/g'`;
} }
}, },
stdout: false, stdout: false
}, },
fixSnackbarMarkup: { fixSnackbarMarkup: {
command: function () { command: function () {
@ -514,7 +430,7 @@ module.exports = function (grunt) {
return `sed -i 's/<div id=snackbar-container\\/>/<div id=snackbar-container>/g' ./node_modules/snackbarjs/src/snackbar.js`; return `sed -i 's/<div id=snackbar-container\\/>/<div id=snackbar-container>/g' ./node_modules/snackbarjs/src/snackbar.js`;
} }
}, },
stdout: false, stdout: false
}, },
}, },
}); });