diff --git a/README.md b/README.md index 7c4d4cd..41f03ab 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,13 @@ # In development ## What +Auto Inject Version (AIV) can: +- inject version from package.json into every bundle file as a comment ( at the top ) +- inject version from package.json into any place in your HTML by special tag <{version}> +- inject version from package.json into any place in CSS/JS file by special tag <{version}> +- auto increase version by --major, --minor, --patch and then inject as chosen + +## Desc AIV can inject version number for all your bundle files (css,js,html).

Example js: ```js @@ -38,29 +45,20 @@ $ npm install webpack-auto-inject-version --save-dev var WebpackAutoInject = require('webpack-auto-inject-version'); module.exports = { - plugins: [ - new WebpackAutoInject({ - autoIncrease : boolean, - injectIntoHtml : boolean, - injectIntoHtmlRegex : regex, - injectIntoAnyFile : boolean - }) + new WebpackAutoInject(options) ] - } ```
## Options -By default you don't need to pass any options, all options from Usage section are set by default.

- -
### autoIncrease Auto increase package.json number.
This option requires extra argument to be sent to webpack build.
+It happens before anything else to make sure that your new version is injected into your files.
Arguments: --major --minor --patch


@@ -76,27 +74,32 @@ Default: true
-### injectIntoHtml -Inject version number ( increased if autoIncrease is set correctly ) into HTML template
-For this to work you need to place <{version}> inside your html file.

-Example: +### injectByTag +Inject version number into your file
+Version will replace the <{version}> tag.
```html My awesome project | <{version}> ``` +```js +var version = '<{version}>'; +``` Default: true
-### injectIntoHtmlRegex -Regex to find your html file, where injectIntoHtml should try to find your <{version}> tag.
+### injectByTagFileRegex +Regex against file name. If match, injectByTag will try to find version tag and replace it. +Only html files: /^(.){1,}\.html$/
+Only js files: ^(.){1,}\.js$
+Any file: (.){1,}
Default: /^index\.html$/
-### injectIntoAnyFile -This will inject your version file as a comment into any css,js,html file.
+### injectAsComment +This will inject your version as a comment into any css,js,html file.
Default: true \ No newline at end of file diff --git a/dist/components/auto-inc-version.js b/dist/components/auto-inc-version.js index 28d591f..e55399d 100644 --- a/dist/components/auto-inc-version.js +++ b/dist/components/auto-inc-version.js @@ -5,6 +5,7 @@ var fs = require('fs'); var u = require('../core/utils'); var chalk = require('chalk'); var Promise = require('bluebird'); +var log = require('../core/log'); var IncVersion = (function () { function IncVersion(context) { this.context = context; @@ -19,7 +20,6 @@ var IncVersion = (function () { }; IncVersion.prototype.start = function () { this.packageFile = this.openPackageFile(); - var argv = process.argv; if (u.isArgv('major')) { this.major(); } @@ -30,8 +30,6 @@ var IncVersion = (function () { this.patch(); } else { - console.log(chalk.bgRed("[@] " + config.SHORT + " error > ") + ' --major --minor --patch missing in arguments. '); - console.log(chalk.bgRed("[@] " + config.SHORT + " how to> ") + ' webpack -w --major'); this.reject(); } }; @@ -46,8 +44,9 @@ var IncVersion = (function () { _this.reject(err); return console.log(err); } - console.log(''); - console.log(chalk.bgGreen("[@] " + config.SHORT + " OK > ") + ' package.json updated : ' + _this.packageFile.version); + log.info("autoIncVersion : new version : " + newVersion); + log.info('package.json updated!'); + _this.context.version = newVersion; _this.resolve(); }); }; diff --git a/dist/components/inject-as-comment.js b/dist/components/inject-as-comment.js new file mode 100644 index 0000000..9308231 --- /dev/null +++ b/dist/components/inject-as-comment.js @@ -0,0 +1,49 @@ +var chalk = require('chalk'); +var path = require('path'); +var endOfLine = require('os').EOL; +var config = require('../config'); +var log = require('../core/log'); +'use strict'; +var InjectAsComment = (function () { + function InjectAsComment(context) { + this.context = context; + } + InjectAsComment.prototype.apply = function () { + var _this = this; + this.context.compiler.plugin('emit', function (compilation, cb) { + for (var basename in compilation.assets) { + var ext = path.extname(basename); + var asset = compilation.assets[basename]; + switch (ext) { + case '.js': + _this.injectIntoJs(asset); + break; + case '.html': + _this.injectIntoHtml(asset); + break; + case '.css': + _this.injectIntoCss(asset); + break; + case 'default': break; + } + log.info("InjectAsComment : match : " + basename + " : injected : " + _this.context.version); + } + cb(); + }); + return new Promise(function (resolve, reject) { resolve(); }); + }; + InjectAsComment.prototype.injectIntoCss = function (asset) { + var modAsset = "/** [" + config.SHORT + "] Build version: " + this.context.version + " **/ " + endOfLine + " " + asset.source() + " "; + asset.source = function () { return modAsset; }; + }; + InjectAsComment.prototype.injectIntoHtml = function (asset) { + var modAsset = " " + endOfLine + " " + asset.source() + " "; + asset.source = function () { return modAsset; }; + }; + InjectAsComment.prototype.injectIntoJs = function (asset) { + var modAsset = "// [" + config.SHORT + "] Build version: " + this.context.version + " " + endOfLine + " " + asset.source() + " "; + asset.source = function () { return modAsset; }; + }; + return InjectAsComment; +}()); +module.exports = InjectAsComment; diff --git a/dist/components/inject-by-tag.js b/dist/components/inject-by-tag.js new file mode 100644 index 0000000..ab5a6b7 --- /dev/null +++ b/dist/components/inject-by-tag.js @@ -0,0 +1,31 @@ +var log = require('../core/log'); +'use strict'; +var InjectByTag = (function () { + function InjectByTag(context) { + this.context = context; + } + InjectByTag.prototype.apply = function () { + var _this = this; + this.context.compiler.plugin('emit', function (compilation, cb) { + var _loop_1 = function() { + if (_this.context.options.injectByTagFileRegex.test(basename)) { + var replaced_1 = 0; + var asset = compilation.assets[basename]; + var modFile_1 = asset.source().replace(/(\<\{version\}\>)/g, function () { + replaced_1++; + return _this.context.version; + }); + asset.source = function () { return modFile_1; }; + log.info("InjectByTag : match : " + basename + " : replaced : " + replaced_1); + } + }; + for (var basename in compilation.assets) { + _loop_1(); + } + cb(); + }); + return new Promise(function (resolve, reject) { resolve(); }); + }; + return InjectByTag; +}()); +module.exports = InjectByTag; diff --git a/dist/config.js b/dist/config.js index b21f989..a350957 100644 --- a/dist/config.js +++ b/dist/config.js @@ -2,18 +2,23 @@ module.exports = { NAME: 'Auto Inject Version', SHORT: 'AIV', PATH_PACKAGE: './package.json', - COMPONENTS: [ + NON_WEBPACK_COMPONENTS: [ { option: 'autoIncrease', path: './components/auto-inc-version' - }, - { - option: 'injectIntoHtml', - path: './components/inject-into-html' - }, - { - option: 'injectIntoAnyFile', - path: './components/inject-into-any-file' } - ] + ], + WEBPACK_COMPONENTS: [ + { + option: 'injectByTag', + path: './components/inject-by-tag' + }, + { + option: 'injectAsComment', + path: './components/inject-as-comment' + } + ], + LOGS_TEXT: { + AIS_START: 'Auto inject version started' + } }; diff --git a/dist/core/log.js b/dist/core/log.js new file mode 100644 index 0000000..ad3f971 --- /dev/null +++ b/dist/core/log.js @@ -0,0 +1,47 @@ +var config = require('../config'); +var chalk = require('chalk'); +var endOfLine = require('os').EOL; +var u = require('./utils'); +var Log = (function () { + function Log() { + this.logLevel = 3; + this.getLogLevel(); + } + Log.prototype.getLogLevel = function () { + if (u.isArgv('aiv-log-full')) { + this.logLevel = 3; + } + else if (u.isArgv('aiv-log-none')) { + this.logLevel = 0; + } + }; + Log.prototype.getHead = function () { + return endOfLine + chalk.bgYellow.black('[AIV] : '); + }; + Log.prototype.getText = function (id) { + return config.LOGS_TEXT[id]; + }; + Log.prototype.call = function (type, msgId) { + if (typeof this[type] === 'function') { + this[type](this.getText(msgId)); + } + }; + Log.prototype.error = function (msg) { + if (this.logLevel < 3) + return; + console.log(this.getHead() + " " + chalk.red('error') + " : " + msg); + }; + Log.prototype.info = function (msg) { + if (!this.logLevel) + return; + console.log(this.getHead() + " " + chalk.blue('info') + " : " + msg); + }; + Log.prototype.warn = function (msg) { + if (!this.logLevel) + return; + console.log(this.getHead() + " " + chalk.yellow('warn') + " : " + msg); + }; + return Log; +}()); +var log = new Log(); +module.exports = log; diff --git a/dist/main.js b/dist/main.js index e367a0e..a05e194 100644 --- a/dist/main.js +++ b/dist/main.js @@ -4,40 +4,49 @@ var path = require('path'); var config = require('./config'); var Promise = require('bluebird'); var u = require('./core/utils'); +var log = require('./core/log'); 'use strict'; var WebpackAutoInject = (function () { function WebpackAutoInject(options) { this.options = u.merge(WebpackAutoInject.options, options); var packageFile = JSON.parse(fs.readFileSync(path.normalize(config.PATH_PACKAGE), 'utf8')); this.version = packageFile.version; + log.call('info', 'AIS_START'); + this.executeNoneWebpackComponents(); } WebpackAutoInject.prototype.apply = function (compiler) { this.compiler = compiler; - this.components = config.COMPONENTS; - this.executeComponents(); + this.executeWebpackComponents(); }; - WebpackAutoInject.prototype.executeComponents = function () { + WebpackAutoInject.prototype.executeNoneWebpackComponents = function () { + this.executeComponents(config.NON_WEBPACK_COMPONENTS, function () { + }); + }; + WebpackAutoInject.prototype.executeWebpackComponents = function () { + this.executeComponents(config.WEBPACK_COMPONENTS, function () { + }); + }; + WebpackAutoInject.prototype.executeComponents = function (components, done) { var _this = this; - if (!this.components.length) { - console.log(chalk.bgRed('AIS: DONE!')); + if (!components.length) { + done(); return; } - var comp = this.components.shift(); - if (this.options[comp.option]) { - var inst = new (require(comp.path))(this); - inst.apply().then(function () { - _this.executeComponents(); - }, function (err) { console.log(err); }); - } - else { - this.executeComponents(); + var comp = components.shift(); + if (!this.options[comp.option]) { + this.executeComponents(components, done); + return; } + var inst = new (require(comp.path))(this); + inst.apply().then(function () { + _this.executeComponents(components, done); + }, function (err) { _this.executeComponents(components, done); }); }; WebpackAutoInject.options = { autoIncrease: true, - injectIntoHtml: true, - injectIntoHtmlRegex: /^index\.html$/, - injectIntoAnyFile: true + injectAsComment: true, + injectByTag: true, + injectByTagFileRegex: /^index\.html$/ }; return WebpackAutoInject; }()); diff --git a/package.json b/package.json index ec912ee..6b42144 100644 --- a/package.json +++ b/package.json @@ -10,11 +10,12 @@ "author": "Radoslaw Swiat", "license": "ISC", "devDependencies": { - "chalk": "^1.1.3", "typings": "^1.4.0" }, "dependencies": { "bluebird": "^3.4.6", - "semver": "^5.3.0" + "semver": "^5.3.0", + "chalk": "^1.1.3" + } } diff --git a/src/components/auto-inc-version.ts b/src/components/auto-inc-version.ts index 474df9f..7f7fa49 100644 --- a/src/components/auto-inc-version.ts +++ b/src/components/auto-inc-version.ts @@ -1,10 +1,11 @@ -var semver = require('semver'); -var config = require('../config'); -var path = require('path'); -var fs = require('fs'); -var u = require('../core/utils'); -var chalk = require('chalk'); -var Promise = require('bluebird'); +const semver = require('semver'); +const config = require('../config'); +const path = require('path'); +const fs = require('fs'); +const u = require('../core/utils'); +const chalk = require('chalk'); +const Promise = require('bluebird'); +const log = require('../core/log'); class IncVersion{ @@ -28,7 +29,6 @@ class IncVersion{ */ private start() { this.packageFile = this.openPackageFile(); - let argv = process.argv; if( u.isArgv('major') ) { this.major(); } @@ -37,8 +37,6 @@ class IncVersion{ }else if( u.isArgv('patch') ) { this.patch(); }else { - console.log(chalk.bgRed(`[@] ${config.SHORT} error > `)+' --major --minor --patch missing in arguments. '); - console.log(chalk.bgRed(`[@] ${config.SHORT} how to> `)+' webpack -w --major'); this.reject(); } } @@ -59,8 +57,9 @@ class IncVersion{ this.packageFile.version = newVersion; fs.writeFile(path.normalize(config.PATH_PACKAGE), JSON.stringify(this.packageFile, null, 4), (err) => { if(err) {this.reject(err); return console.log(err);} - console.log(''); - console.log(chalk.bgGreen(`[@] ${config.SHORT} OK > `)+' package.json updated : ' + this.packageFile.version); + log.info(`autoIncVersion : new version : ${newVersion}`) + log.info('package.json updated!'); + this.context.version = newVersion; this.resolve(); }); } diff --git a/src/components/inject-into-any-file.ts b/src/components/inject-as-comment.ts similarity index 79% rename from src/components/inject-into-any-file.ts rename to src/components/inject-as-comment.ts index 660c84e..d1908a5 100644 --- a/src/components/inject-into-any-file.ts +++ b/src/components/inject-as-comment.ts @@ -1,8 +1,9 @@ /// -var chalk = require('chalk'); -var path = require('path'); -var endOfLine = require('os').EOL; -var config = require('./../config'); +const chalk = require('chalk'); +const path = require('path'); +const endOfLine = require('os').EOL; +const config = require('../config'); +const log = require('../core/log'); 'use strict'; @@ -11,7 +12,7 @@ var config = require('./../config'); * - done by parsing html file, * > replace: <{version}> */ -class InjectIntoAnyFile{ +class InjectAsComment{ constructor(private context) {} @@ -30,7 +31,9 @@ class InjectIntoAnyFile{ case '.css' : this.injectIntoCss(asset); break; + case 'default': break; } + log.info(`InjectAsComment : match : ${basename} : injected : ${this.context.version}`); } cb(); }); @@ -53,4 +56,4 @@ class InjectIntoAnyFile{ } } -module.exports = InjectIntoAnyFile; \ No newline at end of file +module.exports = InjectAsComment; \ No newline at end of file diff --git a/src/components/inject-into-html.ts b/src/components/inject-by-tag.ts similarity index 56% rename from src/components/inject-into-html.ts rename to src/components/inject-by-tag.ts index fd0538d..8643461 100644 --- a/src/components/inject-into-html.ts +++ b/src/components/inject-by-tag.ts @@ -1,4 +1,5 @@ /// +const log = require('../core/log'); 'use strict'; @@ -7,18 +8,24 @@ * - done by parsing html file, * > replace: <{version}> */ -class InjectIntoHtml{ - +class InjectByTag{ constructor(private context) {} apply() { this.context.compiler.plugin('emit', (compilation, cb) => { + // for every output file for ( var basename in compilation.assets ) { - if(this.context.options.injectIntoHtmlRegex.test(basename)) { + // only if match regex + if(this.context.options.injectByTagFileRegex.test(basename)) { + let replaced = 0; let asset = compilation.assets[basename]; - let modFile = asset.source().replace(/(\<\{version\}\>)/g, this.context.version); + let modFile = asset.source().replace(/(\<\{version\}\>)/g, () => { + replaced++; + return this.context.version; + }); asset.source = () => modFile; + log.info(`InjectByTag : match : ${basename} : replaced : ${replaced}`); } } cb(); @@ -27,4 +34,4 @@ class InjectIntoHtml{ } } -module.exports = InjectIntoHtml; \ No newline at end of file +module.exports = InjectByTag; \ No newline at end of file diff --git a/src/config.ts b/src/config.ts index 7d20b63..e64549c 100644 --- a/src/config.ts +++ b/src/config.ts @@ -2,18 +2,23 @@ module.exports = { NAME : 'Auto Inject Version', SHORT : 'AIV', PATH_PACKAGE : './package.json', - COMPONENTS : [ + NON_WEBPACK_COMPONENTS : [ { option : 'autoIncrease', path : './components/auto-inc-version' - }, - { - option : 'injectIntoHtml', - path : './components/inject-into-html' - }, - { - option : 'injectIntoAnyFile', - path : './components/inject-into-any-file' } - ] + ], + WEBPACK_COMPONENTS : [ + { + option : 'injectByTag', + path : './components/inject-by-tag' + }, + { + option : 'injectAsComment', + path : './components/inject-as-comment' + } + ], + LOGS_TEXT : { + AIS_START : 'Auto inject version started' + } } \ No newline at end of file diff --git a/src/core/log.ts b/src/core/log.ts new file mode 100644 index 0000000..533fbce --- /dev/null +++ b/src/core/log.ts @@ -0,0 +1,67 @@ +const config = require('../config'); +const chalk = require('chalk'); +const endOfLine = require('os').EOL; +const u = require('./utils'); + +class Log{ + + private logLevel = 3; // default 1 + + constructor() { + this.getLogLevel(); + } + + private getLogLevel() { + if(u.isArgv('aiv-log-full')){ + this.logLevel = 3; + }else if(u.isArgv('aiv-log-none')) { + this.logLevel = 0; + } + } + + /** + * Get console log head + * @returns {string} + */ + private getHead() { + return endOfLine + chalk.bgYellow.black('[AIV] : ') + } + + /** + * Get log text by ID from config file + */ + private getText(id) { + return config.LOGS_TEXT[id]; + } + + /** + * Call any type + * @param type + * @param msg + */ + call(type, msgId) { + if(typeof this[type] === 'function') { + this[type](this.getText(msgId)); + } + } + + error (msg) { + if(this.logLevel < 3) return; + console.log(`${this.getHead()} ${chalk.red('error')} : ${msg}`); + } + + + info (msg) { + if(!this.logLevel) return; + console.log(`${this.getHead()} ${chalk.blue('info')} : ${msg}`); + } + + warn (msg) { + if(!this.logLevel) return; + console.log(`${this.getHead()} ${chalk.yellow('warn')} : ${msg}`); + } + +} + +var log = new Log(); +module.exports = log; \ No newline at end of file diff --git a/src/main.ts b/src/main.ts index 0fe16fa..538cf35 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,10 +1,11 @@ /// -var chalk = require('chalk'); -var fs = require('fs'); -var path = require('path'); -var config = require('./config'); -var Promise = require('bluebird'); -var u = require('./core/utils'); +const chalk = require('chalk'); +const fs = require('fs'); +const path = require('path'); +const config = require('./config'); +const Promise = require('bluebird'); +const u = require('./core/utils'); +const log = require('./core/log'); 'use strict'; @@ -13,45 +14,86 @@ class WebpackAutoInject{ private options; private compiler; private version; - private components; + /** + * Default options + */ static options = { autoIncrease : true, - injectIntoHtml : true, - injectIntoHtmlRegex : /^index\.html$/, - injectIntoAnyFile : true + injectAsComment : true, + injectByTag : true, + injectByTagFileRegex : /^index\.html$/ } + /** + * Constructor, + * called on webpack config load + * @param options + */ constructor(options) { this.options = u.merge(WebpackAutoInject.options, options); var packageFile = JSON.parse(fs.readFileSync(path.normalize(config.PATH_PACKAGE), 'utf8')); this.version = packageFile.version; + log.call('info', 'AIS_START'); + this.executeNoneWebpackComponents(); } + /** + * Webpack apply call, + * when webpack is initialized and + * plugin has been called by webpack + * @param compiler + */ protected apply(compiler) { - this.compiler = compiler; - - this.components = config.COMPONENTS; - - this.executeComponents(); - + this.executeWebpackComponents(); } - private executeComponents() { + /** + * Execute none webpack components + * - runs as soon as possible, + * > without waiting for webpack init + */ + private executeNoneWebpackComponents() { + this.executeComponents(config.NON_WEBPACK_COMPONENTS, () => { + }); + } - if(!this.components.length) { console.log(chalk.bgRed('AIS: DONE!')); return;} + /** + * Execute webpack components + * - runs when webpack is initialized + * and plugins is called by webpack + */ + private executeWebpackComponents() { + this.executeComponents(config.WEBPACK_COMPONENTS, () => { + }); + } - let comp = this.components.shift(); + /** + * Execute components, + * - general layer for comp execution + * - used for both, webpack and non webpack comp + */ + private executeComponents(components, done) { - if(this.options[comp.option]) { - let inst = new (require(comp.path))(this); - inst.apply().then(() => { - this.executeComponents(); - }, (err) => {console.log(err);}) - }else{ - this.executeComponents(); + // no more components, + // finish + if(!components.length) { done(); return;} + + // take first component + let comp = components.shift(); + + // if component is disabled, call next component + if(!this.options[comp.option]) { + this.executeComponents(components, done); + return; } + + // execute component + let inst = new (require(comp.path))(this); + inst.apply().then(() => { + this.executeComponents(components, done); + }, (err) => {this.executeComponents(components, done);}) } }