changelog2html
Advanced tools
Comparing version 0.0.4 to 0.0.7
212
changelog.js
@@ -1,48 +0,15 @@ | ||
var fs = require('fs'); | ||
var path = require('path'); | ||
var process = require('process'); | ||
var execSync = require('child_process').execSync; | ||
var swig = require('swig'); | ||
var markdown = require('markdown').markdown; | ||
var versions = {}; | ||
var Q = require('q'); | ||
'use strict'; | ||
/** | ||
* Return the git commit hash of the file which created it. | ||
* @param {String} folder - parent folder of file | ||
* @param {String} file - filename of file which should be checked | ||
*/ | ||
function getIshOfFile(folder, file) { | ||
var path = folder + "/" + file; | ||
var output = execSync('git log --oneline --diff-filter=A --pretty=format:%h -- ' + path); | ||
getTagOfIsh(output, path, file); | ||
} | ||
var fileRegex = /([^\.]*)\.([^\.]*)\.(.*)/; | ||
const nodegit = require('nodegit'); | ||
const fs = require('fs'); | ||
/** | ||
* Determine the first git tag in which the ish occurs and add the found information to the versions object. | ||
* @param {String} ish - Git commit hash to be checked. | ||
* @param {String} path - Parent path of the current file. | ||
* @param {String} file - Current filename. | ||
*/ | ||
function getTagOfIsh(ish, path, file) { | ||
var output = execSync('git tag --format \'{ "tag": "%(refname:short)", "date": "%(authordate)" }\' --contains ' + ish); | ||
var infoJSON = output.toString().split('\n')[0]; | ||
if (infoJSON.length != 0) { | ||
var info = JSON.parse(infoJSON); | ||
var content = fs.readFileSync(path, 'utf8'); | ||
var rendered = markdown.toHTML(content); | ||
info.path = path; | ||
info.content = content; | ||
info.contentRendered = rendered; | ||
var matches = fileRegex.exec(file); | ||
info.type = matches[2]; | ||
module.exports = renderChangelogForFolder; | ||
if (typeof versions[info.tag] === 'undefined') { | ||
versions[info.tag] = {}; | ||
} | ||
versions[info.tag][file] = info; | ||
} | ||
} | ||
// Test | ||
let promise = renderChangelogForFolder('.','template.html', 'changes'); | ||
promise.then(function (output) { | ||
console.log("OUTPUT: ", output); | ||
}); | ||
const fileRegex = /([^\.]*)\.([^\.]*)\.(.*)/; | ||
@@ -52,25 +19,158 @@ /** | ||
* @param {String} templateFile - Swig template file which should be used to render the changelog. | ||
* @param {String} changelogFolder - Folder which contains the git changelog files. | ||
* @param {String} pathInRepo - Folder which contains the git changelog files. | ||
* @returns a promise | ||
*/ | ||
function render(templateFile, changelogFolder) { | ||
var deferred = Q.defer(); | ||
function renderChangelogForFolder(repoPath, templateFile, pathInRepo) { | ||
const path = require('path'); | ||
const markdown = require('markdown').markdown; | ||
const swig = require('swig'); | ||
var files = fs.readdirSync(changelogFolder); | ||
files.forEach( function(file, index) { | ||
getIshOfFile(changelogFolder, file); | ||
let repo, tags, headHistory; | ||
// Open repository and list files in folder | ||
return Promise.all([ | ||
nodegit.Repository.open(repoPath) | ||
.then(repository => | ||
Promise.all([ | ||
// We need a commit list of HEAD ... | ||
repository.getHeadCommit() | ||
.then(headCommit => getHistoryOfCommit(headCommit)) | ||
.then(history => headHistory = history), | ||
// ... and all tags in the repo | ||
getTagCommitsOfRepo(repository) | ||
.then(tagList => tags = tagList) | ||
]) | ||
.then(() => repo = repository) | ||
), | ||
findFilesInFolder(path.join(repoPath, pathInRepo)) | ||
]) | ||
// Result is [repo, file list] | ||
.then(result => result[1]) | ||
// Find first tag for each file | ||
.then(fileList => Promise.all(fileList.map( | ||
file => { | ||
return findFirstCommitForFile(headHistory, path.join(pathInRepo, file)) | ||
.then(commit => { | ||
return {tag: findFirstTagWithCommit(tags, commit), commit: commit} | ||
}) | ||
.then( | ||
tag => ({ fileName: file, firstTag: tag.tag, commit: tag.commit}), | ||
error => ({ fileName: file, firstTag: null }) | ||
); | ||
} | ||
))) | ||
// If we can not find the history for a file, remove it from the list | ||
.then(fileList => { | ||
// Create datastructure which will be used for rendering the template | ||
let versions = {}; | ||
fileList.forEach(file => { | ||
let filePath = path.join(pathInRepo, file.fileName); | ||
let content = fs.readFileSync(filePath, 'utf8'); | ||
let rendered = markdown.toHTML(content); | ||
if (!versions[file.firstTag]) { | ||
versions[file.firstTag] = {}; | ||
} | ||
var matches = fileRegex.exec(file.fileName); | ||
versions[file.firstTag][file.fileName] = { | ||
content: content, | ||
contentRendered: rendered, | ||
path: filePath, | ||
date: file.commit.date(), | ||
tag: file.firstTag, | ||
type: matches[2] | ||
}; | ||
}); | ||
return versions; | ||
}) | ||
.then(renderInfo => { | ||
let html = swig.renderFile(templateFile, { | ||
pagename: 'Changelog', | ||
versions: renderInfo | ||
}); | ||
return html; | ||
}) | ||
.catch(console.error.bind(console)); | ||
} | ||
function findFirstCommitForFile(repoHeadHistory, filepath) { | ||
return findAllCommitsForFile(repoHeadHistory, filepath) | ||
.then(allCommits => { | ||
allCommits.sort((a, b) => b.date() - a.date()); | ||
return allCommits.length < 1 ? null : allCommits.pop(); | ||
}); | ||
var html = swig.renderFile(templateFile, { | ||
pagename: 'Changelog', | ||
versions: versions | ||
} | ||
function findAllCommitsForFile(repoHeadHistory, filepath) { | ||
return Promise.all( | ||
repoHeadHistory.map( | ||
commit => commit.getEntry(filepath) | ||
.then( | ||
entry => commit, | ||
fail => null | ||
) | ||
) | ||
) | ||
.then(commitList => commitList.filter(entry => entry != null)); | ||
} | ||
function getTagCommitsOfRepo(repo) { | ||
// Returns tags of the repo (sorted oldest to newest) | ||
// with all commits that happened before the tag | ||
return nodegit.Tag.list(repo) | ||
.then(tagNames => Promise.all(tagNames.map(tagName => | ||
nodegit.Reference.nameToId(repo, 'refs/tags/' + tagName) | ||
.then(oid => repo.getCommit(oid.tostrS())) | ||
.then(commit => | ||
getHistoryOfCommit(commit) | ||
.then(history => { | ||
return { tagName: tagName, headCommit: commit, history: history }; | ||
}) | ||
) | ||
))) | ||
.then(tagList => tagList.sort( | ||
(a, b) => a.headCommit.date() - b.headCommit.date() | ||
)); | ||
} | ||
function getHistoryOfCommit(headCommit) { | ||
return new Promise(resolve => { | ||
let history = headCommit.history(); | ||
let commits = []; | ||
history.on('commit', commit => commits.push(commit)); | ||
history.on('end', () => resolve(commits)); | ||
history.start(); | ||
}); | ||
deferred.resolve(html); | ||
return deferred.promise; | ||
} | ||
module.exports = render; | ||
function findFirstTagWithCommit(tags, commit) { | ||
// tags is sorted (oldest tag .. newest tag) | ||
const commitHash = (typeof commit == 'string') ? commit : commit.sha(); | ||
for (let i = 0; i < tags.length; i++) { | ||
for (let j = 0; j < tags[i].history.length; j++) { | ||
if (tags[i].history[j].sha() == commitHash) { | ||
return tags[i].tagName; | ||
} | ||
} | ||
} | ||
return null; | ||
} | ||
function findFilesInFolder(folder) { | ||
const fs = require('fs'); | ||
return new Promise((success, fail) => { | ||
fs.readdir(folder, (err, fileList) => { | ||
if (err) { | ||
return fail(err); | ||
} else { | ||
return success(fileList); | ||
} | ||
}); | ||
}); | ||
} | ||
if (require.main === module) { | ||
console.log('This script is meant to be used as a library. You probably want to run bin/changelog2html if you\'re looking for a CLI.'); | ||
process.exit(1); | ||
} | ||
} |
{ | ||
"name": "changelog2html", | ||
"version": "0.0.4", | ||
"version": "0.0.7", | ||
"description": "A changelog generator which uses git tags to identify versions and dates for found changelog entry files.", | ||
"keywords": [ "git", "changelog", "tooling" ], | ||
"keywords": [ | ||
"git", | ||
"changelog", | ||
"tooling" | ||
], | ||
"repository": { | ||
@@ -14,2 +18,3 @@ "type": "git", | ||
}, | ||
"engines" : { "node" : ">=4.0.0" }, | ||
"os": [ | ||
@@ -19,2 +24,8 @@ "!win32" | ||
"author": "Johannes Schüth <git@jotschi.de>", | ||
"contributors": [ | ||
{ | ||
"name": "Leon Adler", | ||
"email": "git@leon-adler.com" | ||
} | ||
], | ||
"license": "ISC", | ||
@@ -26,3 +37,3 @@ "preferGlobal": true, | ||
"mkdirp": "^0.5.1", | ||
"q": "1.4.x", | ||
"nodegit": "^0.13.0", | ||
"swig": "^1.4.2" | ||
@@ -29,0 +40,0 @@ }, |
@@ -32,4 +32,2 @@ ## changelog2html | ||
> *Please note that this tool is currently using* **exec** *to invoke the git command line tool.* | ||
```bash | ||
@@ -36,0 +34,0 @@ $ npm install changelog2html -g |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
11469
165
78
2
+ Addednodegit@^0.13.0
+ Addedasap@2.0.6(transitive)
+ Addedbalanced-match@1.0.2(transitive)
+ Addedbrace-expansion@1.1.11(transitive)
+ Addedconcat-map@0.0.1(transitive)
+ Addedfs-extra@0.26.7(transitive)
+ Addedfs.realpath@1.0.0(transitive)
+ Addedglob@7.2.3(transitive)
+ Addedgraceful-fs@4.2.11(transitive)
+ Addedinflight@1.0.6(transitive)
+ Addedinherits@2.0.4(transitive)
+ Addedjsonfile@2.4.0(transitive)
+ Addedklaw@1.3.1(transitive)
+ Addedminimatch@3.1.2(transitive)
+ Addednodegit@0.13.2(transitive)
+ Addednodegit-promise@4.0.0(transitive)
+ Addedonce@1.4.0(transitive)
+ Addedpath-is-absolute@1.0.1(transitive)
+ Addedpromisify-node@0.3.0(transitive)
+ Addedrimraf@2.7.1(transitive)
+ Addedwrappy@1.0.2(transitive)
- Removedq@1.4.x
- Removedq@1.4.1(transitive)