| /******************************* |
| Set-up |
| *******************************/ |
| |
| var |
| fs = require('fs'), |
| path = require('path'), |
| defaults = require('../defaults'), |
| release = require('./release'), |
| |
| requireDotFile = require('require-dot-file') |
| ; |
| |
| /******************************* |
| When to Ask |
| *******************************/ |
| |
| /* Preconditions for install questions */ |
| |
| var when = { |
| |
| // path |
| changeRoot: function(questions) { |
| return (questions.useRoot !== undefined && questions.useRoot !== true); |
| }, |
| |
| // permissions |
| changePermissions: function(questions) { |
| return (questions.changePermissions && questions.changePermissions === true); |
| }, |
| |
| // install |
| hasConfig: function() { |
| return requireDotFile('semantic.json', process.cwd()); |
| }, |
| |
| allowOverwrite: function(questions) { |
| return (questions.overwrite === undefined || questions.overwrite == 'yes'); |
| }, |
| notAuto: function(questions) { |
| return (questions.install !== 'auto' && (questions.overwrite === undefined || questions.overwrite == 'yes')); |
| }, |
| custom: function(questions) { |
| return (questions.install === 'custom' && (questions.overwrite === undefined || questions.overwrite == 'yes')); |
| }, |
| express: function(questions) { |
| return (questions.install === 'express' && (questions.overwrite === undefined || questions.overwrite == 'yes')); |
| }, |
| |
| // customize |
| customize: function(questions) { |
| return (questions.customize === true); |
| }, |
| primaryColor: function(questions) { |
| return (questions.primaryColor); |
| }, |
| secondaryColor: function(questions) { |
| return (questions.secondaryColor); |
| } |
| }; |
| |
| /******************************* |
| Response Filters |
| *******************************/ |
| |
| /* Filters to user input from install questions */ |
| |
| var filter = { |
| removeTrailingSlash: function(path) { |
| return path.replace(/(\/$|\\$)+/mg, ''); |
| } |
| }; |
| |
| /******************************* |
| Configuration |
| *******************************/ |
| |
| module.exports = { |
| |
| // check whether install is setup |
| isSetup: function() { |
| return when.hasConfig(); |
| }, |
| |
| // detect whether there is a semantic.json configuration and that the auto-install option is set to true |
| shouldAutoInstall: function() { |
| var |
| config = when.hasConfig() |
| ; |
| return config['autoInstall']; |
| }, |
| |
| // checks if files are in a PM directory |
| getPackageManager: function(directory) { |
| var |
| // returns last matching result (avoid sub-module detection) |
| walk = function(directory) { |
| var |
| pathArray = directory.split(path.sep), |
| folder = pathArray[pathArray.length - 1], |
| nextDirectory = path.join(directory, path.sep, '..') |
| ; |
| if( folder == 'bower_components') { |
| return { |
| name: 'Bower', |
| root: nextDirectory |
| }; |
| } |
| else if(folder == 'node_modules') { |
| return { |
| name: 'NPM', |
| root: nextDirectory |
| }; |
| } |
| else if(folder == 'composer') { |
| return { |
| name: 'Composer', |
| root: nextDirectory |
| }; |
| } |
| if(path.resolve(directory) == path.resolve(nextDirectory)) { |
| return false; |
| } |
| // recurse downward |
| return walk(nextDirectory); |
| } |
| ; |
| // start walk from current directory if none specified |
| directory = directory || (__dirname + path.sep); |
| return walk(directory); |
| }, |
| |
| // checks if files is PMed submodule |
| isSubModule: function(directory) { |
| var |
| moduleFolders = 0, |
| walk = function(directory) { |
| var |
| pathArray = directory.split(path.sep), |
| folder = pathArray[pathArray.length - 2], |
| nextDirectory = path.join(directory, path.sep, '..') |
| ; |
| if( folder == 'bower_components') { |
| moduleFolders++; |
| } |
| else if(folder == 'node_modules') { |
| moduleFolders++; |
| } |
| else if(folder == 'composer') { |
| moduleFolders++; |
| } |
| if(path.resolve(directory) == path.resolve(nextDirectory)) { |
| return (moduleFolders > 1); |
| } |
| // recurse downward |
| return walk(nextDirectory); |
| } |
| ; |
| // start walk from current directory if none specified |
| directory = directory || (__dirname + path.sep); |
| return walk(directory); |
| }, |
| |
| |
| createJSON: function(answers) { |
| var |
| json = { |
| paths: { |
| source: {}, |
| output: {} |
| } |
| } |
| ; |
| |
| // add components |
| if(answers.components) { |
| json.components = answers.components; |
| } |
| |
| // add rtl choice |
| if(answers.rtl) { |
| json.rtl = answers.rtl; |
| } |
| |
| // add permissions |
| if(answers.permission) { |
| json.permission = answers.permission; |
| } |
| |
| // add path to semantic |
| if(answers.semanticRoot) { |
| json.base = path.normalize(answers.semanticRoot); |
| } |
| |
| // record version number to avoid re-installing on same version |
| json.version = release.version; |
| |
| // add dist folder paths |
| if(answers.dist) { |
| answers.dist = path.normalize(answers.dist); |
| |
| json.paths.output = { |
| packaged : path.normalize(answers.dist + '/'), |
| uncompressed : path.normalize(answers.dist + '/components/'), |
| compressed : path.normalize(answers.dist + '/components/'), |
| themes : path.normalize(answers.dist + '/themes/') |
| }; |
| } |
| |
| // add site path |
| if(answers.site) { |
| json.paths.source.site = path.normalize(answers.site + '/'); |
| } |
| if(answers.packaged) { |
| json.paths.output.packaged = path.normalize(answers.packaged + '/'); |
| } |
| if(answers.compressed) { |
| json.paths.output.compressed = path.normalize(answers.compressed + '/'); |
| } |
| if(answers.uncompressed) { |
| json.paths.output.uncompressed = path.normalize(answers.uncompressed + '/'); |
| } |
| return json; |
| }, |
| |
| // files cleaned up after install |
| setupFiles: [ |
| './src/theme.config.example', |
| './semantic.json.example', |
| './src/_site' |
| ], |
| |
| regExp: { |
| // used to match siteFolder variable in theme.less |
| siteVariable: /@siteFolder .*\'(.*)/mg |
| }, |
| |
| // source paths (when installing) |
| source: { |
| config : './semantic.json.example', |
| definitions : './src/definitions', |
| gulpFile : './gulpfile.js', |
| lessImport : './src/semantic.less', |
| site : './src/_site', |
| tasks : './tasks', |
| themeConfig : './src/theme.config.example', |
| themeImport : './src/theme.less', |
| themes : './src/themes', |
| defaultTheme : './src/themes/default', |
| userGulpFile : './tasks/config/npm/gulpfile.js' |
| }, |
| |
| // expected final filenames |
| files: { |
| config : 'semantic.json', |
| lessImport : 'src/semantic.less', |
| site : 'src/site', |
| themeConfig : 'src/theme.config', |
| themeImport : 'src/theme.less' |
| }, |
| |
| // folder paths to files relative to root |
| folders: { |
| config : './', |
| definitions : 'src/definitions/', |
| lessImport : 'src/', |
| modules : 'node_modules/', |
| site : 'src/site/', |
| tasks : 'tasks/', |
| themeConfig : 'src/', |
| themeImport : 'src/', |
| themes : 'src/themes/', |
| |
| defaultTheme : 'default/' // only path that is relative to another directory and not root |
| }, |
| |
| // questions asked during install |
| questions: { |
| |
| root: [ |
| { |
| type : 'list', |
| name : 'useRoot', |
| message : |
| ' \n' + |
| ' {packageMessage} \n' + |
| ' \n' + |
| ' Is this your project folder?\n' + |
| ' \x1b[92m{root}\x1b[0m \n' + |
| ' \n ' + |
| '\n', |
| choices: [ |
| { |
| name : 'Yes', |
| value : true |
| }, |
| { |
| name : 'No, let me specify', |
| value : false |
| } |
| ] |
| }, |
| { |
| type : 'input', |
| name : 'customRoot', |
| message : 'Please enter the absolute path to your project root', |
| default : '/my/project/path', |
| when : when.changeRoot |
| }, |
| { |
| type : 'input', |
| name : 'semanticRoot', |
| message : 'Where should we put Semantic UI inside your project?', |
| default : 'semantic/' |
| } |
| ], |
| |
| setup: [ |
| { |
| type: 'list', |
| name: 'overwrite', |
| message: 'It looks like you have a semantic.json file already.', |
| when: when.hasConfig, |
| choices: [ |
| { |
| name: 'Yes, extend my current settings.', |
| value: 'yes' |
| }, |
| { |
| name: 'Skip install', |
| value: 'no' |
| } |
| ] |
| }, |
| { |
| type: 'list', |
| name: 'install', |
| message: 'Set-up Semantic UI', |
| when: when.allowOverwrite, |
| choices: [ |
| { |
| name: 'Automatic (Use defaults locations and all components)', |
| value: 'auto' |
| }, |
| { |
| name: 'Express (Set components and output folder)', |
| value: 'express' |
| }, |
| { |
| name: 'Custom (Customize all src/dist values)', |
| value: 'custom' |
| } |
| ] |
| }, |
| { |
| type: 'checkbox', |
| name: 'components', |
| message: 'What components should we include in the package?', |
| |
| // duplicated manually from tasks/defaults.js with additional property |
| choices: [ |
| { name: "reset", checked: true }, |
| { name: "site", checked: true }, |
| { name: "button", checked: true }, |
| { name: "container", checked: true }, |
| { name: "divider", checked: true }, |
| { name: "flag", checked: true }, |
| { name: "header", checked: true }, |
| { name: "icon", checked: true }, |
| { name: "image", checked: true }, |
| { name: "input", checked: true }, |
| { name: "label", checked: true }, |
| { name: "list", checked: true }, |
| { name: "loader", checked: true }, |
| { name: "rail", checked: true }, |
| { name: "reveal", checked: true }, |
| { name: "segment", checked: true }, |
| { name: "step", checked: true }, |
| { name: "breadcrumb", checked: true }, |
| { name: "form", checked: true }, |
| { name: "grid", checked: true }, |
| { name: "menu", checked: true }, |
| { name: "message", checked: true }, |
| { name: "table", checked: true }, |
| { name: "ad", checked: true }, |
| { name: "card", checked: true }, |
| { name: "comment", checked: true }, |
| { name: "feed", checked: true }, |
| { name: "item", checked: true }, |
| { name: "statistic", checked: true }, |
| { name: "accordion", checked: true }, |
| { name: "checkbox", checked: true }, |
| { name: "dimmer", checked: true }, |
| { name: "dropdown", checked: true }, |
| { name: "embed", checked: true }, |
| { name: "modal", checked: true }, |
| { name: "nag", checked: true }, |
| { name: "popup", checked: true }, |
| { name: "progress", checked: true }, |
| { name: "rating", checked: true }, |
| { name: "search", checked: true }, |
| { name: "shape", checked: true }, |
| { name: "sidebar", checked: true }, |
| { name: "sticky", checked: true }, |
| { name: "tab", checked: true }, |
| { name: "transition", checked: true }, |
| { name: "api", checked: true }, |
| { name: "form", checked: true }, |
| { name: "state", checked: true }, |
| { name: "visibility", checked: true } |
| ], |
| when: when.notAuto |
| }, |
| { |
| type: 'list', |
| name: 'changePermissions', |
| when: when.notAuto, |
| message: 'Should we set permissions on outputted files?', |
| choices: [ |
| { |
| name: 'No', |
| value: false |
| }, |
| { |
| name: 'Yes', |
| value: true |
| } |
| ] |
| }, |
| { |
| type: 'input', |
| name: 'permission', |
| message: 'What octal file permission should outputted files receive?', |
| default: defaults.permission, |
| when: when.changePermissions |
| }, |
| { |
| type: 'list', |
| name: 'rtl', |
| message: 'Do you use a RTL (Right-To-Left) language?', |
| when: when.notAuto, |
| choices: [ |
| { |
| name: 'No', |
| value: false |
| }, |
| { |
| name: 'Yes', |
| value: true |
| }, |
| { |
| name: 'Build Both', |
| value: 'both' |
| } |
| ] |
| }, |
| { |
| type: 'input', |
| name: 'dist', |
| message: 'Where should we output Semantic UI?', |
| default: defaults.paths.output.packaged, |
| filter: filter.removeTrailingSlash, |
| when: when.express |
| }, |
| { |
| type: 'input', |
| name: 'site', |
| message: 'Where should we put your site folder?', |
| default: defaults.paths.source.site, |
| filter: filter.removeTrailingSlash, |
| when: when.custom |
| }, |
| { |
| type: 'input', |
| name: 'packaged', |
| message: 'Where should we output a packaged version?', |
| default: defaults.paths.output.packaged, |
| filter: filter.removeTrailingSlash, |
| when: when.custom |
| }, |
| { |
| type: 'input', |
| name: 'compressed', |
| message: 'Where should we output compressed components?', |
| default: defaults.paths.output.compressed, |
| filter: filter.removeTrailingSlash, |
| when: when.custom |
| }, |
| { |
| type: 'input', |
| name: 'uncompressed', |
| message: 'Where should we output uncompressed components?', |
| default: defaults.paths.output.uncompressed, |
| filter: filter.removeTrailingSlash, |
| when: when.custom |
| } |
| ], |
| |
| |
| cleanup: [ |
| { |
| type: 'list', |
| name: 'cleanup', |
| message: 'Should we remove set-up files?', |
| choices: [ |
| { |
| name: 'Yes (re-install will require redownloading semantic).', |
| value: 'yes' |
| }, |
| { |
| name: 'No Thanks', |
| value: 'no' |
| } |
| ] |
| }, |
| { |
| type: 'list', |
| name: 'build', |
| message: 'Do you want to build Semantic now?', |
| choices: [ |
| { |
| name: 'Yes', |
| value: 'yes' |
| }, |
| { |
| name: 'No', |
| value: 'no' |
| } |
| ] |
| }, |
| ], |
| site: [ |
| { |
| type: 'list', |
| name: 'customize', |
| message: 'You have not yet customized your site, can we help you do that?', |
| choices: [ |
| { |
| name: 'Yes, ask me a few questions', |
| value: true |
| }, |
| { |
| name: 'No I\'ll do it myself', |
| value: false |
| } |
| ] |
| }, |
| { |
| type: 'list', |
| name: 'headerFont', |
| message: 'Select your header font', |
| choices: [ |
| { |
| name: 'Helvetica Neue, Arial, sans-serif', |
| value: 'Helvetica Neue, Arial, sans-serif;' |
| }, |
| { |
| name: 'Lato (Google Fonts)', |
| value: 'Lato' |
| }, |
| { |
| name: 'Open Sans (Google Fonts)', |
| value: 'Open Sans' |
| }, |
| { |
| name: 'Source Sans Pro (Google Fonts)', |
| value: 'Source Sans Pro' |
| }, |
| { |
| name: 'Droid (Google Fonts)', |
| value: 'Droid' |
| }, |
| { |
| name: 'I\'ll choose on my own', |
| value: false |
| } |
| ], |
| when: when.customize |
| }, |
| { |
| type: 'list', |
| name: 'pageFont', |
| message: 'Select your page font', |
| choices: [ |
| { |
| name: 'Helvetica Neue, Arial, sans-serif', |
| value: 'Helvetica Neue, Arial, sans-serif;' |
| }, |
| { |
| name: 'Lato (Import from Google Fonts)', |
| value: 'Lato' |
| }, |
| { |
| name: 'Open Sans (Import from Google Fonts)', |
| value: 'Open Sans' |
| }, |
| { |
| name: 'Source Sans Pro (Import from Google Fonts)', |
| value: 'Source Sans Pro' |
| }, |
| { |
| name: 'Droid (Google Fonts)', |
| value: 'Droid' |
| }, |
| { |
| name: 'I\'ll choose on my own', |
| value: false |
| } |
| ], |
| when: when.customize |
| }, |
| { |
| type: 'list', |
| name: 'fontSize', |
| message: 'Select your base font size', |
| default: '14px', |
| choices: [ |
| { |
| name: '12px', |
| }, |
| { |
| name: '13px', |
| }, |
| { |
| name: '14px (Recommended)', |
| value: '14px' |
| }, |
| { |
| name: '15px', |
| }, |
| { |
| name: '16px', |
| }, |
| { |
| name: 'I\'ll choose on my own', |
| value: false |
| } |
| ], |
| when: when.customize |
| }, |
| { |
| type: 'list', |
| name: 'primaryColor', |
| message: 'Select the closest name for your primary brand color', |
| default: '14px', |
| choices: [ |
| { |
| name: 'Blue' |
| }, |
| { |
| name: 'Green' |
| }, |
| { |
| name: 'Orange' |
| }, |
| { |
| name: 'Pink' |
| }, |
| { |
| name: 'Purple' |
| }, |
| { |
| name: 'Red' |
| }, |
| { |
| name: 'Teal' |
| }, |
| { |
| name: 'Yellow' |
| }, |
| { |
| name: 'Black' |
| }, |
| { |
| name: 'I\'ll choose on my own', |
| value: false |
| } |
| ], |
| when: when.customize |
| }, |
| { |
| type: 'input', |
| name: 'PrimaryHex', |
| message: 'Enter a hexcode for your primary brand color', |
| when: when.primaryColor |
| }, |
| { |
| type: 'list', |
| name: 'secondaryColor', |
| message: 'Select the closest name for your secondary brand color', |
| default: '14px', |
| choices: [ |
| { |
| name: 'Blue' |
| }, |
| { |
| name: 'Green' |
| }, |
| { |
| name: 'Orange' |
| }, |
| { |
| name: 'Pink' |
| }, |
| { |
| name: 'Purple' |
| }, |
| { |
| name: 'Red' |
| }, |
| { |
| name: 'Teal' |
| }, |
| { |
| name: 'Yellow' |
| }, |
| { |
| name: 'Black' |
| }, |
| { |
| name: 'I\'ll choose on my own', |
| value: false |
| } |
| ], |
| when: when.customize |
| }, |
| { |
| type: 'input', |
| name: 'secondaryHex', |
| message: 'Enter a hexcode for your secondary brand color', |
| when: when.secondaryColor |
| } |
| ] |
| |
| }, |
| |
| settings: { |
| |
| /* Rename Files */ |
| rename: { |
| json : { extname : '.json' } |
| }, |
| |
| /* Copy Install Folders */ |
| wrench: { |
| |
| // overwrite existing files update & install (default theme / definition) |
| overwrite: { |
| forceDelete : true, |
| excludeHiddenUnix : true, |
| preserveFiles : false |
| }, |
| |
| // only create files that don't exist (site theme update) |
| merge: { |
| forceDelete : false, |
| excludeHiddenUnix : true, |
| preserveFiles : true |
| } |
| |
| } |
| } |
| }; |