@@ -5,8 +5,9 @@ import _ from 'lodash';
55import s from 'underscore.string' ;
66import Promise from 'bluebird' ;
77import semver from 'semver' ;
8- import { appName } from './util.js' ;
9- import { Base } from 'yeoman-generator' ;
8+ import Generator from 'yeoman-generator' ;
9+ import glob from 'glob' ;
10+ import fs from 'fs' ;
1011
1112// extend lodash with underscore.string
1213_ . mixin ( s . exports ( ) ) ;
@@ -29,11 +30,132 @@ function runCmd(cmd) {
2930 } ) ;
3031}
3132
32- export class BaseGenerator extends Base {
33- initializing ( ) {
33+ function appName ( suffix ) {
34+ let counter = 0 ;
35+ // Have to check this because of generator bug` #386
36+ process . argv . forEach ( val => {
37+ if ( val . indexOf ( '--app-suffix' ) > - 1 ) {
38+ counter ++ ;
39+ }
40+ } ) ;
41+ if ( counter === 0 || ( typeof suffix === 'boolean' && suffix ) ) {
42+ suffix = 'App' ;
43+ }
44+ return suffix ? _ . upperFirst ( _ . camelCase ( suffix ) ) : '' ;
45+ }
46+
47+
48+ function expandFiles ( pattern , options ) {
49+ options = options || { } ;
50+ var cwd = options . cwd || process . cwd ( ) ;
51+ return glob . sync ( pattern , options ) . filter ( function ( filepath ) {
52+ return fs . statSync ( path . join ( cwd , filepath ) ) . isFile ( ) ;
53+ } ) ;
54+ }
55+
56+ export function rewriteFile ( args ) {
57+ args . path = args . path || process . cwd ( ) ;
58+ var fullPath = path . join ( args . path , args . file ) ;
59+
60+ args . haystack = fs . readFileSync ( fullPath , 'utf8' ) ;
61+ var body = rewrite ( args ) ;
62+
63+ fs . writeFileSync ( fullPath , body ) ;
64+ }
65+
66+ function escapeRegExp ( str ) {
67+ return str . replace ( / [ \- \[ \] \/ \{ \} \( \) \* \+ \? \. \\ \^ \$ \| ] / g, '\\$&' ) ;
68+ }
69+
70+ export function rewrite ( args ) {
71+ // check if splicable is already in the body text
72+ var re = new RegExp ( args . splicable . map ( function ( line ) {
73+ return '\s*' + escapeRegExp ( line ) ;
74+ } ) . join ( '\n' ) ) ;
75+
76+ if ( re . test ( args . haystack ) ) {
77+ return args . haystack ;
78+ }
79+
80+ var lines = args . haystack . split ( '\n' ) ;
81+
82+ var otherwiseLineIndex = - 1 ;
83+ lines . forEach ( function ( line , i ) {
84+ if ( line . indexOf ( args . needle ) !== - 1 ) {
85+ otherwiseLineIndex = i ;
86+ }
87+ } ) ;
88+ if ( otherwiseLineIndex === - 1 ) return lines . join ( '\n' ) ;
89+
90+ var spaces = 0 ;
91+ while ( lines [ otherwiseLineIndex ] . charAt ( spaces ) === ' ' ) {
92+ spaces += 1 ;
93+ }
94+
95+ var spaceStr = '' ;
96+ while ( ( spaces -= 1 ) >= 0 ) {
97+ spaceStr += ' ' ;
98+ }
99+
100+ lines . splice ( otherwiseLineIndex + 1 , 0 , args . splicable . map ( function ( line ) {
101+ return spaceStr + line ;
102+ } ) . join ( '\n' ) ) ;
103+
104+ return lines . join ( '\n' ) ;
105+ }
106+
107+ export function appSuffix ( self ) {
108+ var suffix = self . options [ 'app-suffix' ] ;
109+ return ( typeof suffix === 'string' ) ? _ . classify ( suffix ) : '' ;
110+ }
111+
112+ export function relativeRequire ( to , fr ) {
113+ fr = this . destinationPath ( fr || this . filePath ) ;
114+ to = this . destinationPath ( to ) ;
115+ return path . relative ( path . dirname ( fr ) , to )
116+ . replace ( / \\ / g, '/' ) // convert win32 separator to posix
117+ . replace ( / ^ (? ! \. \. ) ( .* ) / , './$1' ) // prefix non parent path with ./
118+ . replace ( / [ \/ \\ ] i n d e x \. j s $ / , '' ) ; // strip index.js suffix from path
119+ }
120+
121+ function filterFile ( template ) {
122+ // Find matches for parans
123+ var filterMatches = template . match ( / \( ( [ ^ ) ] + ) \) / g) ;
124+ var filters = [ ] ;
125+ if ( filterMatches ) {
126+ filterMatches . forEach ( function ( filter ) {
127+ filters . push ( filter . replace ( '(' , '' ) . replace ( ')' , '' ) ) ;
128+ template = template . replace ( filter , '' ) ;
129+ } ) ;
130+ }
131+
132+ return { name : template , filters : filters } ;
133+ }
134+
135+ function templateIsUsable ( self , filteredFile ) {
136+ var filters = self . filters || self . config . get ( 'filters' ) ;
137+ var enabledFilters = [ ] ;
138+ for ( var key in filters ) {
139+ if ( filters [ key ] ) enabledFilters . push ( key ) ;
140+ }
141+ var matchedFilters = _ . intersection ( filteredFile . filters , enabledFilters ) ;
142+ // check that all filters on file are matched
143+ if ( filteredFile . filters . length && matchedFilters . length !== filteredFile . filters . length ) {
144+ return false ;
145+ }
146+ return true ;
147+ }
148+
149+ export class BaseGenerator extends Generator {
150+ constructor ( args , opts ) {
151+ // Calling the super constructor is important so our generator is correctly set up
152+ super ( args , opts ) ;
153+
34154 this . argument ( 'name' , { type : String , required : false } ) ;
35155
36- this . lodash = _ ;
156+ this . name = this . options . name ;
157+
158+ // this.lodash = _;
37159
38160 var yoCheckPromise ;
39161
@@ -48,13 +170,8 @@ export class BaseGenerator extends Base {
48170 yoCheckPromise = Promise . resolve ( ) ;
49171 }
50172
51- try {
52- this . appname = require ( path . join ( process . cwd ( ) , 'bower.json' ) ) . name ;
53- } catch ( err ) {
54- this . appname = path . basename ( process . cwd ( ) ) ;
55- }
56- this . appname = _ . slugify ( _ . humanize ( this . appname ) ) ;
57- this . scriptAppName = this . config . get ( 'moduleName' ) || _ . camelize ( this . appname ) + appName ( this ) ;
173+ this . appname = _ . slugify ( _ . humanize ( path . basename ( process . cwd ( ) ) ) ) ;
174+ this . scriptAppName = this . config . get ( 'moduleName' ) || _ . camelize ( this . appname ) + appName ( this . options [ 'app-suffix' ] ) ;
58175
59176 this . cameledName = _ . camelize ( this . name ) ;
60177 this . classedName = _ . classify ( this . name ) ;
@@ -85,6 +202,58 @@ export class BaseGenerator extends Base {
85202
86203 this . sourceRoot ( path . join ( __dirname , '..' , '/templates' ) ) ;
87204
88- return yoCheckPromise ;
205+ // return yoCheckPromise;
206+ }
207+
208+ /**
209+ * Copy templates from `source` to `destination` whily applying name transformations
210+ */
211+ processDirectory ( source , destination ) {
212+ const root = path . isAbsolute ( source ) ? source : path . join ( this . sourceRoot ( ) , source ) ;
213+ const files = expandFiles ( '**' , { dot : true , cwd : root } ) ;
214+
215+ for ( const file of files ) {
216+ var filteredFile = filterFile ( file ) ;
217+
218+ if ( this . basename ) {
219+ filteredFile . name = filteredFile . name . replace ( 'basename' , this . basename ) ;
220+ }
221+
222+ if ( this . name ) {
223+ filteredFile . name = filteredFile . name . replace ( 'name' , this . name ) ;
224+ }
225+
226+ const name = filteredFile . name ;
227+ let copy = false ;
228+ let stripped ;
229+
230+ let src = path . join ( root , file ) ;
231+ let dest = path . join ( destination , name ) ;
232+
233+ if ( this . filters . ts && dest . indexOf ( 'client' ) > - 1 && dest . indexOf ( '.json' ) === - 1 ) {
234+ dest = dest . replace ( '.js' , '.ts' ) ;
235+ }
236+
237+ if ( path . basename ( dest ) . indexOf ( '_' ) === 0 ) {
238+ stripped = path . basename ( dest ) . replace ( / ^ _ / , '' ) ;
239+ dest = path . join ( path . dirname ( dest ) , stripped ) ;
240+ }
241+
242+ if ( path . basename ( dest ) . indexOf ( '!' ) === 0 ) {
243+ stripped = path . basename ( dest ) . replace ( / ^ ! / , '' ) ;
244+ dest = path . join ( path . dirname ( dest ) , stripped ) ;
245+ copy = true ;
246+ }
247+
248+ if ( templateIsUsable ( this , filteredFile ) ) {
249+ if ( copy ) {
250+ this . fs . copy ( src , dest ) ;
251+ } else {
252+ this . filePath = dest ;
253+ this . fs . copyTpl ( src , dest , this ) ;
254+ delete this . filePath ;
255+ }
256+ }
257+ }
89258 }
90259}
0 commit comments