import match from 'minimatch' ; import { IPicGo , IOptions , IFileTree } from '../types' ; import fs from 'fs-extra' ; import path from 'path' ; import globby from 'globby' ; import ejs from 'ejs' ; param { PicGo } ctx param { IOptions } options const generate = async ( ctx , options ) : Promise < any > => { try { const opts = getOptions ( options . tmp ) ; const source = path . join ( options . tmp , 'template' ) ; let answers = { } ; if ( opts . prompts && opts . prompts . length > 0 ) { answers = await ctx . cmd . inquirer . prompt ( opts . prompts ) ; } let _files = await globby ( [ '**/*' ] , { cwd : source , dot : true } ) ; _files = _files . filter ( ( item ) => { let glob = '' ; Object . keys ( opts . filters ) . forEach ( ( key ) => { if ( match ( item , key , { dot : true } ) ) { glob = item ; } } ) ; if ( glob ) { return filters ( ctx , opts . filters [ glob ] , answers ) ; } else { return true ; } } ) ; if ( _files . length === 0 ) { return ctx . log . warn ( 'Template files not found!' ) ; } const files = render ( _files , source , answers ) ; writeFileTree ( options . dest , files ) ; if ( typeof opts . complete === 'function' ) { opts . complete ( { answers , options , files : _files , ctx } ) ; } if ( opts . completeMessage ) { ctx . log . success ( opts . completeMessage ) ; } ctx . log . success ( 'Done!' ) ; } catch ( e ) { return ctx . log . error ( e ) ; } } ; param ctx param exp param data const filters = ( ctx , exp , data ) : boolean => { const fn = new Function ( 'data' , 'with (data) { return ' + exp + '}' ) ; try { return fn ( data ) ; } catch ( e ) { ctx . log . error ( `Error when evaluating filter condition: ${ JSON . stringify ( exp ) }` ) ; return false ; } } ; param { string } templatePath const getOptions = ( templatePath ) : any => { const optionsPath = path . join ( templatePath , 'index.js' ) ; if ( fs . existsSync ( optionsPath ) ) { const options = require ( optionsPath ) ; return options ; } else { return { } ; } } ; param { array } files const render = ( files , source , options ) : any => { const fileTree = { } ; files . forEach ( ( filePath ) : void => { const file = fs . readFileSync ( path . join ( source , filePath ) , 'utf8' ) ; const content = ejs . render ( file , options ) ; if ( Buffer . isBuffer ( content ) || /[^\s]/ . test ( content ) ) { fileTree [ filePath ] = content ; } } ) ; return fileTree ; } ; param { string } dir param { object } files const writeFileTree = ( dir , files ) : void => { Object . keys ( files ) . forEach ( ( name ) => { const filePath = path . join ( dir , name ) ; fs . ensureDirSync ( path . dirname ( filePath ) ) ; fs . writeFileSync ( filePath , files [ name ] ) ; } ) ; } ; export { filters , generate , render , writeFileTree } ;