1
+ const fs = require ( 'fs' )
2
+ const ejs = require ( 'ejs' )
3
+ const path = require ( 'path' )
4
+ const walk = require ( 'klaw-sync' )
1
5
const { error } = require ( './util/log' )
2
6
const mergeDeps = require ( './util/mergeDeps' )
3
- const isObject = val => val && typeof val === 'object'
7
+ const errorParser = require ( 'error-stack-parser' )
8
+
9
+ const isString = val => typeof val === 'string'
4
10
const isFunction = val => typeof val === 'function'
11
+ const isObject = val => val && typeof val === 'object'
5
12
6
13
module . exports = class GeneratorAPI {
7
- constructor ( creator , generator ) {
14
+ constructor ( id , creator ) {
15
+ this . id = id
8
16
this . creator = creator
9
- this . generator = generator
10
17
}
11
18
12
19
injectFeature ( feature ) {
@@ -24,7 +31,7 @@ module.exports = class GeneratorAPI {
24
31
if ( ! prompt ) {
25
32
error (
26
33
`injectOptionForFeature error in generator "${
27
- this . generator . id
34
+ this . id
28
35
} ": prompt "${ name } " does not exist.`
29
36
)
30
37
}
@@ -58,7 +65,7 @@ module.exports = class GeneratorAPI {
58
65
if ( key === 'dependencies' || key === 'devDependencies' ) {
59
66
// use special version resolution merge
60
67
pkg [ key ] = mergeDeps (
61
- this . generator . id ,
68
+ this . id ,
62
69
existing ,
63
70
value ,
64
71
this . creator . depSources
@@ -73,9 +80,40 @@ module.exports = class GeneratorAPI {
73
80
}
74
81
}
75
82
76
- renderFile ( file , additionalData , ejsOptions ) {
77
- // TODO render file based on generator path
78
- // render with ejs & options
79
- return file
83
+ renderFiles ( fileDir , additionalData = { } , ejsOptions = { } ) {
84
+ const baseDir = extractCallDir ( )
85
+ if ( isString ( fileDir ) ) {
86
+ fileDir = path . resolve ( baseDir , fileDir )
87
+ this . injectFileMiddleware ( files => {
88
+ const data = Object . assign ( { } , this . creator . options , additionalData )
89
+ const _files = walk ( fileDir , { nodir : true } )
90
+ for ( const file of _files ) {
91
+ const relativePath = path . relative ( fileDir , file . path )
92
+ files [ relativePath ] = renderFile ( file . path , data , ejsOptions )
93
+ }
94
+ } )
95
+ } else if ( isObject ( fileDir ) ) {
96
+ this . injectFileMiddleware ( files => {
97
+ const data = Object . assign ( { } , this . creator . options , additionalData )
98
+ for ( const targetPath in fileDir ) {
99
+ const sourcePath = path . resolve ( baseDir , fileDir [ targetPath ] )
100
+ files [ targetPath ] = renderFile ( sourcePath , data , ejsOptions )
101
+ }
102
+ } )
103
+ } else if ( isFunction ( fileDir ) ) {
104
+ this . injectFileMiddleware ( fileDir )
105
+ }
80
106
}
81
107
}
108
+
109
+ function extractCallDir ( ) {
110
+ // extract api.renderFiles() callsite file location using error stack
111
+ const obj = { }
112
+ Error . captureStackTrace ( obj )
113
+ const stack = errorParser . parse ( obj )
114
+ return path . dirname ( stack [ 2 ] . fileName )
115
+ }
116
+
117
+ function renderFile ( name , data , ejsOptions ) {
118
+ return ejs . render ( fs . readFileSync ( name , 'utf-8' ) , data , ejsOptions )
119
+ }
0 commit comments