From 7ba8797e630e8ab2488328130862bfc6559400e7 Mon Sep 17 00:00:00 2001
From: ezsh <ezsh.junk@gmail.com>
Date: Sun, 7 Jun 2020 05:00:54 +0200
Subject: [PATCH] Add Gulp build script to support source maps for the game
 sources

---
 build.config.json |  34 +++++++++
 gulpfile.js       | 186 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 220 insertions(+)
 create mode 100644 build.config.json
 create mode 100644 gulpfile.js

diff --git a/build.config.json b/build.config.json
new file mode 100644
index 00000000000..53df91f839f
--- /dev/null
+++ b/build.config.json
@@ -0,0 +1,34 @@
+{
+	"dirs": {
+		"intermediate": "build",
+		"output": "bin"
+	},
+	"output": "FC_pregmod.html",
+	"twineformat": "sugarcube-2",
+	"gitVersionFile": "src/002-config/fc-version.js.commitHash.js",
+	"sources": {
+		"module": {
+			"js": ["js/**/*.js"]
+		},
+		"story": {
+			"css": ["src/**/*.css"],
+			"js": ["src/**/*.js"],
+			"twee": ["src/**/*.tw"],
+			"media": [
+				"src/art/vector/layers",
+				"src/art/vector_revamp/layers"
+			]
+		},
+		"head": "devTools/head.html"
+	},
+	"options": {
+		"css": {
+			"autoprefix": true
+		},
+		"twee": {
+			"environment": {
+				"TWEEGO_PATH": "devTools/tweeGo/storyFormats"
+			}
+		}
+	}
+}
diff --git a/gulpfile.js b/gulpfile.js
new file mode 100644
index 00000000000..295949532d6
--- /dev/null
+++ b/gulpfile.js
@@ -0,0 +1,186 @@
+const gulp = require('gulp'),
+	concat = require('gulp-concat'),
+	git = require('gulp-git'),
+	log = require('fancy-log-levels'),
+	noop = require('gulp-noop'),
+	postcss = require('gulp-postcss'),
+	shell = require('gulp-shell'),
+	sort = require('gulp-sort'),
+	sourcemaps = require('gulp-sourcemaps'),
+	autoprefixer = require('autoprefixer'),
+	which = require('which'),
+	fs = require('fs'),
+	path = require('path'),
+	os = require('os'),
+	yargs = require('yargs'),
+	cfg = require('./build.config.json');
+
+const args = yargs.options({
+	verbosity: {type: 'number', default: 0},
+	release: {type: 'boolean', default: false},
+	embedsourcemaps: {type: 'boolean', default: false},
+	sourcemapsincludecontent: {type: 'boolean', default: false}
+}).argv;
+
+const htmlOut = "tmp.html";
+
+log(args.verbosity);
+
+function tweeCompilerExecutable() {
+	const systemTweego = which.sync('tweego', {nothrow: true});
+	if (systemTweego) {
+		log.info('Found system tweego at ', systemTweego);
+		return systemTweego;
+	}
+	const archSuffix = os.arch() === 'x64' ? '64' : '86';
+	const platformSuffix = {
+		'Darwin': 'osx',
+		'Linux': 'nix',
+		'Windows_NT': 'win'
+	}[os.type()];
+	const extension = os.type() === 'Windows_NT' ? '.exe' : '';
+	const res = path.join('.', 'devTools', 'tweeGo', `tweego_${platformSuffix}${archSuffix}${extension}`);
+	log.info('Using bundled tweego at ', res);
+	return res;
+}
+
+function concatFiles(srcGlob, destDir, destFileName) {
+	return gulp.src(srcGlob)
+		.pipe(sort())
+		.pipe(concat(destFileName))
+		.pipe(gulp.dest(destDir));
+}
+
+function processScripts(srcGlob, destDir, destFileName) {
+	const addSourcemaps = !args.release;
+	const prefix = path.relative(destDir, srcGlob.substr(0, srcGlob.indexOf('*')));
+	return gulp.src(srcGlob)
+		.pipe(sort())
+		.pipe(addSourcemaps ? sourcemaps.init() : noop())
+		.pipe(concat(destFileName))
+		.pipe(addSourcemaps ?
+			sourcemaps.write(args.embedsourcemaps ? undefined : '.', {includeContent: args.sourcemapsincludecontent, sourceRoot: prefix}) :
+			noop())
+		.pipe(gulp.dest(destDir));
+}
+
+function processStylesheets(srcGlob, destDir, destFileName) {
+	const addSourcemaps = !args.release;
+	const prefix = path.relative(destDir, srcGlob.substr(0, srcGlob.indexOf('*')));
+	return gulp.src(srcGlob)
+		.pipe(sort())
+		.pipe(addSourcemaps ? sourcemaps.init() : noop())
+		.pipe(concat(destFileName))
+		.pipe(cfg.options.css.autoprefix ?
+			postcss([autoprefixer({overrideBrowserslist: ['last 2 versions']})]) :
+			noop())
+		.pipe(addSourcemaps ?
+			sourcemaps.write(args.embedsourcemaps ? undefined : '.', {includeContent: args.sourcemapsincludecontent, sourceRoot: prefix}) :
+			noop())
+		.pipe(gulp.dest(destDir));
+}
+
+function processSrc(name, processorFunc, globs, destDir, destFileName, ...args) {
+	let tasks = [];
+	if (!Array.isArray(globs) || globs.length === 1) {
+		const src = Array.isArray(globs) ? globs[0] : globs;
+		tasks.push(() => processorFunc(src, destDir, destFileName, args));
+		tasks[tasks.length - 1].displayName = "process-" + name;
+	} else { // many globs
+		const ext = path.extname(destFileName);
+		const bn = path.basename(destFileName, ext);
+		for (let i = 0; i < globs.length; ++i) {
+			tasks.push(() => processorFunc(globs[i], destDir, `${bn}-${i}${ext}`, args));
+			tasks[tasks.length - 1].displayName = `process-${name}-${i}`;
+		}
+	}
+	const res = gulp.parallel(...tasks);
+	res.displayName = name;
+	return res;
+}
+
+function injectGitCommit(cb) {
+	git.revParse({args: '--short HEAD'}, function(err, hash) {
+		if (!err) {
+			log.info('current git hash: ', hash);
+			fs.writeFile(cfg.gitVersionFile, `App.Version.commitHash = '${hash}';\n`, cb);
+		} else {
+			cb();
+		}
+	});
+}
+
+function cleanupGit(cb) {
+	fs.unlink(cfg.gitVersionFile, cb);
+}
+
+function compileStory() {
+	let sources = [path.join(cfg.dirs.intermediate, "story")];
+	sources.push(...cfg.sources.story.media);
+
+	let modules = [path.join(cfg.dirs.intermediate, "module")];
+	let moduleArgs = modules.map(fn => `--module=${fn}`);
+	const cmdLine = `${tweeCompilerExecutable()} -f ${cfg.twineformat} --head=${cfg.sources.head} -o ${path.join(cfg.dirs.intermediate, htmlOut)} ${moduleArgs.join(' ')} ${sources.join(' ')}`;
+
+	log.info(cmdLine);
+	return gulp.src(sources, {read: false})
+		.pipe(shell(cmdLine, {env: cfg.options.twee.environment}));
+}
+
+const processors = {
+	"css": {
+		func: processStylesheets,
+		output: "styles.css"
+	},
+	"js": {
+		func: processScripts,
+		output: "script.js"
+	},
+	"twee": {
+		func: concatFiles,
+		output: "story.twee"
+	},
+	"media": {
+		func: null
+	}
+};
+
+function prepareComponent(name) {
+	const c = cfg.sources[name];
+	const outDir = path.join(cfg.dirs.intermediate, name);
+	const subTasks = [];
+	for (const srcType in c) {
+		const proc = processors[srcType];
+		if (proc.func) {
+			subTasks.push(processSrc(`${name}-${srcType}`, proc.func, c[srcType], outDir, proc.output, cfg.options[srcType]));
+		}
+	}
+	let r = gulp.parallel(subTasks);
+	r.displayName = "prepare-" + name;
+	return r;
+}
+
+function moveHTMLInPlace(cb) {
+	fs.rename(path.join(cfg.dirs.intermediate, htmlOut), path.join(cfg.dirs.output, cfg.output), cb);
+}
+
+function clean(cb) {
+	if (fs.existsSync(cfg.gitVersionFile)) {
+		fs.unlinkSync(cfg.gitVersionFile);
+	}
+	fs.rmdirSync(cfg.dirs.intermediate, {recursive: true});
+	cb();
+}
+
+function prepare(cb) {
+	return gulp.series(clean, injectGitCommit, gulp.parallel(prepareComponent("module"), prepareComponent("story")))(cb);
+}
+
+if (fs.statSync('.git').isDirectory()) {
+	gulp.task('buildHTML', gulp.series(prepare, compileStory, cleanupGit));
+} else {
+	gulp.task('buildHTML', gulp.series(prepare, compileStory));
+}
+
+exports.clean = clean;
+exports.default = gulp.series('buildHTML', moveHTMLInPlace);
-- 
GitLab