github.com/fanux/shipyard@v0.0.0-20161009071005-6515ce223235/controller/static/semantic/tasks/install.js (about) 1 /******************************* 2 Install Task 3 *******************************/ 4 5 /* 6 Install tasks 7 8 For more notes 9 10 * Runs automatically after npm update (hooks) 11 * (NPM) Install - Will ask for where to put semantic (outside pm folder) 12 * (NPM) Upgrade - Will look for semantic install, copy over files and update if new version 13 * Standard installer runs asking for paths to site files etc 14 15 */ 16 17 var 18 gulp = require('gulp'), 19 20 // node dependencies 21 console = require('better-console'), 22 extend = require('extend'), 23 fs = require('fs'), 24 mkdirp = require('mkdirp'), 25 path = require('path'), 26 27 // gulp dependencies 28 chmod = require('gulp-chmod'), 29 del = require('del'), 30 jsonEditor = require('gulp-json-editor'), 31 plumber = require('gulp-plumber'), 32 prompt = require('gulp-prompt'), 33 rename = require('gulp-rename'), 34 replace = require('gulp-replace'), 35 requireDotFile = require('require-dot-file'), 36 wrench = require('wrench'), 37 38 // install config 39 install = require('./config/project/install'), 40 41 // user config 42 config = require('./config/user'), 43 44 // release config (name/title/etc) 45 release = require('./config/project/release'), 46 47 // shorthand 48 questions = install.questions, 49 files = install.files, 50 folders = install.folders, 51 regExp = install.regExp, 52 settings = install.settings, 53 source = install.source 54 ; 55 56 // Export install task 57 module.exports = function () { 58 59 var 60 currentConfig = requireDotFile('semantic.json'), 61 manager = install.getPackageManager(), 62 rootQuestions = questions.root 63 ; 64 65 console.clear(); 66 67 /* Test NPM 68 manager = { 69 name : 'NPM', 70 root : path.normalize(__dirname + '/../') 71 }; 72 */ 73 74 /*-------------- 75 PM Config 76 ---------------*/ 77 78 /* Don't do end user config if SUI is a sub-module */ 79 if( install.isSubModule() ) { 80 console.info('SUI is a sub-module, skipping end-user install'); 81 return; 82 } 83 84 // run update scripts if semantic.json exists 85 if(currentConfig && manager.name === 'NPM') { 86 87 var 88 updateFolder = path.join(manager.root, currentConfig.base), 89 updatePaths = { 90 config : path.join(manager.root, files.config), 91 tasks : path.join(updateFolder, folders.tasks), 92 themeImport : path.join(updateFolder, folders.themeImport), 93 definition : path.join(currentConfig.paths.source.definitions), 94 site : path.join(currentConfig.paths.source.site), 95 theme : path.join(currentConfig.paths.source.themes) 96 } 97 ; 98 99 // duck-type if there is a project installed 100 if( fs.existsSync(updatePaths.definition) ) { 101 102 // perform update if new version 103 if(currentConfig.version !== release.version) { 104 console.log('Updating Semantic UI from ' + currentConfig.version + ' to ' + release.version); 105 106 console.info('Updating ui definitions...'); 107 wrench.copyDirSyncRecursive(source.definitions, updatePaths.definition, settings.wrench.update); 108 109 console.info('Updating default theme...'); 110 wrench.copyDirSyncRecursive(source.themes, updatePaths.theme, settings.wrench.update); 111 112 console.info('Updating tasks...'); 113 wrench.copyDirSyncRecursive(source.tasks, updatePaths.tasks, settings.wrench.update); 114 115 console.info('Updating gulpfile.js'); 116 gulp.src(source.userGulpFile) 117 .pipe(plumber()) 118 .pipe(gulp.dest(updateFolder)) 119 ; 120 121 // copy theme import 122 console.info('Updating theme import file'); 123 gulp.src(source.themeImport) 124 .pipe(plumber()) 125 .pipe(gulp.dest(updatePaths.themeImport)) 126 ; 127 128 console.info('Adding new site theme files...'); 129 wrench.copyDirSyncRecursive(source.site, updatePaths.site, settings.wrench.site); 130 131 console.info('Updating version...'); 132 133 // update version number in semantic.json 134 gulp.src(updatePaths.config) 135 .pipe(plumber()) 136 .pipe(rename(settings.rename.json)) // preserve file extension 137 .pipe(jsonEditor({ 138 version: release.version 139 })) 140 .pipe(gulp.dest(manager.root)) 141 ; 142 143 console.info('Update complete! Run "\033[92mgulp build\033[0m" to rebuild dist/ files.'); 144 145 return; 146 } 147 else { 148 console.log('Current version of Semantic UI already installed'); 149 return; 150 } 151 152 } 153 else { 154 console.error('Cannot locate files to update at path: ', updatePaths.definition); 155 console.log('Running installer'); 156 } 157 158 } 159 160 /*-------------- 161 Determine Root 162 ---------------*/ 163 164 // PM that supports Build Tools (NPM Only Now) 165 if(manager.name == 'NPM') { 166 rootQuestions[0].message = rootQuestions[0].message 167 .replace('{packageMessage}', 'We detected you are using \033[92m' + manager.name + '\033[0m. Nice! ') 168 .replace('{root}', manager.root) 169 ; 170 // set default path to detected PM root 171 rootQuestions[0].default = manager.root; 172 rootQuestions[1].default = manager.root; 173 174 // insert PM questions after "Install Type" question 175 Array.prototype.splice.apply(questions.setup, [2, 0].concat(rootQuestions)); 176 177 // omit cleanup questions for managed install 178 questions.cleanup = []; 179 } 180 181 /*-------------- 182 Set-up 183 ---------------*/ 184 185 return gulp 186 .src('gulpfile.js') 187 .pipe(prompt.prompt(questions.setup, function(answers) { 188 189 /*-------------- 190 Exit Conditions 191 ---------------*/ 192 193 // if config exists and user specifies not to proceed 194 if(answers.overwrite !== undefined && answers.overwrite == 'no') { 195 return; 196 } 197 198 console.clear(); 199 console.log('Installing'); 200 console.log('------------------------------'); 201 202 203 /*-------------- 204 Paths 205 ---------------*/ 206 207 var 208 installPaths = { 209 config : files.config, 210 configFolder : folders.config, 211 site : answers.site || folders.site, 212 themeConfig : files.themeConfig, 213 themeConfigFolder : folders.themeConfig 214 }, 215 installFolder = false 216 ; 217 218 /*-------------- 219 PM Install 220 ---------------*/ 221 222 // Check if PM install 223 if(answers.useRoot || answers.customRoot) { 224 225 // Set root to custom root path if set 226 if(answers.customRoot) { 227 if(answers.customRoot === '') { 228 console.log('Unable to proceed, invalid project root'); 229 return; 230 } 231 manager.root = answers.customRoot; 232 } 233 234 // special install paths only for PM install 235 installPaths = extend(false, {}, installPaths, { 236 definition : folders.definitions, 237 lessImport : folders.lessImport, 238 tasks : folders.tasks, 239 theme : folders.themes, 240 themeImport : folders.themeImport 241 }); 242 243 // add project root to semantic root 244 installFolder = path.join(manager.root, answers.semanticRoot); 245 246 // add install folder to all output paths 247 for(var destination in installPaths) { 248 if( installPaths.hasOwnProperty(destination) ) { 249 // config goes in project root, rest in install folder 250 installPaths[destination] = (destination == 'config' || destination == 'configFolder') 251 ? path.normalize( path.join(manager.root, installPaths[destination]) ) 252 : path.normalize( path.join(installFolder, installPaths[destination]) ) 253 ; 254 } 255 } 256 257 // create project folders 258 try { 259 mkdirp.sync(installFolder); 260 mkdirp.sync(installPaths.definition); 261 mkdirp.sync(installPaths.theme); 262 mkdirp.sync(installPaths.tasks); 263 } 264 catch(error) { 265 console.error('NPM does not have permissions to create folders at your specified path. Adjust your folders permissions and run "npm install" again'); 266 } 267 268 console.log('Installing to \033[92m' + answers.semanticRoot + '\033[0m'); 269 270 console.info('Copying UI definitions'); 271 wrench.copyDirSyncRecursive(source.definitions, installPaths.definition, settings.wrench.install); 272 wrench.copyDirSyncRecursive(source.themes, installPaths.theme, settings.wrench.install); 273 274 console.info('Copying gulp tasks'); 275 wrench.copyDirSyncRecursive(source.tasks, installPaths.tasks, settings.wrench.install); 276 277 // copy theme import 278 console.info('Adding theme files'); 279 gulp.src(source.themeImport) 280 .pipe(plumber()) 281 .pipe(gulp.dest(installPaths.themeImport)) 282 ; 283 gulp.src(source.lessImport) 284 .pipe(plumber()) 285 .pipe(gulp.dest(installPaths.lessImport)) 286 ; 287 288 // create gulp file 289 console.info('Creating gulpfile.js'); 290 gulp.src(source.userGulpFile) 291 .pipe(plumber()) 292 .pipe(gulp.dest(installFolder)) 293 ; 294 295 } 296 297 /*-------------- 298 Site Theme 299 ---------------*/ 300 301 // Copy _site templates folder to destination 302 if( fs.existsSync(installPaths.site) ) { 303 console.info('Site folder exists, merging files (no overwrite)', installPaths.site); 304 } 305 else { 306 console.info('Creating site theme folder', installPaths.site); 307 } 308 wrench.copyDirSyncRecursive(source.site, installPaths.site, settings.wrench.site); 309 310 /*-------------- 311 Theme Config 312 ---------------*/ 313 314 var 315 // determine path to site theme folder from theme config 316 // force CSS path variable to use forward slashes for paths 317 pathToSite = path.relative(path.resolve(installPaths.themeConfigFolder), path.resolve(installPaths.site)).replace(/\\/g,'/'), 318 siteVariable = "@siteFolder : '" + pathToSite + "/';" 319 ; 320 321 // rewrite site variable in theme.less 322 console.info('Adjusting @siteFolder to: ', pathToSite + '/'); 323 324 if(fs.existsSync(installPaths.themeConfig)) { 325 console.info('Modifying src/theme.config (LESS config)', installPaths.themeConfig); 326 gulp.src(installPaths.themeConfig) 327 .pipe(plumber()) 328 .pipe(replace(regExp.siteVariable, siteVariable)) 329 .pipe(gulp.dest(installPaths.themeConfigFolder)) 330 ; 331 } 332 else { 333 console.info('Creating src/theme.config (LESS config)', installPaths.themeConfig); 334 gulp.src(source.themeConfig) 335 .pipe(plumber()) 336 .pipe(rename({ extname : '' })) 337 .pipe(replace(regExp.siteVariable, siteVariable)) 338 .pipe(gulp.dest(installPaths.themeConfigFolder)) 339 ; 340 } 341 342 /*-------------- 343 Semantic.json 344 ---------------*/ 345 346 var 347 jsonConfig = install.createJSON(answers) 348 ; 349 350 // adjust variables in theme.less 351 if( fs.existsSync(files.config) ) { 352 console.info('Extending config file (semantic.json)', installPaths.config); 353 gulp.src(installPaths.config) 354 .pipe(plumber()) 355 .pipe(rename(settings.rename.json)) // preserve file extension 356 .pipe(jsonEditor(jsonConfig)) 357 .pipe(gulp.dest(installPaths.configFolder)) 358 ; 359 } 360 else { 361 console.info('Creating config file (semantic.json)', installPaths.config); 362 gulp.src(source.config) 363 .pipe(plumber()) 364 .pipe(rename({ extname : '' })) // remove .template from ext 365 .pipe(jsonEditor(jsonConfig)) 366 .pipe(gulp.dest(installPaths.configFolder)) 367 ; 368 } 369 370 // Completion Message 371 if(installFolder) { 372 console.log('Install complete! Navigate to \033[92m' + answers.semanticRoot + '\033[0m and run "\033[92mgulp build\033[0m" to build'); 373 } 374 else { 375 console.log(''); 376 console.log(''); 377 } 378 379 })) 380 .pipe(prompt.prompt(questions.cleanup, function(answers) { 381 if(answers.cleanup == 'yes') { 382 del(install.setupFiles); 383 } 384 if(answers.build == 'yes') { 385 gulp.start('build'); 386 } 387 })) 388 ; 389 390 391 };