diff --git a/templates/package-builder/package.json b/templates/package-builder/package.json index b65ceb0..a6e26aa 100644 --- a/templates/package-builder/package.json +++ b/templates/package-builder/package.json @@ -10,6 +10,7 @@ "author": "Microsoft", "license": "Apache-2.0", "dependencies": { + "@types/chalk": "^0.4.31", "@types/semver": "^5.3.30", "diff": "^2.2.2", "gitignore-parser": "0.0.2", diff --git a/templates/package-builder/src/build/build.ts b/templates/package-builder/src/build/build.ts index c5d6a75..9896dc4 100644 --- a/templates/package-builder/src/build/build.ts +++ b/templates/package-builder/src/build/build.ts @@ -8,7 +8,7 @@ import * as rimraf from 'rimraf'; import * as childProcess from 'child_process'; const isWindows = /^win/.test(process.platform); -const textFileExtensions = ['.gitignore', 'template_gitignore', '.config', '.cs', '.cshtml', 'Dockerfile', '.html', '.js', '.json', '.jsx', '.md', '.nuspec', '.ts', '.tsx', '.xproj']; +const textFileExtensions = ['.gitignore', 'template_gitignore', '.config', '.cs', '.cshtml', '.csproj', 'Dockerfile', '.html', '.js', '.json', '.jsx', '.md', '.nuspec', '.ts', '.tsx', '.xproj']; const yeomanGeneratorSource = './src/yeoman'; // For the Angular 2 template, we want to bundle prebuilt dist dev-mode files, because the VS template can't auto-run @@ -88,14 +88,19 @@ function buildYeomanNpmPackage() { // Copy template files const filenameReplacements = [ - { from: /.*\.xproj$/, to: 'tokenreplace-namePascalCase.xproj' } + { from: /.*\.xproj$/, to: 'tokenreplace-namePascalCase.xproj' }, + { from: /.*\.csproj$/, to: 'tokenreplace-namePascalCase.csproj' } ]; const contentReplacements = [ + // .xproj items { from: /\bWebApplicationBasic\b/g, to: '<%= namePascalCase %>' }, { from: /[0-9a-f\-]{36}<\/ProjectGuid>/g, to: '<%= projectGuid %>' }, { from: /.*?<\/RootNamespace>/g, to: '<%= namePascalCase %>'}, { from: /\s*/g, to: '' }, { from: /\s*/g, to: '' }, + + // global.json items + { from: /1\.0\.0-preview2-1-003177/, to: '<%= sdkVersion %>' } ]; _.forEach(templates, (templateConfig, templateName) => { const outputDir = path.join(outputTemplatesRoot, templateName); @@ -119,6 +124,7 @@ function buildDotNetNewNuGetPackage() { const sourceProjectName = 'WebApplicationBasic'; const projectGuid = '00000000-0000-0000-0000-000000000000'; const filenameReplacements = [ + // TODO: For dotnetnew templates, switch to csproj. No need for SDK choice as it can be Preview3+ only. { from: /.*\.xproj$/, to: `${sourceProjectName}.xproj` }, { from: /\btemplate_gitignore$/, to: '.gitignore' } ]; diff --git a/templates/package-builder/src/yeoman/app/index.ts b/templates/package-builder/src/yeoman/app/index.ts index 53f18c9..08a52de 100644 --- a/templates/package-builder/src/yeoman/app/index.ts +++ b/templates/package-builder/src/yeoman/app/index.ts @@ -4,6 +4,7 @@ import * as yeoman from 'yeoman-generator'; import * as uuid from 'node-uuid'; import * as glob from 'glob'; import * as semver from 'semver'; +import * as chalk from 'chalk'; import { execSync } from 'child_process'; import npmWhich = require('npm-which'); const yosay = require('yosay'); @@ -42,6 +43,20 @@ const templates = [ { value: 'react-redux', name: 'React with Redux', tests: false } ]; +// Once everyone is on .csproj-compatible tooling, we might be able to remove the global.json files and eliminate +// this SDK choice altogether. That would be good because then it would work with whatever SDK version you have +// installed. For now, we need to specify an SDK version explicitly, because there's no support for wildcards, and +// preview3+ tooling doesn't support project.json at all. +const sdkChoices = [{ + value: '1.0.0-preview2-1-003177', // Current released version + name: 'project.json' + chalk.gray(' (compatible with .NET Core tooling preview 2 and Visual Studio 2015)'), + includeFiles: [/^project.json$/, /\.xproj$/] +}, { + value: '1.0.0-preview3-004056', // Version that ships with VS2017RC + name: '.csproj' + chalk.gray(' (compatible with .NET Core tooling preview 3 and Visual Studio 2017)'), + includeFiles: [/\.csproj$/] +}]; + class MyGenerator extends yeoman.Base { private _answers: any; private _optionOrPrompt: YeomanPrompt; @@ -65,8 +80,13 @@ class MyGenerator extends yeoman.Base { name: 'framework', message: 'Framework', choices: templates - }], frameworkAnswer => { - const frameworkChoice = templates.filter(t => t.value === frameworkAnswer.framework)[0]; + }, { + type: 'list', + name: 'sdkVersion', + message: 'What type of project do you want to create?', + choices: sdkChoices + }], firstAnswers => { + const frameworkChoice = templates.filter(t => t.value === firstAnswers.framework)[0]; const furtherQuestions = [{ type: 'input', name: 'name', @@ -84,9 +104,10 @@ class MyGenerator extends yeoman.Base { } this._optionOrPrompt(furtherQuestions, answers => { - answers.framework = frameworkAnswer.framework; + answers.framework = firstAnswers.framework; this._answers = answers; - this._answers.framework = frameworkAnswer.framework; + this._answers.framework = firstAnswers.framework; + this._answers.sdkVersion = firstAnswers.sdkVersion; this._answers.namePascalCase = toPascalCase(answers.name); this._answers.projectGuid = this.options['projectguid'] || uuid.v4(); done(); @@ -95,7 +116,8 @@ class MyGenerator extends yeoman.Base { } writing() { - var templateRoot = this.templatePath(this._answers.framework); + const templateRoot = this.templatePath(this._answers.framework); + const chosenSdk = sdkChoices.filter(sdk => sdk.value === this._answers.sdkVersion)[0]; glob.sync('**/*', { cwd: templateRoot, dot: true, nodir: true }).forEach(fn => { // Token replacement in filenames let outputFn = fn.replace(/tokenreplace\-([^\.\/]*)/g, (substr, token) => this._answers[token]); @@ -105,9 +127,14 @@ class MyGenerator extends yeoman.Base { outputFn = path.join(path.dirname(fn), '.gitignore'); } - // Exclude test-specific files (unless the user has said they want tests) + // Decide whether to emit this file const isTestSpecificFile = testSpecificPaths.some(regex => regex.test(outputFn)); - if (this._answers.tests || !isTestSpecificFile) { + const isSdkSpecificFile = sdkChoices.some(sdk => sdk.includeFiles.some(regex => regex.test(outputFn))); + const matchesChosenSdk = chosenSdk.includeFiles.some(regex => regex.test(outputFn)); + const emitFile = (matchesChosenSdk || !isSdkSpecificFile) + && (this._answers.tests || !isTestSpecificFile); + + if (emitFile) { let inputFullPath = path.join(templateRoot, fn); let destinationFullPath = this.destinationPath(outputFn); if (path.basename(fn) === 'package.json') { diff --git a/templates/package-builder/src/yeoman/package.json b/templates/package-builder/src/yeoman/package.json index 30fb434..171dbd9 100644 --- a/templates/package-builder/src/yeoman/package.json +++ b/templates/package-builder/src/yeoman/package.json @@ -18,6 +18,7 @@ "url": "https://github.com/aspnet/JavaScriptServices.git" }, "dependencies": { + "chalk": "^1.1.3", "glob": "^7.0.3", "node-uuid": "^1.4.7", "npm-which": "^3.0.1",