mirror of
https://github.com/lloeki/umodule-js.git
synced 2025-12-06 02:24:41 +01:00
umodule.js: first public release
This commit is contained in:
commit
c375db3ddf
11 changed files with 306 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
*.js
|
||||||
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
[submodule "uspec"]
|
||||||
|
path = uspec
|
||||||
|
url = https://github.com/lloeki/uspec-js.git
|
||||||
24
LICENSE
Normal file
24
LICENSE
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
Copyright (c) 2013, Loic Nageleisen
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
* Neither the name of the copyright holder nor the
|
||||||
|
names of its contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
|
||||||
|
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
22
Makefile
Normal file
22
Makefile
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
all: release
|
||||||
|
|
||||||
|
release: umodule.js
|
||||||
|
|
||||||
|
%.js: %.coffee
|
||||||
|
coffee --compile $<
|
||||||
|
|
||||||
|
uspec_module.js: uspec/uspec.js wrapper
|
||||||
|
./wrap_module uspec $< > $@
|
||||||
|
|
||||||
|
run_spec.js: umodule.js uspec_module.js umodule_spec.js
|
||||||
|
cat $^ > $@
|
||||||
|
|
||||||
|
phantom_spec: run_spec.js
|
||||||
|
phantomjs $<
|
||||||
|
|
||||||
|
spec: phantom_spec
|
||||||
|
|
||||||
|
clean:
|
||||||
|
@rm -f *.js
|
||||||
|
|
||||||
|
.PHONY: release node_spec phantom_spec spec
|
||||||
65
README.mdown
Normal file
65
README.mdown
Normal file
|
|
@ -0,0 +1,65 @@
|
||||||
|
# µModule
|
||||||
|
|
||||||
|
µModule is a minimalist CommonJS module definition and requirement implementation, squarely
|
||||||
|
aimed at browsers.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Load `umodule.js` before any other:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<script src='/path/to/umodule.js'></script>
|
||||||
|
<script src='/path/to/modularized.js'></script>
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
Then in your application assets:
|
||||||
|
|
||||||
|
```coffee
|
||||||
|
# umodule.js is itsef a module and only exports `require` globally.
|
||||||
|
define = require('module').define
|
||||||
|
|
||||||
|
# define a module
|
||||||
|
define 'foo', (exports) ->
|
||||||
|
exports.hello = (w) -> 'hello, #{w}!'
|
||||||
|
```
|
||||||
|
|
||||||
|
Subsequently, in another asset:
|
||||||
|
|
||||||
|
```coffee
|
||||||
|
foo = require('foo')
|
||||||
|
|
||||||
|
console.log foo.hello()
|
||||||
|
```
|
||||||
|
|
||||||
|
There is no loader: all code is supposed to be loaded by an asset pipeline and
|
||||||
|
your typical user agent request. Therefore the goal is merely to isolate code
|
||||||
|
into modules and retrieve their exported interface in a given scope, using
|
||||||
|
CommonJS semantics. If you want a loader behavior, look into RequireJS.
|
||||||
|
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
Although available as a global, require is passed as a second argument,
|
||||||
|
shadowing the global and (NIY) allowing for relative imports:
|
||||||
|
|
||||||
|
```coffee
|
||||||
|
Module = require('module')
|
||||||
|
|
||||||
|
Module.define 'bob/alice', (exports, require) ->
|
||||||
|
foo = require 'foo'
|
||||||
|
exports.eve = -> foo.hello()
|
||||||
|
```
|
||||||
|
|
||||||
|
The module itself is passed as a third argument.
|
||||||
|
|
||||||
|
```coffee
|
||||||
|
Module.define 'dave', (exports, require, module) ->
|
||||||
|
my_exports = require module.id
|
||||||
|
```
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
Run with `make spec`. Testing depends on [uspec][uspec], included as a git submodule, and runs on phantomjs.
|
||||||
|
|
||||||
|
[uspec]: https://github.com/lloeki/uspec-js
|
||||||
39
umodule.coffee
Normal file
39
umodule.coffee
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
###
|
||||||
|
# umodule.js v0.5
|
||||||
|
# (c) 2013 Loic Nageleisen
|
||||||
|
# Licensed under 3-clause BSD
|
||||||
|
###
|
||||||
|
|
||||||
|
root = global ? window
|
||||||
|
|
||||||
|
|
||||||
|
require = (id) ->
|
||||||
|
target = Module.root
|
||||||
|
target = target[item] for item in id.split('/')
|
||||||
|
throw new Error("module not found: #{id}") if typeof target is 'undefined'
|
||||||
|
target.exports
|
||||||
|
|
||||||
|
|
||||||
|
class Module
|
||||||
|
constructor: (@id) ->
|
||||||
|
@exports = {}
|
||||||
|
|
||||||
|
@define: (target, name, block) ->
|
||||||
|
if arguments.length < 3
|
||||||
|
[target, name, block] = [Module.root, arguments...]
|
||||||
|
|
||||||
|
top = target
|
||||||
|
target = target[item] or= new Module(item) for item in name.split '/'
|
||||||
|
block.call(target, target.exports, target.require, target)
|
||||||
|
|
||||||
|
target
|
||||||
|
|
||||||
|
require: -> require()
|
||||||
|
|
||||||
|
|
||||||
|
Module.root = new Module('root')
|
||||||
|
Module.root.exports = root
|
||||||
|
Module.root.module = new Module('module')
|
||||||
|
Module.root.module.exports = Module
|
||||||
|
|
||||||
|
root.require = require
|
||||||
70
umodule.js
Normal file
70
umodule.js
Normal file
|
|
@ -0,0 +1,70 @@
|
||||||
|
// Generated by CoffeeScript 1.6.2
|
||||||
|
/*
|
||||||
|
# umodule.js v0.5
|
||||||
|
# (c) 2013 Loic Nageleisen
|
||||||
|
# Licensed under 3-clause BSD
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
var Module, require, root,
|
||||||
|
__slice = [].slice;
|
||||||
|
|
||||||
|
root = typeof global !== "undefined" && global !== null ? global : window;
|
||||||
|
|
||||||
|
require = function(id) {
|
||||||
|
var item, target, _i, _len, _ref;
|
||||||
|
|
||||||
|
target = Module.root;
|
||||||
|
_ref = id.split('/');
|
||||||
|
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||||
|
item = _ref[_i];
|
||||||
|
target = target[item];
|
||||||
|
}
|
||||||
|
if (typeof target === 'undefined') {
|
||||||
|
throw new Error("module not found: " + id);
|
||||||
|
}
|
||||||
|
return target.exports;
|
||||||
|
};
|
||||||
|
|
||||||
|
Module = (function() {
|
||||||
|
function Module(id) {
|
||||||
|
this.id = id;
|
||||||
|
this.exports = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
Module.define = function(target, name, block) {
|
||||||
|
var item, top, _i, _len, _ref, _ref1;
|
||||||
|
|
||||||
|
if (arguments.length < 3) {
|
||||||
|
_ref = [Module.root].concat(__slice.call(arguments)), target = _ref[0], name = _ref[1], block = _ref[2];
|
||||||
|
}
|
||||||
|
top = target;
|
||||||
|
_ref1 = name.split('/');
|
||||||
|
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
|
||||||
|
item = _ref1[_i];
|
||||||
|
target = target[item] || (target[item] = new Module(item));
|
||||||
|
}
|
||||||
|
block.call(target, target.exports, target.require, target);
|
||||||
|
return target;
|
||||||
|
};
|
||||||
|
|
||||||
|
Module.prototype.require = function() {
|
||||||
|
return require();
|
||||||
|
};
|
||||||
|
|
||||||
|
return Module;
|
||||||
|
|
||||||
|
})();
|
||||||
|
|
||||||
|
Module.root = new Module('root');
|
||||||
|
|
||||||
|
Module.root.exports = root;
|
||||||
|
|
||||||
|
Module.root.module = new Module('module');
|
||||||
|
|
||||||
|
Module.root.module.exports = Module;
|
||||||
|
|
||||||
|
root.require = require;
|
||||||
|
|
||||||
|
}).call(this);
|
||||||
70
umodule_spec.coffee
Normal file
70
umodule_spec.coffee
Normal file
|
|
@ -0,0 +1,70 @@
|
||||||
|
uspec = require('uspec')
|
||||||
|
describe = uspec.describe
|
||||||
|
pending = uspec.pending
|
||||||
|
assert = uspec.assert
|
||||||
|
assert_throws = uspec.assert_throws
|
||||||
|
Module = require('module')
|
||||||
|
|
||||||
|
|
||||||
|
describe 'require',
|
||||||
|
|
||||||
|
# CommonJS
|
||||||
|
|
||||||
|
'should be a function': ->
|
||||||
|
assert -> require instanceof Function
|
||||||
|
|
||||||
|
'should accept a module identifier': -> pending('how to test that?')
|
||||||
|
|
||||||
|
'should return the exported API of the foreign module': ->
|
||||||
|
Module.define 'foo', (exports) -> exports.bar = 'bar'
|
||||||
|
assert -> require('foo').bar isnt undefined
|
||||||
|
assert -> require('foo').bar == 'bar'
|
||||||
|
|
||||||
|
'should throw an error if the module cannot be returned': ->
|
||||||
|
assert_throws Error, -> require 'nonexistent/module'
|
||||||
|
|
||||||
|
|
||||||
|
describe 'Module',
|
||||||
|
|
||||||
|
# CommonJS
|
||||||
|
|
||||||
|
'should have an `export` var, that is an Object': ->
|
||||||
|
Module.define 'foo', (exports) ->
|
||||||
|
assert -> typeof exports == 'object'
|
||||||
|
|
||||||
|
'should have a `require` var, conformant with the spec': ->
|
||||||
|
Module.define 'foo', (exports, require) ->
|
||||||
|
assert -> typeof require == 'function'
|
||||||
|
|
||||||
|
'should have a `module` var': ->
|
||||||
|
Module.define 'foo', (exports, require, module) ->
|
||||||
|
assert -> module instanceof Module
|
||||||
|
assert -> module.id == 'foo'
|
||||||
|
|
||||||
|
'should export by adding to the exports var': ->
|
||||||
|
m = Module.define 'foo', (exports) -> exports.bar = 'bar'
|
||||||
|
assert -> m.exports.bar == 'bar'
|
||||||
|
|
||||||
|
'should have id property': ->
|
||||||
|
m = Module.define 'foo', ->
|
||||||
|
assert -> m.id isnt undefined
|
||||||
|
|
||||||
|
'should have its id set so that requiring it returns its exports': ->
|
||||||
|
m = Module.define 'foo', (exports) -> exports.bar = 'bar'
|
||||||
|
assert -> require(m.id) == m.exports
|
||||||
|
|
||||||
|
# Other
|
||||||
|
|
||||||
|
'should define a Module class': ->
|
||||||
|
assert -> Module isnt undefined
|
||||||
|
|
||||||
|
'should define a root module': ->
|
||||||
|
assert -> Module.root isnt undefined
|
||||||
|
assert -> Module.root.id == 'root'
|
||||||
|
|
||||||
|
|
||||||
|
results = uspec.run()
|
||||||
|
rc = if uspec.summary(results) then 0 else 1
|
||||||
|
|
||||||
|
phantom.exit(rc) unless typeof phantom is 'undefined'
|
||||||
|
process.exit(rc) unless typeof process is 'undefined'
|
||||||
1
uspec
Submodule
1
uspec
Submodule
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit ec516c106c35d2a66b124a2a5497e17d5377575b
|
||||||
5
wrap_module
Executable file
5
wrap_module
Executable file
|
|
@ -0,0 +1,5 @@
|
||||||
|
#!/bin/bash
|
||||||
|
sed -e "s/#MODULE_NAME#/$1/" -e "/#MODULE#/ {
|
||||||
|
r $2
|
||||||
|
d
|
||||||
|
}" wrapper
|
||||||
6
wrapper
Normal file
6
wrapper
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
(function () {
|
||||||
|
Module = require('module');
|
||||||
|
Module.define('#MODULE_NAME#', function (exports, require, module) {
|
||||||
|
#MODULE#
|
||||||
|
});
|
||||||
|
}).call(this);
|
||||||
Loading…
Add table
Add a link
Reference in a new issue