github.com/fanux/shipyard@v0.0.0-20161009071005-6515ce223235/controller/static/semantic/tasks/config/project/install.js (about) 1 /******************************* 2 Set-up 3 *******************************/ 4 5 var 6 fs = require('fs'), 7 path = require('path'), 8 defaults = require('../defaults'), 9 release = require('./release'), 10 11 requireDotFile = require('require-dot-file') 12 ; 13 14 /******************************* 15 When to Ask 16 *******************************/ 17 18 /* Preconditions for install questions */ 19 20 var when = { 21 22 // path 23 changeRoot: function(questions) { 24 return (questions.useRoot !== undefined && questions.useRoot !== true); 25 }, 26 27 // permissions 28 changePermissions: function(questions) { 29 return (questions.changePermissions && questions.changePermissions === true); 30 }, 31 32 // install 33 hasConfig: function() { 34 return requireDotFile('semantic.json'); 35 }, 36 37 allowOverwrite: function(questions) { 38 return (questions.overwrite === undefined || questions.overwrite == 'yes'); 39 }, 40 notAuto: function(questions) { 41 return (questions.install !== 'auto' && (questions.overwrite === undefined || questions.overwrite == 'yes')); 42 }, 43 custom: function(questions) { 44 return (questions.install === 'custom' && (questions.overwrite === undefined || questions.overwrite == 'yes')); 45 }, 46 express: function(questions) { 47 return (questions.install === 'express' && (questions.overwrite === undefined || questions.overwrite == 'yes')); 48 }, 49 50 // customize 51 customize: function(questions) { 52 return (questions.customize === true); 53 }, 54 primaryColor: function(questions) { 55 return (questions.primaryColor); 56 }, 57 secondaryColor: function(questions) { 58 return (questions.secondaryColor); 59 } 60 }; 61 62 /******************************* 63 Response Filters 64 *******************************/ 65 66 /* Filters to user input from install questions */ 67 68 var filter = { 69 removeTrailingSlash: function(path) { 70 return path.replace(/(\/$|\\$)+/mg, ''); 71 } 72 }; 73 74 /******************************* 75 Configuration 76 *******************************/ 77 78 module.exports = { 79 80 // check whether install is setup 81 isSetup: function() { 82 return when.hasConfig(); 83 }, 84 85 // checks if files are in a PM directory 86 getPackageManager: function(directory) { 87 var 88 // returns last matching result (avoid sub-module detection) 89 walk = function(directory) { 90 var 91 pathArray = directory.split(path.sep), 92 folder = pathArray[pathArray.length - 1], 93 nextDirectory = path.join(directory, path.sep, '..') 94 ; 95 console.log(folder, nextDirectory); 96 if( folder == 'bower_components') { 97 return { 98 name: 'Bower', 99 root: nextDirectory 100 }; 101 } 102 else if(folder == 'node_modules') { 103 return { 104 name: 'NPM', 105 root: nextDirectory 106 }; 107 } 108 else if(folder == 'composer') { 109 return { 110 name: 'Composer', 111 root: nextDirectory 112 }; 113 } 114 if(path.resolve(directory) == path.resolve(nextDirectory)) { 115 return false; 116 } 117 // recurse downward 118 return walk(nextDirectory); 119 } 120 ; 121 // start walk from current directory if none specified 122 directory = directory || (__dirname + path.sep); 123 return walk(directory); 124 }, 125 126 // checks if files is PMed submodule 127 isSubModule: function(directory) { 128 var 129 moduleFolders = 0, 130 walk = function(directory) { 131 var 132 pathArray = directory.split(path.sep), 133 folder = pathArray[pathArray.length - 2], 134 nextDirectory = path.join(directory, path.sep, '..') 135 ; 136 if( folder == 'bower_components') { 137 moduleFolders++; 138 } 139 else if(folder == 'node_modules') { 140 moduleFolders++; 141 } 142 else if(folder == 'composer') { 143 moduleFolders++; 144 } 145 if(path.resolve(directory) == path.resolve(nextDirectory)) { 146 return (moduleFolders > 1); 147 } 148 // recurse downward 149 return walk(nextDirectory); 150 } 151 ; 152 // start walk from current directory if none specified 153 directory = directory || (__dirname + path.sep); 154 return walk(directory); 155 }, 156 157 158 createJSON: function(answers) { 159 var 160 json = { 161 paths: { 162 source: {}, 163 output: {} 164 } 165 } 166 ; 167 168 // add components 169 if(answers.components) { 170 json.components = answers.components; 171 } 172 173 // add rtl choice 174 if(answers.rtl) { 175 json.rtl = answers.rtl; 176 } 177 178 // add permissions 179 if(answers.permission) { 180 json.permission = answers.permission; 181 } 182 183 // add path to semantic 184 if(answers.semanticRoot) { 185 json.base = path.normalize(answers.semanticRoot); 186 } 187 188 // record version number to avoid re-installing on same version 189 json.version = release.version; 190 191 // add dist folder paths 192 if(answers.dist) { 193 answers.dist = path.normalize(answers.dist); 194 195 json.paths.output = { 196 packaged : path.normalize(answers.dist + '/'), 197 uncompressed : path.normalize(answers.dist + '/components/'), 198 compressed : path.normalize(answers.dist + '/components/'), 199 themes : path.normalize(answers.dist + '/themes/') 200 }; 201 } 202 203 // add site path 204 if(answers.site) { 205 json.paths.source.site = path.normalize(answers.site + '/'); 206 } 207 if(answers.packaged) { 208 json.paths.output.packaged = path.normalize(answers.packaged + '/'); 209 } 210 if(answers.compressed) { 211 json.paths.output.compressed = path.normalize(answers.compressed + '/'); 212 } 213 if(answers.uncompressed) { 214 json.paths.output.uncompressed = path.normalize(answers.uncompressed + '/'); 215 } 216 return json; 217 }, 218 219 // files cleaned up after install 220 setupFiles: [ 221 './src/theme.config.example', 222 './semantic.json.example', 223 './src/_site' 224 ], 225 226 regExp: { 227 // used to match siteFolder variable in theme.less 228 siteVariable: /@siteFolder .*\'(.*)/mg 229 }, 230 231 // source paths (relative to tasks/install.js ) 232 source: { 233 config : './semantic.json.example', 234 definitions : './src/definitions', 235 gulpFile : './gulpfile.js', 236 lessImport : './src/semantic.less', 237 site : './src/_site', 238 tasks : './tasks', 239 themeConfig : './src/theme.config.example', 240 themeImport : './src/theme.less', 241 themes : './src/themes', 242 userGulpFile : './tasks/config/npm/gulpfile.js' 243 }, 244 245 // expected final filenames 246 files: { 247 config : 'semantic.json', 248 lessImport : 'src/semantic.less', 249 site : 'src/site', 250 themeConfig : 'src/theme.config', 251 themeImport : 'src/theme.less' 252 }, 253 254 // folder paths to files relative to root 255 folders: { 256 config : './', 257 definitions : 'src/definitions/', 258 lessImport : 'src/', 259 modules : 'node_modules/', 260 site : 'src/site/', 261 tasks : 'tasks/', 262 themeConfig : 'src/', 263 themeImport : 'src/', 264 themes : 'src/themes/' 265 }, 266 267 // questions asked during install 268 questions: { 269 270 root: [ 271 { 272 type : 'list', 273 name : 'useRoot', 274 message : 275 ' \n' + 276 ' {packageMessage} \n' + 277 ' \n' + 278 ' Is this your project folder?\n' + 279 ' \033[92m{root}\033[0m \n' + 280 ' \n ' + 281 '\n', 282 choices: [ 283 { 284 name : 'Yes', 285 value : true 286 }, 287 { 288 name : 'No, let me specify', 289 value : false 290 } 291 ] 292 }, 293 { 294 type : 'input', 295 name : 'customRoot', 296 message : 'Please enter the absolute path to your project root', 297 default : '/my/project/path', 298 when : when.changeRoot 299 }, 300 { 301 type : 'input', 302 name : 'semanticRoot', 303 message : 'Where should we put Semantic UI inside your project?', 304 default : 'semantic/' 305 } 306 ], 307 308 setup: [ 309 { 310 type: 'list', 311 name: 'overwrite', 312 message: 'It looks like you have a semantic.json file already.', 313 when: when.hasConfig, 314 choices: [ 315 { 316 name: 'Yes, extend my current settings.', 317 value: 'yes' 318 }, 319 { 320 name: 'Skip install', 321 value: 'no' 322 } 323 ] 324 }, 325 { 326 type: 'list', 327 name: 'install', 328 message: 'Set-up Semantic UI', 329 when: when.allowOverwrite, 330 choices: [ 331 { 332 name: 'Automatic (Use defaults locations and all components)', 333 value: 'auto' 334 }, 335 { 336 name: 'Express (Set components and output folder)', 337 value: 'express' 338 }, 339 { 340 name: 'Custom (Customize all src/dist values)', 341 value: 'custom' 342 } 343 ] 344 }, 345 { 346 type: 'checkbox', 347 name: 'components', 348 message: 'What components should we include in the package?', 349 350 // duplicated manually from tasks/defaults.js with additional property 351 choices: [ 352 { name: "reset", checked: true }, 353 { name: "site", checked: true }, 354 { name: "button", checked: true }, 355 { name: "divider", checked: true }, 356 { name: "flag", checked: true }, 357 { name: "header", checked: true }, 358 { name: "icon", checked: true }, 359 { name: "image", checked: true }, 360 { name: "input", checked: true }, 361 { name: "label", checked: true }, 362 { name: "list", checked: true }, 363 { name: "loader", checked: true }, 364 { name: "rail", checked: true }, 365 { name: "reveal", checked: true }, 366 { name: "segment", checked: true }, 367 { name: "step", checked: true }, 368 { name: "breadcrumb", checked: true }, 369 { name: "form", checked: true }, 370 { name: "grid", checked: true }, 371 { name: "menu", checked: true }, 372 { name: "message", checked: true }, 373 { name: "table", checked: true }, 374 { name: "ad", checked: true }, 375 { name: "card", checked: true }, 376 { name: "comment", checked: true }, 377 { name: "feed", checked: true }, 378 { name: "item", checked: true }, 379 { name: "statistic", checked: true }, 380 { name: "accordion", checked: true }, 381 { name: "checkbox", checked: true }, 382 { name: "dimmer", checked: true }, 383 { name: "dropdown", checked: true }, 384 { name: "modal", checked: true }, 385 { name: "nag", checked: true }, 386 { name: "popup", checked: true }, 387 { name: "progress", checked: true }, 388 { name: "rating", checked: true }, 389 { name: "search", checked: true }, 390 { name: "shape", checked: true }, 391 { name: "sidebar", checked: true }, 392 { name: "sticky", checked: true }, 393 { name: "tab", checked: true }, 394 { name: "transition", checked: true }, 395 { name: "video", checked: true }, 396 { name: "api", checked: true }, 397 { name: "form", checked: true }, 398 { name: "state", checked: true }, 399 { name: "visibility", checked: true } 400 ], 401 when: when.notAuto 402 }, 403 { 404 type: 'list', 405 name: 'changePermisions', 406 when: when.notAuto, 407 message: 'Should we set permissions on outputted files?', 408 choices: [ 409 { 410 name: 'No', 411 value: false 412 }, 413 { 414 name: 'Yes', 415 value: true 416 }, 417 ] 418 }, 419 { 420 type: 'input', 421 name: 'permission', 422 message: 'What octal file permission should outputted files receive?', 423 default: defaults.permission, 424 when: when.changePermissions 425 }, 426 { 427 type: 'list', 428 name: 'rtl', 429 message: 'Do you use a RTL (Right-To-Left) language?', 430 when: when.notAuto, 431 choices: [ 432 { 433 name: 'No', 434 value: false 435 }, 436 { 437 name: 'Yes', 438 value: true 439 }, 440 ] 441 }, 442 { 443 type: 'input', 444 name: 'dist', 445 message: 'Where should we output Semantic UI?', 446 default: defaults.paths.output.packaged, 447 filter: filter.removeTrailingSlash, 448 when: when.express 449 }, 450 { 451 type: 'input', 452 name: 'site', 453 message: 'Where should we put your site folder?', 454 default: defaults.paths.source.site, 455 filter: filter.removeTrailingSlash, 456 when: when.custom 457 }, 458 { 459 type: 'input', 460 name: 'packaged', 461 message: 'Where should we output a packaged version?', 462 default: defaults.paths.output.packaged, 463 filter: filter.removeTrailingSlash, 464 when: when.custom 465 }, 466 { 467 type: 'input', 468 name: 'compressed', 469 message: 'Where should we output compressed components?', 470 default: defaults.paths.output.compressed, 471 filter: filter.removeTrailingSlash, 472 when: when.custom 473 }, 474 { 475 type: 'input', 476 name: 'uncompressed', 477 message: 'Where should we output uncompressed components?', 478 default: defaults.paths.output.uncompressed, 479 filter: filter.removeTrailingSlash, 480 when: when.custom 481 } 482 ], 483 484 485 cleanup: [ 486 { 487 type: 'list', 488 name: 'cleanup', 489 message: 'Should we remove set-up files?', 490 choices: [ 491 { 492 name: 'Yes (re-install will require redownloading semantic).', 493 value: 'yes' 494 }, 495 { 496 name: 'No Thanks', 497 value: 'no' 498 } 499 ] 500 }, 501 { 502 type: 'list', 503 name: 'build', 504 message: 'Do you want to build Semantic now?', 505 choices: [ 506 { 507 name: 'Yes', 508 value: 'yes' 509 }, 510 { 511 name: 'No', 512 value: 'no' 513 } 514 ] 515 }, 516 ], 517 site: [ 518 { 519 type: 'list', 520 name: 'customize', 521 message: 'You have not yet customized your site, can we help you do that?', 522 choices: [ 523 { 524 name: 'Yes, ask me a few questions', 525 value: true 526 }, 527 { 528 name: 'No I\'ll do it myself', 529 value: false 530 } 531 ] 532 }, 533 { 534 type: 'list', 535 name: 'headerFont', 536 message: 'Select your header font', 537 choices: [ 538 { 539 name: 'Helvetica Neue, Arial, sans-serif', 540 value: 'Helvetica Neue, Arial, sans-serif;' 541 }, 542 { 543 name: 'Lato (Google Fonts)', 544 value: 'Lato' 545 }, 546 { 547 name: 'Open Sans (Google Fonts)', 548 value: 'Open Sans' 549 }, 550 { 551 name: 'Source Sans Pro (Google Fonts)', 552 value: 'Source Sans Pro' 553 }, 554 { 555 name: 'Droid (Google Fonts)', 556 value: 'Droid' 557 }, 558 { 559 name: 'I\'ll choose on my own', 560 value: false 561 } 562 ], 563 when: when.customize 564 }, 565 { 566 type: 'list', 567 name: 'pageFont', 568 message: 'Select your page font', 569 choices: [ 570 { 571 name: 'Helvetica Neue, Arial, sans-serif', 572 value: 'Helvetica Neue, Arial, sans-serif;' 573 }, 574 { 575 name: 'Lato (Import from Google Fonts)', 576 value: 'Lato' 577 }, 578 { 579 name: 'Open Sans (Import from Google Fonts)', 580 value: 'Open Sans' 581 }, 582 { 583 name: 'Source Sans Pro (Import from Google Fonts)', 584 value: 'Source Sans Pro' 585 }, 586 { 587 name: 'Droid (Google Fonts)', 588 value: 'Droid' 589 }, 590 { 591 name: 'I\'ll choose on my own', 592 value: false 593 } 594 ], 595 when: when.customize 596 }, 597 { 598 type: 'list', 599 name: 'fontSize', 600 message: 'Select your base font size', 601 default: '14px', 602 choices: [ 603 { 604 name: '12px', 605 }, 606 { 607 name: '13px', 608 }, 609 { 610 name: '14px (Recommended)', 611 value: '14px' 612 }, 613 { 614 name: '15px', 615 }, 616 { 617 name: '16px', 618 }, 619 { 620 name: 'I\'ll choose on my own', 621 value: false 622 } 623 ], 624 when: when.customize 625 }, 626 { 627 type: 'list', 628 name: 'primaryColor', 629 message: 'Select the closest name for your primary brand color', 630 default: '14px', 631 choices: [ 632 { 633 name: 'Blue' 634 }, 635 { 636 name: 'Green' 637 }, 638 { 639 name: 'Orange' 640 }, 641 { 642 name: 'Pink' 643 }, 644 { 645 name: 'Purple' 646 }, 647 { 648 name: 'Red' 649 }, 650 { 651 name: 'Teal' 652 }, 653 { 654 name: 'Yellow' 655 }, 656 { 657 name: 'Black' 658 }, 659 { 660 name: 'I\'ll choose on my own', 661 value: false 662 } 663 ], 664 when: when.customize 665 }, 666 { 667 type: 'input', 668 name: 'PrimaryHex', 669 message: 'Enter a hexcode for your primary brand color', 670 when: when.primaryColor 671 }, 672 { 673 type: 'list', 674 name: 'secondaryColor', 675 message: 'Select the closest name for your secondary brand color', 676 default: '14px', 677 choices: [ 678 { 679 name: 'Blue' 680 }, 681 { 682 name: 'Green' 683 }, 684 { 685 name: 'Orange' 686 }, 687 { 688 name: 'Pink' 689 }, 690 { 691 name: 'Purple' 692 }, 693 { 694 name: 'Red' 695 }, 696 { 697 name: 'Teal' 698 }, 699 { 700 name: 'Yellow' 701 }, 702 { 703 name: 'Black' 704 }, 705 { 706 name: 'I\'ll choose on my own', 707 value: false 708 } 709 ], 710 when: when.customize 711 }, 712 { 713 type: 'input', 714 name: 'secondaryHex', 715 message: 'Enter a hexcode for your secondary brand color', 716 when: when.secondaryColor 717 } 718 ] 719 720 }, 721 722 settings: { 723 724 /* Rename Files */ 725 rename: { 726 json : { extname : '.json' }, 727 }, 728 729 /* Copy Install Folders */ 730 wrench: { 731 732 // copy during npm update (default theme / definition) 733 update: { 734 forceDelete : true, 735 excludeHiddenUnix : true, 736 preserveFiles : false 737 }, 738 739 // copy during first npm install 740 install: { 741 forceDelete : true, 742 excludeHiddenUnix : true, 743 preserveFiles : false 744 }, 745 746 // copy for node_modules 747 modules: { 748 forceDelete : true, 749 excludeHiddenUnix : true, 750 preserveFiles : false 751 }, 752 753 // copy for site theme 754 site: { 755 forceDelete : false, 756 excludeHiddenUnix : true, 757 preserveFiles : true 758 } 759 } 760 } 761 762 };