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  };