Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Update readme, set 0.0.1 release.

  • Loading branch information...
commit 2a6af80630fa026dc37565d1f0aa24b56baa21d2 1 parent 4f33ffc
@jrburke authored
Showing with 387 additions and 15 deletions.
  1. +80 −14 README.md
  2. +1 −1  almond.js
  3. +306 −0 dist/almond-0.0.1.js
View
94 README.md
@@ -1,23 +1,89 @@
#almond
-An AMD a replacement loader for RequireJS that is only good for apps
-that use AMD modules and:
-
-* have already optimized all the modules into one file.
-* therefore, all modules have IDs and dependency arrays in their define() calls.
-* do not use loader plugins.
-* do not use requirejs.ready().
-* avoid circular dependencies.
-* do not use RequireJS multiversion support/contexts.
-* does not use require.toUrl() or require.nameToUrl().
-* does not use packages/packagePaths config.
-* no auto-detection of jQuery as a module, only uses the global jQuery object.
+An replacement [AMD](https://github.com/amdjs/amdjs-api/wiki/AMD) loader for
+[RequireJS](http://requirejs.org). It is a smaller "shim" loader, providing the
+minimal AMD API footprint that includes [loader plugin](http://requirejs.org/docs/plugins.html) support.
+
+## Why
+
+Some developers like to code modular JavaScript that uses the AMD API, but after doing an optimized build,
+they prefer to not include a full AMD loader like RequireJS, since they do not need all that functionality.
+Some use cases, like mobile, are very sensitive to file sizes.
+
+By including almond in the built file, there is no need for RequireJS.
+almond is **948 bytes** when minified with Closure Compiler and gzipped.
+
+Since it can support certain types of loader plugin-optimized resources, it is a great
+fit for a library that wants to use [text templates](http://requirejs.org/docs/api.html#text)
+or [CoffeeScript](https://github.com/jrburke/require-cs) as part of
+their project, but get a tiny download in one file after using the optimizer.
+
+If you are building a library, the wrap=true support in the RequireJS optimizer
+(available after the 0.26.0 release, [dev snapshot here](https://raw.github.com/jrburke/r.js/master/dist/r-20110821.js)),
+the optimized file can be wrapped in a closure, so the define/require AMD API does not
+escape the file. All users of the optimized file see is the global API you decide
+to export. See the usage section below for more details.
+
+So, you get great code cleanliness with AMD and the use of powerful loader plugins
+in a tiny wrapper that makes it easy for others to use your code even if they do not use AMD
+in their code.
+
+## Restrictions
+
+It is best used for libraries or apps that use an AMD loader and:
+
+* have already optimized all the modules into one file -- no dynamic code loading.
+* all modules have IDs and dependency arrays in their define() calls -- the default behavior of the RequireJS optimizer.
+* do not use requirejs.ready(). If you use explicit dependencies for all modules, and you place
+the optimized file in a script tag before the ending body tag, then this should not be a problem.
+* the modules avoid circular dependencies. Some kinds may work, but you will likely have to manually control
+the module listing order in the optimizer build profile.
+* do not use [RequireJS multiversion support/contexts](http://requirejs.org/docs/api.html#multiversion).
+* do not use require.toUrl() or require.nameToUrl().
+* do not use [packages/packagePaths config](http://requirejs.org/docs/api.html#packages).
What is supported:
-* dependencies with relative IDs
+* dependencies with relative IDs.
* define('id', {}) definitions.
* define(), require() and requirejs() calls.
+* loader plugins that can inline their resources into optimized files, and
+can access those inlined resources synchronously. The [text](http://requirejs.org/docs/api.html#text)
+and [CoffeeScript](https://github.com/jrburke/require-cs) plugins are two such plugins.
+
+
+## Current Release
+
+[Version 0.0.1](https://github.com/jrburke/almond/tree/master/dist/almond-0.0.1.js)
+
+## Usage
+
+[Download this snapshot of the optimizer](https://raw.github.com/jrburke/r.js/master/dist/r-20110821.js)
+to get a version of the optimizer with wrap=true support
+(release 0.27.0 or later will have wrap=true support).
+
+Download the current release of almond.js: [0.0.1](https://github.com/jrburke/almond/tree/master/dist/almond-0.0.1.js).
+
+Run the optimizer using [Node](http://nodejs.org) (also [works in Java](https://github.com/jrburke/r.js/blob/master/README.md)):
+
+ node r.js -o baseUrl=. name=path/to/almond.js include=main out=main-built.js wrap=true
+
+This assumes your top-level script file in your project is called main.js and the command
+above is run from the directory that contains main.js.
+
+The wrap=true will add this wrapper around the main-built.js contents (which will be minified by UglifyJS:
+
+ (function () {
+ //almond will be here
+ //main and its nested dependencies will be here
+ }());
+
+If you do not want that wrapper, leave off the wrap=true argument.
+
+These optimizer arguments can also be used in a build config object so it can be used
+in [runtime-generated server builds](https://github.com/jrburke/r.js/blob/master/build/tests/http/httpBuild.js).
-Still under development.
+## How to get help
+* Contact the [requirejs list](https://groups.google.com/group/requirejs).
+* Open issues in the [issue tracker](https://github.com/jrburke/almond/issues).
View
2  almond.js
@@ -1,5 +1,5 @@
/**
- * almond 0.0.0 Copyright (c) 2011, The Dojo Foundation All Rights Reserved.
+ * almond 0.0.1 Copyright (c) 2011, The Dojo Foundation All Rights Reserved.
* Available via the MIT or new BSD license.
* see: http://github.com/jrburke/almond for details
*/
View
306 dist/almond-0.0.1.js
@@ -0,0 +1,306 @@
+/**
+ * almond 0.0.1 Copyright (c) 2011, The Dojo Foundation All Rights Reserved.
+ * Available via the MIT or new BSD license.
+ * see: http://github.com/jrburke/almond for details
+ */
+/*jslint strict: false, plusplus: false */
+/*global setTimeout: false */
+
+var requirejs, require, define;
+(function () {
+
+ var defined = {},
+ aps = Array.prototype.slice,
+ ostring = Object.prototype.toString,
+ req;
+
+ function isFunction(it) {
+ return ostring.call(it) === "[object Function]";
+ }
+
+ function isArray(it) {
+ return ostring.call(it) === "[object Array]";
+ }
+
+ if (typeof define === "function" && define.amd) {
+ //If a define is already in play via another AMD loader,
+ //do not overwrite.
+ return;
+ }
+
+ /**
+ * Trims the . and .. from an array of path segments.
+ * It will keep a leading path segment if a .. will become
+ * the first path segment, to help with module name lookups,
+ * which act like paths, but can be remapped. But the end result,
+ * all paths that use this function should look normalized.
+ * NOTE: this method MODIFIES the input array.
+ * @param {Array} ary the array of path segments.
+ */
+ function trimDots(ary) {
+ var i, part;
+ for (i = 0; (part = ary[i]); i++) {
+ if (part === ".") {
+ ary.splice(i, 1);
+ i -= 1;
+ } else if (part === "..") {
+ if (i === 1 && (ary[2] === '..' || ary[0] === '..')) {
+ //End of the line. Keep at least one non-dot
+ //path segment at the front so it can be mapped
+ //correctly to disk. Otherwise, there is likely
+ //no path mapping for a path starting with '..'.
+ //This can still fail, but catches the most reasonable
+ //uses of ..
+ break;
+ } else if (i > 0) {
+ ary.splice(i - 1, 2);
+ i -= 2;
+ }
+ }
+ }
+ }
+
+ /**
+ * Given a relative module name, like ./something, normalize it to
+ * a real name that can be mapped to a path.
+ * @param {String} name the relative name
+ * @param {String} baseName a real name that the name arg is relative
+ * to.
+ * @returns {String} normalized name
+ */
+ function normalize(name, baseName) {
+ //Adjust any relative paths.
+ if (name && name.charAt(0) === ".") {
+ //If have a base name, try to normalize against it,
+ //otherwise, assume it is a top-level require that will
+ //be relative to baseUrl in the end.
+ if (baseName) {
+ //Convert baseName to array, and lop off the last part,
+ //so that . matches that "directory" and not name of the baseName's
+ //module. For instance, baseName of "one/two/three", maps to
+ //"one/two/three.js", but we want the directory, "one/two" for
+ //this normalization.
+ baseName = baseName.split("/");
+ baseName = baseName.slice(0, baseName.length - 1);
+
+ name = baseName.concat(name.split("/"));
+ trimDots(name);
+
+ name = name.join("/");
+ }
+ }
+ return name;
+ }
+
+ /**
+ * Helper function that creates a setExports function for a "module"
+ * CommonJS dependency. Do this here to avoid creating a closure that
+ * is part of a loop.
+ */
+ function makeSetExports(moduleObj) {
+ return function (exports) {
+ moduleObj.exports = exports;
+ };
+ }
+
+ function makeRequire(relName, forceSync) {
+ return function () {
+ //A version of a require function that passes a moduleName
+ //value for items that may need to
+ //look up paths relative to the moduleName
+ var args = aps.call(arguments, 0);
+ args.push(relName);
+ if (forceSync) {
+ args.push(true);
+ }
+ return req.apply(null, args);
+ };
+ }
+
+ function makeNormalize(relName) {
+ return function (name) {
+ return normalize(name, relName);
+ };
+ }
+
+ function makeLoad(depName) {
+ return function (value) {
+ defined[depName] = value;
+ };
+ }
+
+ /**
+ * Makes a name map, normalizing the name, and using a plugin
+ * for normalization if necessary. Grabs a ref to plugin
+ * too, as an optimization.
+ */
+ function makeMap(name, relName) {
+ var prefix, plugin,
+ index = name.indexOf('!');
+
+ if (index !== -1) {
+ prefix = normalize(name.substring(0, index), relName);
+ name = name.substring(index + 1);
+ plugin = defined[prefix];
+
+ //Normalize according
+ if (plugin && plugin.normalize) {
+ name = plugin.normalize(name, makeNormalize(relName));
+ } else {
+ name = normalize(name, relName);
+ }
+ } else {
+ name = normalize(name, relName);
+ }
+
+ return {
+ fullName: prefix ? prefix + '!' + name : name,
+ name: name,
+ prefix: prefix,
+ plugin: plugin
+ };
+ }
+
+ function main(name, deps, callback, relName) {
+ var args = [],
+ usingExports = false,
+ cjsModule, depName, i, ret, map;
+
+ //Use name if no relName
+ if (!relName) {
+ relName = name;
+ }
+
+ //Call the callback to define the module, if necessary.
+ if (isFunction(callback)) {
+ //Pull out the defined dependencies and pass the ordered
+ //values to the callback.
+ if (deps) {
+ for (i = 0; i < deps.length; i++) {
+ map = makeMap(deps[i], relName);
+ depName = map.fullName;
+
+ //Fast path CommonJS standard dependencies.
+ if (depName === "require") {
+ args[i] = makeRequire(name);
+ } else if (depName === "exports") {
+ //CommonJS module spec 1.1
+ args[i] = defined[name] = {};
+ usingExports = true;
+ } else if (depName === "module") {
+ //CommonJS module spec 1.1
+ cjsModule = args[i] = {
+ id: name,
+ uri: '',
+ exports: defined[name]
+ };
+ cjsModule.setExports = makeSetExports(cjsModule);
+ } else if (depName in defined) {
+ args[i] = defined[depName];
+ } else if (map.plugin) {
+ map.plugin.load(map.name, makeRequire(relName, true), makeLoad(depName), {});
+ args[i] = defined[depName];
+ } else {
+ args[i] = undefined;
+ }
+ }
+ }
+
+ ret = callback.apply(defined[name], args);
+
+ if (name) {
+ //If setting exports via "module" is in play,
+ //favor that over return value and exports. After that,
+ //favor a non-undefined return value over exports use.
+ if (cjsModule && cjsModule.exports !== undefined) {
+ ret = defined[name] = cjsModule.exports;
+ } else if (ret === undefined && usingExports) {
+ //exports already set the defined value.
+ ret = defined[name];
+ } else {
+ //Use the return value from the function.
+ defined[name] = ret;
+ }
+ }
+ } else if (name) {
+ //May just be an object definition for the module. Only
+ //worry about defining if have a module name.
+ defined[name] = callback;
+ }
+ }
+
+ requirejs = req = function (deps, callback, relName, forceSync) {
+ var moduleName, fullName, config;
+
+ //Determine if have config object in the call.
+ //Drop the config stuff on the ground.
+ if (!isArray(deps) && typeof deps !== "string") {
+ // deps is a config object
+ config = deps;
+ if (isArray(callback)) {
+ // Adjust args if there are dependencies
+ deps = callback;
+ callback = arguments[2];
+ } else {
+ deps = [];
+ }
+ }
+
+ if (typeof deps === "string") {
+
+ //Just return the module wanted. In this scenario, the
+ //second arg (if passed) is just the relModuleMap.
+ moduleName = deps;
+ relName = callback;
+
+ //Normalize module name, if it contains . or ..
+ fullName = makeMap(moduleName, relName).fullName;
+
+ if (!(fullName in defined)) {
+ throw new Error("Module name '" +
+ fullName +
+ "' has not been loaded.");
+ }
+ return defined[fullName];
+ }
+
+ //Simulate async callback;
+ if (forceSync) {
+ main(null, deps, callback, relName);
+ } else {
+ setTimeout(function () {
+ main(null, deps, callback, relName);
+ }, 15);
+ }
+
+ return req;
+ };
+
+ /**
+ * Support require.config() to make it easier to cooperate with other
+ * AMD loaders on globally agreed names.
+ */
+ req.config = function (config) {
+ return req(config);
+ };
+
+ /**
+ * Export require as a global, but only if it does not already exist.
+ */
+ if (typeof require === "undefined") {
+ require = req;
+ }
+
+ define = function (name, deps, callback) {
+
+ //This module may not have dependencies
+ if (!isArray(deps)) {
+ callback = deps;
+ deps = [];
+ }
+
+ main(name, deps, callback);
+ };
+
+ define.amd = {};
+}());
Please sign in to comment.
Something went wrong with that request. Please try again.