@@ -5,28 +5,19 @@ import * as path from 'path';
5
5
import * as _ from 'lodash' ;
6
6
import * as mkdirp from 'mkdirp' ;
7
7
import * as rimraf from 'rimraf' ;
8
+ import * as childProcess from 'child_process' ;
8
9
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' ;
10
13
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' }
16
19
} ;
17
20
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
-
30
21
function isTextFile ( filename : string ) : boolean {
31
22
return textFileExtensions . indexOf ( path . extname ( filename ) . toLowerCase ( ) ) >= 0 ;
32
23
}
@@ -49,7 +40,7 @@ function listFilesExcludingGitignored(root: string): string[] {
49
40
. filter ( fn => gitignoreEvaluator . accepts ( fn ) ) ;
50
41
}
51
42
52
- function writeTemplate ( sourceRoot : string , destRoot : string ) {
43
+ function writeTemplate ( sourceRoot : string , destRoot : string , contentReplacements : { from : RegExp , to : string } [ ] , filenameReplacements : { from : RegExp , to : string } [ ] ) {
53
44
listFilesExcludingGitignored ( sourceRoot ) . forEach ( fn => {
54
45
let sourceContent = fs . readFileSync ( path . join ( sourceRoot , fn ) ) ;
55
46
@@ -80,20 +71,90 @@ function copyRecursive(sourceRoot: string, destRoot: string, matchGlob: string)
80
71
} ) ;
81
72
}
82
73
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)' ) ;
86
99
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
+ } ) ;
92
139
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
+ }
97
158
98
- // Clean up
99
- rimraf . sync ( tempRoot ) ;
159
+ buildYeomanNpmPackage ( ) ;
160
+ buildDotNetNewNuGetPackage ( ) ;
0 commit comments