From c5d0f2d1b8ce218a0b255b29d3df1159220ef27d Mon Sep 17 00:00:00 2001 From: versustunez Date: Wed, 17 Feb 2021 12:23:08 +0100 Subject: [PATCH] init commit --- .gitignore | 2 + buildConfig.example.json | 30 ++++++++++++ gulpfile.js | 17 +++++++ index.js | 10 ++++ package.json | 27 +++++++++++ task/smartcss.js | 55 ++++++++++++++++++++++ task/smartjs.js | 98 ++++++++++++++++++++++++++++++++++++++++ tools/buildConfig.js | 31 +++++++++++++ tools/helperUnit.js | 52 +++++++++++++++++++++ 9 files changed, 322 insertions(+) create mode 100644 .gitignore create mode 100644 buildConfig.example.json create mode 100644 gulpfile.js create mode 100644 index.js create mode 100644 package.json create mode 100644 task/smartcss.js create mode 100644 task/smartjs.js create mode 100644 tools/buildConfig.js create mode 100644 tools/helperUnit.js diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..504afef --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +node_modules/ +package-lock.json diff --git a/buildConfig.example.json b/buildConfig.example.json new file mode 100644 index 0000000..351c404 --- /dev/null +++ b/buildConfig.example.json @@ -0,0 +1,30 @@ +{ + "src": "$dir/src", + "out": "$dir/public/out", + "js": [ + { + "name": "main", + "minify": true, + "onlyMinify": true, + "input": "$src/js/", + "output": "$out/js/", + "files": [ + "app.js" + ], + "compiler": { + "compilation_level": "ADVANCED", + "warning_level": "VERBOSE", + "language_in": "ECMASCRIPT6_STRICT", + "language_out": "ECMASCRIPT6_STRICT", + "js_output_file": "$name.min.js" + } + } + ], + "scss": [ + { + "name": "main", + "input": "$src/theme/**/*.scss", + "output": "$out/theme/$name" + } + ] +} diff --git a/gulpfile.js b/gulpfile.js new file mode 100644 index 0000000..a8239ce --- /dev/null +++ b/gulpfile.js @@ -0,0 +1,17 @@ +const gulp = require('gulp'), + config = require('./tools/buildConfig'), + smartJS = require('./task/smartjs'), + smartCss = require('./task/smartcss'); + +config.prepare(); +smartJS.prepare(config); +smartCss.prepare(config); + +gulp.task('watchMe', () => { + smartJS.startWatch(); + smartCss.startWatch(); +}); + +gulp.task('default', gulp.parallel([...smartJS.build(), ...smartCss.build()])); + +gulp.task('watch', gulp.parallel(['watchMe', ...smartJS.build(), ...smartCss.build()])); diff --git a/index.js b/index.js new file mode 100644 index 0000000..b6cf764 --- /dev/null +++ b/index.js @@ -0,0 +1,10 @@ +const gulp = require('gulp-cli'), + shouldWatch = process.argv.length > 2 && process.argv[2] === 'watch'; + +gulp() +require('./gulpfile') +if (shouldWatch) { + gulp.series('watchMe')(); +} else { + gulp.series('default')(); +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..729e651 --- /dev/null +++ b/package.json @@ -0,0 +1,27 @@ +{ + "name": "v-build", + "version": "1.0.0", + "description": "A Small Gulp Build System for Dynamic JS and SCSs", + "main": "index.js", + "scripts": { + "build-nm": "./node_modules/gulp-cli/bin/gulp.js", + "watch-nm": "./node_modules/gulp-cli/bin/gulp.js watch", + "build": "gulp", + "watch": "gulp watch" + }, + "keywords": [ + "GULP", + "JS", + "SCSS" + ], + "author": "Maurice Grönwoldt", + "license": "GPL-3.0-or-later", + "dependencies": { + "google-closure-compiler": "^20210202.0.0", + "gulp": "^4.0.2", + "gulp-clean-css": "^4.3.0", + "gulp-cli": "^2.3.0", + "gulp-concat": "^2.6.1", + "gulp-sass": "^4.1.0" + } +} diff --git a/task/smartcss.js b/task/smartcss.js new file mode 100644 index 0000000..177755a --- /dev/null +++ b/task/smartcss.js @@ -0,0 +1,55 @@ +const gulp = require('gulp'), + HelperUnit = require('./../tools/helperUnit'), + sass = require('gulp-sass'), + clean = require('gulp-clean-css'), + path = require('path'), + workers = []; + +class SCSSWorker { + constructor(config, helper) { + this.config = config; + this.helper = helper.clone(); + this.input = this.helper.replaceVariables(this.config.input); + this.helper.addConfigItem("$name", this.config.name); + this.helper.addConfigItem("$", this.input); + this.out = this.helper.replaceVariables(this.config.output); + this.watch = this.helper.replaceVariables(this.config.watch || '$/**/*.{scss,sass}'); + gulp.task(this.taskName, this.work.bind(this)); + } + + startWatch() { + gulp.watch(this.watch, gulp.series(this.taskName)) + } + + get taskName() { + return `scss-${this.config.name || 'unknown'}`; + } + + work() { + return gulp.src(this.input) + .pipe(sass().on('error', sass.logError)) + .pipe(clean()) + .pipe(gulp.dest(this.out)); + } +} + +module.exports = { + build: function () { + let array = []; + for (let worker of workers) { + array.push(worker.taskName); + } + return array; + }, + prepare: function (config) { + const scss = config.scss || []; + for (let scssItem of scss) { + workers.push(new SCSSWorker(scssItem, config.helper)); + } + }, + startWatch: function () { + for (let worker of workers) { + worker.startWatch(); + } + } +} diff --git a/task/smartjs.js b/task/smartjs.js new file mode 100644 index 0000000..df8a6da --- /dev/null +++ b/task/smartjs.js @@ -0,0 +1,98 @@ +const closureCompiler = require('google-closure-compiler').gulp(), + concat = require('gulp-concat'), + gulp = require('gulp'), + path = require('path'), + workers = []; + +class JSWorker { + constructor(config, helper) { + this.config = config; + this.helper = helper.clone(); + if (!this.config.name) { + throw Error("Found Empty name for JS Job..."); + } + this.validateConfig(); + this.input = this.helper.replaceVariables(this.config.input); + this.helper.addConfigItem("$name", this.config.name); + this.helper.addConfigItem("$", this.input); + this.getCompilerConfig(); + this.out = this.helper.replaceVariables(this.config.output); + this.watch = this.helper.replaceVariables(this.config.watch || '$/**/*.js'); + this.prepareFiles(this.config.files) + this.path = path.parse(this.out); + gulp.task(this.taskName, this.work.bind(this)); + } + + validateConfig() { + let config = this.config; + config.onlyMinify = config.onlyMinify || false; + config.minify = config.minify || false; + if (!this.config.input || !this.config.output || !this.config.files) { + throw Error("Invalid Config for: " + this.config.name + ")"); + } + } + + getCompilerConfig() { + this.compiler = { + compilation_level: 'SIMPLE', + warning_level: 'VERBOSE', + language_in: 'ECMASCRIPT6_STRICT', + language_out: 'ECMASCRIPT6_STRICT', + js_output_file: this.config.name + ".min.js" + } + if (this.config.compiler) { + this.compiler = Object.assign(this.compiler, this.config.compiler); + } + this.compiler.js_output_file = this.helper.replaceVariables(this.compiler.js_output_file); + } + + startWatch() { + gulp.watch(this.watch, gulp.series(this.taskName)) + } + + get taskName() { + return `js-${this.config.name}`; + } + + prepareFiles(files) { + this.files = []; + for (const file of files) { + this.files.push(this.input + "/" + this.helper.replaceVariables(file)); + } + } + + work() { + let d = gulp.src(this.files) + if (!this.config.onlyMinify) { + d.pipe(concat(this.config.name + '.js')) + .pipe(gulp.dest(this.path.dir)); + } + if (this.config.minify) { + d.pipe(closureCompiler(this.compiler)).pipe(gulp.dest(this.path.dir)); + } + return d; + } +} + +module.exports = { + build: function () { + let array = []; + for (let worker of workers) { + array.push(worker.taskName); + } + return array; + }, + prepare: function (config) { + // we load the json and parse it here + const js = config.js || []; + for (let jsConfig of js) { + const worker = new JSWorker(jsConfig, config.helper); + workers.push(worker); + } + }, + startWatch: function () { + for (let worker of workers) { + worker.startWatch(); + } + } +} diff --git a/tools/buildConfig.js b/tools/buildConfig.js new file mode 100644 index 0000000..ab266b3 --- /dev/null +++ b/tools/buildConfig.js @@ -0,0 +1,31 @@ +const fs = require('fs'), + HelperUnit = require('./helperUnit'), + helper = new HelperUnit(), + config = {}; + +module.exports = { + config: config, + helper: helper, + prepare: function () { + if (!fs.existsSync(__dirname + '/../../buildConfig.json')) { + console.error("Cannot find Config JSON"); + process.exit(40); + } + const baseDir = __dirname + '/../..'; + const data = JSON.parse(fs.readFileSync(__dirname + '/../../buildConfig.json').toString()); + const src = data['src'].replace(/(\$dir)/gm, baseDir); + const out = data['out'].replace(/(\$dir)/gm, baseDir); + helper.setConfig({ + $dir: baseDir, + $out: out, + $src: src, + }) + config.dir = baseDir; + config.src = src; + config.out = out; + config.js = data.js || []; + config.scss = data.scss || []; + this.js = config.js; + this.scss = config.scss; + } +} diff --git a/tools/helperUnit.js b/tools/helperUnit.js new file mode 100644 index 0000000..ca4a592 --- /dev/null +++ b/tools/helperUnit.js @@ -0,0 +1,52 @@ +let inConfig = { + $dir: __dirname, + $out: __dirname, + $src: __dirname, + $: __dirname +} + +class HelperUnit { + constructor(config = null) { + this.config = config || inConfig; + this.regEx = {}; + this.buildRegex(); + } + + static setGlobalConfig(config) { + inConfig = config; + } + + addConfigItem(name, value, regexOnly = false) { + if (!regexOnly) { + this.config[name] = value; + } + let replace = name.replace("$", "\\$"); + this.regEx[name] = new RegExp(`(${replace})`, "gm"); + } + + setConfig(config) { + this.config = config; + this.buildRegex(); + } + + buildRegex() { + const keys = Object.keys(this.config); + this.regEx = {}; + for (const key of keys) { + this.addConfigItem(key, null, true); + } + } + + replaceVariables(string) { + const keys = Object.keys(this.config); + for (const key of keys) { + string = string.replace(this.regEx[key], this.config[key]); + } + return string; + } + + clone() { + return new HelperUnit(this.config); + } +} +module.exports = HelperUnit;