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