diff --git a/.gitignore b/.gitignore index 3d341f5c10..1c23ecef2b 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,7 @@ .sass-cache/* .yardoc _build +.customizer bower_components bundle diff --git a/customizer/complete.json b/customizer/complete.json new file mode 100644 index 0000000000..9244c56190 --- /dev/null +++ b/customizer/complete.json @@ -0,0 +1,46 @@ +{ + "modules": [ + "grid", + "typography", + "button", + "forms", + "abide", + "accordion", + "accordion_menu", + "badge", + "breadcrumbs", + "button_group", + "callout", + "close_button", + "menu", + "menu_icon", + "drilldown_menu", + "dropdown", + "dropdown_menu", + "equalizer", + "flex_video", + "interchange", + "label", + "magellan", + "media_object", + "off_canvas", + "orbit", + "pagination", + "progress_bar", + "responsive_menu", + "responsive_toggle", + "reveal", + "slider", + "sticky", + "switch", + "table", + "tabs", + "thumbnail", + "title_bar", + "toggler", + "tooltip", + "top_bar", + "visibility", + "float" + ] +} diff --git a/customizer/config.yml b/customizer/config.yml new file mode 100644 index 0000000000..a315fc33cc --- /dev/null +++ b/customizer/config.yml @@ -0,0 +1,204 @@ +# This is the customizer's master module list. +# Each item in the list is a module with any of these keys: +# - sass: Name of the CSS export. 'grid' becomes '@include foundation-grid;' +# - js: Name of the JavaScript file. 'accordion' becomes 'foundation.accordion.js' +# - js_utils: Names of plugin dependencies. 'box' becomes 'foundation.util.box.js' + +grid: + sass: grid + +typography: + sass: typography + +button: + sass: button + +forms: + sass: forms + +input_range: + sass: range-input + +abide: + js: abide + +accordion: + sass: accordion + js: accordion + js_utils: + - keyboard + - motion + +accordion_menu: + sass: accordion-menu + js: accordionMenu + js_utils: + - keyboard + - motion + - nest + +badge: + sass: badge + +breadcrumbs: + sass: breadcrumbs + +button_group: + sass: button-group + +callout: + sass: callout + +close_button: + sass: close-button + +drilldown_menu: + sass: drilldown-menu + js: drilldown + js_utils: + - keyboard + - motion + - nest + +dropdown: + sass: dropdown + js: dropdown + js_utils: + - keyboard + - box + - triggers + +dropdown_menu: + sass: dropdown-menu + js: dropdownMenu + js_utils: + - keyboard + - motion + - box + - nest + +equalizer: + js: equalizer + +flex_video: + sass: flex-video + +interchange: + js: interchange + js_utils: + - triggers + - timerAndImageLoader + +label: + sass: label + +magellan: + js: magellan + js_utils: + - motion + +media_object: + sass: media-object + +menu: + sass: menu + +off_canvas: + sass: off-canvas + js: offcanvas + +orbit: + sass: orbit + js: orbit + js_utils: + - motion + - timerAndImageLoader + - keyboard + - touch + +progress_bar: + sass: progress-bar + +progress_element: + sass: progress-element + +responsive_menu: + js: responsiveMenu + js_utils: + - triggers + - mediaQuery + +responsive_toggle: + js: responsiveToggle + js_utils: + - mediaQuery + +meter_element: + sass: meter-element + +slider: + sass: slider + js: slider + js_utils: + - box + - motion + - triggers + - mediaQuery + +sticky: + sass: sticky + js: sticky + js_utils: + - triggers + - mediaQuery + +reveal: + sass: reveal + js: reveal + js_utils: + - box + - motion + - triggers + - mediaQuery + +switch: + sass: switch + +table: + sass: table + +tabs: + sass: tabs + js: tabs + js_utils: + - keyboard + - timerAndImageLoader + +thumbnail: + sass: thumbnail + +title_bar: + sass: title-bar + +toggler: + js: toggler + js_utils: + - motion + +tooltip: + sass: tooltip + js: tooltip + js_utils: + - box + - triggers + - mediaQuery + - motion + +top_bar: + sass: top-bar + +visibility: + sass: visibility-classes + +float: + sass: float-classes diff --git a/customizer/essential.json b/customizer/essential.json new file mode 100644 index 0000000000..05ed36302d --- /dev/null +++ b/customizer/essential.json @@ -0,0 +1,11 @@ +{ + "modules": [ + "typography", + "grid", + "forms", + "button", + "callout", + "reveal" + ], + "variables": {} +} diff --git a/customizer/index.html b/customizer/index.html new file mode 100644 index 0000000000..486ac94ed9 --- /dev/null +++ b/customizer/index.html @@ -0,0 +1,169 @@ + + + + + + + Foundation for Sites + + + + +
+
+

Welcome to Foundation

+
+
+ +
+
+
+

We’re stoked you want to try Foundation!

+

To get going, this file (index.html) includes some basic styles you can modify, play around with, or totally destroy to get going.

+

Once you've exhausted the fun in this document, you should check out:

+
+
+

Foundation Documentation
Everything you need to know about using the framework.

+
+
+

Foundation Code Skills
These online courses offer you a chance to better understand how Foundation works and how you can master it to create awesome projects.

+
+
+

Foundation Forum
Join the Foundation community to ask a question or show off your knowlege.

+
+
+
+
+

Foundation on Github
Latest code, issue reports, feature requests and more.

+
+
+

@zurbfoundation
Ping us on Twitter if you have questions. When you build something with this we'd love to see it (and send you a totally boss sticker).

+
+
+
+
+
+ +
+
+
Here’s your basic grid:
+ + +
+
+
+

This is a twelve column section in a row. Each of these includes a div.callout element so you can see where the columns are - it's not required at all for the grid.

+
+
+
+
+
+
+

Six columns

+
+
+
+
+

Six columns

+
+
+
+
+
+
+

Four columns

+
+
+
+
+

Four columns

+
+
+
+
+

Four columns

+
+
+
+ +
+ +
We bet you’ll need a form somewhere:
+
+
+
+ + +
+
+
+
+ + +
+
+ + +
+
+
+ +
+ + .com +
+
+
+
+
+
+ + +
+
+
+
+ + + +
+
+ + + +
+
+
+
+ + +
+
+
+
+ +
+
Try one of these buttons:
+

Simple Button
+ Success Btn
+ Alert Btn
+ Secondary Btn

+
+
So many components, girl!
+

A whole kitchen sink of goodies comes with Foundation. Check out the docs to see them all, along with details on making them your own.

+ Go to Foundation Docs +
+
+
+ + + + + + + diff --git a/customizer/lib/index.js b/customizer/lib/index.js new file mode 100644 index 0000000000..ba43e9a8a1 --- /dev/null +++ b/customizer/lib/index.js @@ -0,0 +1,4 @@ +module.exports = { + sass: require('./sass'), + js: require('./js') +} diff --git a/customizer/lib/js.js b/customizer/lib/js.js new file mode 100644 index 0000000000..e7763d1f88 --- /dev/null +++ b/customizer/lib/js.js @@ -0,0 +1,45 @@ +var empty = require('is-empty-object'); +var unique = require('array-uniq'); + +/** + * Creates an array of file paths that can be passed to `gulp.src()`. + * @param {Object} config - Customizer configuration file. + * @param {String[]} modules - Modules to include in the file list. + * @returns {String[]} Array of file paths. + */ +module.exports = function(config, modules) { + var files = ['core']; + var utils = ['mediaQuery']; + var libraries = []; + + if (empty(modules)) { + modules = Object.keys(config); + } + + for (var i in modules) { + var name = modules[i]; + + // Check if the module has JS files + if (config[name] && config[name].js) { + libraries.push(config[name].js); + + // Check if the module has dependencies + if (config[name].js_utils) { + utils = utils.concat(config[name].js_utils); + } + } + } + + // Prune duplicate entries from the list of utility files + utils = unique(utils).map(function(name) { + return 'util.' + name; + }); + + // Combine foundation.core.js, utilities, and plugins into one array + files = files.concat(utils, libraries); + + // Format the modules as paths + return files.map(function(file) { + return 'js/foundation.' + file + '.js'; + }); +} diff --git a/customizer/lib/sass.js b/customizer/lib/sass.js new file mode 100644 index 0000000000..1df0a10712 --- /dev/null +++ b/customizer/lib/sass.js @@ -0,0 +1,76 @@ +var empty = require('is-empty-object'); +var format = require('util').format; +var multiline = require('multiline').stripIndent; + +var SASS_TEMPLATE = multiline(function() {/* + @charset 'utf-8'; + + // Variables go here + %s + + // Core imports go here + @import 'foundation'; + @import 'motion-ui'; + + // Modules go here + %s + + // Motion UI goes here + @include motion-ui-transitions; + @include motion-ui-animations; +*/}); + +/** + * Generates an entry point Sass file with a custom list of CSS exports and Sass variables. + * @param {Object} config - Customizer configuration object. + * @param {String[]} modules - Modules to include CSS for. + * @param {Object} variables - Sass variable overrides to include. The key is the name of the variable, and the value is the value. + * @returns {String} Formatted Sass file. + */ +module.exports = function(config, modules, variables) { + var variableList = []; + var colorList = {}; + var exportList = ['@include foundation-global-styles;']; + + if (empty(modules)) { + modules = Object.keys(config); + } + + // Create variable overrides code + for (var i in variables) { + var name = i.replace('_', '-'); + if (name.match(/-color$/)) { + var key = name.replace('-color', ''); + colorList[key] = variables[i]; + } + else { + variableList.push(format('$%s: %s;', name, variables[i])); + } + } + + if (!empty(colorList)) { + variableList.push(createPaletteMap(colorList)); + } + + // Create module exports with @include + for (var i in modules) { + var name = modules[i]; + + if (config[name] && config[name].sass) { + exportList.push(format('@include foundation-%s;', config[name].sass)); + } + } + + return format(SASS_TEMPLATE, variableList.join('\n'), exportList.join('\n')) +} + +function createPaletteMap(colors) { + var output = '$foundation-palette: (%s\n);'; + var keys = ''; + + for (var i in colors) { + keys += format('\n %s: %s,', i, colors[i]); + } + + return format(output, keys); +} diff --git a/gulp/customizer.js b/gulp/customizer.js new file mode 100644 index 0000000000..e033244b58 --- /dev/null +++ b/gulp/customizer.js @@ -0,0 +1,115 @@ +var addSrc = require('gulp-add-src'); +var babel = require('gulp-babel'); +var concat = require('gulp-concat'); +var cssnano = require('gulp-cssnano'); +var customizer = require('../customizer/lib'); +var File = require('vinyl'); +var fs = require('fs'); +var gulp = require('gulp'); +var If = require('gulp-if'); +var path = require('path'); +var Readable = require('stream').Readable; +var replace = require('gulp-replace'); +var rename = require('gulp-rename'); +var rimraf = require('rimraf'); +var sass = require('gulp-sass'); +var source = require('vinyl-source-stream'); +var touch = require('touch'); +var uglify = require('gulp-uglify'); +var yaml = require('js-yaml').safeLoad; +var yargs = require('yargs'); +var zip = require('gulp-zip'); + +var ARGS = require('yargs').argv; +var FOUNDATION_VERSION = require('../package.json').version; +var OUTPUT_DIR = ARGS.output || 'custom-build'; +var CUSTOMIZER_CONFIG; +var MODULE_LIST; +var VARIABLE_LIST; + +// Load the configuration file for the customizer. It's a list of modules to load and Sass variables to override +gulp.task('customizer:loadConfig', function(done) { + fs.readFile('customizer/config.yml', function(err, data) { + var moduleListPath = ARGS.modules || '../customizer/complete'; + var moduleList = require(moduleListPath); + + CUSTOMIZER_CONFIG = yaml(data.toString()); + MODULE_LIST = moduleList.modules; + VARIABLE_LIST = moduleList.variables || {}; + done(); + }); +}); + +// Creates a Sass file from the module/variable list and creates foundation.css and foundation.min.css +gulp.task('customizer:sass', ['customizer:loadConfig'], function() { + var sassFile = customizer.sass(CUSTOMIZER_CONFIG, MODULE_LIST, VARIABLE_LIST); + + // Create a stream with our makeshift Sass file + var stream = new Readable({ objectMode: true }); + stream._read = function() {}; + stream.push(new File({ + path: 'foundation.scss', + contents: new Buffer(sassFile) + })); + stream.push(null); + + return stream + .pipe(sass({ + includePaths: [ + 'scss', + 'node_modules/motion-ui/src' + ] + })) + .pipe(gulp.dest(path.join(OUTPUT_DIR, 'css'))) + .pipe(cssnano()) + .pipe(rename('foundation.min.css')) + .pipe(gulp.dest(path.join(OUTPUT_DIR, 'css'))); +}); + +// Creates a Foundation JavaScript file from the module list, and also copies dependencies (jQuery, what-input) +gulp.task('customizer:javascript', ['customizer:loadConfig'], function() { + var jsPaths = customizer.js(CUSTOMIZER_CONFIG, MODULE_LIST); + + return gulp.src(jsPaths) + .pipe(babel()) + .pipe(concat('foundation.js')) + .pipe(gulp.dest(path.join(OUTPUT_DIR, 'js/vendor'))) + .pipe(uglify()) + .pipe(rename('foundation.min.js')) + .pipe(addSrc([ + 'node_modules/jquery/dist/jquery.js', + 'node_modules/what-input/what-input.js' + ])) + .pipe(gulp.dest(path.join(OUTPUT_DIR, 'js/vendor'))); +}); + +// Copies the boilerplate index.html to the custom download folder +gulp.task('customizer:html', ['customizer:loadConfig'], function() { + var rtlEnabled = VARIABLE_LIST['global-text-direction'] && VARIABLE_LIST['global-text-direction'] === 'rtl'; + + return gulp.src('customizer/index.html') + .pipe(If(rtlEnabled, replace('ltr', 'rtl'))) + .pipe(gulp.dest(OUTPUT_DIR)); +}); + +// Creates a custom build by: +// - Generating a CSS file +// - Generating a JS file +// - Copying the index.html file +// - Creating a blank app.css file +// - Creating an app.js file with Foundation initialization code +gulp.task('customizer', ['customizer:sass', 'customizer:javascript', 'customizer:html'], function(done) { + var outputFolder = path.dirname(OUTPUT_DIR); + var outputFileName = path.basename(OUTPUT_DIR); + + touch(path.join(OUTPUT_DIR, 'css/app.css')); + touch(path.join(OUTPUT_DIR, 'js/app.js')); + fs.writeFileSync(path.join(OUTPUT_DIR, 'js/app.js'), '$(document).foundation()\n'); + + gulp.src(path.join(OUTPUT_DIR, '/**/*')) + .pipe(zip(path.basename(outputFileName) + '.zip')) + .pipe(gulp.dest(outputFolder)) + .on('finish', function() { + rimraf(OUTPUT_DIR, done); + }); +}); diff --git a/lib/util-map.json b/lib/util-map.json deleted file mode 100644 index b181491432..0000000000 --- a/lib/util-map.json +++ /dev/null @@ -1,88 +0,0 @@ -{ - "accordion": [ - "foundation.util.keyboard.js", - "foundation.util.motion.js" - ], - "accordionMenu": [ - "foundation.util.keyboard.js", - "foundation.util.motion.js", - "foundation.util.nest.js" - ], - "drilldown": [ - "foundation.util.keyboard.js", - "foundation.util.motion.js", - "foundation.util.nest.js" - ], - "dropdownMenu": [ - "foundation.util.keyboard.js", - "foundation.util.motion.js", - "foundation.util.box.js", - "foundation.util.nest.js" - ], - "dropdown": [ - "foundation.util.keyboard.js", - "foundation.util.box.js", - "foundation.util.triggers.js" - ], - "interchange": [ - "foundation.util.triggers.js", - "foundation.util.timerAndImageLoader.js" - ], - "magellan": [ - "foundation.util.motion.js" - ], - "offcanvas": [ - "foundation.util.mediaQuery.js", - "foundation.util.motion.js", - "foundation.util.triggers.js" - ], - "orbit": [ - "foundation.util.motion.js", - "foundation.util.timerAndImageLoader.js", - "foundation.util.keyboard.js", - "foundation.util.touch.js" - ], - "responsiveMenu": [ - "foundation.util.triggers.js", - "foundation.util.mediaQuery.js", - "foundation.accordionMenu.js", - "foundation.drilldown.js", - "foundation.dropdownMenu.js", - "foundation.util.nest.js" - ], - "responsiveToggle": [ - "foundation.util.mediaQuery.js" - ], - "reveal": [ - "foundation.util.box.js", - "foundation.util.motion.js", - "foundation.util.triggers.js", - "foundation.util.mediaQuery.js" - ], - "slider": [ - "foundation.util.triggers.js", - "foundation.util.motion.js", - "foundation.util.keyboard.js", - "foundation.util.touch.js" - ], - "sticky": [ - "foundation.util.triggers.js", - "foundation.util.mediaQuery.js" - ], - "tabs": [ - "foundation.util.keyboard.js", - "foundation.util.timerAndImageLoader.js" - ], - "toggler": [ - "foundation.util.motion.js" - ], - "tooltip": [ - "foundation.util.box.js", - "foundation.util.triggers.js", - "foundation.util.mediaQuery.js", - "foundation.util.motion.js" - ], - "motion-ui": [ - "foundation.util.motion.js" - ] -} diff --git a/package.json b/package.json index 46a8a1750c..12e6256349 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ }, "license": "MIT", "devDependencies": { + "array-uniq": "^1.0.2", "babel-core": "^6.3.26", "babel-eslint": "^5.0.0", "babel-plugin-transform-es2015-arrow-functions": "^6.3.13", @@ -38,6 +39,7 @@ "corejs-typeahead": "corejavascript/typeahead.js", "foundation-docs": "zurb/foundation-docs", "gulp": "^3.8.10", + "gulp-add-src": "^0.2.0", "gulp-autoprefixer": "^2.3.1", "gulp-babel": "^6.1.1", "gulp-cache-bust": "^1.0.2", @@ -45,6 +47,7 @@ "gulp-cssnano": "^2.1.0", "gulp-eslint": "^2.0.0", "gulp-filter": "^3.0.1", + "gulp-if": "^2.0.0", "gulp-load-plugins": "^1.2.0", "gulp-mocha": "^2.2.0", "gulp-newer": "^1.1.0", @@ -58,10 +61,14 @@ "gulp-scss-lint": "^0.3.9", "gulp-sourcemaps": "^1.6.0", "gulp-uglify": "^1.1.0", + "gulp-zip": "^3.2.0", "inquirer": "^0.11.4", + "is-empty-object": "^1.1.1", + "js-yaml": "^3.5.4", "mocha": "^2.3.3", "mocha-phantomjs": "^4.0.2", "motion-ui": "^1.1.0", + "multiline": "^1.0.2", "octophant": "^1.0.0", "opener": "^1.4.1", "panini": "^1.1.1", @@ -72,7 +79,11 @@ "run-sequence": "^1.1.4", "sass-true": "^2.0.3", "sinon": "^1.17.3", - "supercollider": "^1.4.0" + "supercollider": "^1.4.0", + "touch": "^1.0.0", + "vinyl": "^1.1.1", + "vinyl-source-stream": "^1.1.0", + "yargs": "^4.2.0" }, "repository": { "type": "git",