Skip to content
Snippets Groups Projects
gulpfile.js 6.8 KiB
Newer Older
  • Learn to ignore specific revisions
  • 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'),
    
    	stripCssJSComments = require('gulp-strip-comments'),
    
    	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 tweeCompileCommand() {
    	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}`);
    	return `${tweeCompilerExecutable()} -f ${cfg.twineformat} --head=${cfg.sources.head} -o ${path.join(cfg.dirs.intermediate, htmlOut)} ${moduleArgs.join(' ')} ${sources.join(' ')}`;
    }
    
    
    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 ?
    
    ezsh's avatar
    ezsh committed
    			sourcemaps.write(args.embedsourcemaps ? undefined : '.', {
    				includeContent: args.sourcemapsincludecontent,
    				sourceRoot: prefix,
    				sourceMappingURLPrefix: path.relative(cfg.dirs.output, destDir)
    			}) :
    
    			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 ?
    
    ezsh's avatar
    ezsh committed
    			sourcemaps.write(args.embedsourcemaps ? undefined : '.', {
    				includeContent: args.sourcemapsincludecontent,
    				sourceRoot: prefix,
    				sourceMappingURLPrefix: path.relative(cfg.dirs.output, destDir)
    			}) :
    
    			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) {
    
    	if (fs.existsSync(cfg.gitVersionFile)) {
    		fs.unlink(cfg.gitVersionFile, cb);
    	} else {
    		cb();
    	}
    
    gulp.task('compileStory', shell.task(tweeCompileCommand(), {env: {...process.env, ...cfg.options.twee.environment}, verbose: false}));
    
    
    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 makeThemeCompilationTask(themeName) {
    	const taskName = `make-theme-${themeName}`;
    	gulp.task(taskName, function() {
    
    		return concatFiles(`themes/${themeName}/**/*.css`, cfg.dirs.output, `${themeName}.css`);
    
    	});
    	return taskName;
    }
    
    
    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));
    
    	gulp.task('buildHTML', gulp.series(prepare, 'compileStory'));
    
    ezsh's avatar
    ezsh committed
    const themeTasks = fs.readdirSync('themes')
    	.filter(entry => fs.statSync(path.join('themes', entry)).isDirectory())
    	.map(entry => makeThemeCompilationTask(entry));
    
    exports.html = gulp.series('buildHTML', moveHTMLInPlace);
    exports.themes = gulp.parallel(themeTasks);
    
    
    exports.default = exports.html;
    exports.all = gulp.parallel(exports.html, exports.themes);
    
    
    // legacy tasks
    
    gulp.task('twineCSS', function() {
    	return concatFiles([...cfg.sources.module.css, ...cfg.sources.story.css], 'devNotes', 'twine CSS.txt');
    });
    
    gulp.task('twineJS', function() {
    	return gulp.src([...cfg.sources.module.js, ...cfg.sources.story.js, '!src/art/assistantArt.js'])
    		.pipe(stripCssJSComments({trim: true}))
    		.pipe(sort())
    		.pipe(concat('twine JS.txt'))
    		.pipe(gulp.dest('devNotes'));
    });
    
    exports.twine = gulp.parallel('twineCSS', 'twineJS');