diff --git a/tasks/build.js b/tasks/build.js index 7e81e296a..00c402c8c 100644 --- a/tasks/build.js +++ b/tasks/build.js @@ -13,6 +13,7 @@ var chmod = require('gulp-chmod'), clone = require('gulp-clone'), flatten = require('gulp-flatten'), + gulpif = require('gulp-if'), header = require('gulp-header'), less = require('gulp-less'), minifyCSS = require('gulp-minify-css'), @@ -25,8 +26,9 @@ var // user config config = require('./config/user'), - // task config - tasks = require('./config/tasks'), + // install config + tasks = require('./config/project/tasks'), + install = require('./config/project/install'), // shorthand globs = config.globs, @@ -34,13 +36,13 @@ var output = config.paths.output, source = config.paths.source, + banner = tasks.banner, comments = tasks.regExp.comments, log = tasks.log, settings = tasks.settings ; - -// gulp task to build all files from source +// exports gulp task module.exports = function(callback) { var @@ -51,8 +53,8 @@ module.exports = function(callback) { console.info('Building Semantic'); - if(!fs.existsSync(config.files.theme)) { - console.error('Cant build LESS. Run "gulp install" to create a theme config file'); + if( !install.isSetup() ) { + console.error('Cannot build files. Run "gulp install" to set-up Semantic'); return; } @@ -62,37 +64,12 @@ module.exports = function(callback) { return; } - // copy assets - gulp.src(source.themes + '**/assets/**/' + globs.components + '?(s).*') - .pipe(chmod(config.permission)) - .pipe(gulp.dest(output.themes)) - ; - - // copy source javascript - gulp.src(source.definitions + '**/' + globs.components + '.js') - .pipe(plumber()) - .pipe(flatten()) - .pipe(chmod(config.permission)) - .pipe(gulp.dest(output.uncompressed)) - .pipe(print(log.created)) - .pipe(uglify(settings.uglify)) - .pipe(rename(settings.rename.minJS)) - .pipe(header(config.banner, settings.header)) - .pipe(chmod(config.permission)) - .pipe(gulp.dest(output.compressed)) - .pipe(print(log.created)) - .on('end', function() { - gulp.start('package compressed js'); - gulp.start('package uncompressed js'); - }) - ; - // unified css stream stream = gulp.src(source.definitions + '**/' + globs.components + '.less') .pipe(plumber()) .pipe(less(settings.less)) - .pipe(flatten()) .pipe(autoprefixer(settings.prefix)) + .pipe(flatten()) ; // two concurrent streams from same source to concat release @@ -106,8 +83,8 @@ module.exports = function(callback) { .pipe(replace(comments.small.in, comments.small.out)) .pipe(replace(comments.tiny.in, comments.tiny.out)) .pipe(replace(assets.source, assets.uncompressed)) - .pipe(header(config.banner, settings.header)) - .pipe(chmod(config.permission)) + .pipe(header(banner, settings.header)) + .pipe(gulpif(config.hasPermission, chmod(config.permission))) .pipe(gulp.dest(output.uncompressed)) .pipe(print(log.created)) .on('end', function() { @@ -121,8 +98,8 @@ module.exports = function(callback) { .pipe(replace(assets.source, assets.compressed)) .pipe(minifyCSS(settings.minify)) .pipe(rename(settings.rename.minCSS)) - .pipe(header(config.banner, settings.header)) - .pipe(chmod(config.permission)) + .pipe(header(banner, settings.header)) + .pipe(gulpif(config.hasPermission, chmod(config.permission))) .pipe(gulp.dest(output.compressed)) .pipe(print(log.created)) .on('end', function() { @@ -130,4 +107,30 @@ module.exports = function(callback) { gulp.start('package compressed css'); }) ; + + // copy assets + gulp.src(source.themes + '**/assets/**/' + globs.components + '?(s).*') + .pipe(gulpif(config.hasPermission, chmod(config.permission))) + .pipe(gulp.dest(output.themes)) + ; + + // copy source javascript + gulp.src(source.definitions + '**/' + globs.components + '.js') + .pipe(plumber()) + .pipe(flatten()) + .pipe(gulp.dest(output.uncompressed)) + .pipe(gulpif(config.hasPermission, chmod(config.permission))) + .pipe(print(log.created)) + .pipe(uglify(settings.uglify)) + .pipe(rename(settings.rename.minJS)) + .pipe(header(banner, settings.header)) + .pipe(gulp.dest(output.compressed)) + .pipe(gulpif(config.hasPermission, chmod(config.permission))) + .pipe(print(log.created)) + .on('end', function() { + gulp.start('package compressed js'); + gulp.start('package uncompressed js'); + }) + ; + }; \ No newline at end of file diff --git a/tasks/clean.js b/tasks/clean.js index 190d6190d..f6b770e5e 100644 --- a/tasks/clean.js +++ b/tasks/clean.js @@ -3,11 +3,12 @@ *******************************/ var - config = require('config'), - del = require('del') + del = require('del'), + config = require('config/user'), + tasks = require('config/project/tasks') ; // cleans distribution files module.exports = function(callback) { - return del([config.clean], settings.del, callback); + return del([config.clean], tasks.settings.del, callback); }; \ No newline at end of file diff --git a/tasks/config/user/defaults.js b/tasks/config/defaults.js similarity index 66% rename from tasks/config/user/defaults.js rename to tasks/config/defaults.js index 52ab65d77..61cdd68b7 100644 --- a/tasks/config/user/defaults.js +++ b/tasks/config/defaults.js @@ -30,16 +30,18 @@ module.exports = { clean : 'dist/' }, - // globs globs : { // files ignored for concatenated release ignored : '!(*.min|*.map|*.rtl)' }, + // components to include in package components: [ + // global 'reset', 'site', + // elements 'button', 'divider', @@ -55,6 +57,7 @@ module.exports = { 'reveal', 'segment', 'step', + // collections 'breadcrumb', 'form', @@ -62,6 +65,7 @@ module.exports = { 'menu', 'message', 'table', + // views 'ad', 'card', @@ -69,6 +73,7 @@ module.exports = { 'feed', 'item', 'statistic', + // modules 'accordion', 'checkbox', @@ -86,6 +91,7 @@ module.exports = { 'tab', 'transition', 'video', + // behaviors 'api', 'form', @@ -93,46 +99,7 @@ module.exports = { 'visibility' ], - /* Install Move */ - files: { - composer : 'composer.json', - config : './semantic.json', - npm : './package.json', - meteor : './package.js', - site : './src/site', - theme : './src/theme.config' - }, - - // path to theme.config from project root - themePath : './src/theme.config', - // whether to load admin tasks - admin: false, + admin: false - docs : { - source : '../docs/server/files/release/', - output : '../docs/release/' - }, - - // files cleaned after install - setupFiles: [ - './src/theme.config.example', - './semantic.json.example', - './src/_site' - ], - - - // modified to create configs - templates: { - config : './semantic.json.example', - site : './src/_site', - theme : './src/theme.config.example' - }, - - // folder paths - folders: { - config : './', - site : './src/site', - theme : './src/' - } }; diff --git a/tasks/config/install/questions.js b/tasks/config/install/questions.js deleted file mode 100644 index 4c9729e30..000000000 --- a/tasks/config/install/questions.js +++ /dev/null @@ -1,453 +0,0 @@ -/******************************* - Install Questions -*******************************/ - -var defaults, fs, filter, when; - -fs = require('fs'); -defaults = require('./defaults'); - -filter = { - removeTrailingSlash: function(path) { - return path.replace(/(\/$|\\$)+/mg, ''); - } -}; - -when = { - - // set-up - hasConfig: function() { - return( fs.existsSync('./semantic.json') ); - }, - 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); - } -}; - -module.exports = { - - 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: "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: "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: "video", checked: true }, - { name: "api", checked: true }, - { name: "form", checked: true }, - { name: "state", checked: true }, - { name: "visibility", checked: true } - ], - when: when.notAuto - }, - { - type: 'input', - name: 'permission', - message: 'What octal file permission should outputted files receive?', - default: defaults.permission, - when: when.notAuto - }, - { - type: 'list', - name: 'rtl', - message: 'Do you use a RTL (Right-To-Left) language?', - when: when.notAuto, - choices: [ - { - name: 'No', - value: 'no' - }, - { - name: 'Yes', - value: 'yes' - }, - ] - }, - { - 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: 'None really fit', - value: 'custom' - }, - { - 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: 'None really fit', - value: 'custom' - }, - { - 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 - } - ] - -}; \ No newline at end of file diff --git a/tasks/config/project/install.js b/tasks/config/project/install.js new file mode 100644 index 000000000..132eb428b --- /dev/null +++ b/tasks/config/project/install.js @@ -0,0 +1,498 @@ +/******************************* + Set-up +*******************************/ + +var + fs = require('fs'), + defaults = require('../defaults'), + + when, + filter +; + +/******************************* + When to Ask +*******************************/ + +when = { + + // install + hasConfig: function() { + return( fs.existsSync('./semantic.json') ); + }, + 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 +*******************************/ + +filter = { + removeTrailingSlash: function(path) { + return path.replace(/(\/$|\\$)+/mg, ''); + } +}; + +/******************************* + Configuration +*******************************/ + +module.exports = { + + // check whether install is setup + isSetup: function() { + return true; + }, + + // files cleaned up after install + setupFiles: [ + './src/theme.config.example', + './semantic.json.example', + './src/_site' + ], + + // modified to create configs + templates: { + config : './semantic.json.example', + site : './src/_site', + theme : './src/theme.config.example' + }, + + // folder paths + folders: { + config : './', + site : './src/site', + theme : './src/' + }, + + questions: { + + 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: "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: "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: "video", checked: true }, + { name: "api", checked: true }, + { name: "form", checked: true }, + { name: "state", checked: true }, + { name: "visibility", checked: true } + ], + when: when.notAuto + }, + { + type: 'input', + name: 'permission', + message: 'What octal file permission should outputted files receive?', + default: defaults.permission, + when: when.notAuto + }, + { + type: 'list', + name: 'rtl', + message: 'Do you use a RTL (Right-To-Left) language?', + when: when.notAuto, + choices: [ + { + name: 'No', + value: 'no' + }, + { + name: 'Yes', + value: 'yes' + }, + ] + }, + { + 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: 'None really fit', + value: 'custom' + }, + { + 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: 'None really fit', + value: 'custom' + }, + { + 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 + } + ] + + } + +}; \ No newline at end of file diff --git a/tasks/config/project/release.js b/tasks/config/project/release.js new file mode 100644 index 000000000..f8403b8b0 --- /dev/null +++ b/tasks/config/project/release.js @@ -0,0 +1,60 @@ +/******************************* + Set-up +*******************************/ + +var + requireDotFile = require('require-dot-file'), + package +; + + +/******************************* + Derived Values +*******************************/ + +try { + // looks for config file across all parent directories + package = requireDotFile('package.json'); +} + +catch(error) { + // generate fake package + package = { + version: 'x.x' + }; +} + +/******************************* + Export +*******************************/ + +module.exports = { + + title : 'Semantic UI', + repository : 'https://github.com/Semantic-Org/Semantic-UI', + url : 'http://www.semantic-ui.com/', + + banner: '' + + ' /*' + '\n' + + ' * # <%= title %> - <%= version %>' + '\n' + + ' * <%= repository %>' + '\n' + + ' * <%= url %>' + '\n' + + ' *' + '\n' + + ' * Copyright 2014 Contributors' + '\n' + + ' * Released under the MIT license' + '\n' + + ' * http://opensource.org/licenses/MIT' + '\n' + + ' *' + '\n' + + ' */' + '\n', + + files: { + composer : 'composer.json', + config : 'semantic.json', + npm : 'package.json', + meteor : 'package.js', + site : 'src/site', + theme : 'src/theme.config' + }, + + version : package.version + +}; diff --git a/tasks/config/tasks/index.js b/tasks/config/project/tasks.js similarity index 72% rename from tasks/config/tasks/index.js rename to tasks/config/project/tasks.js index 4830fc84f..88041f140 100644 --- a/tasks/config/tasks/index.js +++ b/tasks/config/project/tasks.js @@ -1,24 +1,11 @@ var - config = require('./config') + config = require('../user'), + release = require('./release') ; module.exports = { - title : 'Semantic UI', - repository : 'https://github.com/Semantic-Org/Semantic-UI', - url : 'http://www.semantic-ui.com/', - - banner: '' - + ' /*' + '\n' - + ' * # <%= title %> - <%= version %>' + '\n' - + ' * <%= repository %>' + '\n' - + ' * <%= url %>' + '\n' - + ' *' + '\n' - + ' * Copyright 2014 Contributors' + '\n' - + ' * Released under the MIT license' + '\n' - + ' * http://opensource.org/licenses/MIT' + '\n' - + ' *' + '\n' - + ' */' + '\n', + banner : release.banner, log: { created: function(file) { @@ -52,7 +39,10 @@ module.exports = { in : /(\/\* [\s\S]+? \*\/)/mg, out : '\n$1' } - } + }, + + theme: /.*\/themes\/.*?\//mg + }, settings: { @@ -64,10 +54,10 @@ module.exports = { /* Comment Banners */ header: { - title : config.title, - version : config.version, - repository : config.repository, - url : config.url + title : release.title, + version : release.version, + repository : release.repository, + url : release.url }, /* Minified CSS Settings */ diff --git a/tasks/config/user/index.js b/tasks/config/user.js similarity index 84% rename from tasks/config/user/index.js rename to tasks/config/user.js index ee643d676..ba5d0fedd 100644 --- a/tasks/config/user/index.js +++ b/tasks/config/user.js @@ -1,17 +1,19 @@ -var +/******************************* + Set-up +*******************************/ - // npm deps +var + // npm dependencies extend = require('extend'), fs = require('fs'), path = require('path'), requireDotFile = require('require-dot-file'), + // semantic.json defaults defaults = require('./defaults'), - // holds package.json contents - package, + // final config object config - ; @@ -22,7 +24,6 @@ var try { // looks for config file across all parent directories config = requireDotFile('semantic.json'); - package = requireDotFile('package.json'); } catch(error) { if(error.code === 'MODULE_NOT_FOUND') { @@ -41,21 +42,12 @@ else { /******************************* - Derived Values + Derived Values *******************************/ -/*-------------- - Version ----------------*/ - -// npm package.json is only location that holds true "version" -config.version = (package !== undefined) - ? package.version || 'Unknown' - : 'Unknown' -; /*-------------- - File Paths + File Paths ---------------*/ // resolve source paths @@ -89,9 +81,21 @@ config.paths.assets = { packaged : path.relative(config.paths.output.packaged, config.paths.output.themes).replace(/\\/g,'/') }; +/*-------------- + Permission +---------------*/ + +if(config.permission) { + config.hasPermissions = true; +} +else { + // pass blank object to avoid causing errors + config.permission = {}; + config.hasPermissions = false; +} /*-------------- - Globs + Globs ---------------*/ // takes component object and creates file glob matching selected components diff --git a/tasks/watch.js b/tasks/watch.js index cbb9150cc..e7500bcad 100644 --- a/tasks/watch.js +++ b/tasks/watch.js @@ -2,53 +2,54 @@ Watch Task *******************************/ - var - gulp = require('gulp-help')(require('gulp')), + gulp = require('gulp-help')(require('gulp')), // node deps - fs = require('fs'), + console = require('better-console'), + fs = require('fs'), // gulp deps - autoprefixer = require('gulp-autoprefixer'), - chmod = require('gulp-chmod'), - clone = require('gulp-clone'), - header = require('gulp-header'), - less = require('gulp-less'), - minifyCSS = require('gulp-minify-css'), - plumber = require('gulp-plumber'), - print = require('gulp-print'), - rename = require('gulp-rename'), - replace = require('gulp-replace'), - uglify = require('gulp-uglify'), - util = require('gulp-util'), - watch = require('gulp-watch'), + autoprefixer = require('gulp-autoprefixer'), + chmod = require('gulp-chmod'), + clone = require('gulp-clone'), + header = require('gulp-header'), + less = require('gulp-less'), + minifyCSS = require('gulp-minify-css'), + plumber = require('gulp-plumber'), + print = require('gulp-print'), + rename = require('gulp-rename'), + replace = require('gulp-replace'), + uglify = require('gulp-uglify'), + util = require('gulp-util'), + watch = require('gulp-watch'), // user config - config = require('config'), + config = require('./config/user'), - // gulp config - banner = require('./tasks/config/gulp/banner'), - comments = require('./tasks/config/gulp/comments'), - log = require('./tasks/config/gulp/log'), - settings = require('./tasks/config/gulp/settings'), + // task config + tasks = require('./config/project/tasks'), + install = require('./config/project/install'), // shorthand - paths = config.paths, - globs = config.globs, + globs = config.globs, + assets = config.paths.assets, + output = config.paths.output, + source = config.paths.source, - assets = paths.assets, - output = paths.output, - source = paths.source + banner = tasks.banner, + comments = tasks.regExp.comments, + log = tasks.log, + settings = tasks.settings ; module.exports = function(callback) { - // Exit conditions - if(!fs.existsSync(config.files.theme)) { - console.error('Cant compile LESS. Run "gulp install" to create a theme config file'); + + if( !install.isSetup() ) { + console.error('Cannot watch files. Run "gulp install" to set-up Semantic'); return; } @@ -71,7 +72,7 @@ module.exports = function(callback) { source.themes + '**/*.{overrides,variables}' ], function(file) { var - srcPath, + lessPath, stream, compressedStream, uncompressedStream, @@ -81,35 +82,41 @@ module.exports = function(callback) { isConfig ; + // log modified file gulp.src(file.path) .pipe(print(log.modified)) ; // recompile on *.override , *.variable change - isDefinition = (file.path.indexOf(source.definitions) !== -1); + isConfig = (file.path.indexOf('.config') !== -1); isPackagedTheme = (file.path.indexOf(source.themes) !== -1); isSiteTheme = (file.path.indexOf(source.site) !== -1); - isConfig = (file.path.indexOf('.config') !== -1); + isDefinition = (file.path.indexOf(source.definitions) !== -1); - if(isDefinition || isPackagedTheme || isSiteTheme) { - // rebuild only matching definition file - srcPath = util.replaceExtension(file.path, '.less'); - srcPath = srcPath.replace(config.regExp.themePath, source.definitions); - srcPath = srcPath.replace(source.site, source.definitions); - } - else if(isConfig) { - // impossible to tell which file was updated in theme.config, rebuild all + if(isConfig) { console.log('Change detected in theme config'); + // impossible to tell which file was updated in theme.config, rebuild all gulp.start('build'); } - else { - srcPath = util.replaceExtension(file.path, '.less'); + else if(isPackagedTheme) { + console.log('Change detected in packaged theme'); + lessPath = lessPath.replace(tasks.regExp.theme, source.definitions); + lessPath = util.replaceExtension(file.path, '.less'); + } + else if(isSiteTheme) { + console.log('Change detected in site theme'); + lessPath = lessPath.replace(source.site, source.definitions); + lessPath = util.replaceExtension(file.path, '.less'); + } + else if(isDefinition) { + console.log('Change detected in definition'); + lessPath = util.replaceExtension(file.path, '.less'); } - if( fs.existsSync(srcPath) ) { + if( fs.existsSync(lessPath) ) { // unified css stream - stream = gulp.src(srcPath) + stream = gulp.src(lessPath) .pipe(plumber()) .pipe(less(settings.less)) .pipe(replace(comments.variables.in, comments.variables.out)) @@ -152,7 +159,7 @@ module.exports = function(callback) { } else { - console.log('SRC Path Does Not Exist', srcPath); + console.log('Cannot find UI definition at path', lessPath); } }) ;