mirror of
https://github.com/aspnet/JavaScriptServices.git
synced 2025-12-24 10:40:23 +00:00
96 lines
4.0 KiB
TypeScript
96 lines
4.0 KiB
TypeScript
import * as yeoman from 'yeoman-generator';
|
|
import * as glob from 'glob';
|
|
import * as gitignore from 'gitignore-parser';
|
|
import * as fs from 'fs';
|
|
import * as path from 'path';
|
|
import * as _ from 'lodash';
|
|
import * as diff from 'diff';
|
|
import * as mkdirp from 'mkdirp';
|
|
import * as rimraf from 'rimraf';
|
|
|
|
const textFileExtensions = ['.gitignore', '.config', '.cs', '.cshtml', 'Dockerfile', '.html', '.js', '.json', '.jsx', '.md', '.ts', '.tsx'];
|
|
|
|
const templates = {
|
|
'angular-2': '../../templates/Angular2Spa/',
|
|
'knockout': '../../templates/KnockoutSpa/',
|
|
'react-redux': '../../templates/ReactReduxSpa/',
|
|
'react': '../../templates/ReactSpa/'
|
|
};
|
|
|
|
function isTextFile(filename: string): boolean {
|
|
return textFileExtensions.indexOf(path.extname(filename).toLowerCase()) >= 0;
|
|
}
|
|
|
|
function writeFileEnsuringDirExists(root: string, filename: string, contents: string | Buffer) {
|
|
let fullPath = path.join(root, filename);
|
|
mkdirp.sync(path.dirname(fullPath));
|
|
fs.writeFileSync(fullPath, contents);
|
|
}
|
|
|
|
function listFilesExcludingGitignored(root: string): string[] {
|
|
let gitignoreEvaluator = gitignore.compile(fs.readFileSync(path.join(root, '.gitignore'), 'utf8'));
|
|
return glob.sync('**/*', { cwd: root, dot: true, nodir: true })
|
|
.filter(fn => gitignoreEvaluator.accepts(fn));
|
|
}
|
|
|
|
function writeCommonFiles(outDir: string) {
|
|
let filesByTemplate = _.mapValues(templates, listFilesExcludingGitignored);
|
|
let commonFiles = _.intersection.apply(_, _.values(filesByTemplate));
|
|
|
|
commonFiles.forEach(fn => {
|
|
let templateRoots = _.values(templates);
|
|
let origContent = fs.readFileSync(path.join(templateRoots[0], fn));
|
|
|
|
if (isTextFile(fn)) {
|
|
// For text files, we copy the portion that's common to all the templates
|
|
let commonText = origContent.toString('utf8');
|
|
templateRoots.slice(1).forEach(otherTemplateRoot => {
|
|
let otherTemplateContent = fs.readFileSync(path.join(otherTemplateRoot, fn), 'utf8');
|
|
commonText = diff.diffLines(commonText, otherTemplateContent)
|
|
.filter(c => !(c.added || c.removed))
|
|
.map(c => c.value)
|
|
.join('');
|
|
});
|
|
|
|
writeFileEnsuringDirExists(outDir, fn, commonText);
|
|
} else {
|
|
// For binary (or maybe-binary) files, we only consider them common if they are identical across all templates
|
|
let isIdenticalEverywhere = !templateRoots.slice(1).some(otherTemplateRoot => {
|
|
return !fs.readFileSync(path.join(otherTemplateRoot, fn)).equals(origContent);
|
|
});
|
|
if (isIdenticalEverywhere) {
|
|
writeFileEnsuringDirExists(outDir, fn, origContent);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
function writeDiffsForTemplate(sourceRoot: string, destRoot: string, commonRoot: string) {
|
|
listFilesExcludingGitignored(sourceRoot).forEach(fn => {
|
|
const commonFn = path.join(commonRoot, fn);
|
|
const sourceContent = fs.readFileSync(path.join(sourceRoot, fn));
|
|
|
|
if (!fs.existsSync(commonFn)) {
|
|
// This file is unique to this template - just copy as-is
|
|
writeFileEnsuringDirExists(destRoot, fn, sourceContent);
|
|
} else {
|
|
let commonText = fs.readFileSync(commonFn, 'utf8');
|
|
let sourceText = sourceContent.toString('utf8');
|
|
if (commonText !== sourceText) {
|
|
// Write a diff vs the common version of this file
|
|
let fileDiff = diff.createPatch(fn, commonText, sourceText, null, null);
|
|
writeFileEnsuringDirExists(destRoot, fn + '.patch', fileDiff);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
const outputRoot = './generator-aspnet-spa';
|
|
const commonRoot = path.join(outputRoot, 'templates/common');
|
|
rimraf.sync(outputRoot);
|
|
writeCommonFiles(commonRoot);
|
|
|
|
_.forEach(templates, (templateRootDir, templateName) => {
|
|
writeDiffsForTemplate(templateRootDir, path.join(outputRoot, 'templates', templateName), commonRoot);
|
|
});
|