diff --git a/.gitignore b/.gitignore
index 965f8ef..b1c5951 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
components/
bower_components/
+node_modules/
diff --git a/Gruntfile.js b/Gruntfile.js
new file mode 100644
index 0000000..dafc0b6
--- /dev/null
+++ b/Gruntfile.js
@@ -0,0 +1,81 @@
+
+// -------------------------- grunt -------------------------- //
+
+module.exports = function( grunt ) {
+
+ var bowerJSON = grunt.file.readJSON('bower.json');
+
+ // get banner comment from draggabilly.js
+ var banner = ( function() {
+ var src = grunt.file.read('imagesloaded.js');
+ var re = new RegExp('^\\s*(?:\\/\\*[\\s\\S]*?\\*\\/)\\s*');
+ var matches = src.match( re );
+ return matches[0].replace( 'ImagesLoaded', 'ImagesLoaded PACKAGED' );
+ })();
+
+ grunt.initConfig({
+
+ concat: {
+ pkgd: {
+ // src will be set in package-sources task
+ src: [ bowerJSON.main ],
+ dest: 'imagesloaded.pkgd.js',
+ options: {
+ banner: banner
+ }
+ },
+ css: {
+ src: [ 'components/normalize-css/normalize.css', 'assets/*.css' ],
+ dest: 'build/styles.css'
+ }
+ },
+
+ uglify: {
+ pkgd: {
+ files: {
+ // 'build/imagesloaded.pkgd.min.js' will be set in bower-list-sources
+ },
+ options: {
+ banner: banner
+ }
+ }
+ },
+
+ copy: {
+ scripts: {
+ files: {
+ 'build/scripts.js': 'assets/scripts.js'
+ }
+ }
+ },
+
+ watch: {
+ content: {
+ files: [ 'assets/*', 'README.md' ],
+ tasks: [ 'concat', 'page', 'copy' ]
+ },
+ js: {
+ files: [ 'imagesloaded.js' ],
+ tasks: [ 'concat', 'uglify' ]
+ }
+ }
+
+ });
+
+ grunt.loadNpmTasks('grunt-contrib-concat');
+ grunt.loadNpmTasks('grunt-contrib-copy');
+ grunt.loadNpmTasks('grunt-contrib-uglify');
+ grunt.loadNpmTasks('grunt-contrib-watch');
+
+ // load all tasks in tasks/
+ grunt.loadTasks('tasks/');
+
+ grunt.registerTask( 'default', [
+ 'bower-list-sources',
+ 'concat',
+ 'uglify',
+ 'page',
+ 'copy'
+ ]);
+
+};
diff --git a/assets/page.html b/assets/page.html
new file mode 100644
index 0000000..e4462ca
--- /dev/null
+++ b/assets/page.html
@@ -0,0 +1,31 @@
+
+
+
+
+
+ Draggabilly
+
+
+
+
+
+
+
+
+
+
+
+ {{{ content }}}
+
+
+
+
+
+
+
+
+
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..0142c8a
--- /dev/null
+++ b/package.json
@@ -0,0 +1,27 @@
+{
+ "name": "imagesloaded",
+ "version": "3.0.0",
+ "description": "You images done yet or what?",
+ "main": "imagesloaded.js",
+ "dependencies": {},
+ "devDependencies": {
+ "grunt": "~0.4.0",
+ "grunt-contrib-concat": "~0.1.3",
+ "grunt-contrib-copy": "~0.4.0",
+ "grunt-contrib-jshint": "~0.1.1",
+ "grunt-contrib-uglify": "~0.1.2",
+ "grunt-contrib-watch": "~0.3.1",
+ "highlight.js": "~7.3.0",
+ "marked": "~0.2.8"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git://github.com/desandro/imagesloaded.git"
+ },
+ "keywords": [
+ "images",
+ "loaded",
+ "ui"
+ ],
+ "license": "MIT"
+}
diff --git a/tasks/bower-list-sources.js b/tasks/bower-list-sources.js
new file mode 100644
index 0000000..02831fe
--- /dev/null
+++ b/tasks/bower-list-sources.js
@@ -0,0 +1,45 @@
+/**
+ * bower-list-map task
+ */
+
+var spawn = require('child_process').spawn;
+
+module.exports = function( grunt ) {
+
+ 'use strict';
+
+ grunt.registerTask( 'bower-list-sources', function() {
+ var done = this.async();
+
+ // get map JSON from bower list --map
+ var childProc = spawn('bower', 'list --sources'.split(' ') );
+ var sourcesSrc = '';
+ childProc.stdout.setEncoding('utf8');
+ childProc.stdout.on('data', function( data ) {
+ sourcesSrc += data;
+ });
+
+ childProc.on('close', function() {
+ var bowerSources = JSON.parse( sourcesSrc );
+ // set bowerMap
+
+ // remove EventEmitter.min.js
+ var bowerJsSources = bowerSources['.js'].filter( function( src ) {
+ return src.indexOf('.min.js') === -1;
+ });
+ // add bower JS to JS collection
+ var jsSrcs = grunt.config.get('concat.pkgd.src');
+ jsSrcs = bowerJsSources.concat( jsSrcs );
+
+ // set config so it gets concat and uglified
+ grunt.config.set( 'concat.pkgd.src', jsSrcs );
+ grunt.config.set( 'uglify.pkgd.files', {
+ 'imagesloaded.pkgd.min.js': jsSrcs
+ });
+
+ done();
+ });
+
+ });
+
+};
diff --git a/tasks/page.js b/tasks/page.js
new file mode 100644
index 0000000..56de2e2
--- /dev/null
+++ b/tasks/page.js
@@ -0,0 +1,30 @@
+/**
+ * creates page for the World Wide Webinars
+**/
+
+
+var highlightjs = require('highlight.js');
+var marked = require('marked');
+
+// alias XML syntax highlighting as HTML
+highlightjs.LANGUAGES.html = highlightjs.LANGUAGES.xml;
+// alias js as javascript
+highlightjs.LANGUAGES.js = highlightjs.LANGUAGES.javascript;
+
+marked.setOptions({
+ highlight: function( code, lang ) {
+ return lang ? highlightjs.highlight( lang, code ).value : code;
+ }
+});
+
+module.exports = function( grunt ) {
+
+ grunt.registerTask( 'page', function() {
+ var readmeHTML = marked( grunt.file.read('README.md') );
+ var page = grunt.file.read('assets/page.html');
+ var content = page.replace( '{{{ content }}}', readmeHTML );
+
+ grunt.file.write( 'build/index.html', content );
+ });
+
+};