mirror of
https://github.com/tobspr/shapez.io.git
synced 2025-12-11 09:11:50 +00:00
Squashed commit of the following:
commit 176343785eea110e529f26027bf864ae04068384
Author: EmeraldBlock <yygengjunior@gmail.com>
Date: Fri Dec 8 23:03:51 2023 -0600
update readme
commit 8c1c3a0c47f5125126cb00d32a48f4f9344a3fb3
Author: EmeraldBlock <yygengjunior@gmail.com>
Date: Fri Dec 8 23:00:05 2023 -0600
fix bugs
commit ea881e68c693a447e0698a3a6e7cfb1f25ccb6cc
Author: EmeraldBlock <yygengjunior@gmail.com>
Date: Fri Dec 8 22:46:46 2023 -0600
expose all tasks with old api
commit fa6d7a3920ff573eadb61425cc077f0e00406164
Author: EmeraldBlock <yygengjunior@gmail.com>
Date: Fri Dec 8 21:51:20 2023 -0600
switch to exported gulp tasks
commit 348b19a0171e65400bcd434cf7b7432f3488a411
Author: EmeraldBlock <yygengjunior@gmail.com>
Date: Mon Nov 20 22:55:38 2023 -0600
parallelize dev build
commit 56de73e2d18d20e5ea7202afc021573a746e5012
Author: EmeraldBlock <yygengjunior@gmail.com>
Date: Mon Nov 20 20:44:10 2023 -0600
use promises in gulpfile
commit 6ab54372482f26acb4769428eefbdc48240a12a1
Author: EmeraldBlock <yygengjunior@gmail.com>
Date: Mon Nov 20 20:33:36 2023 -0600
make java -version print again
commit b0e4cf57bdc404bb3b0e45b7b233d5f7648c800e
Author: EmeraldBlock <yygengjunior@gmail.com>
Date: Mon Nov 20 20:14:13 2023 -0600
use promises for gulp tasks
This commit is contained in:
parent
b5a7f7736a
commit
39b7e6cb59
@ -57,8 +57,7 @@ and does not intend to provide compatibility for older clients.
|
||||
### Prerequisites
|
||||
|
||||
- [ffmpeg](https://www.ffmpeg.org/download.html)
|
||||
- [Node.js 16](https://nodejs.org/en/about/previous-releases)
|
||||
(not 17+, see <https://github.com/tobspr-games/shapez.io/issues/1473>)
|
||||
- [Node.js](https://nodejs.org)
|
||||
- [Yarn 1](https://classic.yarnpkg.com/en/docs/install) (not 2, we haven't migrated yet)
|
||||
- [Java](https://www.oracle.com/java/technologies/downloads/) (or [OpenJDK](https://openjdk.org/)) to run the texture packer
|
||||
- [cURL](https://curl.se/download.html)[^1] to download the texture packer
|
||||
|
||||
44
gulp/config.js
Normal file
44
gulp/config.js
Normal file
@ -0,0 +1,44 @@
|
||||
import path from "path/posix";
|
||||
import BrowserSync from "browser-sync";
|
||||
|
||||
export const baseDir = path.resolve("..");
|
||||
export const buildFolder = path.join(baseDir, "build");
|
||||
export const buildOutputFolder = path.join(baseDir, "build_output");
|
||||
|
||||
// Globs for atlas resources
|
||||
export const rawImageResourcesGlobs = ["../res_raw/atlas.json", "../res_raw/**/*.png"];
|
||||
|
||||
// Globs for non-ui resources
|
||||
export const nonImageResourcesGlobs = ["../res/**/*.woff2", "../res/*.ico", "../res/**/*.webm"];
|
||||
|
||||
// Globs for ui resources
|
||||
export const imageResourcesGlobs = [
|
||||
"../res/**/*.png",
|
||||
"../res/**/*.svg",
|
||||
"../res/**/*.jpg",
|
||||
"../res/**/*.gif",
|
||||
];
|
||||
|
||||
export const browserSync = BrowserSync.create({});
|
||||
|
||||
// Check environment variables
|
||||
|
||||
const envVars = [
|
||||
"SHAPEZ_CLI_SERVER_HOST",
|
||||
"SHAPEZ_CLI_ALPHA_FTP_USER",
|
||||
"SHAPEZ_CLI_ALPHA_FTP_PW",
|
||||
"SHAPEZ_CLI_STAGING_FTP_USER",
|
||||
"SHAPEZ_CLI_STAGING_FTP_PW",
|
||||
"SHAPEZ_CLI_LIVE_FTP_USER",
|
||||
"SHAPEZ_CLI_LIVE_FTP_PW",
|
||||
"SHAPEZ_CLI_APPLE_ID",
|
||||
"SHAPEZ_CLI_APPLE_CERT_NAME",
|
||||
"SHAPEZ_CLI_GITHUB_USER",
|
||||
"SHAPEZ_CLI_GITHUB_TOKEN",
|
||||
];
|
||||
|
||||
for (let i = 0; i < envVars.length; ++i) {
|
||||
if (!process.env[envVars[i]]) {
|
||||
console.warn("Unset environment variable, might cause issues:", envVars[i]);
|
||||
}
|
||||
}
|
||||
188
gulp/css.js
188
gulp/css.js
@ -1,5 +1,7 @@
|
||||
import path from "path/posix";
|
||||
import gulp from "gulp";
|
||||
import { getRevision } from "./buildutils.js";
|
||||
import { buildFolder, browserSync } from "./config.js";
|
||||
|
||||
import gulpPostcss from "gulp-postcss";
|
||||
import postcssAssets from "postcss-assets";
|
||||
@ -13,112 +15,106 @@ import gulpDartSass from "gulp-dart-sass";
|
||||
import gulpPlumber from "gulp-plumber";
|
||||
import gulpRename from "gulp-rename";
|
||||
|
||||
export default function gulptasksCSS(gulp, buildFolder, browserSync) {
|
||||
// The assets plugin copies the files
|
||||
const commitHash = getRevision();
|
||||
const postcssAssetsPlugin = postcssAssets({
|
||||
loadPaths: [path.join(buildFolder, "res", "ui")],
|
||||
basePath: buildFolder,
|
||||
baseUrl: ".",
|
||||
});
|
||||
// The assets plugin copies the files
|
||||
const commitHash = getRevision();
|
||||
const postcssAssetsPlugin = postcssAssets({
|
||||
loadPaths: [path.join(buildFolder, "res", "ui")],
|
||||
basePath: buildFolder,
|
||||
baseUrl: ".",
|
||||
});
|
||||
|
||||
// Postcss configuration
|
||||
const postcssPlugins = prod => {
|
||||
const plugins = [postcssAssetsPlugin];
|
||||
if (prod) {
|
||||
plugins.unshift(
|
||||
postcssPresetEnv({
|
||||
browsers: ["> 0.1%"],
|
||||
})
|
||||
);
|
||||
// Postcss configuration
|
||||
const postcssPlugins = prod => {
|
||||
const plugins = [postcssAssetsPlugin];
|
||||
if (prod) {
|
||||
plugins.unshift(
|
||||
postcssPresetEnv({
|
||||
browsers: ["> 0.1%"],
|
||||
})
|
||||
);
|
||||
|
||||
plugins.push(
|
||||
cssMqpacker({
|
||||
sort: true,
|
||||
}),
|
||||
cssnano({
|
||||
preset: [
|
||||
"advanced",
|
||||
{
|
||||
cssDeclarationSorter: false,
|
||||
discardUnused: true,
|
||||
mergeIdents: false,
|
||||
reduceIdents: true,
|
||||
zindex: true,
|
||||
},
|
||||
],
|
||||
}),
|
||||
postcssRoundSubpixels()
|
||||
);
|
||||
}
|
||||
return plugins;
|
||||
};
|
||||
|
||||
// Performs linting on css
|
||||
gulp.task("css.lint", () => {
|
||||
return gulp
|
||||
.src(["../src/css/**/*.scss"])
|
||||
.pipe(gulpSassLint({ configFile: ".sasslint.yml" }))
|
||||
.pipe(gulpSassLint.format())
|
||||
.pipe(gulpSassLint.failOnError());
|
||||
});
|
||||
|
||||
function resourcesTask({ isProd }) {
|
||||
return gulp
|
||||
.src("../src/css/main.scss")
|
||||
.pipe(gulpPlumber())
|
||||
.pipe(gulpDartSass.sync().on("error", gulpDartSass.logError))
|
||||
.pipe(
|
||||
gulpPostcss([
|
||||
postcssCriticalSplit({
|
||||
blockTag: "@load-async",
|
||||
}),
|
||||
])
|
||||
)
|
||||
.pipe(gulpRename("async-resources.css"))
|
||||
.pipe(gulpPostcss(postcssPlugins(isProd)))
|
||||
.pipe(gulp.dest(buildFolder))
|
||||
.pipe(browserSync.stream());
|
||||
plugins.push(
|
||||
cssMqpacker({
|
||||
sort: true,
|
||||
}),
|
||||
cssnano({
|
||||
preset: [
|
||||
"advanced",
|
||||
{
|
||||
cssDeclarationSorter: false,
|
||||
discardUnused: true,
|
||||
mergeIdents: false,
|
||||
reduceIdents: true,
|
||||
zindex: true,
|
||||
},
|
||||
],
|
||||
}),
|
||||
postcssRoundSubpixels()
|
||||
);
|
||||
}
|
||||
return plugins;
|
||||
};
|
||||
|
||||
// Performs linting on css
|
||||
export function lint() {
|
||||
return gulp
|
||||
.src(["../src/css/**/*.scss"])
|
||||
.pipe(gulpSassLint({ configFile: ".sasslint.yml" }))
|
||||
.pipe(gulpSassLint.format())
|
||||
.pipe(gulpSassLint.failOnError());
|
||||
}
|
||||
|
||||
function resourcesTask({ isProd }) {
|
||||
return gulp
|
||||
.src("../src/css/main.scss")
|
||||
.pipe(gulpPlumber())
|
||||
.pipe(gulpDartSass.sync().on("error", gulpDartSass.logError))
|
||||
.pipe(
|
||||
gulpPostcss([
|
||||
postcssCriticalSplit({
|
||||
blockTag: "@load-async",
|
||||
}),
|
||||
])
|
||||
)
|
||||
.pipe(gulpRename("async-resources.css"))
|
||||
.pipe(gulpPostcss(postcssPlugins(isProd)))
|
||||
.pipe(gulp.dest(buildFolder))
|
||||
.pipe(browserSync.stream());
|
||||
}
|
||||
|
||||
export const resources = {
|
||||
// Builds the css resources
|
||||
gulp.task("css.resources.dev", () => {
|
||||
return resourcesTask({ isProd: false });
|
||||
});
|
||||
dev: () => resourcesTask({ isProd: false }),
|
||||
|
||||
// Builds the css resources in prod (=minified)
|
||||
gulp.task("css.resources.prod", () => {
|
||||
return resourcesTask({ isProd: true });
|
||||
});
|
||||
prod: () => resourcesTask({ isProd: true }),
|
||||
};
|
||||
|
||||
function mainTask({ isProd }) {
|
||||
return gulp
|
||||
.src("../src/css/main.scss")
|
||||
.pipe(gulpPlumber())
|
||||
.pipe(gulpDartSass.sync().on("error", gulpDartSass.logError))
|
||||
.pipe(
|
||||
gulpPostcss([
|
||||
postcssCriticalSplit({
|
||||
blockTag: "@load-async",
|
||||
output: "rest",
|
||||
}),
|
||||
])
|
||||
)
|
||||
.pipe(gulpPostcss(postcssPlugins(isProd)))
|
||||
.pipe(gulp.dest(buildFolder))
|
||||
.pipe(browserSync.stream());
|
||||
}
|
||||
function mainTask({ isProd }) {
|
||||
return gulp
|
||||
.src("../src/css/main.scss")
|
||||
.pipe(gulpPlumber())
|
||||
.pipe(gulpDartSass.sync().on("error", gulpDartSass.logError))
|
||||
.pipe(
|
||||
gulpPostcss([
|
||||
postcssCriticalSplit({
|
||||
blockTag: "@load-async",
|
||||
output: "rest",
|
||||
}),
|
||||
])
|
||||
)
|
||||
.pipe(gulpPostcss(postcssPlugins(isProd)))
|
||||
.pipe(gulp.dest(buildFolder))
|
||||
.pipe(browserSync.stream());
|
||||
}
|
||||
|
||||
export const main = {
|
||||
// Builds the css main
|
||||
gulp.task("css.main.dev", () => {
|
||||
return mainTask({ isProd: false });
|
||||
});
|
||||
dev: () => mainTask({ isProd: false }),
|
||||
|
||||
// Builds the css main in prod (=minified)
|
||||
gulp.task("css.main.prod", () => {
|
||||
return mainTask({ isProd: true });
|
||||
});
|
||||
prod: () => mainTask({ isProd: true }),
|
||||
};
|
||||
|
||||
gulp.task("css.dev", gulp.parallel("css.main.dev", "css.resources.dev"));
|
||||
gulp.task("css.prod", gulp.parallel("css.main.prod", "css.resources.prod"));
|
||||
}
|
||||
export const dev = gulp.parallel(main.dev, resources.dev);
|
||||
export const prod = gulp.parallel(main.prod, resources.prod);
|
||||
|
||||
62
gulp/docs.js
62
gulp/docs.js
@ -1,38 +1,36 @@
|
||||
import path from "path/posix";
|
||||
import fs from "fs";
|
||||
import fs from "fs/promises";
|
||||
import gulp from "gulp";
|
||||
|
||||
import gulpRename from "gulp-rename";
|
||||
import stripJsonComments from "strip-json-comments";
|
||||
|
||||
export default function gulptasksDocs(gulp, buildFolder) {
|
||||
gulp.task("docs.convertJsToTs", () => {
|
||||
return gulp
|
||||
.src(path.join("..", "src", "js", "**", "*.js"))
|
||||
.pipe(
|
||||
gulpRename(path => {
|
||||
path.extname = ".ts";
|
||||
})
|
||||
)
|
||||
.pipe(gulp.dest(path.join("..", "tsc_temp")));
|
||||
});
|
||||
|
||||
gulp.task("docs.copyTsconfigForHints", cb => {
|
||||
const src = fs.readFileSync(path.join("..", "src", "js", "tsconfig.json")).toString();
|
||||
const baseConfig = JSON.parse(stripJsonComments(src));
|
||||
|
||||
baseConfig.allowJs = false;
|
||||
baseConfig.checkJs = false;
|
||||
baseConfig.declaration = true;
|
||||
baseConfig.noEmit = false;
|
||||
baseConfig.strict = false;
|
||||
baseConfig.strictFunctionTypes = false;
|
||||
baseConfig.strictBindCallApply = false;
|
||||
baseConfig.alwaysStrict = false;
|
||||
baseConfig.composite = true;
|
||||
baseConfig.outFile = "bundled-ts.js";
|
||||
fs.writeFileSync(path.join("..", "tsc_temp", "tsconfig.json"), JSON.stringify(baseConfig));
|
||||
cb();
|
||||
});
|
||||
|
||||
gulp.task("main.prepareDocs", gulp.series("docs.convertJsToTs", "docs.copyTsconfigForHints"));
|
||||
export function convertJsToTs() {
|
||||
return gulp
|
||||
.src(path.join("..", "src", "js", "**", "*.js"))
|
||||
.pipe(
|
||||
gulpRename(path => {
|
||||
path.extname = ".ts";
|
||||
})
|
||||
)
|
||||
.pipe(gulp.dest(path.join("..", "tsc_temp")));
|
||||
}
|
||||
|
||||
export async function copyTsconfigForHints() {
|
||||
const src = (await fs.readFile(path.join("..", "src", "js", "tsconfig.json"))).toString();
|
||||
const baseConfig = JSON.parse(stripJsonComments(src));
|
||||
|
||||
baseConfig.allowJs = false;
|
||||
baseConfig.checkJs = false;
|
||||
baseConfig.declaration = true;
|
||||
baseConfig.noEmit = false;
|
||||
baseConfig.strict = false;
|
||||
baseConfig.strictFunctionTypes = false;
|
||||
baseConfig.strictBindCallApply = false;
|
||||
baseConfig.alwaysStrict = false;
|
||||
baseConfig.composite = true;
|
||||
baseConfig.outFile = "bundled-ts.js";
|
||||
await fs.writeFile(path.join("..", "tsc_temp", "tsconfig.json"), JSON.stringify(baseConfig));
|
||||
}
|
||||
|
||||
export const prepareDocs = gulp.series(convertJsToTs, copyTsconfigForHints);
|
||||
|
||||
137
gulp/ftp.js
137
gulp/ftp.js
@ -1,68 +1,69 @@
|
||||
import path from "path/posix";
|
||||
import fs from "fs";
|
||||
import fs from "fs/promises";
|
||||
import gulp from "gulp";
|
||||
import { buildFolder } from "./config.js";
|
||||
|
||||
import { getRevision, getVersion } from "./buildutils.js";
|
||||
|
||||
import gulpRename from "gulp-rename";
|
||||
import gulpSftp from "gulp-sftp";
|
||||
|
||||
export default function gulptasksFTP(gulp, buildFolder) {
|
||||
const commitHash = getRevision();
|
||||
const commitHash = getRevision();
|
||||
|
||||
const additionalFolder = path.join("additional_build_files");
|
||||
const additionalFolder = path.join("additional_build_files");
|
||||
|
||||
const additionalFiles = [
|
||||
path.join(additionalFolder, "*"),
|
||||
path.join(additionalFolder, "*.*"),
|
||||
path.join(additionalFolder, ".*"),
|
||||
];
|
||||
const additionalGlobs = [
|
||||
path.join(additionalFolder, "*"),
|
||||
path.join(additionalFolder, "*.*"),
|
||||
path.join(additionalFolder, ".*"),
|
||||
];
|
||||
|
||||
const credentials = {
|
||||
alpha: {
|
||||
host: process.env.SHAPEZ_CLI_SERVER_HOST,
|
||||
user: process.env.SHAPEZ_CLI_ALPHA_FTP_USER,
|
||||
pass: process.env.SHAPEZ_CLI_ALPHA_FTP_PW,
|
||||
},
|
||||
staging: {
|
||||
host: process.env.SHAPEZ_CLI_SERVER_HOST,
|
||||
user: process.env.SHAPEZ_CLI_STAGING_FTP_USER,
|
||||
pass: process.env.SHAPEZ_CLI_STAGING_FTP_PW,
|
||||
},
|
||||
prod: {
|
||||
host: process.env.SHAPEZ_CLI_SERVER_HOST,
|
||||
user: process.env.SHAPEZ_CLI_LIVE_FTP_USER,
|
||||
pass: process.env.SHAPEZ_CLI_LIVE_FTP_PW,
|
||||
},
|
||||
};
|
||||
const credentials = {
|
||||
alpha: {
|
||||
host: process.env.SHAPEZ_CLI_SERVER_HOST,
|
||||
user: process.env.SHAPEZ_CLI_ALPHA_FTP_USER,
|
||||
pass: process.env.SHAPEZ_CLI_ALPHA_FTP_PW,
|
||||
},
|
||||
staging: {
|
||||
host: process.env.SHAPEZ_CLI_SERVER_HOST,
|
||||
user: process.env.SHAPEZ_CLI_STAGING_FTP_USER,
|
||||
pass: process.env.SHAPEZ_CLI_STAGING_FTP_PW,
|
||||
},
|
||||
prod: {
|
||||
host: process.env.SHAPEZ_CLI_SERVER_HOST,
|
||||
user: process.env.SHAPEZ_CLI_LIVE_FTP_USER,
|
||||
pass: process.env.SHAPEZ_CLI_LIVE_FTP_PW,
|
||||
},
|
||||
};
|
||||
|
||||
// Write the "commit.txt" file
|
||||
gulp.task("ftp.writeVersion", cb => {
|
||||
fs.writeFileSync(
|
||||
path.join(buildFolder, "version.json"),
|
||||
JSON.stringify(
|
||||
{
|
||||
commit: getRevision(),
|
||||
appVersion: getVersion(),
|
||||
buildTime: new Date().getTime(),
|
||||
},
|
||||
null,
|
||||
4
|
||||
)
|
||||
);
|
||||
cb();
|
||||
});
|
||||
// Write the "commit.txt" file
|
||||
export async function writeVersion() {
|
||||
await fs.writeFile(
|
||||
path.join(buildFolder, "version.json"),
|
||||
JSON.stringify(
|
||||
{
|
||||
commit: getRevision(),
|
||||
appVersion: getVersion(),
|
||||
buildTime: new Date().getTime(),
|
||||
},
|
||||
null,
|
||||
4
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
const gameSrcGlobs = [
|
||||
path.join(buildFolder, "**/*.*"),
|
||||
path.join(buildFolder, "**/.*"),
|
||||
path.join(buildFolder, "**/*"),
|
||||
path.join(buildFolder, "!**/index.html"),
|
||||
];
|
||||
const gameSrcGlobs = [
|
||||
path.join(buildFolder, "**/*.*"),
|
||||
path.join(buildFolder, "**/.*"),
|
||||
path.join(buildFolder, "**/*"),
|
||||
path.join(buildFolder, "!**/index.html"),
|
||||
];
|
||||
|
||||
for (const deployEnv of ["alpha", "prod", "staging"]) {
|
||||
export const upload = Object.fromEntries(
|
||||
["alpha", "prod", "staging"].map(deployEnv => {
|
||||
const deployCredentials = credentials[deployEnv];
|
||||
|
||||
gulp.task(`ftp.upload.${deployEnv}.game`, () => {
|
||||
function game() {
|
||||
return gulp
|
||||
.src(gameSrcGlobs, { base: buildFolder })
|
||||
.pipe(
|
||||
@ -71,30 +72,28 @@ export default function gulptasksFTP(gulp, buildFolder) {
|
||||
})
|
||||
)
|
||||
.pipe(gulpSftp(deployCredentials));
|
||||
});
|
||||
}
|
||||
|
||||
gulp.task(`ftp.upload.${deployEnv}.indexHtml`, () => {
|
||||
function indexHtml() {
|
||||
return gulp
|
||||
.src([path.join(buildFolder, "index.html"), path.join(buildFolder, "version.json")], {
|
||||
base: buildFolder,
|
||||
})
|
||||
.pipe(gulpSftp(deployCredentials));
|
||||
});
|
||||
}
|
||||
|
||||
gulp.task(`ftp.upload.${deployEnv}.additionalFiles`, () => {
|
||||
return gulp
|
||||
.src(additionalFiles, { base: additionalFolder }) //
|
||||
.pipe(gulpSftp(deployCredentials));
|
||||
});
|
||||
function additionalFiles() {
|
||||
return gulp.src(additionalGlobs, { base: additionalFolder }).pipe(gulpSftp(deployCredentials));
|
||||
}
|
||||
|
||||
gulp.task(
|
||||
`ftp.upload.${deployEnv}`,
|
||||
gulp.series(
|
||||
"ftp.writeVersion",
|
||||
`ftp.upload.${deployEnv}.game`,
|
||||
`ftp.upload.${deployEnv}.indexHtml`,
|
||||
`ftp.upload.${deployEnv}.additionalFiles`
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
return [
|
||||
deployEnv,
|
||||
{
|
||||
game,
|
||||
indexHtml,
|
||||
additionalFiles,
|
||||
all: gulp.series(writeVersion, game, indexHtml, additionalFiles),
|
||||
},
|
||||
];
|
||||
})
|
||||
);
|
||||
|
||||
310
gulp/gulpfile.js
310
gulp/gulpfile.js
@ -1,303 +1,23 @@
|
||||
import gulp from "gulp";
|
||||
import BrowserSync from "browser-sync";
|
||||
const browserSync = BrowserSync.create({});
|
||||
import path from "path/posix";
|
||||
import pathNative from "path";
|
||||
import deleteEmpty from "delete-empty";
|
||||
import { execSync } from "child_process";
|
||||
|
||||
// Load other plugins
|
||||
import gulpClean from "gulp-clean";
|
||||
import gulpWebserver from "gulp-webserver";
|
||||
|
||||
// Check environment variables
|
||||
|
||||
const envVars = [
|
||||
"SHAPEZ_CLI_SERVER_HOST",
|
||||
"SHAPEZ_CLI_ALPHA_FTP_USER",
|
||||
"SHAPEZ_CLI_ALPHA_FTP_PW",
|
||||
"SHAPEZ_CLI_STAGING_FTP_USER",
|
||||
"SHAPEZ_CLI_STAGING_FTP_PW",
|
||||
"SHAPEZ_CLI_LIVE_FTP_USER",
|
||||
"SHAPEZ_CLI_LIVE_FTP_PW",
|
||||
"SHAPEZ_CLI_APPLE_ID",
|
||||
"SHAPEZ_CLI_APPLE_CERT_NAME",
|
||||
"SHAPEZ_CLI_GITHUB_USER",
|
||||
"SHAPEZ_CLI_GITHUB_TOKEN",
|
||||
];
|
||||
|
||||
for (let i = 0; i < envVars.length; ++i) {
|
||||
if (!process.env[envVars[i]]) {
|
||||
console.warn("Unset environment variable, might cause issues:", envVars[i]);
|
||||
}
|
||||
}
|
||||
|
||||
const baseDir = path.resolve("..");
|
||||
const buildFolder = path.join(baseDir, "build");
|
||||
const buildOuptutFolder = path.join(baseDir, "build_output");
|
||||
|
||||
import gulptasksImageResources, * as imgres from "./image-resources.js";
|
||||
gulptasksImageResources(gulp, buildFolder);
|
||||
|
||||
import gulptasksCSS from "./css.js";
|
||||
gulptasksCSS(gulp, buildFolder, browserSync);
|
||||
|
||||
import gulptasksSounds from "./sounds.js";
|
||||
gulptasksSounds(gulp, buildFolder);
|
||||
|
||||
import gulptasksLocalConfig from "./local-config.js";
|
||||
gulptasksLocalConfig(gulp);
|
||||
|
||||
import gulptasksJS from "./js.js";
|
||||
gulptasksJS(gulp, buildFolder, browserSync);
|
||||
|
||||
import gulptasksHTML from "./html.js";
|
||||
gulptasksHTML(gulp, buildFolder);
|
||||
|
||||
import gulptasksFTP from "./ftp.js";
|
||||
gulptasksFTP(gulp, buildFolder);
|
||||
|
||||
import gulptasksDocs from "./docs.js";
|
||||
gulptasksDocs(gulp, buildFolder);
|
||||
|
||||
import gulptasksStandalone from "./standalone.js";
|
||||
gulptasksStandalone(gulp);
|
||||
|
||||
import gulptasksTranslations from "./translations.js";
|
||||
import { BUILD_VARIANTS } from "./build_variants.js";
|
||||
gulptasksTranslations(gulp);
|
||||
|
||||
///////////////////// BUILD TASKS /////////////////////
|
||||
|
||||
// Cleans up everything
|
||||
gulp.task("utils.cleanBuildFolder", () => {
|
||||
return gulp.src(buildFolder, { read: false, allowEmpty: true }).pipe(gulpClean({ force: true }));
|
||||
});
|
||||
gulp.task("utils.cleanBuildOutputFolder", () => {
|
||||
return gulp.src(buildOuptutFolder, { read: false, allowEmpty: true }).pipe(gulpClean({ force: true }));
|
||||
});
|
||||
gulp.task("utils.cleanBuildTempFolder", () => {
|
||||
return gulp
|
||||
.src(path.join("..", "src", "js", "built-temp"), { read: false, allowEmpty: true })
|
||||
.pipe(gulpClean({ force: true }));
|
||||
});
|
||||
gulp.task("utils.cleanImageBuildFolder", () => {
|
||||
return gulp
|
||||
.src(path.join("res_built"), { read: false, allowEmpty: true })
|
||||
.pipe(gulpClean({ force: true }));
|
||||
});
|
||||
|
||||
gulp.task(
|
||||
"utils.cleanup",
|
||||
gulp.series("utils.cleanBuildFolder", "utils.cleanImageBuildFolder", "utils.cleanBuildTempFolder")
|
||||
);
|
||||
|
||||
// Requires no uncomitted files
|
||||
gulp.task("utils.requireCleanWorkingTree", cb => {
|
||||
let output = execSync("git status -su").toString("ascii").trim().replace(/\r/gi, "").split("\n");
|
||||
|
||||
// Filter files which are OK to be untracked
|
||||
output = output
|
||||
.map(x => x.replace(/[\r\n]+/gi, ""))
|
||||
.filter(x => x.indexOf(".local.js") < 0)
|
||||
.filter(x => x.length > 0);
|
||||
if (output.length > 0) {
|
||||
console.error("\n\nYou have unstaged changes, please commit everything first!");
|
||||
console.error("Unstaged files:");
|
||||
console.error(output.map(x => "'" + x + "'").join("\n"));
|
||||
process.exit(1);
|
||||
}
|
||||
cb();
|
||||
});
|
||||
|
||||
gulp.task("utils.copyAdditionalBuildFiles", cb => {
|
||||
const additionalFolder = path.join("additional_build_files");
|
||||
const additionalSrcGlobs = [
|
||||
path.join(additionalFolder, "**/*.*"),
|
||||
path.join(additionalFolder, "**/.*"),
|
||||
path.join(additionalFolder, "**/*"),
|
||||
];
|
||||
|
||||
return gulp.src(additionalSrcGlobs).pipe(gulp.dest(buildFolder));
|
||||
});
|
||||
|
||||
// Starts a webserver on the built directory (useful for testing prod build)
|
||||
gulp.task("main.webserver", () => {
|
||||
return gulp.src(buildFolder).pipe(
|
||||
gulpWebserver({
|
||||
livereload: {
|
||||
enable: true,
|
||||
},
|
||||
directoryListing: false,
|
||||
open: true,
|
||||
port: 3005,
|
||||
})
|
||||
);
|
||||
});
|
||||
import * as tasks from "./tasks.js";
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {object} param0
|
||||
* @param {keyof typeof BUILD_VARIANTS} param0.version
|
||||
* @typedef {import("gulp").TaskFunction} TaskFunction
|
||||
* @typedef {TaskFunction | { [k: string]: Tasks }} Tasks
|
||||
*/
|
||||
function serveHTML({ version = "web-dev" }) {
|
||||
browserSync.init({
|
||||
server: [buildFolder, path.join(baseDir, "mod_examples")],
|
||||
port: 3005,
|
||||
ghostMode: {
|
||||
clicks: false,
|
||||
scroll: false,
|
||||
location: false,
|
||||
forms: false,
|
||||
},
|
||||
logLevel: "info",
|
||||
logPrefix: "BS",
|
||||
online: false,
|
||||
xip: false,
|
||||
notify: false,
|
||||
reloadDebounce: 100,
|
||||
reloadOnRestart: true,
|
||||
watchEvents: ["add", "change"],
|
||||
});
|
||||
|
||||
// Watch .scss files, those trigger a css rebuild
|
||||
gulp.watch(["../src/**/*.scss"], gulp.series("css.dev"));
|
||||
|
||||
// Watch .html files, those trigger a html rebuild
|
||||
gulp.watch("../src/**/*.html", gulp.series("html.dev"));
|
||||
gulp.watch("./preloader/*.*", gulp.series("html.dev"));
|
||||
|
||||
// Watch translations
|
||||
gulp.watch("../translations/**/*.yaml", gulp.series("translations.convertToJson"));
|
||||
|
||||
gulp.watch(
|
||||
["../res_raw/sounds/sfx/*.mp3", "../res_raw/sounds/sfx/*.wav"],
|
||||
gulp.series("sounds.sfx", "sounds.copy")
|
||||
);
|
||||
gulp.watch(
|
||||
["../res_raw/sounds/music/*.mp3", "../res_raw/sounds/music/*.wav"],
|
||||
gulp.series("sounds.music", "sounds.copy")
|
||||
);
|
||||
|
||||
// Watch resource files and copy them on change
|
||||
gulp.watch(imgres.rawImageResourcesGlobs, gulp.series("imgres.buildAtlas"));
|
||||
gulp.watch(imgres.nonImageResourcesGlobs, gulp.series("imgres.copyNonImageResources"));
|
||||
gulp.watch(imgres.imageResourcesGlobs, gulp.series("imgres.copyImageResources"));
|
||||
|
||||
// Watch .atlas files and recompile the atlas on change
|
||||
gulp.watch("../res_built/atlas/*.atlas", gulp.series("imgres.atlasToJson"));
|
||||
gulp.watch("../res_built/atlas/*.json", gulp.series("imgres.atlas"));
|
||||
|
||||
// Watch the build folder and reload when anything changed
|
||||
const extensions = ["html", "js", "png", "gif", "jpg", "svg", "mp3", "ico", "woff2", "json"];
|
||||
gulp.watch(extensions.map(ext => path.join(buildFolder, "**", "*." + ext))).on("change", function (p) {
|
||||
return gulp
|
||||
.src(pathNative.resolve(p).replaceAll(pathNative.sep, path.sep))
|
||||
.pipe(browserSync.reload({ stream: true }));
|
||||
});
|
||||
|
||||
gulp.watch("../src/js/built-temp/*.json").on("change", function (p) {
|
||||
return gulp
|
||||
.src(pathNative.resolve(p).replaceAll(pathNative.sep, path.sep))
|
||||
.pipe(browserSync.reload({ stream: true }));
|
||||
});
|
||||
|
||||
gulp.series("js." + version + ".dev.watch")(() => true);
|
||||
}
|
||||
|
||||
// Pre and postbuild
|
||||
gulp.task("step.baseResources", gulp.series("imgres.allOptimized"));
|
||||
gulp.task("step.deleteEmpty", cb => {
|
||||
deleteEmpty.sync(buildFolder);
|
||||
cb();
|
||||
});
|
||||
|
||||
gulp.task("step.postbuild", gulp.series("imgres.cleanupUnusedCssInlineImages", "step.deleteEmpty"));
|
||||
|
||||
///////////////////// RUNNABLE TASKS /////////////////////
|
||||
|
||||
// Builds everything (dev)
|
||||
gulp.task(
|
||||
"build.prepare.dev",
|
||||
gulp.series(
|
||||
"utils.cleanup",
|
||||
"utils.copyAdditionalBuildFiles",
|
||||
"localConfig.findOrCreate",
|
||||
"imgres.buildAtlas",
|
||||
"imgres.atlasToJson",
|
||||
"imgres.atlas",
|
||||
"sounds.dev",
|
||||
"imgres.copyImageResources",
|
||||
"imgres.copyNonImageResources",
|
||||
"translations.fullBuild",
|
||||
"css.dev"
|
||||
)
|
||||
);
|
||||
|
||||
// Builds everything for every variant
|
||||
for (const variant in BUILD_VARIANTS) {
|
||||
const data = BUILD_VARIANTS[variant];
|
||||
const buildName = "build." + variant;
|
||||
|
||||
// build
|
||||
gulp.task(
|
||||
buildName + ".code",
|
||||
gulp.series(
|
||||
data.standalone ? "sounds.fullbuildHQ" : "sounds.fullbuild",
|
||||
"translations.fullBuild",
|
||||
"js." + variant + ".prod"
|
||||
)
|
||||
);
|
||||
|
||||
gulp.task(buildName + ".resourcesAndCode", gulp.parallel("step.baseResources", buildName + ".code"));
|
||||
|
||||
gulp.task(buildName + ".all", gulp.series(buildName + ".resourcesAndCode", "css.prod", "html.prod"));
|
||||
|
||||
gulp.task(buildName, gulp.series("utils.cleanup", buildName + ".all", "step.postbuild"));
|
||||
|
||||
// Tasks for creating packages. These packages are already distributable, but usually can be further
|
||||
// wrapped in a different format (an installer for Windows, tarball for Linux, DMG for macOS).
|
||||
if (data.standalone) {
|
||||
const packageTasks = [
|
||||
"win32-x64",
|
||||
"win32-arm64",
|
||||
"linux-x64",
|
||||
"linux-arm64",
|
||||
"darwin-x64",
|
||||
"darwin-arm64",
|
||||
"all",
|
||||
];
|
||||
|
||||
for (const task of packageTasks) {
|
||||
gulp.task(
|
||||
`package.${variant}.${task}`,
|
||||
gulp.series(
|
||||
"localConfig.findOrCreate",
|
||||
`build.${variant}`,
|
||||
"utils.cleanBuildOutputFolder",
|
||||
`standalone.${variant}.prepare`,
|
||||
`standalone.${variant}.package.${task}`
|
||||
)
|
||||
);
|
||||
}
|
||||
/**
|
||||
* @param {Tasks} tasks
|
||||
* @param {string=} prefix
|
||||
*/
|
||||
function register(tasks, prefix) {
|
||||
if (tasks instanceof Function) {
|
||||
gulp.task(prefix, tasks);
|
||||
return;
|
||||
}
|
||||
for (const [k, v] of Object.entries(tasks)) {
|
||||
register(v, prefix == null ? k : `${prefix}.${k}`);
|
||||
}
|
||||
|
||||
// serve
|
||||
gulp.task(
|
||||
"serve." + variant,
|
||||
gulp.series("build.prepare.dev", "html.dev", () => serveHTML({ version: variant }))
|
||||
);
|
||||
}
|
||||
|
||||
// Deploying!
|
||||
gulp.task(
|
||||
"deploy.staging",
|
||||
gulp.series("utils.requireCleanWorkingTree", "build.web-shapezio-beta", "ftp.upload.staging")
|
||||
);
|
||||
gulp.task(
|
||||
"deploy.prod",
|
||||
gulp.series("utils.requireCleanWorkingTree", "build.web-shapezio", "ftp.upload.prod")
|
||||
);
|
||||
|
||||
// Default task (dev, localhost)
|
||||
gulp.task("default", gulp.series("serve.standalone-steam"));
|
||||
register(tasks);
|
||||
|
||||
144
gulp/html.js
144
gulp/html.js
@ -2,6 +2,8 @@ import { getRevision } from "./buildutils.js";
|
||||
import fs from "fs";
|
||||
import path from "path/posix";
|
||||
import crypto from "crypto";
|
||||
import gulp from "gulp";
|
||||
import { buildFolder } from "./config.js";
|
||||
|
||||
import gulpDom from "gulp-dom";
|
||||
import gulpHtmlmin from "gulp-htmlmin";
|
||||
@ -20,32 +22,31 @@ function computeIntegrityHash(fullPath, algorithm = "sha256") {
|
||||
* html.dev
|
||||
* html.prod
|
||||
*/
|
||||
export default function gulptasksHTML(gulp, buildFolder) {
|
||||
const commitHash = getRevision();
|
||||
async function buildHtml({ integrity = true }) {
|
||||
return gulp
|
||||
.src("../src/html/index.html")
|
||||
.pipe(
|
||||
gulpDom(
|
||||
/** @this {Document} **/ function () {
|
||||
const document = this;
|
||||
const commitHash = getRevision();
|
||||
async function buildHtml({ integrity = true }) {
|
||||
return gulp
|
||||
.src("../src/html/index.html")
|
||||
.pipe(
|
||||
gulpDom(
|
||||
/** @this {Document} **/ function () {
|
||||
const document = this;
|
||||
|
||||
// Append css
|
||||
const css = document.createElement("link");
|
||||
css.rel = "stylesheet";
|
||||
css.type = "text/css";
|
||||
css.media = "none";
|
||||
css.setAttribute("onload", "this.media='all'");
|
||||
css.href = "main.css";
|
||||
if (integrity) {
|
||||
css.setAttribute(
|
||||
"integrity",
|
||||
computeIntegrityHash(path.join(buildFolder, "main.css"))
|
||||
);
|
||||
}
|
||||
document.head.appendChild(css);
|
||||
// Append css
|
||||
const css = document.createElement("link");
|
||||
css.rel = "stylesheet";
|
||||
css.type = "text/css";
|
||||
css.media = "none";
|
||||
css.setAttribute("onload", "this.media='all'");
|
||||
css.href = "main.css";
|
||||
if (integrity) {
|
||||
css.setAttribute(
|
||||
"integrity",
|
||||
computeIntegrityHash(path.join(buildFolder, "main.css"))
|
||||
);
|
||||
}
|
||||
document.head.appendChild(css);
|
||||
|
||||
let fontCss = `
|
||||
let fontCss = `
|
||||
@font-face {
|
||||
font-family: "GameFont";
|
||||
font-style: normal;
|
||||
@ -54,59 +55,54 @@ export default function gulptasksHTML(gulp, buildFolder) {
|
||||
src: url('res/fonts/GameFont.woff2') format("woff2");
|
||||
}
|
||||
`;
|
||||
let loadingCss =
|
||||
fontCss + fs.readFileSync(path.join("preloader", "preloader.css")).toString();
|
||||
let loadingCss =
|
||||
fontCss + fs.readFileSync(path.join("preloader", "preloader.css")).toString();
|
||||
|
||||
const style = document.createElement("style");
|
||||
style.setAttribute("type", "text/css");
|
||||
style.textContent = loadingCss;
|
||||
document.head.appendChild(style);
|
||||
const style = document.createElement("style");
|
||||
style.setAttribute("type", "text/css");
|
||||
style.textContent = loadingCss;
|
||||
document.head.appendChild(style);
|
||||
|
||||
let bodyContent = fs
|
||||
.readFileSync(path.join("preloader", "preloader.html"))
|
||||
.toString();
|
||||
let bodyContent = fs.readFileSync(path.join("preloader", "preloader.html")).toString();
|
||||
|
||||
const bundleScript = document.createElement("script");
|
||||
bundleScript.type = "text/javascript";
|
||||
bundleScript.src = "bundle.js";
|
||||
if (integrity) {
|
||||
bundleScript.setAttribute(
|
||||
"integrity",
|
||||
computeIntegrityHash(path.join(buildFolder, "bundle.js"))
|
||||
);
|
||||
}
|
||||
document.head.appendChild(bundleScript);
|
||||
|
||||
document.body.innerHTML = bodyContent;
|
||||
const bundleScript = document.createElement("script");
|
||||
bundleScript.type = "text/javascript";
|
||||
bundleScript.src = "bundle.js";
|
||||
if (integrity) {
|
||||
bundleScript.setAttribute(
|
||||
"integrity",
|
||||
computeIntegrityHash(path.join(buildFolder, "bundle.js"))
|
||||
);
|
||||
}
|
||||
)
|
||||
)
|
||||
.pipe(
|
||||
gulpHtmlmin({
|
||||
caseSensitive: true,
|
||||
collapseBooleanAttributes: true,
|
||||
collapseInlineTagWhitespace: true,
|
||||
collapseWhitespace: true,
|
||||
preserveLineBreaks: true,
|
||||
minifyJS: true,
|
||||
minifyCSS: true,
|
||||
quoteCharacter: '"',
|
||||
useShortDoctype: true,
|
||||
})
|
||||
)
|
||||
.pipe(gulpHtmlBeautify())
|
||||
.pipe(gulpRename("index.html"))
|
||||
.pipe(gulp.dest(buildFolder));
|
||||
}
|
||||
document.head.appendChild(bundleScript);
|
||||
|
||||
gulp.task("html.dev", () => {
|
||||
return buildHtml({
|
||||
integrity: false,
|
||||
});
|
||||
});
|
||||
gulp.task("html.prod", () => {
|
||||
return buildHtml({
|
||||
integrity: true,
|
||||
});
|
||||
});
|
||||
document.body.innerHTML = bodyContent;
|
||||
}
|
||||
)
|
||||
)
|
||||
.pipe(
|
||||
gulpHtmlmin({
|
||||
caseSensitive: true,
|
||||
collapseBooleanAttributes: true,
|
||||
collapseInlineTagWhitespace: true,
|
||||
collapseWhitespace: true,
|
||||
preserveLineBreaks: true,
|
||||
minifyJS: true,
|
||||
minifyCSS: true,
|
||||
quoteCharacter: '"',
|
||||
useShortDoctype: true,
|
||||
})
|
||||
)
|
||||
.pipe(gulpHtmlBeautify())
|
||||
.pipe(gulpRename("index.html"))
|
||||
.pipe(gulp.dest(buildFolder));
|
||||
}
|
||||
|
||||
export const dev = () =>
|
||||
buildHtml({
|
||||
integrity: false,
|
||||
});
|
||||
export const prod = () =>
|
||||
buildHtml({
|
||||
integrity: true,
|
||||
});
|
||||
|
||||
@ -1,12 +1,19 @@
|
||||
import fs from "fs";
|
||||
import fs from "fs/promises";
|
||||
import path from "path/posix";
|
||||
import atlasToJson from "./atlas2json.js";
|
||||
import gulp from "gulp";
|
||||
import { buildFolder } from "./config.js";
|
||||
import atlas2Json from "./atlas2json.js";
|
||||
|
||||
import { execSync } from "child_process";
|
||||
const execute = command =>
|
||||
execSync(command, {
|
||||
import childProcess from "child_process";
|
||||
import { promisify } from "util";
|
||||
const exec = promisify(childProcess.exec);
|
||||
const execute = command => {
|
||||
const promise = exec(command, {
|
||||
encoding: "utf-8",
|
||||
});
|
||||
promise.child.stderr.pipe(process.stderr);
|
||||
return promise;
|
||||
};
|
||||
|
||||
import gulpImagemin from "gulp-imagemin";
|
||||
import imageminJpegtran from "imagemin-jpegtran";
|
||||
@ -15,182 +22,161 @@ import imageminPngquant from "imagemin-pngquant";
|
||||
import gulpIf from "gulp-if";
|
||||
import gulpCached from "gulp-cached";
|
||||
import gulpClean from "gulp-clean";
|
||||
|
||||
// Globs for atlas resources
|
||||
export const rawImageResourcesGlobs = ["../res_raw/atlas.json", "../res_raw/**/*.png"];
|
||||
|
||||
// Globs for non-ui resources
|
||||
export const nonImageResourcesGlobs = ["../res/**/*.woff2", "../res/*.ico", "../res/**/*.webm"];
|
||||
|
||||
// Globs for ui resources
|
||||
export const imageResourcesGlobs = [
|
||||
"../res/**/*.png",
|
||||
"../res/**/*.svg",
|
||||
"../res/**/*.jpg",
|
||||
"../res/**/*.gif",
|
||||
];
|
||||
import { nonImageResourcesGlobs, imageResourcesGlobs } from "./config.js";
|
||||
|
||||
// Link to download LibGDX runnable-texturepacker.jar
|
||||
const runnableTPSource =
|
||||
"https://libgdx-nightlies.s3.eu-central-1.amazonaws.com/libgdx-runnables/runnable-texturepacker.jar";
|
||||
|
||||
export default function gulptasksImageResources(gulp, buildFolder) {
|
||||
// Lossless options
|
||||
const minifyImagesOptsLossless = () => [
|
||||
imageminJpegtran({
|
||||
progressive: true,
|
||||
}),
|
||||
gulpImagemin.svgo({}),
|
||||
gulpImagemin.optipng({
|
||||
optimizationLevel: 3,
|
||||
}),
|
||||
imageminGifsicle({
|
||||
optimizationLevel: 3,
|
||||
colors: 128,
|
||||
}),
|
||||
];
|
||||
// Lossless options
|
||||
const minifyImagesOptsLossless = () => [
|
||||
imageminJpegtran({
|
||||
progressive: true,
|
||||
}),
|
||||
gulpImagemin.svgo({}),
|
||||
gulpImagemin.optipng({
|
||||
optimizationLevel: 3,
|
||||
}),
|
||||
imageminGifsicle({
|
||||
optimizationLevel: 3,
|
||||
colors: 128,
|
||||
}),
|
||||
];
|
||||
|
||||
// Lossy options
|
||||
const minifyImagesOpts = () => [
|
||||
gulpImagemin.mozjpeg({
|
||||
quality: 80,
|
||||
maxMemory: 1024 * 1024 * 8,
|
||||
}),
|
||||
gulpImagemin.svgo({}),
|
||||
imageminPngquant({
|
||||
speed: 1,
|
||||
strip: true,
|
||||
quality: [0.65, 0.9],
|
||||
dithering: false,
|
||||
verbose: false,
|
||||
}),
|
||||
gulpImagemin.optipng({
|
||||
optimizationLevel: 3,
|
||||
}),
|
||||
imageminGifsicle({
|
||||
optimizationLevel: 3,
|
||||
colors: 128,
|
||||
}),
|
||||
];
|
||||
// Lossy options
|
||||
const minifyImagesOpts = () => [
|
||||
gulpImagemin.mozjpeg({
|
||||
quality: 80,
|
||||
maxMemory: 1024 * 1024 * 8,
|
||||
}),
|
||||
gulpImagemin.svgo({}),
|
||||
imageminPngquant({
|
||||
speed: 1,
|
||||
strip: true,
|
||||
quality: [0.65, 0.9],
|
||||
dithering: false,
|
||||
verbose: false,
|
||||
}),
|
||||
gulpImagemin.optipng({
|
||||
optimizationLevel: 3,
|
||||
}),
|
||||
imageminGifsicle({
|
||||
optimizationLevel: 3,
|
||||
colors: 128,
|
||||
}),
|
||||
];
|
||||
|
||||
// Where the resources folder are
|
||||
const resourcesDestFolder = path.join(buildFolder, "res");
|
||||
// Where the resources folder are
|
||||
const resourcesDestFolder = path.join(buildFolder, "res");
|
||||
|
||||
/**
|
||||
* Determines if an atlas must use lossless compression
|
||||
* @param {string} fname
|
||||
*/
|
||||
function fileMustBeLossless(fname) {
|
||||
return fname.indexOf("lossless") >= 0;
|
||||
}
|
||||
|
||||
/////////////// ATLAS /////////////////////
|
||||
|
||||
gulp.task("imgres.buildAtlas", cb => {
|
||||
const config = JSON.stringify("../res_raw/atlas.json");
|
||||
const source = JSON.stringify("../res_raw");
|
||||
const dest = JSON.stringify("../res_built/atlas");
|
||||
|
||||
try {
|
||||
// First check whether Java is installed
|
||||
execute("java -version");
|
||||
// Now check and try downloading runnable-texturepacker.jar (22MB)
|
||||
if (!fs.existsSync("./runnable-texturepacker.jar")) {
|
||||
const escapedLink = JSON.stringify(runnableTPSource);
|
||||
|
||||
try {
|
||||
execute(`curl -o runnable-texturepacker.jar ${escapedLink}`);
|
||||
} catch {
|
||||
throw new Error("Failed to download runnable-texturepacker.jar!");
|
||||
}
|
||||
}
|
||||
|
||||
execute(`java -jar runnable-texturepacker.jar ${source} ${dest} atlas0 ${config}`);
|
||||
} catch {
|
||||
console.warn("Building atlas failed. Java not found / unsupported version?");
|
||||
}
|
||||
cb();
|
||||
});
|
||||
|
||||
// Converts .atlas LibGDX files to JSON
|
||||
gulp.task("imgres.atlasToJson", cb => {
|
||||
atlasToJson("../res_built/atlas");
|
||||
cb();
|
||||
});
|
||||
|
||||
// Copies the atlas to the final destination
|
||||
gulp.task("imgres.atlas", () => {
|
||||
return gulp.src(["../res_built/atlas/*.png"]).pipe(gulp.dest(resourcesDestFolder));
|
||||
});
|
||||
|
||||
// Copies the atlas to the final destination after optimizing it (lossy compression)
|
||||
gulp.task("imgres.atlasOptimized", () => {
|
||||
return gulp
|
||||
.src(["../res_built/atlas/*.png"])
|
||||
.pipe(
|
||||
gulpIf(
|
||||
fname => fileMustBeLossless(fname.history[0]),
|
||||
gulpImagemin(minifyImagesOptsLossless()),
|
||||
gulpImagemin(minifyImagesOpts())
|
||||
)
|
||||
)
|
||||
.pipe(gulp.dest(resourcesDestFolder));
|
||||
});
|
||||
|
||||
//////////////////// RESOURCES //////////////////////
|
||||
|
||||
// Copies all resources which are no ui resources
|
||||
gulp.task("imgres.copyNonImageResources", () => {
|
||||
return gulp.src(nonImageResourcesGlobs).pipe(gulp.dest(resourcesDestFolder));
|
||||
});
|
||||
|
||||
// Copies all ui resources
|
||||
gulp.task("imgres.copyImageResources", () => {
|
||||
return gulp
|
||||
.src(imageResourcesGlobs)
|
||||
|
||||
.pipe(gulpCached("imgres.copyImageResources"))
|
||||
.pipe(gulp.dest(path.join(resourcesDestFolder)));
|
||||
});
|
||||
|
||||
// Copies all ui resources and optimizes them
|
||||
gulp.task("imgres.copyImageResourcesOptimized", () => {
|
||||
return gulp
|
||||
.src(imageResourcesGlobs)
|
||||
.pipe(
|
||||
gulpIf(
|
||||
fname => fileMustBeLossless(fname.history[0]),
|
||||
gulpImagemin(minifyImagesOptsLossless()),
|
||||
gulpImagemin(minifyImagesOpts())
|
||||
)
|
||||
)
|
||||
.pipe(gulp.dest(path.join(resourcesDestFolder)));
|
||||
});
|
||||
|
||||
// Copies all resources and optimizes them
|
||||
gulp.task(
|
||||
"imgres.allOptimized",
|
||||
gulp.parallel(
|
||||
"imgres.buildAtlas",
|
||||
"imgres.atlasToJson",
|
||||
"imgres.atlasOptimized",
|
||||
"imgres.copyNonImageResources",
|
||||
"imgres.copyImageResourcesOptimized"
|
||||
)
|
||||
);
|
||||
|
||||
// Cleans up unused images which are instead inline into the css
|
||||
gulp.task("imgres.cleanupUnusedCssInlineImages", () => {
|
||||
return gulp
|
||||
.src(
|
||||
[
|
||||
path.join(buildFolder, "res", "ui", "**", "*.png"),
|
||||
path.join(buildFolder, "res", "ui", "**", "*.jpg"),
|
||||
path.join(buildFolder, "res", "ui", "**", "*.svg"),
|
||||
path.join(buildFolder, "res", "ui", "**", "*.gif"),
|
||||
],
|
||||
{ read: false }
|
||||
)
|
||||
.pipe(gulpIf(fname => fname.history[0].indexOf("noinline") < 0, gulpClean({ force: true })));
|
||||
});
|
||||
/**
|
||||
* Determines if an atlas must use lossless compression
|
||||
* @param {string} fname
|
||||
*/
|
||||
function fileMustBeLossless(fname) {
|
||||
return fname.indexOf("lossless") >= 0;
|
||||
}
|
||||
|
||||
/////////////// ATLAS /////////////////////
|
||||
|
||||
export async function buildAtlas() {
|
||||
const config = JSON.stringify("../res_raw/atlas.json");
|
||||
const source = JSON.stringify("../res_raw");
|
||||
const dest = JSON.stringify("../res_built/atlas");
|
||||
|
||||
try {
|
||||
// First check whether Java is installed
|
||||
await execute("java -version");
|
||||
// Now check and try downloading runnable-texturepacker.jar (22MB)
|
||||
try {
|
||||
await fs.access("./runnable-texturepacker.jar");
|
||||
} catch {
|
||||
const escapedLink = JSON.stringify(runnableTPSource);
|
||||
|
||||
try {
|
||||
execute(`curl -o runnable-texturepacker.jar ${escapedLink}`);
|
||||
} catch {
|
||||
throw new Error("Failed to download runnable-texturepacker.jar!");
|
||||
}
|
||||
}
|
||||
|
||||
await execute(`java -jar runnable-texturepacker.jar ${source} ${dest} atlas0 ${config}`);
|
||||
} catch {
|
||||
console.warn("Building atlas failed. Java not found / unsupported version?");
|
||||
}
|
||||
}
|
||||
|
||||
// Converts .atlas LibGDX files to JSON
|
||||
export async function atlasToJson() {
|
||||
atlas2Json("../res_built/atlas");
|
||||
}
|
||||
|
||||
// Copies the atlas to the final destination
|
||||
export function atlas() {
|
||||
return gulp.src(["../res_built/atlas/*.png"]).pipe(gulp.dest(resourcesDestFolder));
|
||||
}
|
||||
|
||||
// Copies the atlas to the final destination after optimizing it (lossy compression)
|
||||
export function atlasOptimized() {
|
||||
return gulp
|
||||
.src(["../res_built/atlas/*.png"])
|
||||
.pipe(
|
||||
gulpIf(
|
||||
fname => fileMustBeLossless(fname.history[0]),
|
||||
gulpImagemin(minifyImagesOptsLossless()),
|
||||
gulpImagemin(minifyImagesOpts())
|
||||
)
|
||||
)
|
||||
.pipe(gulp.dest(resourcesDestFolder));
|
||||
}
|
||||
|
||||
//////////////////// RESOURCES //////////////////////
|
||||
|
||||
// Copies all resources which are no ui resources
|
||||
export function copyNonImageResources() {
|
||||
return gulp.src(nonImageResourcesGlobs).pipe(gulp.dest(resourcesDestFolder));
|
||||
}
|
||||
|
||||
// Copies all ui resources
|
||||
export function copyImageResources() {
|
||||
return gulp
|
||||
.src(imageResourcesGlobs)
|
||||
.pipe(gulpCached("imgres.copyImageResources"))
|
||||
.pipe(gulp.dest(path.join(resourcesDestFolder)));
|
||||
}
|
||||
|
||||
// Copies all ui resources and optimizes them
|
||||
export function copyImageResourcesOptimized() {
|
||||
return gulp
|
||||
.src(imageResourcesGlobs)
|
||||
.pipe(
|
||||
gulpIf(
|
||||
fname => fileMustBeLossless(fname.history[0]),
|
||||
gulpImagemin(minifyImagesOptsLossless()),
|
||||
gulpImagemin(minifyImagesOpts())
|
||||
)
|
||||
)
|
||||
.pipe(gulp.dest(path.join(resourcesDestFolder)));
|
||||
}
|
||||
|
||||
// Copies all resources and optimizes them
|
||||
export const allOptimized = gulp.parallel(
|
||||
gulp.series(buildAtlas, atlasToJson, atlasOptimized),
|
||||
copyNonImageResources,
|
||||
copyImageResourcesOptimized
|
||||
);
|
||||
|
||||
// Cleans up unused images which are instead inline into the css
|
||||
export function cleanupUnusedCssInlineImages() {
|
||||
return gulp
|
||||
.src(
|
||||
[
|
||||
path.join(buildFolder, "res", "ui", "**", "*.png"),
|
||||
path.join(buildFolder, "res", "ui", "**", "*.jpg"),
|
||||
path.join(buildFolder, "res", "ui", "**", "*.svg"),
|
||||
path.join(buildFolder, "res", "ui", "**", "*.gif"),
|
||||
],
|
||||
{ read: false }
|
||||
)
|
||||
.pipe(gulpIf(fname => fname.history[0].indexOf("noinline") < 0, gulpClean({ force: true })));
|
||||
}
|
||||
|
||||
77
gulp/js.js
77
gulp/js.js
@ -1,4 +1,6 @@
|
||||
import gulp from "gulp";
|
||||
import { BUILD_VARIANTS } from "./build_variants.js";
|
||||
import { buildFolder, browserSync } from "./config.js";
|
||||
|
||||
import webpackConfig from "./webpack.config.js";
|
||||
import webpackProductionConfig from "./webpack.production.config.js";
|
||||
@ -15,64 +17,69 @@ import gulpRename from "gulp-rename";
|
||||
*
|
||||
*/
|
||||
|
||||
export default function gulptasksJS(gulp, buildFolder, browserSync) {
|
||||
//// DEV
|
||||
//// DEV
|
||||
|
||||
for (const variant in BUILD_VARIANTS) {
|
||||
const data = BUILD_VARIANTS[variant];
|
||||
|
||||
gulp.task("js." + variant + ".dev.watch", () => {
|
||||
gulp.src("../src/js/main.js")
|
||||
export default Object.fromEntries(
|
||||
Object.entries(BUILD_VARIANTS).map(([variant, data]) => {
|
||||
function watch() {
|
||||
return gulp
|
||||
.src("../src/js/main.js")
|
||||
.pipe(webpackStream(webpackConfig))
|
||||
.pipe(gulp.dest(buildFolder))
|
||||
.pipe(browserSync.stream());
|
||||
});
|
||||
}
|
||||
|
||||
function build() {
|
||||
return gulp
|
||||
.src("../src/js/main.js")
|
||||
.pipe(webpackStream(webpackConfig))
|
||||
.pipe(gulp.dest(buildFolder));
|
||||
}
|
||||
|
||||
const dev = {
|
||||
watch,
|
||||
build,
|
||||
};
|
||||
|
||||
let prod;
|
||||
if (!data.standalone) {
|
||||
// WEB
|
||||
|
||||
gulp.task("js." + variant + ".dev", () => {
|
||||
return gulp
|
||||
.src("../src/js/main.js")
|
||||
.pipe(webpackStream(webpackConfig))
|
||||
.pipe(gulp.dest(buildFolder));
|
||||
});
|
||||
|
||||
gulp.task("js." + variant + ".prod.transpiled", () => {
|
||||
function transpiled() {
|
||||
return gulp
|
||||
.src("../src/js/main.js")
|
||||
.pipe(webpackStream(webpackProductionConfig))
|
||||
.pipe(gulpRename("bundle-transpiled.js"))
|
||||
.pipe(gulp.dest(buildFolder));
|
||||
});
|
||||
}
|
||||
|
||||
gulp.task("js." + variant + ".prod.es6", () => {
|
||||
function es6() {
|
||||
return gulp
|
||||
.src("../src/js/main.js")
|
||||
.pipe(webpackStream(webpackProductionConfig))
|
||||
.pipe(gulp.dest(buildFolder));
|
||||
});
|
||||
gulp.task(
|
||||
"js." + variant + ".prod",
|
||||
}
|
||||
|
||||
// transpiled currently not used
|
||||
// gulp.parallel("js." + variant + ".prod.transpiled", "js." + variant + ".prod.es6")
|
||||
gulp.parallel("js." + variant + ".prod.es6")
|
||||
);
|
||||
prod = {
|
||||
transpiled,
|
||||
es6,
|
||||
build:
|
||||
// transpiled currently not used
|
||||
// gulp.parallel("js." + variant + ".prod.transpiled", "js." + variant + ".prod.es6")
|
||||
es6,
|
||||
};
|
||||
} else {
|
||||
// STANDALONE
|
||||
gulp.task("js." + variant + ".dev", () => {
|
||||
return gulp
|
||||
.src("../src/js/main.js")
|
||||
.pipe(webpackStream(webpackConfig))
|
||||
.pipe(gulp.dest(buildFolder));
|
||||
});
|
||||
gulp.task("js." + variant + ".prod", () => {
|
||||
function build() {
|
||||
return gulp
|
||||
.src("../src/js/main.js")
|
||||
.pipe(webpackStream(webpackProductionConfig))
|
||||
.pipe(gulp.dest(buildFolder));
|
||||
});
|
||||
}
|
||||
|
||||
prod = { build };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return [variant, { dev, prod }];
|
||||
})
|
||||
);
|
||||
|
||||
@ -1,14 +1,10 @@
|
||||
import fs from "fs";
|
||||
import fs from "fs/promises";
|
||||
|
||||
const configTemplatePath = "../src/js/core/config.local.template.js";
|
||||
const configPath = "../src/js/core/config.local.js";
|
||||
|
||||
export default function gulptasksLocalConfig(gulp) {
|
||||
gulp.task("localConfig.findOrCreate", cb => {
|
||||
if (!fs.existsSync(configPath)) {
|
||||
fs.copyFileSync(configTemplatePath, configPath);
|
||||
}
|
||||
|
||||
cb();
|
||||
});
|
||||
export async function findOrCreate() {
|
||||
try {
|
||||
await fs.copyFile(configTemplatePath, configPath, fs.constants.COPYFILE_EXCL);
|
||||
} catch {}
|
||||
}
|
||||
|
||||
229
gulp/sounds.js
229
gulp/sounds.js
@ -1,135 +1,132 @@
|
||||
import path from "path/posix";
|
||||
import audiosprite from "gulp-audiosprite";
|
||||
import gulp from "gulp";
|
||||
import { buildFolder } from "./config.js";
|
||||
|
||||
import gulpAudiosprite from "gulp-audiosprite";
|
||||
import gulpClean from "gulp-clean";
|
||||
import gulpCache from "gulp-cache";
|
||||
import gulpPlumber from "gulp-plumber";
|
||||
import gulpFluentFfmpeg from "gulp-fluent-ffmpeg";
|
||||
|
||||
export default function gulptasksSounds(gulp, buildFolder) {
|
||||
// Gather some basic infos
|
||||
const soundsDir = path.join("..", "res_raw", "sounds");
|
||||
const builtSoundsDir = path.join("..", "res_built", "sounds");
|
||||
// Gather some basic infos
|
||||
const soundsDir = path.join("..", "res_raw", "sounds");
|
||||
const builtSoundsDir = path.join("..", "res_built", "sounds");
|
||||
|
||||
gulp.task("sounds.clear", () => {
|
||||
return gulp.src(builtSoundsDir, { read: false, allowEmpty: true }).pipe(gulpClean({ force: true }));
|
||||
});
|
||||
export function clear() {
|
||||
return gulp.src(builtSoundsDir, { read: false, allowEmpty: true }).pipe(gulpClean({ force: true }));
|
||||
}
|
||||
|
||||
const filters = ["volume=0.2"];
|
||||
const filters = ["volume=0.2"];
|
||||
|
||||
const fileCache = new gulpCache.Cache({
|
||||
cacheDirName: "shapezio-precompiled-sounds",
|
||||
});
|
||||
const fileCache = new gulpCache.Cache({
|
||||
cacheDirName: "shapezio-precompiled-sounds",
|
||||
});
|
||||
|
||||
function getFileCacheValue(file) {
|
||||
const { _isVinyl, base, cwd, contents, history, stat, path } = file;
|
||||
const encodedContents = Buffer.from(contents).toString("base64");
|
||||
return { _isVinyl, base, cwd, contents: encodedContents, history, stat, path };
|
||||
}
|
||||
function getFileCacheValue(file) {
|
||||
const { _isVinyl, base, cwd, contents, history, stat, path } = file;
|
||||
const encodedContents = Buffer.from(contents).toString("base64");
|
||||
return { _isVinyl, base, cwd, contents: encodedContents, history, stat, path };
|
||||
}
|
||||
|
||||
// Encodes the game music
|
||||
gulp.task("sounds.music", () => {
|
||||
return gulp
|
||||
.src([path.join(soundsDir, "music", "**", "*.wav"), path.join(soundsDir, "music", "**", "*.mp3")])
|
||||
.pipe(gulpPlumber())
|
||||
.pipe(
|
||||
gulpCache(
|
||||
gulpFluentFfmpeg("mp3", function (cmd) {
|
||||
return cmd
|
||||
.audioBitrate(48)
|
||||
.audioChannels(1)
|
||||
.audioFrequency(22050)
|
||||
.audioCodec("libmp3lame")
|
||||
.audioFilters(["volume=0.15"]);
|
||||
}),
|
||||
{
|
||||
name: "music",
|
||||
fileCache,
|
||||
value: getFileCacheValue,
|
||||
}
|
||||
)
|
||||
)
|
||||
.pipe(gulp.dest(path.join(builtSoundsDir, "music")));
|
||||
});
|
||||
|
||||
// Encodes the game music in high quality for the standalone
|
||||
gulp.task("sounds.musicHQ", () => {
|
||||
return gulp
|
||||
.src([path.join(soundsDir, "music", "**", "*.wav"), path.join(soundsDir, "music", "**", "*.mp3")])
|
||||
.pipe(gulpPlumber())
|
||||
.pipe(
|
||||
gulpCache(
|
||||
gulpFluentFfmpeg("mp3", function (cmd) {
|
||||
return cmd
|
||||
.audioBitrate(256)
|
||||
.audioChannels(2)
|
||||
.audioFrequency(44100)
|
||||
.audioCodec("libmp3lame")
|
||||
.audioFilters(["volume=0.15"]);
|
||||
}),
|
||||
{
|
||||
name: "music-high-quality",
|
||||
fileCache,
|
||||
value: getFileCacheValue,
|
||||
}
|
||||
)
|
||||
)
|
||||
.pipe(gulp.dest(path.join(builtSoundsDir, "music")));
|
||||
});
|
||||
|
||||
// Encodes the ui sounds
|
||||
gulp.task("sounds.sfxGenerateSprites", () => {
|
||||
return gulp
|
||||
.src([path.join(soundsDir, "sfx", "**", "*.wav"), path.join(soundsDir, "sfx", "**", "*.mp3")])
|
||||
.pipe(gulpPlumber())
|
||||
.pipe(
|
||||
audiosprite({
|
||||
format: "howler",
|
||||
output: "sfx",
|
||||
gap: 0.1,
|
||||
export: "mp3",
|
||||
})
|
||||
)
|
||||
.pipe(gulp.dest(path.join(builtSoundsDir)));
|
||||
});
|
||||
gulp.task("sounds.sfxOptimize", () => {
|
||||
return gulp
|
||||
.src([path.join(builtSoundsDir, "sfx.mp3")])
|
||||
.pipe(gulpPlumber())
|
||||
.pipe(
|
||||
// Encodes the game music
|
||||
export function music() {
|
||||
return gulp
|
||||
.src([path.join(soundsDir, "music", "**", "*.wav"), path.join(soundsDir, "music", "**", "*.mp3")])
|
||||
.pipe(gulpPlumber())
|
||||
.pipe(
|
||||
gulpCache(
|
||||
gulpFluentFfmpeg("mp3", function (cmd) {
|
||||
return cmd
|
||||
.audioBitrate(128)
|
||||
.audioBitrate(48)
|
||||
.audioChannels(1)
|
||||
.audioFrequency(22050)
|
||||
.audioCodec("libmp3lame")
|
||||
.audioFilters(filters);
|
||||
})
|
||||
.audioFilters(["volume=0.15"]);
|
||||
}),
|
||||
{
|
||||
name: "music",
|
||||
fileCache,
|
||||
value: getFileCacheValue,
|
||||
}
|
||||
)
|
||||
.pipe(gulp.dest(path.join(builtSoundsDir)));
|
||||
});
|
||||
gulp.task("sounds.sfxCopyAtlas", () => {
|
||||
return gulp
|
||||
.src([path.join(builtSoundsDir, "sfx.json")])
|
||||
.pipe(gulp.dest(path.join("..", "src", "js", "built-temp")));
|
||||
});
|
||||
|
||||
gulp.task(
|
||||
"sounds.sfx",
|
||||
gulp.series("sounds.sfxGenerateSprites", "sounds.sfxOptimize", "sounds.sfxCopyAtlas")
|
||||
);
|
||||
|
||||
gulp.task("sounds.copy", () => {
|
||||
return gulp
|
||||
.src(path.join(builtSoundsDir, "**", "*.mp3"))
|
||||
.pipe(gulpPlumber())
|
||||
.pipe(gulp.dest(path.join(buildFolder, "res", "sounds")));
|
||||
});
|
||||
|
||||
gulp.task("sounds.buildall", gulp.parallel("sounds.music", "sounds.sfx"));
|
||||
gulp.task("sounds.buildallHQ", gulp.parallel("sounds.musicHQ", "sounds.sfx"));
|
||||
|
||||
gulp.task("sounds.fullbuild", gulp.series("sounds.clear", "sounds.buildall", "sounds.copy"));
|
||||
gulp.task("sounds.fullbuildHQ", gulp.series("sounds.clear", "sounds.buildallHQ", "sounds.copy"));
|
||||
gulp.task("sounds.dev", gulp.series("sounds.buildall", "sounds.copy"));
|
||||
)
|
||||
.pipe(gulp.dest(path.join(builtSoundsDir, "music")));
|
||||
}
|
||||
|
||||
// Encodes the game music in high quality for the standalone
|
||||
export function musicHQ() {
|
||||
return gulp
|
||||
.src([path.join(soundsDir, "music", "**", "*.wav"), path.join(soundsDir, "music", "**", "*.mp3")])
|
||||
.pipe(gulpPlumber())
|
||||
.pipe(
|
||||
gulpCache(
|
||||
gulpFluentFfmpeg("mp3", function (cmd) {
|
||||
return cmd
|
||||
.audioBitrate(256)
|
||||
.audioChannels(2)
|
||||
.audioFrequency(44100)
|
||||
.audioCodec("libmp3lame")
|
||||
.audioFilters(["volume=0.15"]);
|
||||
}),
|
||||
{
|
||||
name: "music-high-quality",
|
||||
fileCache,
|
||||
value: getFileCacheValue,
|
||||
}
|
||||
)
|
||||
)
|
||||
.pipe(gulp.dest(path.join(builtSoundsDir, "music")));
|
||||
}
|
||||
|
||||
// Encodes the ui sounds
|
||||
export function sfxGenerateSprites() {
|
||||
return gulp
|
||||
.src([path.join(soundsDir, "sfx", "**", "*.wav"), path.join(soundsDir, "sfx", "**", "*.mp3")])
|
||||
.pipe(gulpPlumber())
|
||||
.pipe(
|
||||
gulpAudiosprite({
|
||||
format: "howler",
|
||||
output: "sfx",
|
||||
gap: 0.1,
|
||||
export: "mp3",
|
||||
})
|
||||
)
|
||||
.pipe(gulp.dest(path.join(builtSoundsDir)));
|
||||
}
|
||||
export function sfxOptimize() {
|
||||
return gulp
|
||||
.src([path.join(builtSoundsDir, "sfx.mp3")])
|
||||
.pipe(gulpPlumber())
|
||||
.pipe(
|
||||
gulpFluentFfmpeg("mp3", function (cmd) {
|
||||
return cmd
|
||||
.audioBitrate(128)
|
||||
.audioChannels(1)
|
||||
.audioFrequency(22050)
|
||||
.audioCodec("libmp3lame")
|
||||
.audioFilters(filters);
|
||||
})
|
||||
)
|
||||
.pipe(gulp.dest(path.join(builtSoundsDir)));
|
||||
}
|
||||
export function sfxCopyAtlas() {
|
||||
return gulp
|
||||
.src([path.join(builtSoundsDir, "sfx.json")])
|
||||
.pipe(gulp.dest(path.join("..", "src", "js", "built-temp")));
|
||||
}
|
||||
|
||||
export const sfx = gulp.series(sfxGenerateSprites, sfxOptimize, sfxCopyAtlas);
|
||||
|
||||
export function copy() {
|
||||
return gulp
|
||||
.src(path.join(builtSoundsDir, "**", "*.mp3"))
|
||||
.pipe(gulpPlumber())
|
||||
.pipe(gulp.dest(path.join(buildFolder, "res", "sounds")));
|
||||
}
|
||||
|
||||
export const buildall = gulp.parallel(music, sfx);
|
||||
export const buildallHQ = gulp.parallel(musicHQ, sfx);
|
||||
|
||||
export const fullbuild = gulp.series(clear, buildall, copy);
|
||||
export const fullbuildHQ = gulp.series(clear, buildallHQ, copy);
|
||||
export const dev = gulp.series(buildall, copy);
|
||||
|
||||
@ -2,8 +2,11 @@ import packager from "electron-packager";
|
||||
import pj from "../electron/package.json" assert { type: "json" };
|
||||
import path from "path/posix";
|
||||
import { getVersion } from "./buildutils.js";
|
||||
import fs from "fs";
|
||||
import { execSync } from "child_process";
|
||||
import fs from "fs/promises";
|
||||
import childProcess from "child_process";
|
||||
import { promisify } from "util";
|
||||
const exec = promisify(childProcess.exec);
|
||||
import gulp from "gulp";
|
||||
import { BUILD_VARIANTS } from "./build_variants.js";
|
||||
|
||||
import gulpClean from "gulp-clean";
|
||||
@ -11,121 +14,132 @@ import gulpClean from "gulp-clean";
|
||||
const platforms = /** @type {const} */ (["win32", "linux", "darwin"]);
|
||||
const architectures = /** @type {const} */ (["x64", "arm64"]);
|
||||
|
||||
export default function gulptasksStandalone(gulp) {
|
||||
for (const variant in BUILD_VARIANTS) {
|
||||
const variantData = BUILD_VARIANTS[variant];
|
||||
if (!variantData.standalone) {
|
||||
continue;
|
||||
}
|
||||
const tempDestDir = path.join("..", "build_output", variant);
|
||||
const taskPrefix = "standalone." + variant;
|
||||
const electronBaseDir = path.join("..", "electron");
|
||||
const tempDestBuildDir = path.join(tempDestDir, "built");
|
||||
export default Object.fromEntries(
|
||||
Object.entries(BUILD_VARIANTS)
|
||||
.filter(([variant, variantData]) => variantData.standalone)
|
||||
.map(([variant, variantData]) => {
|
||||
const tempDestDir = path.join("..", "build_output", variant);
|
||||
const electronBaseDir = path.join("..", "electron");
|
||||
const tempDestBuildDir = path.join(tempDestDir, "built");
|
||||
|
||||
gulp.task(taskPrefix + ".prepare.cleanup", () => {
|
||||
return gulp.src(tempDestDir, { read: false, allowEmpty: true }).pipe(gulpClean({ force: true }));
|
||||
});
|
||||
function cleanup() {
|
||||
return gulp
|
||||
.src(tempDestDir, { read: false, allowEmpty: true })
|
||||
.pipe(gulpClean({ force: true }));
|
||||
}
|
||||
|
||||
gulp.task(taskPrefix + ".prepare.copyPrefab", () => {
|
||||
const requiredFiles = [
|
||||
path.join(electronBaseDir, "node_modules", "**", "*.*"),
|
||||
path.join(electronBaseDir, "node_modules", "**", ".*"),
|
||||
path.join(electronBaseDir, "favicon*"),
|
||||
];
|
||||
return gulp.src(requiredFiles, { base: electronBaseDir }).pipe(gulp.dest(tempDestBuildDir));
|
||||
});
|
||||
function copyPrefab() {
|
||||
const requiredFiles = [
|
||||
path.join(electronBaseDir, "node_modules", "**", "*.*"),
|
||||
path.join(electronBaseDir, "node_modules", "**", ".*"),
|
||||
path.join(electronBaseDir, "favicon*"),
|
||||
];
|
||||
return gulp.src(requiredFiles, { base: electronBaseDir }).pipe(gulp.dest(tempDestBuildDir));
|
||||
}
|
||||
|
||||
gulp.task(taskPrefix + ".prepare.writePackageJson", cb => {
|
||||
const packageJsonString = JSON.stringify(
|
||||
{
|
||||
scripts: {
|
||||
start: pj.scripts.start,
|
||||
async function writePackageJson() {
|
||||
const packageJsonString = JSON.stringify(
|
||||
{
|
||||
scripts: {
|
||||
start: pj.scripts.start,
|
||||
},
|
||||
devDependencies: pj.devDependencies,
|
||||
dependencies: pj.dependencies,
|
||||
optionalDependencies: pj.optionalDependencies,
|
||||
},
|
||||
devDependencies: pj.devDependencies,
|
||||
dependencies: pj.dependencies,
|
||||
optionalDependencies: pj.optionalDependencies,
|
||||
},
|
||||
null,
|
||||
4
|
||||
);
|
||||
null,
|
||||
4
|
||||
);
|
||||
|
||||
fs.writeFileSync(path.join(tempDestBuildDir, "package.json"), packageJsonString);
|
||||
|
||||
cb();
|
||||
});
|
||||
|
||||
gulp.task(taskPrefix + ".prepare.minifyCode", () => {
|
||||
return gulp.src(path.join(electronBaseDir, "*.js")).pipe(gulp.dest(tempDestBuildDir));
|
||||
});
|
||||
|
||||
gulp.task(taskPrefix + ".prepare.copyGamefiles", () => {
|
||||
return gulp.src("../build/**/*.*", { base: "../build" }).pipe(gulp.dest(tempDestBuildDir));
|
||||
});
|
||||
|
||||
gulp.task(taskPrefix + ".killRunningInstances", cb => {
|
||||
try {
|
||||
execSync("taskkill /F /IM shapezio.exe");
|
||||
} catch (ex) {
|
||||
console.warn("Failed to kill running instances, maybe none are up.");
|
||||
}
|
||||
cb();
|
||||
});
|
||||
|
||||
gulp.task(
|
||||
taskPrefix + ".prepare",
|
||||
gulp.series(
|
||||
taskPrefix + ".killRunningInstances",
|
||||
taskPrefix + ".prepare.cleanup",
|
||||
taskPrefix + ".prepare.copyPrefab",
|
||||
taskPrefix + ".prepare.writePackageJson",
|
||||
taskPrefix + ".prepare.minifyCode",
|
||||
taskPrefix + ".prepare.copyGamefiles"
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {typeof platforms[number] | (typeof platforms[number])[]} platform
|
||||
* @param {typeof architectures[number] | (typeof architectures[number])[]} arch
|
||||
* @param {function():void} cb
|
||||
*/
|
||||
async function packageStandalone(platform, arch, cb) {
|
||||
const appPaths = await packager({
|
||||
dir: tempDestBuildDir,
|
||||
appCopyright: "tobspr Games",
|
||||
appVersion: getVersion(),
|
||||
buildVersion: "1.0.0",
|
||||
arch,
|
||||
platform,
|
||||
asar: true,
|
||||
executableName: "shapezio",
|
||||
icon: path.join(electronBaseDir, "favicon"),
|
||||
name: "shapez",
|
||||
out: tempDestDir,
|
||||
overwrite: true,
|
||||
appBundleId: "tobspr.shapezio." + variant,
|
||||
appCategoryType: "public.app-category.games",
|
||||
});
|
||||
|
||||
console.log("Packages created:", appPaths);
|
||||
for (const appPath of appPaths) {
|
||||
fs.writeFileSync(path.join(appPath, "LICENSE"), fs.readFileSync(path.join("..", "LICENSE")));
|
||||
await fs.writeFile(path.join(tempDestBuildDir, "package.json"), packageJsonString);
|
||||
}
|
||||
|
||||
cb();
|
||||
}
|
||||
function minifyCode() {
|
||||
return gulp.src(path.join(electronBaseDir, "*.js")).pipe(gulp.dest(tempDestBuildDir));
|
||||
}
|
||||
|
||||
for (const platform of platforms) {
|
||||
for (const arch of architectures) {
|
||||
gulp.task(taskPrefix + `.package.${platform}-${arch}`, cb =>
|
||||
packageStandalone(platform, arch, cb)
|
||||
function copyGamefiles() {
|
||||
return gulp.src("../build/**/*.*", { base: "../build" }).pipe(gulp.dest(tempDestBuildDir));
|
||||
}
|
||||
|
||||
async function killRunningInstances() {
|
||||
try {
|
||||
await exec("taskkill /F /IM shapezio.exe");
|
||||
} catch (ex) {
|
||||
console.warn("Failed to kill running instances, maybe none are up.");
|
||||
}
|
||||
}
|
||||
|
||||
const prepare = {
|
||||
cleanup,
|
||||
copyPrefab,
|
||||
writePackageJson,
|
||||
minifyCode,
|
||||
copyGamefiles,
|
||||
all: gulp.series(
|
||||
killRunningInstances,
|
||||
cleanup,
|
||||
copyPrefab,
|
||||
writePackageJson,
|
||||
minifyCode,
|
||||
copyGamefiles
|
||||
),
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {typeof platforms[number] | (typeof platforms[number])[]} platform
|
||||
* @param {typeof architectures[number] | (typeof architectures[number])[]} arch
|
||||
*/
|
||||
async function packageStandalone(platform, arch) {
|
||||
const appPaths = await packager({
|
||||
dir: tempDestBuildDir,
|
||||
appCopyright: "tobspr Games",
|
||||
appVersion: getVersion(),
|
||||
buildVersion: "1.0.0",
|
||||
arch,
|
||||
platform,
|
||||
asar: true,
|
||||
executableName: "shapezio",
|
||||
icon: path.join(electronBaseDir, "favicon"),
|
||||
name: "shapez",
|
||||
out: tempDestDir,
|
||||
overwrite: true,
|
||||
appBundleId: "tobspr.shapezio." + variant,
|
||||
appCategoryType: "public.app-category.games",
|
||||
});
|
||||
|
||||
console.log("Packages created:", appPaths);
|
||||
await Promise.all(
|
||||
appPaths.map(async appPath => {
|
||||
await fs.writeFile(
|
||||
path.join(appPath, "LICENSE"),
|
||||
await fs.readFile(path.join("..", "LICENSE"))
|
||||
);
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Review this hack forced by readonly types
|
||||
gulp.task(taskPrefix + ".package.all", cb =>
|
||||
packageStandalone([...platforms], [...architectures], cb)
|
||||
);
|
||||
}
|
||||
}
|
||||
const pack = {
|
||||
...Object.fromEntries(
|
||||
platforms.flatMap(platform =>
|
||||
architectures.map(arch => [
|
||||
`${platform}-${arch}`,
|
||||
() => packageStandalone(platform, arch),
|
||||
])
|
||||
)
|
||||
),
|
||||
// TODO: Review this hack forced by readonly types
|
||||
all: () => packageStandalone([...platforms], [...architectures]),
|
||||
};
|
||||
|
||||
return [
|
||||
variant,
|
||||
{
|
||||
killRunningInstances,
|
||||
prepare,
|
||||
package: pack,
|
||||
},
|
||||
];
|
||||
})
|
||||
);
|
||||
|
||||
304
gulp/tasks.js
Normal file
304
gulp/tasks.js
Normal file
@ -0,0 +1,304 @@
|
||||
import gulp from "gulp";
|
||||
import path from "path/posix";
|
||||
import pathNative from "path";
|
||||
import delEmpty from "delete-empty";
|
||||
import childProcess from "child_process";
|
||||
import { promisify } from "util";
|
||||
const exec = promisify(childProcess.exec);
|
||||
import { BUILD_VARIANTS } from "./build_variants.js";
|
||||
import {
|
||||
baseDir,
|
||||
buildFolder,
|
||||
buildOutputFolder,
|
||||
browserSync,
|
||||
rawImageResourcesGlobs,
|
||||
nonImageResourcesGlobs,
|
||||
imageResourcesGlobs,
|
||||
} from "./config.js";
|
||||
|
||||
// Load other plugins
|
||||
import gulpClean from "gulp-clean";
|
||||
import gulpWebserver from "gulp-webserver";
|
||||
|
||||
import * as imgres from "./image-resources.js";
|
||||
import * as css from "./css.js";
|
||||
import * as sounds from "./sounds.js";
|
||||
import * as localConfig from "./local-config.js";
|
||||
import js from "./js.js";
|
||||
import * as html from "./html.js";
|
||||
import * as ftp from "./ftp.js";
|
||||
import * as docs from "./docs.js";
|
||||
import standalone from "./standalone.js";
|
||||
import * as translations from "./translations.js";
|
||||
|
||||
export { imgres, css, sounds, localConfig, js, html, ftp, docs, standalone, translations };
|
||||
|
||||
///////////////////// BUILD TASKS /////////////////////
|
||||
|
||||
// Cleans up everything
|
||||
function cleanBuildFolder() {
|
||||
return gulp.src(buildFolder, { read: false, allowEmpty: true }).pipe(gulpClean({ force: true }));
|
||||
}
|
||||
function cleanBuildOutputFolder() {
|
||||
return gulp.src(buildOutputFolder, { read: false, allowEmpty: true }).pipe(gulpClean({ force: true }));
|
||||
}
|
||||
function cleanBuildTempFolder() {
|
||||
return gulp
|
||||
.src(path.join("..", "src", "js", "built-temp"), { read: false, allowEmpty: true })
|
||||
.pipe(gulpClean({ force: true }));
|
||||
}
|
||||
function cleanImageBuildFolder() {
|
||||
return gulp
|
||||
.src(path.join("res_built"), { read: false, allowEmpty: true })
|
||||
.pipe(gulpClean({ force: true }));
|
||||
}
|
||||
|
||||
const cleanup = gulp.series(cleanBuildFolder, cleanImageBuildFolder, cleanBuildTempFolder);
|
||||
|
||||
// Requires no uncomitted files
|
||||
async function requireCleanWorkingTree() {
|
||||
let output = (await exec("git status -su", { encoding: "buffer" })).stdout
|
||||
.toString("ascii")
|
||||
.trim()
|
||||
.replace(/\r/gi, "")
|
||||
.split("\n");
|
||||
|
||||
// Filter files which are OK to be untracked
|
||||
output = output
|
||||
.map(x => x.replace(/[\r\n]+/gi, ""))
|
||||
.filter(x => x.indexOf(".local.js") < 0)
|
||||
.filter(x => x.length > 0);
|
||||
if (output.length > 0) {
|
||||
console.error("\n\nYou have unstaged changes, please commit everything first!");
|
||||
console.error("Unstaged files:");
|
||||
console.error(output.map(x => "'" + x + "'").join("\n"));
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
function copyAdditionalBuildFiles() {
|
||||
const additionalFolder = path.join("additional_build_files");
|
||||
const additionalSrcGlobs = [
|
||||
path.join(additionalFolder, "**/*.*"),
|
||||
path.join(additionalFolder, "**/.*"),
|
||||
path.join(additionalFolder, "**/*"),
|
||||
];
|
||||
|
||||
return gulp.src(additionalSrcGlobs).pipe(gulp.dest(buildFolder));
|
||||
}
|
||||
|
||||
export const utils = {
|
||||
cleanBuildFolder,
|
||||
cleanBuildOutputFolder,
|
||||
cleanBuildTempFolder,
|
||||
cleanImageBuildFolder,
|
||||
cleanup,
|
||||
requireCleanWorkingTree,
|
||||
copyAdditionalBuildFiles,
|
||||
};
|
||||
|
||||
// Starts a webserver on the built directory (useful for testing prod build)
|
||||
function webserver() {
|
||||
return gulp.src(buildFolder).pipe(
|
||||
gulpWebserver({
|
||||
livereload: {
|
||||
enable: true,
|
||||
},
|
||||
directoryListing: false,
|
||||
open: true,
|
||||
port: 3005,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {object} param0
|
||||
* @param {keyof typeof BUILD_VARIANTS} param0.version
|
||||
*/
|
||||
function serveHTML({ version = "web-dev" }) {
|
||||
browserSync.init({
|
||||
server: [buildFolder, path.join(baseDir, "mod_examples")],
|
||||
port: 3005,
|
||||
ghostMode: {
|
||||
clicks: false,
|
||||
scroll: false,
|
||||
location: false,
|
||||
forms: false,
|
||||
},
|
||||
logLevel: "info",
|
||||
logPrefix: "BS",
|
||||
online: false,
|
||||
xip: false,
|
||||
notify: false,
|
||||
reloadDebounce: 100,
|
||||
reloadOnRestart: true,
|
||||
watchEvents: ["add", "change"],
|
||||
});
|
||||
|
||||
// Watch .scss files, those trigger a css rebuild
|
||||
gulp.watch(["../src/**/*.scss"], css.dev);
|
||||
|
||||
// Watch .html files, those trigger a html rebuild
|
||||
gulp.watch("../src/**/*.html", html.dev);
|
||||
gulp.watch("./preloader/*.*", html.dev);
|
||||
|
||||
// Watch translations
|
||||
gulp.watch("../translations/**/*.yaml", translations.convertToJson);
|
||||
|
||||
gulp.watch(
|
||||
["../res_raw/sounds/sfx/*.mp3", "../res_raw/sounds/sfx/*.wav"],
|
||||
gulp.series(sounds.sfx, sounds.copy)
|
||||
);
|
||||
gulp.watch(
|
||||
["../res_raw/sounds/music/*.mp3", "../res_raw/sounds/music/*.wav"],
|
||||
gulp.series(sounds.music, sounds.copy)
|
||||
);
|
||||
|
||||
// Watch resource files and copy them on change
|
||||
gulp.watch(rawImageResourcesGlobs, imgres.buildAtlas);
|
||||
gulp.watch(nonImageResourcesGlobs, imgres.copyNonImageResources);
|
||||
gulp.watch(imageResourcesGlobs, imgres.copyImageResources);
|
||||
|
||||
// Watch .atlas files and recompile the atlas on change
|
||||
gulp.watch("../res_built/atlas/*.atlas", imgres.atlasToJson);
|
||||
gulp.watch("../res_built/atlas/*.json", imgres.atlas);
|
||||
|
||||
// Watch the build folder and reload when anything changed
|
||||
const extensions = ["html", "js", "png", "gif", "jpg", "svg", "mp3", "ico", "woff2", "json"];
|
||||
gulp.watch(extensions.map(ext => path.join(buildFolder, "**", "*." + ext))).on("change", p =>
|
||||
gulp
|
||||
.src(pathNative.resolve(p).replaceAll(pathNative.sep, path.sep))
|
||||
.pipe(browserSync.reload({ stream: true }))
|
||||
);
|
||||
|
||||
gulp.watch("../src/js/built-temp/*.json").on("change", p =>
|
||||
gulp
|
||||
.src(pathNative.resolve(p).replaceAll(pathNative.sep, path.sep))
|
||||
.pipe(browserSync.reload({ stream: true }))
|
||||
);
|
||||
|
||||
gulp.series(js[version].dev.watch)(() => true);
|
||||
}
|
||||
|
||||
// Pre and postbuild
|
||||
const baseResources = imgres.allOptimized;
|
||||
async function deleteEmpty() {
|
||||
await delEmpty(buildFolder);
|
||||
}
|
||||
|
||||
const postbuild = gulp.series(imgres.cleanupUnusedCssInlineImages, deleteEmpty);
|
||||
|
||||
export const step = {
|
||||
baseResources,
|
||||
deleteEmpty,
|
||||
postbuild,
|
||||
};
|
||||
|
||||
///////////////////// RUNNABLE TASKS /////////////////////
|
||||
|
||||
// Builds everything (dev)
|
||||
const prepare = {
|
||||
dev: gulp.series(
|
||||
utils.cleanup,
|
||||
utils.copyAdditionalBuildFiles,
|
||||
localConfig.findOrCreate,
|
||||
gulp.parallel(
|
||||
gulp.series(imgres.buildAtlas, imgres.atlasToJson, imgres.atlas),
|
||||
sounds.dev,
|
||||
gulp.series(imgres.copyImageResources, css.dev),
|
||||
imgres.copyNonImageResources,
|
||||
translations.fullBuild
|
||||
)
|
||||
),
|
||||
};
|
||||
|
||||
/**
|
||||
* @typedef {import("gulp").TaskFunction} TaskFunction
|
||||
*/
|
||||
|
||||
export const build =
|
||||
/**
|
||||
* @type {Record<string, {
|
||||
* code: TaskFunction,
|
||||
* resourcesAndCode: TaskFunction,
|
||||
* all: TaskFunction,
|
||||
* full: TaskFunction,
|
||||
* }> & { prepare: typeof prepare }}
|
||||
*/
|
||||
({
|
||||
prepare,
|
||||
});
|
||||
/**
|
||||
* @type {Record<string, Record<string, TaskFunction>>}
|
||||
*/
|
||||
const pack = {};
|
||||
export { pack as package };
|
||||
/** @type {Record<string, TaskFunction>} */
|
||||
export const serve = {};
|
||||
|
||||
// Builds everything for every variant
|
||||
for (const variant in BUILD_VARIANTS) {
|
||||
const data = BUILD_VARIANTS[variant];
|
||||
|
||||
// build
|
||||
const code = gulp.series(
|
||||
data.standalone ? sounds.fullbuildHQ : sounds.fullbuild,
|
||||
translations.fullBuild,
|
||||
js[variant].prod.build
|
||||
);
|
||||
|
||||
const resourcesAndCode = gulp.parallel(step.baseResources, code);
|
||||
|
||||
const all = gulp.series(resourcesAndCode, css.prod, html.prod);
|
||||
|
||||
const full = gulp.series(utils.cleanup, all, step.postbuild);
|
||||
|
||||
build[variant] = { code, resourcesAndCode, all, full };
|
||||
|
||||
// Tasks for creating packages. These packages are already distributable, but usually can be further
|
||||
// wrapped in a different format (an installer for Windows, tarball for Linux, DMG for macOS).
|
||||
if (data.standalone) {
|
||||
const packageTasks = [
|
||||
"win32-x64",
|
||||
"win32-arm64",
|
||||
"linux-x64",
|
||||
"linux-arm64",
|
||||
"darwin-x64",
|
||||
"darwin-arm64",
|
||||
"all",
|
||||
];
|
||||
|
||||
pack[variant] = {};
|
||||
for (const task of packageTasks) {
|
||||
pack[variant][task] = gulp.series(
|
||||
localConfig.findOrCreate,
|
||||
full,
|
||||
utils.cleanBuildOutputFolder,
|
||||
standalone[variant].prepare.all,
|
||||
standalone[variant].package[task]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// serve
|
||||
serve[variant] = gulp.series(build.prepare.dev, html.dev, () => serveHTML({ version: variant }));
|
||||
}
|
||||
|
||||
// Deploying!
|
||||
export const deploy = {
|
||||
staging: gulp.series(
|
||||
utils.requireCleanWorkingTree,
|
||||
build["web-shapezio-beta"].full,
|
||||
ftp.upload.staging.all
|
||||
),
|
||||
prod: gulp.series(utils.requireCleanWorkingTree, build["web-shapezio"].full, ftp.upload.prod.all),
|
||||
};
|
||||
|
||||
export const main = {
|
||||
prepareDocs: docs.prepareDocs,
|
||||
webserver,
|
||||
};
|
||||
|
||||
// Default task (dev, localhost)
|
||||
export default gulp.series(serve["standalone-steam"]);
|
||||
@ -1,21 +1,20 @@
|
||||
import path from "path/posix";
|
||||
import fs from "fs";
|
||||
import gulpYaml from "gulp-yaml";
|
||||
import fs from "fs/promises";
|
||||
import YAML from "yaml";
|
||||
import gulp from "gulp";
|
||||
|
||||
import gulpPlumber from "gulp-plumber";
|
||||
import gulpYaml from "gulp-yaml";
|
||||
|
||||
const translationsSourceDir = path.join("..", "translations");
|
||||
const translationsJsonDir = path.join("..", "src", "js", "built-temp");
|
||||
|
||||
export default function gulptasksTranslations(gulp) {
|
||||
gulp.task("translations.convertToJson", () => {
|
||||
return gulp
|
||||
.src(path.join(translationsSourceDir, "*.yaml"))
|
||||
.pipe(gulpPlumber())
|
||||
.pipe(gulpYaml({ space: 2, safe: true }))
|
||||
.pipe(gulp.dest(translationsJsonDir));
|
||||
});
|
||||
|
||||
gulp.task("translations.fullBuild", gulp.series("translations.convertToJson"));
|
||||
export function convertToJson() {
|
||||
return gulp
|
||||
.src(path.join(translationsSourceDir, "*.yaml"))
|
||||
.pipe(gulpPlumber())
|
||||
.pipe(gulpYaml({ space: 2, safe: true }))
|
||||
.pipe(gulp.dest(translationsJsonDir));
|
||||
}
|
||||
|
||||
export const fullBuild = convertToJson;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user