Skip to content

Commit

Permalink
Automatic semicolon detection (to be discarded)
Browse files Browse the repository at this point in the history
  • Loading branch information
axelpale committed Jan 1, 2018
1 parent c8dae89 commit 228cb73
Show file tree
Hide file tree
Showing 8 changed files with 291 additions and 150 deletions.
39 changes: 29 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,34 +4,52 @@

![Logo](doc/logo.png?raw=true "Abracadabra...and behold!")

So you want `yourmodule.version` to follow the version in package.json but are tired of updating it manually every time the version changes? You could import your package.json into the module but you know it is a naughty thing to do! Genversion to the rescue!
So you want `yourmodule.version` to follow the version in package.json but are tired of updating it manually every time the version changes? You could import your package.json into the module but you know it is a **naughty** thing to do! Genversion to the rescue!

Usage is simple. First install via npm.
## Try it out

Usage is simple:

$ cd yourmodule
$ npm install -g genversion
$ genversion lib/version.js

Voilà! The new lib/version.js:

module.exports = '1.2.3'

## Integrate to your build

First install via [npm](https://www.npmjs.com/package/genversion).

$ npm install genversion --save-dev

Genversion works by first reading the current version from package.json and then generating a simple CommonJS module file that exports the version:
Genversion works by first reading the current version from package.json and then generating a simple CommonJS module file that exports the version string. For safety, the version file begins with a signature that tells genversion that the file can be overwritten.

module.exports = '1.2.3';
// generated by genversion
module.exports = '1.2.3'

Your job is to 1) choose a location for the file, 2) require() the new file into your module, and 3) add genversion as a part of your build or release pipeline. For example, let us choose location 'lib/version.js' and import it into yourmodule:
Now, your job is to 1) choose a path for the version file, 2) require() the new file into your module, and 3) add genversion as a part of your build or release pipeline. For example, let us choose the path 'lib/version.js' and require it in yourmodule/index.js:

// At yourmodule/index.js
exports.version = require('./lib/version');
...
exports.version = require('./lib/version')
...

Then, let us integrate genversion into our build task. The target location is given as the first argument. If the file already exists, it is replaced with the new one. But do not worry, genversion will only replace files generated by genversion itself.
Then, let us integrate genversion into your build task.

"scripts": {
"build": "genversion lib/version.js && other build stuff"
}

After this, your module has a version property that matches with package.json and is updated every time you build the project.
The target path is given as the first argument. If the file already exists and has been previously created by genversion, it is replaced with the new one.

Finished! Now your module has a version property that matches with package.json and is updated every time you build the project.

> var yourmodule = require('yourmodule')
> yourmodule.version
'1.2.3'

Great! Having a version property in your module is very convenient for debugging. More than once we have needed to debug a module for a long time just to find that it was a cached old version that caused the error. An inspectable version property would have helped a big time.
Great! Having a version property in your module is very convenient for debugging. More than once we have needed to painstakingly debug a module, just to find out that it was a cached old version that caused the error. An inspectable version property would have helped a big time.


## Command line API
Expand Down Expand Up @@ -111,6 +129,7 @@ The version string of genversion module in [semantic versioning](http://semver.o

- [genversion](https://www.npmjs.com/package/genversion)
- [poisson-process](https://www.npmjs.com/package/poisson-process)
- [taaspace](https://www.npmjs.com/package/taaspace)
- [taach](https://www.npmjs.com/package/taach)


Expand Down
52 changes: 24 additions & 28 deletions bin/genversion.js
Original file line number Diff line number Diff line change
@@ -1,76 +1,72 @@
#!/usr/bin/env node

var gv = require('../lib/genversion');
var v = require('../lib/version');
var program = require('commander');
var path = require('path');

var gv = require('../lib/genversion')
var v = require('../lib/version')
var program = require('commander')
var path = require('path')

var increaseVerbosity = function (verb, total) {
return total + 1;
};

return total + 1
}

program
.version(v)
.usage('[options] <target>')
.description('Generates a version module at the target filepath.')
.option('-v, --verbose', 'Output the new version.', increaseVerbosity, 0)
.action(function (target) {

gv.check(target, function (err, doesExist, isByGenversion) {
if (err) {
console.error(err.toString());
process.exit(1);
console.error(err.toString())
process.exit(1)
}

if (doesExist) {
if (isByGenversion) {
gv.generate(target, function (errg, version) {
if (errg) {
console.error(errg);
return;
console.error(errg)
return
}

if (program.verbose >= 1) {
console.log('File ' + path.basename(target) +
' was successfully updated to ' + version);
' was successfully updated to ' + version)
}
});
})
} else {
// FAIL, unknown file, do not replace
console.error(
'ERROR: File ' + target + ' is not generated by genversion and ' +
'therefore will not be replaced. Please ensure that the file can ' +
'be destroyed and remove it manually before retry.'
);
)
}
} else {
// OK, file does not exist.
gv.generate(target, function (errg, version) {
if (errg) {
console.error(errg);
return;
console.error(errg)
return
}

if (program.verbose >= 1) {
console.log('File ' + path.basename(target) +
' was successfully generated with version ' + version);
' was successfully generated with version ' + version)
}
});
})
}
});

});
})
})

program.on('--help', function () {
// Additional newline.
console.log('');
});
console.log('')
})

program.parse(process.argv);
program.parse(process.argv)

if (program.args.length === 0) {
console.error('ERROR: Missing argument <target>');
program.outputHelp();
console.error('ERROR: Missing argument <target>')
program.outputHelp()
}
106 changes: 106 additions & 0 deletions lib/detectSemicolon.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
var findPackage = require('find-package')
var path = require('path')
var find = require('find')
var findInFiles = require('find-in-files')

var countSemiFiles = function (dirPath, excludePath, callback) {
// Find the number of js files.
// If there is more files with trailing semicolons than no semis
// then we use semis.
//
find.file(/\.js$/, dirPath, function (files) {
//
// Do not count in the possibly existing version file.
files = files.filter(function (fp) {
return fp !== excludePath
})

findInFiles.find(';\n', dirPath, /\.js$/).then(function (results) {
var num, key, numSemi

num = files.length
numSemi = 0

for (key in results) {
if (results.hasOwnProperty(key)) {
if (key !== excludePath) {
numSemi += 1
}
}
}

return callback(null, {
numFiles: num,
numFilesWithSemis: numSemi
})

// var mostSemi = false
//
// if (num === 0) {
// mostSemi = false // arbitrary
// } else {
// if (numSemi >= Math.ceil(num / 2)) {
// mostSemi = true
// } else {
// mostSemi = false
// }
// }
//
// console.log('mostSemi', mostSemi)
//
// return callback(null, mostSemi)
})
})
}

module.exports = function (targetPath, callback) {
// Detect if the project uses semicolons or not.
//
// Parameters
// targetPath
// string. Absolute path to initial location to begin search.
// callback
// function (err, useSemicolon)
// Parameters
// err
// useSemicolon
// bool. True if semicolon is used
//
var pjson = findPackage(targetPath, true) // true adds .paths property

// If project uses standardjs, no semicolon.
if (pjson.dependencies) {
if (pjson.dependencies.hasOwnProperty('standard')) {
return callback(null, false)
}
}

var dirPath = path.dirname(targetPath)

// TODO If there is no files, try bin/, lib/, src/

// Find the number of js files.
// If there is more files with trailing semicolons than no semis
// then we use semis.
countSemiFiles(dirPath, targetPath, function (errs, results) {
if (errs) {
return callback(errs)
}

var num = results.numFiles
var numSemi = results.numFilesWithSemis
var mostSemi

if (num === 0) {
mostSemi = false // arbitrary
} else {
if (numSemi >= Math.ceil(num / 2)) {
mostSemi = true
} else {
mostSemi = false
}
}

return callback(null, mostSemi)
})
}
Loading

0 comments on commit 228cb73

Please sign in to comment.