Skip to content

Commit d3ded5b

Browse files
Workaround for Yeoman generators not producing .gitignore files due to Yeoman issue #1862
1 parent 7e51fc4 commit d3ded5b

File tree

9 files changed

+32
-17
lines changed

9 files changed

+32
-17
lines changed

.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,10 @@ project.lock.json
2929
.vs/
3030
npm-debug.log
3131
/.build/
32+
33+
# The templates can't contain their own .gitignore files, because Yeoman has strange default handling for
34+
# files with that name (https://github.com/npm/npm/issues/1862). So, each template instead has a template_gitignore
35+
# file which gets renamed after the files are copied. And so any files that need to be excluded in the source
36+
# repo have to be excluded here.
37+
/templates/*/node_modules/
38+
/templates/*/wwwroot/dist/
File renamed without changes.
File renamed without changes.

templates/yeoman/src/build/build.ts

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import * as _ from 'lodash';
66
import * as mkdirp from 'mkdirp';
77
import * as rimraf from 'rimraf';
88

9-
const textFileExtensions = ['.gitignore', '.config', '.cs', '.cshtml', 'Dockerfile', '.html', '.js', '.json', '.jsx', '.md', '.ts', '.tsx', '.xproj'];
9+
const textFileExtensions = ['.gitignore', 'template_gitignore', '.config', '.cs', '.cshtml', 'Dockerfile', '.html', '.js', '.json', '.jsx', '.md', '.ts', '.tsx', '.xproj'];
1010

1111
const templates = {
1212
'angular-2': '../../templates/Angular2Spa/',
@@ -33,12 +33,15 @@ function isTextFile(filename: string): boolean {
3333

3434
function writeFileEnsuringDirExists(root: string, filename: string, contents: string | Buffer) {
3535
let fullPath = path.join(root, filename);
36-
mkdirp.sync(path.dirname(fullPath));
36+
mkdirp.sync(path.dirname(fullPath));
3737
fs.writeFileSync(fullPath, contents);
3838
}
3939

40-
function listFilesExcludingGitignored(root: string): string[] {
41-
let gitIgnorePath = path.join(root, '.gitignore');
40+
function listFilesExcludingGitignored(root: string): string[] {
41+
// Note that the gitignore files, prior to be written by the generator, are called 'template_gitignore'
42+
// instead of '.gitignore'. This is a workaround for Yeoman doing strange stuff with .gitignore files
43+
// (it renames them to .npmignore, which is not helpful).
44+
let gitIgnorePath = path.join(root, 'template_gitignore');
4245
let gitignoreEvaluator = fs.existsSync(gitIgnorePath)
4346
? gitignore.compile(fs.readFileSync(gitIgnorePath, 'utf8'))
4447
: { accepts: () => true };
@@ -49,36 +52,36 @@ function listFilesExcludingGitignored(root: string): string[] {
4952
function writeTemplate(sourceRoot: string, destRoot: string) {
5053
listFilesExcludingGitignored(sourceRoot).forEach(fn => {
5154
let sourceContent = fs.readFileSync(path.join(sourceRoot, fn));
52-
55+
5356
// For text files, replace hardcoded values with template tags
5457
if (isTextFile(fn)) {
5558
let sourceText = sourceContent.toString('utf8');
5659
contentReplacements.forEach(replacement => {
5760
sourceText = sourceText.replace(replacement.from, replacement.to);
5861
});
59-
62+
6063
sourceContent = new Buffer(sourceText, 'utf8');
6164
}
62-
65+
6366
// Also apply replacements in filenames
6467
filenameReplacements.forEach(replacement => {
6568
fn = fn.replace(replacement.from, replacement.to);
6669
});
67-
70+
6871
writeFileEnsuringDirExists(destRoot, fn, sourceContent);
69-
});
72+
});
7073
}
7174

7275
function copyRecursive(sourceRoot: string, destRoot: string, matchGlob: string) {
7376
glob.sync(matchGlob, { cwd: sourceRoot, dot: true, nodir: true })
7477
.forEach(fn => {
75-
const sourceContent = fs.readFileSync(path.join(sourceRoot, fn));
78+
const sourceContent = fs.readFileSync(path.join(sourceRoot, fn));
7679
writeFileEnsuringDirExists(destRoot, fn, sourceContent);
7780
});
7881
}
7982

8083
const outputRoot = './generator-aspnetcore-spa';
81-
const outputTemplatesRoot = path.join(outputRoot, 'app/templates');
84+
const outputTemplatesRoot = path.join(outputRoot, 'app/templates');
8285
rimraf.sync(outputTemplatesRoot);
8386

8487
// Copy template files

templates/yeoman/src/generator/app/index.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ class MyGenerator extends yeoman.Base {
2222

2323
prompting() {
2424
const done = this.async();
25-
25+
2626
this.prompt([{
2727
type: 'list',
2828
name: 'framework',
@@ -40,29 +40,34 @@ class MyGenerator extends yeoman.Base {
4040
done();
4141
});
4242
}
43-
43+
4444
writing() {
4545
var templateRoot = this.templatePath(this._answers.framework);
4646
glob.sync('**/*', { cwd: templateRoot, dot: true, nodir: true }).forEach(fn => {
4747
// Token replacement in filenames
4848
let outputFn = fn.replace(/tokenreplace\-([^\.\/]*)/g, (substr, token) => this._answers[token]);
49-
49+
50+
// Rename template_gitignore to .gitignore in output
51+
if (path.basename(fn) === 'template_gitignore') {
52+
outputFn = path.join(path.dirname(fn), '.gitignore');
53+
}
54+
5055
this.fs.copyTpl(
5156
path.join(templateRoot, fn),
5257
this.destinationPath(outputFn),
5358
this._answers
5459
);
5560
});
5661
}
57-
62+
5863
installingDeps() {
5964
this.installDependencies({
6065
npm: true,
6166
bower: false,
6267
callback: () => {
6368
this.spawnCommandSync('dotnet', ['restore']);
6469
this.spawnCommandSync('./node_modules/.bin/webpack', ['--config', 'webpack.config.vendor.js']);
65-
this.spawnCommandSync('./node_modules/.bin/webpack');
70+
this.spawnCommandSync('./node_modules/.bin/webpack');
6671
}
6772
});
6873
}

templates/yeoman/src/generator/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "generator-aspnetcore-spa",
3-
"version": "0.1.5",
3+
"version": "0.1.6",
44
"description": "Single-Page App templates for ASP.NET Core",
55
"author": "Microsoft",
66
"license": "Apache-2.0",

0 commit comments

Comments
 (0)