@@ -5,28 +5,19 @@ import * as path from 'path'
55import * as _ from 'lodash' ;
66import * as mkdirp from 'mkdirp' ;
77import * as rimraf from 'rimraf' ;
8+ import * as childProcess from 'child_process' ;
89
9- const textFileExtensions = [ '.gitignore' , 'template_gitignore' , '.config' , '.cs' , '.cshtml' , 'Dockerfile' , '.html' , '.js' , '.json' , '.jsx' , '.md' , '.ts' , '.tsx' , '.xproj' ] ;
10+ const isWindows = / ^ w i n / . test ( process . platform ) ;
11+ const textFileExtensions = [ '.gitignore' , 'template_gitignore' , '.config' , '.cs' , '.cshtml' , 'Dockerfile' , '.html' , '.js' , '.json' , '.jsx' , '.md' , '.nuspec' , '.ts' , '.tsx' , '.xproj' ] ;
12+ const yeomanGeneratorSource = './src/generator' ;
1013
11- const templates = {
12- 'angular-2' : '../../templates/Angular2Spa/' ,
13- 'knockout' : '../../templates/KnockoutSpa/' ,
14- 'react-redux' : '../../templates/ReactReduxSpa/' ,
15- 'react' : '../../templates/ReactSpa/'
14+ const templates : { [ key : string ] : { dir : string , dotNetNewId : string , displayName : string } } = {
15+ 'angular-2' : { dir : '../../templates/Angular2Spa/' , dotNetNewId : 'Angular' , displayName : 'Angular 2' } ,
16+ 'knockout' : { dir : '../../templates/KnockoutSpa/' , dotNetNewId : 'Knockout' , displayName : 'Knockout.js' } ,
17+ 'react-redux' : { dir : '../../templates/ReactReduxSpa/' , dotNetNewId : 'ReactRedux' , displayName : 'React.js and Redux' } ,
18+ 'react' : { dir : '../../templates/ReactSpa/' , dotNetNewId : 'React' , displayName : 'React.js' }
1619} ;
1720
18- const contentReplacements : { from : RegExp , to : string } [ ] = [
19- { from : / \b W e b A p p l i c a t i o n B a s i c \b / g, to : '<%= namePascalCase %>' } ,
20- { from : / < P r o j e c t G u i d > [ 0 - 9 a - f \- ] { 36 } < \/ P r o j e c t G u i d > / g, to : '<ProjectGuid><%= projectGuid %></ProjectGuid>' } ,
21- { from : / < R o o t N a m e s p a c e > .* ?< \/ R o o t N a m e s p a c e > / g, to : '<RootNamespace><%= namePascalCase %></RootNamespace>' } ,
22- { from : / \s * < B a s e I n t e r m e d i a t e O u t p u t P a t h .* ?< \/ B a s e I n t e r m e d i a t e O u t p u t P a t h > / g, to : '' } ,
23- { from : / \s * < O u t p u t P a t h .* ?< \/ O u t p u t P a t h > / g, to : '' } ,
24- ] ;
25-
26- const filenameReplacements : { from : RegExp , to : string } [ ] = [
27- { from : / .* \. x p r o j $ / , to : 'tokenreplace-namePascalCase.xproj' }
28- ] ;
29-
3021function isTextFile ( filename : string ) : boolean {
3122return textFileExtensions . indexOf ( path . extname ( filename ) . toLowerCase ( ) ) >= 0 ;
3223}
@@ -49,7 +40,7 @@ function listFilesExcludingGitignored(root: string): string[]{
4940. filter ( fn => gitignoreEvaluator . accepts ( fn ) ) ;
5041}
5142
52- function writeTemplate ( sourceRoot : string , destRoot : string ) {
43+ function writeTemplate ( sourceRoot : string , destRoot : string , contentReplacements : { from : RegExp , to : string } [ ] , filenameReplacements : { from : RegExp , to : string } [ ] ) {
5344listFilesExcludingGitignored ( sourceRoot ) . forEach ( fn => {
5445let sourceContent = fs . readFileSync ( path . join ( sourceRoot , fn ) ) ;
5546
@@ -80,20 +71,90 @@ function copyRecursive(sourceRoot: string, destRoot: string, matchGlob: string)
8071} ) ;
8172}
8273
83- const outputRoot = './generator-aspnetcore-spa' ;
84- const outputTemplatesRoot = path . join ( outputRoot , 'app/templates' ) ;
85- rimraf . sync ( outputTemplatesRoot ) ;
74+ function buildYeomanNpmPackage ( ) {
75+ const outputRoot = './dist/generator-aspnetcore-spa' ;
76+ const outputTemplatesRoot = path . join ( outputRoot , 'app/templates' ) ;
77+ rimraf . sync ( outputTemplatesRoot ) ;
78+
79+ // Copy template files
80+ const filenameReplacements = [
81+ { from : / .* \. x p r o j $ / , to : 'tokenreplace-namePascalCase.xproj' }
82+ ] ;
83+ const contentReplacements = [
84+ { from : / \b W e b A p p l i c a t i o n B a s i c \b / g, to : '<%= namePascalCase %>' } ,
85+ { from : / < P r o j e c t G u i d > [ 0 - 9 a - f \- ] { 36 } < \/ P r o j e c t G u i d > / g, to : '<ProjectGuid><%= projectGuid %></ProjectGuid>' } ,
86+ { from : / < R o o t N a m e s p a c e > .* ?< \/ R o o t N a m e s p a c e > / g, to : '<RootNamespace><%= namePascalCase %></RootNamespace>' } ,
87+ { from : / \s * < B a s e I n t e r m e d i a t e O u t p u t P a t h .* ?< \/ B a s e I n t e r m e d i a t e O u t p u t P a t h > / g, to : '' } ,
88+ { from : / \s * < O u t p u t P a t h .* ?< \/ O u t p u t P a t h > / g, to : '' } ,
89+ ] ;
90+ _ . forEach ( templates , ( templateConfig , templateName ) => {
91+ const outputDir = path . join ( outputTemplatesRoot , templateName ) ;
92+ writeTemplate ( templateConfig . dir , outputDir , contentReplacements , filenameReplacements ) ;
93+ } ) ;
94+
95+ // Also copy the generator files (that's the compiled .js files, plus all other non-.ts files)
96+ const tempRoot = './tmp' ;
97+ copyRecursive ( path . join ( tempRoot , 'generator' ) , outputRoot , '**/*.js' ) ;
98+ copyRecursive ( yeomanGeneratorSource , outputRoot , '**/!(*.ts)' ) ;
8699
87- // Copy template files
88- _ . forEach ( templates , ( templateRootDir , templateName ) => {
89- const outputDir = path . join ( outputTemplatesRoot , templateName ) ;
90- writeTemplate ( templateRootDir , outputDir ) ;
91- } ) ;
100+ // Clean up
101+ rimraf . sync ( tempRoot ) ;
102+ }
103+
104+ function buildDotNetNewNuGetPackage ( ) {
105+ const outputRoot = './dist/dotnetnew' ;
106+ rimraf . sync ( outputRoot ) ;
107+
108+ // Copy template files
109+ const sourceProjectName = 'WebApplicationBasic' ;
110+ const projectGuid = '00000000-0000-0000-0000-000000000000' ;
111+ const filenameReplacements = [
112+ { from : / .* \. x p r o j $ / , to : `${ sourceProjectName } .xproj` } ,
113+ { from : / \b t e m p l a t e _ g i t i g n o r e $ / , to : '.gitignore' }
114+ ] ;
115+ const contentReplacements = [
116+ { from : / < P r o j e c t G u i d > [ 0 - 9 a - f \- ] { 36 } < \/ P r o j e c t G u i d > / g, to : `<ProjectGuid>${ projectGuid } </ProjectGuid>` } ,
117+ { from : / < R o o t N a m e s p a c e > .* ?< \/ R o o t N a m e s p a c e > / g, to : `<RootNamespace>${ sourceProjectName } </RootNamespace>` } ,
118+ { from : / \s * < B a s e I n t e r m e d i a t e O u t p u t P a t h .* ?< \/ B a s e I n t e r m e d i a t e O u t p u t P a t h > / g, to : '' } ,
119+ { from : / \s * < O u t p u t P a t h .* ?< \/ O u t p u t P a t h > / g, to : '' } ,
120+ ] ;
121+ _ . forEach ( templates , ( templateConfig , templateName ) => {
122+ const templateOutputDir = path . join ( outputRoot , 'templates' , templateName ) ;
123+ const templateOutputProjectDir = path . join ( templateOutputDir , sourceProjectName ) ;
124+ writeTemplate ( templateConfig . dir , templateOutputProjectDir , contentReplacements , filenameReplacements ) ;
125+
126+ // Add a .netnew.json file
127+ fs . writeFileSync ( path . join ( templateOutputDir , '.netnew.json' ) , JSON . stringify ( {
128+ author : 'Microsoft' ,
129+ classifications : [ 'Standard>>Quick Starts' ] ,
130+ name : `ASP.NET Core SPA with ${ templateConfig . displayName } ` ,
131+ groupIdentity : `Microsoft.AspNetCore.Spa.${ templateConfig . dotNetNewId } ` ,
132+ identity : `Microsoft.AspNetCore.Spa.${ templateConfig . dotNetNewId } ` ,
133+ shortName : `aspnetcorespa-${ templateConfig . dotNetNewId . toLowerCase ( ) } ` ,
134+ tags : { language : 'C#' } ,
135+ guids : [ projectGuid ] ,
136+ sourceName : sourceProjectName
137+ } , null , 2 ) ) ;
138+ } ) ;
92139
93- // Also copy the generator files (that's the compiled .js files, plus all other non-.ts files)
94- const tempRoot = './tmp' ;
95- copyRecursive ( path . join ( tempRoot , 'generator' ) , outputRoot , '**/*.js' ) ;
96- copyRecursive ( './src/generator' , outputRoot , '**/!(*.ts)' ) ;
140+ // Invoke NuGet to create the final package
141+ const yeomanPackageVersion = JSON . parse ( fs . readFileSync ( path . join ( yeomanGeneratorSource , 'package.json' ) , 'utf8' ) ) . version ;
142+ writeTemplate ( './src/dotnetnew' , outputRoot , [
143+ { from : / \{ v e r s i o n \} / g, to : yeomanPackageVersion } ,
144+ ] , [ ] ) ;
145+ const nugetExe = path . join ( process . cwd ( ) , './bin/NuGet.exe' ) ;
146+ const nugetStartInfo = { cwd : outputRoot , stdio : 'inherit' } ;
147+ if ( isWindows ) {
148+ // Invoke NuGet.exe directly
149+ childProcess . spawnSync ( nugetExe , [ 'pack' ] , nugetStartInfo ) ;
150+ } else {
151+ // Invoke via Mono (relying on that being available)
152+ childProcess . spawnSync ( 'mono' , [ nugetExe , 'pack' ] , nugetStartInfo ) ;
153+ }
154+
155+ // Clean up
156+ rimraf . sync ( './tmp' ) ;
157+ }
97158
98- // Clean up
99- rimraf . sync ( tempRoot ) ;
159+ buildYeomanNpmPackage ( ) ;
160+ buildDotNetNewNuGetPackage ( ) ;
0 commit comments