소스 검색

new lumbar-based solution for building fullcalendar submodules

Adam Shaw 13 년 전
부모
커밋
95c16e274f
7개의 변경된 파일185개의 추가작업 그리고 481개의 파일을 삭제
  1. 1 0
      .gitignore
  2. 106 111
      Gruntfile.js
  3. 0 312
      build/loader.js
  4. 1 0
      build/watch
  5. 0 57
      files.js
  6. 75 0
      lumbar.json
  7. 2 1
      package.json

+ 1 - 0
.gitignore

@@ -1,4 +1,5 @@
 build/out
+build/archive
 build/component
 dist
 

+ 106 - 111
Gruntfile.js

@@ -1,9 +1,7 @@
 
-var _ = require('underscore');
-
-
 module.exports = function(grunt) {
 
+	var _ = require('underscore');
 
 	// Load required NPM tasks.
 	// You must first run `npm install` in the project's root directory to get these dependencies.
@@ -12,197 +10,194 @@ module.exports = function(grunt) {
 	grunt.loadNpmTasks('grunt-contrib-copy');
 	grunt.loadNpmTasks('grunt-contrib-compress');
 	grunt.loadNpmTasks('grunt-contrib-clean');
+	grunt.loadNpmTasks('lumbar');
 
-
-	var fileIndex = require('./files.js'); // lists of source/dependency files
-	var loaderUtils = require('./build/loader.js');
-
-	// read config files, and combine into one "meta" object
+	// Parse config files
+	var lumbarConfig = grunt.file.readJSON('lumbar.json');
 	var packageConfig = grunt.file.readJSON('package.json');
 	var componentConfig = grunt.file.readJSON('component.json');
 	var pluginConfig = grunt.file.readJSON('fullcalendar.jquery.json');
-	var meta = _.extend({}, packageConfig, componentConfig, pluginConfig);
 	
-	// this will eventually get passed to grunt.initConfig
+	// This will eventually get passed to grunt.initConfig()
+	// Initialize multitasks...
 	var config = {
-		meta: meta, // do this primarily for templating (<%= %>)
-		concat: {}, // initialize multitasks...
+		concat: {},
 		uglify: {},
 		copy: {},
 		compress: {},
 		clean: {}
 	};
 
+	// Combine configs for the "meta" template variable (<%= meta.whatever %>)
+	config.meta = _.extend({}, packageConfig, componentConfig, pluginConfig);
 
-	/* Important Top-Level Tasks
-	----------------------------------------------------------------------------------------------------*/
-
-	grunt.registerTask('default', 'dist'); // what will be run with a plain old "grunt" command
+	// The "grunt" command with no arguments
+	grunt.registerTask('default', 'archive');
 
-	grunt.registerTask('dist', 'Create a distributable ZIP file', [
-		'clean:build',
-		'concat',
-		'uglify',
-		'copy:dependencies',
-		'copy:demos',
-		'copy:misc',
-		'compress'
-	]);
 
 
-	/* Concatenate Submodules
+	/* FullCalendar Modules
 	----------------------------------------------------------------------------------------------------*/
 
-	_.each(fileIndex.fullcalendar, function(submodule, name) {
-
-		if (submodule.js) {
-			config.concat[name + '-js'] = {
-				options: {
-					process: true // replace template variables
-				},
-				src: submodule.js,
-				dest: 'build/out/fullcalendar/' + name + '.js'
-			};
-		}
-
-		if (submodule.css) {
-			config.concat[name + '-css'] = {
-				options: {
-					process: true // replace template variables
-				},
-				src: submodule.css,
-				dest: 'build/out/fullcalendar/' + name + '.css'
-			};
-		}
+	grunt.registerTask('modules', 'Build the FullCalendar modules', [
+		'lumbar:build',
+		'concat:moduleVariables',
+		'uglify:modules'
+	]);
 
-		if (submodule.printCss) {
-			config.concat[name + '-print-css'] = {
-				options: {
-					process: true // replace template variables
-				},
-				src: submodule.printCss,
-				dest: 'build/out/fullcalendar/' + name + '.print.css'
-			};
+	// assemble modules
+	config.lumbar = {
+		build: {
+			build: 'lumbar.json',
+			output: 'build/out' // a directory. lumbar doesn't like trailing slash
 		}
+	};
 
-	});
-
-
-	/* Minify the JavaScript
-	----------------------------------------------------------------------------------------------------*/
+	// replace template variables (<%= %>), IN PLACE
+	config.concat.moduleVariables = {
+		options: {
+			process: true // replace
+		},
+		expand: true,
+		cwd: 'build/out/',
+		src: [ '*.js', '*.css', '!jquery*' ],
+		dest: 'build/out/'
+	};
 
-	config.uglify.all = {
+	// create minified versions (*.min.js)
+	config.uglify.modules = {
 		options: {
 			preserveComments: 'some' // keep comments starting with /*!
 		},
 		expand: true,
-		src: 'build/out/fullcalendar/*.js',
+		src: 'build/out/fullcalendar.js', // only do it for fullcalendar.js
 		ext: '.min.js'
 	}
 
+	config.clean.modules = 'build/out/*';
 
-	/* Copy Dependencies
+
+
+	/* Archive
 	----------------------------------------------------------------------------------------------------*/
 
-	config.copy.dependencies = {
+	grunt.registerTask('archive', 'Create a distributable ZIP archive', [
+		'clean:modules',
+		'clean:archive',
+		'modules',
+		'copy:archiveModules',
+		'copy:archiveDependencies',
+		'copy:archiveDemos',
+		'copy:archiveMisc',
+		'compress:archive'
+	]);
+
+	// copy FullCalendar modules into ./fullcalendar/ directory
+	config.copy.archiveModules = {
+		expand: true,
+		cwd: 'build/out/',
+		src: [ '*.js', '*.css', '!jquery*' ],
+		dest: 'build/archive/fullcalendar/'
+	};
+
+	// copy jQuery and jQuery UI into the ./jquery/ directory
+	config.copy.archiveDependencies = {
 		expand: true,
 		flatten: true,
 		src: [
-			fileIndex['jquery'].js,
-			fileIndex['jquery-ui'].js
+			// we want to retain the original filenames
+			lumbarConfig.modules['jquery'].scripts[0],
+			lumbarConfig.modules['jquery-ui'].scripts[0]
 		],
-		dest: 'build/out/jquery/'
+		dest: 'build/archive/jquery/'
 	};
 
-
-	/* Demos
-	----------------------------------------------------------------------------------------------------*/
-
-	config.copy.demos = {
+	// copy demo files into ./demos/ directory
+	config.copy.archiveDemos = {
 		options: {
-			// while copying demo files over, replace loader.js <script> with actual tags
 			processContentExclude: 'demos/*/**', // don't process anything more than 1 level deep (like assets)
 			processContent: function(content) {
-				content = content.replace(
-					/<script[^>]*loader\.js[^>]*?(?:data-modules=['"](.*?)['"])?><\/script>/i, // match loader.js tag and modules param
-					function(wholeMatch, moduleString) {
-						return loaderUtils.buildTags('..', fileIndex, moduleString, 'dist');
-					}
-				);
+				content = content.replace(/((?:src|href)=['"])([^'"]*)(['"])/g, function(m0, m1, m2, m3) {
+					return m1 + transformDemoPath(m2) + m3;
+				});
 				return content;
 			}
 		},
 		src: 'demos/**',
-		dest: 'build/out/'
+		dest: 'build/archive/'
 	};
 
+	// in demo HTML, rewrites paths to work in the archive
+	function transformDemoPath(path) {
+		path = path.replace('/build/out/jquery.js', '/' + lumbarConfig.modules['jquery'].scripts[0]);
+		path = path.replace('/build/out/jquery-ui.js', '/' + lumbarConfig.modules['jquery-ui'].scripts[0]);
+		path = path.replace('/lib/', '/jquery/');
+		path = path.replace('/build/out/', '/fullcalendar/');
+		path = path.replace('/fullcalendar.js', '/fullcalendar.min.js');
+		return path;
+	}
 
-	/* Copy Misc Files
-	----------------------------------------------------------------------------------------------------*/
-
-	config.copy.misc = {
-		src: "*.txt", // license and changelog
-		dest: 'build/out/'
+	// copy license and changelog
+	config.copy.archiveMisc = {
+		src: "*.txt",
+		dest: 'build/archive/'
 	};
 
-
-	/* Create ZIP file
-	----------------------------------------------------------------------------------------------------*/
-
-	config.compress.all = {
+	// create the ZIP
+	config.compress.archive = {
 		options: {
 			archive: 'dist/<%= meta.name %>-<%= meta.version %>.zip'
 		},
 		expand: true,
-		cwd: 'build/out/',
+		cwd: 'build/archive/',
 		src: '**',
 		dest: '<%= meta.name %>-<%= meta.version %>/' // have a top-level directory in the ZIP file
 	};
 
+	config.clean.archive = 'build/archive/*';
+	config.clean.dist = 'dist/*';
+
+
 
-	/* Bower Component
+	/* Bower Component (http://twitter.github.com/bower/)
 	----------------------------------------------------------------------------------------------------*/
-	// http://twitter.github.com/bower/
 
 	grunt.registerTask('component', 'Build the FullCalendar component for the Bower package manager', [
+		'clean:modules',
 		'clean:component',
-		'concat',
-		'uglify', // we want the minified JS in there
-		'copy:component',
-		'copy:component-readme',
-		'component.json'
+		'modules',
+		'copy:componentModules',
+		'copy:componentReadme',
+		'componentConfig'
 	]);
 
-	config.copy.component = {
+	// copy FullCalendar modules into component root
+	config.copy.componentModules = {
 		expand: true,
-		cwd: 'build/out/fullcalendar/',
-		src: '**',
+		cwd: 'build/out/',
+		src: [ '*.js', '*.css', '!jquery*' ],
 		dest: 'build/component/',
 	};
 
-	config.copy['component-readme'] = {
+	// copy the component-specific README
+	config.copy.componentReadme = {
 		src: 'build/component-readme.md',
 		dest: 'build/component/readme.md'
 	};
 
-	grunt.registerTask('component.json', function() {
+	// assemble the component's config from existing configs
+	grunt.registerTask('componentConfig', function() {
 		grunt.file.write(
 			'build/component/component.json',
 			JSON.stringify(
-				_.extend({}, pluginConfig, componentConfig), // combine the 2 configs
+				_.extend({}, pluginConfig, componentConfig), // combine 2 configs
 				null, // replacer
 				2 // indent
 			)
 		);
 	});
 
-
-	/* Clean Up Files
-	----------------------------------------------------------------------------------------------------*/
-
-	config.clean.build = 'build/out/*';
 	config.clean.component = 'build/component/*';
-	config.clean.dist = 'dist/*';
 
 
 

+ 0 - 312
build/loader.js

@@ -1,312 +0,0 @@
-(function() {
-
-
-/*
- * Modules that will be implicitly included
- */
-var DEFAULT_MODULES = [ 'jquery', 'jquery-ui', 'fullcalendar'/*the submodule*/ ];
-
-
-/*
- * Generate HTML script/link tags for loading resources.
- *
- * @param {String} root
- *     Path to the project or distributable's root directory from the HTML file running this script.
- *
- * @param {Object} fileIndex
- *     File location information for each module/submodule (everything in files.js).
- *
- * @param {String} moduleString
- *     A comma-separated string with names of additional modules to load.
- *
- * @param {string} [buildType]
- *     unspecified - use source JS/CSS files
- *     "concat" - use concatenated JS/CSS files
- *     "min" - use minified JS files, concatenated CSS files
- *     "dist" - use minified JS files, concatenated CSS files, and write paths for distributable
- */
-function buildTags(root, fileIndex, moduleString, buildType) {
-
-	var extraModuleNames = moduleString ? moduleString.split(',') : [];
-	var moduleNames = DEFAULT_MODULES.concat(extraModuleNames);
-
-	var jsPaths = [];
-	var cssPaths = [];
-	var printCssPaths = [];
-
-	var buildRoot;
-	if (buildType == 'dist') {
-		buildRoot = root; // in the distributable, the build root IS the root
-	}
-	else {
-		buildRoot = root + '/build/out';
-	}
-
-	each(moduleNames, function(moduleName) {
-
-		var submodule = fileIndex.fullcalendar[moduleName];
-		var module = submodule || fileIndex[moduleName];
-
-		if (module) {
-
-			var js = arrayify(module.js);
-			var css = arrayify(module.css);
-			var printCss = arrayify(module.printCss);
-
-			if (buildType && submodule) {
-				//
-				// paths for a "built" fullcalendar submodule
-				//
-				if (js.length) {
-					jsPaths.push(buildRoot + '/fullcalendar/' + moduleName + (buildType == 'concat' ? '' : '.min') + '.js');
-				}
-				if (css.length) {
-					cssPaths.push(buildRoot + '/fullcalendar/' + moduleName + '.css');
-				}
-				if (printCss.length) {
-					printCssPaths.push(buildRoot + '/fullcalendar/' + moduleName + '.print.css');
-				}
-			}
-			else if (buildType == 'dist' && !submodule) {
-				//
-				// 3rd-party paths in the distributable (they all go in jquery/ for now)
-				//
-				each(js, function(path) {
-					jsPaths.push(buildRoot + '/jquery/' + basename(path));
-				});
-				each(css, function(path) {
-					cssPaths.push(buildRoot + '/jquery/' + basename(path));
-				});
-				each(printCss, function(path) {
-					printCssPaths.push(buildRoot + '/jquery/' + basename(path));
-				});
-			}
-			else {
-				//
-				// paths for development
-				//
-				each(js, function(path) {
-					if (!/(intro|outro)\.js$/.test(path)) { // don't write syntactically incorrect intro.js/outro.js
-						jsPaths.push(root + '/' + path);
-					}
-				});
-				each(css, function(path) {
-					cssPaths.push(root + '/' + path);
-				});
-				each(printCss, function(path) {
-					printCssPaths.push(root + '/' + path);
-				});
-			}
-		}
-	});
-
-	return [].concat(
-		map(cssPaths, buildCssTag),
-		map(printCssPaths, buildPrintCssTag),
-		map(jsPaths, buildJsTag)
-		)
-		.join('\n');
-}
-
-
-/* When run in a browser...
-====================================================================================================*/
-
-
-/*
- * Writes script/link tags for resources.
- * Attributes can be added to loader.js's script tag to change its behavior:
- *    data-modules="..." (a comma-separated list of additional modules to load)
- *    data-debug="true"
- */
-function run() {
-
-	var thisScript = getLastScript();
-	var src = thisScript.getAttribute('src');
-	var cwd = dirname(src);
-	var projectRoot = dirname(cwd);
-	var moduleString = thisScript.getAttribute('data-modules');
-	var debugEnabled = !!thisScript.getAttribute('data-debug');
-	var buildType = getQueryStringVar('build');
-
-	if (debugEnabled) {
-		buildType = buildType || getCookieVar('build'); // fall back to cookie
-		initDebug(buildType);
-	}
-
-	loadScript(projectRoot + '/files.js', function(fileIndex) {
-		document.write(
-			buildTags(projectRoot, fileIndex, moduleString, buildType)
-		);
-	});
-}
-
-
-/*
- * Installs a build-switching <select> box at top left of screen.
- */
-function initDebug(currentBuildType) {
-	window.onload = function() {
-		var form = $(
-			"<form type='GET' style='position:absolute;top:5px;left:5px'>" +
-				"<select name='build'>" +
-					"<option value=''>src</option>" +
-					"<option value='concat'>concat</option>" +
-					"<option value='min'>min</option>" +
-				"</select>" +
-			"</form>"
-		);
-
-		var select = form.find('select')
-			.on('change', function() {
-				var val = select.val();
-				if (!val) {
-					select.remove(); // erases from resulting query string
-				}
-				document.cookie = 'build=' + val; // save cookie
-				form.submit();
-			})
-			.val(currentBuildType || '');
-
-		$('body').append(form);
-	};
-}
-
-
-/* HTML-building Utilities
-====================================================================================================*/
-
-
-function buildJsTag(path) {
-	return "<script src='" + path + "'></script>"
-}
-
-
-function buildCssTag(path) {
-	return "<link href='" + path + "' rel='stylesheet' />";
-}
-
-
-function buildPrintCssTag(path) {
-	return "<link href='" + path + "' rel='stylesheet' media='print' />";
-}
-
-
-/* DOM Utilities
-====================================================================================================*/
-
-/*
- * Loads an external JS file in the global scope, and calls `callback` when done.
- * If the JS file is a CommonJS module, the module's "exports" will be given to the callback.
- */
-function loadScript(path, callback) {
-	var funcName = ('_scriptCallback' + Math.random()).replace('.', '');
-	document.write("<script>exports = {}; module = { exports: exports }</script>");
-	document.write("<script src='" + path + "'></script>");
-	document.write("<script>" + funcName + "()</script>");
-	window[funcName] = function() {
-		removeLastScript();
-		removeLastScript();
-		removeLastScript();
-		var exports = module.exports;
-		delete window.module;
-		delete window.exports;
-		delete window[funcName];
-		if (callback) {
-			callback(exports);
-		}
-	};
-}
-
-
-function removeLastScript() {
-	var script = getLastScript();
-	script.parentNode.removeChild(script);
-}
-
-
-function getLastScript() {
-	var scripts = document.getElementsByTagName('script');
-	return scripts[scripts.length - 1];
-}
-
-
-function getQueryStringVar(name) {
-	var qs = extractQueryString(window.location.href);
-	var match = new RegExp(name + '=([^&]*)').exec(qs);
-	if (match) {
-		return match[1];
-	}
-}
-
-
-function getCookieVar(name) {
-	var match = new RegExp(name + '=([^;]*)').exec(document.cookie);
-	if (match) {
-		return match[1];
-	}
-}
-
-
-/* File Path Utilities
-====================================================================================================*/
-
-
-function basename(path) {
-	var match = /.*\/(.*)/.exec(path);
-	return match ? match[1] : path;
-}
-
-
-function dirname(path) {
-	var match = /(.*)\//.exec(path);
-	return match ? match[1] : '.';
-}
-
-
-function extractQueryString(url) {
-	var match = /\?(.*)/.exec(url);
-	return match ? match[1] : '';
-}
-
-
-/* Language Utilities
-====================================================================================================*/
-
-
-function each(a, f) {
-	for (var i=0; i<a.length; i++) {
-		f(a[i], i);
-	}
-}
-
-
-function map(a, f) {
-	var res = [];
-	for (var i=0; i<a.length; i++) {
-		res.push(
-			f(a[i], i)
-		);
-	}
-	return res;
-}
-
-
-function arrayify(a) {
-	return [].concat(a || []);
-}
-
-
-/* RUN!
-====================================================================================================*/
-
-
-if (typeof exports != 'undefined') {
-	exports.buildTags = buildTags; // if we are running in Node, provide the buildTags() utility
-}
-else {
-	run(); // we are running in a web browser
-}
-
-
-})();

+ 1 - 0
build/watch

@@ -0,0 +1 @@
+"`dirname $0`/../node_modules/lumbar/bin/lumbar" watch "$@" "`dirname $0`/out"

+ 0 - 57
files.js

@@ -1,57 +0,0 @@
-
-module.exports = {
-
-	jquery: {
-		js: 'lib/jquery-1.9.1.min.js'
-	},
-
-	'jquery-ui': {
-		js: 'lib/jquery-ui-1.10.1.custom.min.js'
-	},
-
-	fullcalendar: {
-
-		fullcalendar: {
-			js: [
-				'src/intro.js',
-				'src/defaults.js',
-				'src/main.js',
-				'src/Calendar.js',
-				'src/Header.js',
-				'src/EventManager.js',
-				'src/date_util.js',
-				'src/util.js',
-				'src/basic/MonthView.js',
-				'src/basic/BasicWeekView.js',
-				'src/basic/BasicDayView.js',
-				'src/basic/BasicView.js',
-				'src/basic/BasicEventRenderer.js',
-				'src/agenda/AgendaWeekView.js',
-				'src/agenda/AgendaDayView.js',
-				'src/agenda/AgendaView.js',
-				'src/agenda/AgendaEventRenderer.js',
-				'src/common/View.js',
-				'src/common/DayEventRenderer.js',
-				'src/common/SelectionManager.js',
-				'src/common/OverlayManager.js',
-				'src/common/CoordinateGrid.js',
-				'src/common/HoverListener.js',
-				'src/common/HorizontalPositionCache.js',
-				'src/outro.js'
-			],
-			css: [
-				'src/main.css',
-				'src/common/common.css',
-				'src/basic/basic.css',
-				'src/agenda/agenda.css'
-			],
-			printCss: 'src/common/print.css'
-		},
-
-		gcal: {
-			js: 'src/gcal/gcal.js'
-		}
-
-	}
-
-};

+ 75 - 0
lumbar.json

@@ -0,0 +1,75 @@
+{
+  "scope": "none",
+  "packages": {
+    "dependencies": {
+      "modules": [
+        "jquery",
+        "jquery-ui"
+      ]
+    },
+    "fullcalendar": {
+      "modules": [
+        "fullcalendar",
+        "fullcalendar.print",
+        "gcal"
+      ]
+    }
+  },
+  "modules": {
+    "jquery": {
+      "scripts": [
+        "lib/jquery-1.9.1.min.js"
+      ]
+    },
+    "jquery-ui": {
+      "scripts": [
+        "lib/jquery-ui-1.10.1.custom.min.js"
+      ]
+    },
+    "fullcalendar": {
+      "scripts": [
+        "src/intro.js",
+        "src/defaults.js",
+        "src/main.js",
+        "src/Calendar.js",
+        "src/Header.js",
+        "src/EventManager.js",
+        "src/date_util.js",
+        "src/util.js",
+        "src/basic/MonthView.js",
+        "src/basic/BasicWeekView.js",
+        "src/basic/BasicDayView.js",
+        "src/basic/BasicView.js",
+        "src/basic/BasicEventRenderer.js",
+        "src/agenda/AgendaWeekView.js",
+        "src/agenda/AgendaDayView.js",
+        "src/agenda/AgendaView.js",
+        "src/agenda/AgendaEventRenderer.js",
+        "src/common/View.js",
+        "src/common/DayEventRenderer.js",
+        "src/common/SelectionManager.js",
+        "src/common/OverlayManager.js",
+        "src/common/CoordinateGrid.js",
+        "src/common/HoverListener.js",
+        "src/common/HorizontalPositionCache.js",
+        "src/outro.js"
+      ],
+      "styles": [
+        "src/main.css",
+        "src/common/common.css",
+        "src/basic/basic.css",
+        "src/agenda/agenda.css"
+      ]
+    },
+    "fullcalendar.print": {
+      "styles": [
+        "src/common/print.css"
+      ]
+    },
+    "gcal": {
+      "scripts": [
+        "src/gcal/gcal.js"
+      ]
+    }
+  }
+}

+ 2 - 1
package.json

@@ -6,6 +6,7 @@
     "grunt-contrib-uglify": "~0.1.1",
     "grunt-contrib-copy": "~0.4.0",
     "grunt-contrib-compress": "~0.4.0",
-    "grunt-contrib-clean": "~0.4.0"
+    "grunt-contrib-clean": "~0.4.0",
+    "lumbar": "~2.0.0-beta19"
   }
 }