Make a SJW package out of UnitJS
This commit is contained in:
parent
56afea119a
commit
a888e1ce70
12 changed files with 362 additions and 303 deletions
5
CHANGELOG.md
Normal file
5
CHANGELOG.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
# Revision history for UnitJS
|
||||||
|
|
||||||
|
## 0.1.0 -- 2020-05-17
|
||||||
|
|
||||||
|
* Release UnitJS as a [SJW](https://git.marvid.fr/Tissevert/SJW) package still useable as a standalone script.
|
2
Makefile
2
Makefile
|
@ -1,6 +1,6 @@
|
||||||
BUILD_DIR=dist
|
BUILD_DIR=dist
|
||||||
TARGET=$(BUILD_DIR)/unit.js
|
TARGET=$(BUILD_DIR)/unit.js
|
||||||
SRC=$(wildcard *.js)
|
SRC=$(wildcard src/UnitJS/*.js)
|
||||||
TEMPLATE=unit.js.tpl
|
TEMPLATE=unit.js.tpl
|
||||||
|
|
||||||
all: $(TARGET)
|
all: $(TARGET)
|
||||||
|
|
43
README.md
Normal file
43
README.md
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
# UnitJS
|
||||||
|
|
||||||
|
UnitJS is a tiny Javascript framework to write web applications. It provides four essential modules to deal with asynchronous functions (technically, it's a monad obtained by currifying the CPS functions of Javascript like `setTimeout`), value caching, DOM manipulation and basic functional needs like composition or object projections.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### With [SJW](https://git.marvid.fr/Tissevert/SJW)
|
||||||
|
|
||||||
|
UnitJS comes as a SJW package. You can install it by copying the `src/` directory of this repository to your package database by issuing the following command from the current directory :
|
||||||
|
|
||||||
|
```
|
||||||
|
$ cp -r src/ ~/.sjw/unitJS
|
||||||
|
```
|
||||||
|
|
||||||
|
Then, using unitJS in your projects is as simple as writing :
|
||||||
|
|
||||||
|
```
|
||||||
|
import * as Async from UnitJS.Async;
|
||||||
|
```
|
||||||
|
|
||||||
|
in any module if you want to use the `Async` module for instance and compile your code using the `--include` option of `sjw` with package `unitJS` :
|
||||||
|
|
||||||
|
```
|
||||||
|
$ sjw -I unitJS your/code/src -o your/code/main.js
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that all modules have their path prefixed by a common `UnitJS` component and that SJW will only include the modules actually used in your code, not all of UnitJS.
|
||||||
|
|
||||||
|
### As a standalone JS script
|
||||||
|
|
||||||
|
If you don't want to or can't use SJW, it's still possible to use UnitJS by generating a single script that can then be loaded from your web page like this :
|
||||||
|
|
||||||
|
```
|
||||||
|
<script src="/path/to/unit.js"></script>
|
||||||
|
```
|
||||||
|
|
||||||
|
The file `unit.js` can be easily generated with `make`, which actually just calls the `unit.js.tpl` script. Note that you can still generate custom «partial» versions of `unit.js` if you don't use all of it by overriding the `SRC` variable of the `Makefile` like so :
|
||||||
|
|
||||||
|
```
|
||||||
|
make SRC="src/UnitJS/Dom.js src/UnitJS/Cache.js"
|
||||||
|
```
|
||||||
|
|
||||||
|
or by manually calling `./unit.js.tpl` with the files you want, like the `Makefile` does.
|
131
async.js
131
async.js
|
@ -1,131 +0,0 @@
|
||||||
function Async() {
|
|
||||||
return {
|
|
||||||
apply: apply,
|
|
||||||
bind: bind,
|
|
||||||
fail: fail,
|
|
||||||
http: http,
|
|
||||||
map: map,
|
|
||||||
parallel: parallel,
|
|
||||||
run: run,
|
|
||||||
sequence: sequence,
|
|
||||||
wait: wait,
|
|
||||||
wrap: wrap
|
|
||||||
};
|
|
||||||
|
|
||||||
function apply(f, x) {
|
|
||||||
return function(g) {
|
|
||||||
g(f(x));
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function bind() {
|
|
||||||
var m, steps, i;
|
|
||||||
if(arguments.length < 1) {
|
|
||||||
return wrap();
|
|
||||||
}
|
|
||||||
m = arguments[0];
|
|
||||||
steps = arguments;
|
|
||||||
i = 1;
|
|
||||||
return function(f) {
|
|
||||||
var step = function(x) {
|
|
||||||
if(i < steps.length) {
|
|
||||||
steps[i++](x)(step);
|
|
||||||
} else {
|
|
||||||
return f(x);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m(step);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function fail(message) {
|
|
||||||
return function(f) {
|
|
||||||
console.log(message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function map(mapper) {
|
|
||||||
return function(x) {
|
|
||||||
return function(f) {
|
|
||||||
f(mapper(x));
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function parallel() {
|
|
||||||
var threads = arguments;
|
|
||||||
var pending = threads.length;
|
|
||||||
var results = [];
|
|
||||||
var returned = [];
|
|
||||||
return function(f) {
|
|
||||||
var useResult = function(i) {
|
|
||||||
return function(x) {
|
|
||||||
if(!returned[i]) {
|
|
||||||
results[i] = x;
|
|
||||||
returned[i] = true;
|
|
||||||
pending--;
|
|
||||||
if(pending < 1) {
|
|
||||||
f(results);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
for(var i = 0; i < threads.length; i++) {
|
|
||||||
threads[i](useResult(i));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function run() {
|
|
||||||
var m;
|
|
||||||
if(arguments.length == 1) {
|
|
||||||
m = arguments[0];
|
|
||||||
} else {
|
|
||||||
m = sequence.apply(null, arguments);
|
|
||||||
}
|
|
||||||
m(function() {});
|
|
||||||
}
|
|
||||||
|
|
||||||
function sequence() {
|
|
||||||
var steps = arguments;
|
|
||||||
var i = 0;
|
|
||||||
return function(f) {
|
|
||||||
var step = function(x) {
|
|
||||||
if(i < steps.length) {
|
|
||||||
steps[i++](step);
|
|
||||||
} else {
|
|
||||||
f(x);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
step();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function wait(delay) {
|
|
||||||
return function(f) {
|
|
||||||
setTimeout(f, delay);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function wrap(x) {
|
|
||||||
return function(f) {
|
|
||||||
f(x);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function http(query) {
|
|
||||||
return function(f) {
|
|
||||||
var xhr = new XMLHttpRequest();
|
|
||||||
xhr.addEventListener('load', function() {
|
|
||||||
f(this);
|
|
||||||
});
|
|
||||||
xhr.open(query.method, query.url);
|
|
||||||
if(query.method == 'POST') {
|
|
||||||
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
|
|
||||||
}
|
|
||||||
xhr.send(query.body);
|
|
||||||
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
54
cache.js
54
cache.js
|
@ -1,54 +0,0 @@
|
||||||
function Cache() {
|
|
||||||
function Cache(loader) {
|
|
||||||
this.loader = loader;
|
|
||||||
this.loaded = {};
|
|
||||||
this.loading = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
Cache.prototype.get = function(key) {
|
|
||||||
return function(f) {
|
|
||||||
if(this.loaded[key] != undefined) {
|
|
||||||
f(this.loaded[key]);
|
|
||||||
} else {
|
|
||||||
this.startLoading(key);
|
|
||||||
this.loading[key].push(f);
|
|
||||||
this.loader(key)(this.store(key));
|
|
||||||
}
|
|
||||||
}.bind(this);
|
|
||||||
};
|
|
||||||
|
|
||||||
Cache.prototype.warmUp = function(key) {
|
|
||||||
if(this.loaded[key] == undefined) {
|
|
||||||
this.startLoading(key);
|
|
||||||
this.loader(key)(this.store(key));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Cache.prototype.startLoading = function(key) {
|
|
||||||
if(this.loading[key] == undefined) {
|
|
||||||
this.loading[key] = [];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Cache.prototype.store = function(key) {
|
|
||||||
return function(value) {
|
|
||||||
this.loaded[key] = value;
|
|
||||||
for(var i = 0; i < this.loading[key].length; i++) {
|
|
||||||
this.loading[key][i](value);
|
|
||||||
}
|
|
||||||
this.loading[key] = null;
|
|
||||||
}.bind(this);
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
|
||||||
make: make
|
|
||||||
};
|
|
||||||
|
|
||||||
function make(loader) {
|
|
||||||
var cache = new Cache(loader);
|
|
||||||
return {
|
|
||||||
get: cache.get.bind(cache),
|
|
||||||
warmUp: cache.warmUp.bind(cache)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
39
dom.js
39
dom.js
|
@ -1,39 +0,0 @@
|
||||||
function Dom() {
|
|
||||||
return {
|
|
||||||
clear: clear,
|
|
||||||
make: make
|
|
||||||
}
|
|
||||||
|
|
||||||
function clear(elem) {
|
|
||||||
while(elem.firstChild) {
|
|
||||||
elem.removeChild(elem.firstChild);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function make(tag, properties, children) {
|
|
||||||
var e = document.createElement(tag);
|
|
||||||
properties = properties || {};
|
|
||||||
children = children || [];
|
|
||||||
for(key in properties) {
|
|
||||||
var value = properties[key];
|
|
||||||
switch(key) {
|
|
||||||
case "class":
|
|
||||||
e.className = Array.isArray(value) ? value.join(' ') : value;
|
|
||||||
break;;
|
|
||||||
case "maxlength":
|
|
||||||
e.setAttribute("maxlength", value);
|
|
||||||
break;
|
|
||||||
case "onClick":
|
|
||||||
e.addEventListener("click", value);
|
|
||||||
break;;
|
|
||||||
default:
|
|
||||||
e[key] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for(var i = 0; i < children.length; i++) {
|
|
||||||
e.appendChild(children[i]);
|
|
||||||
}
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
74
fun.js
74
fun.js
|
@ -1,74 +0,0 @@
|
||||||
function Fun() {
|
|
||||||
return {
|
|
||||||
compare: compare,
|
|
||||||
compose: compose,
|
|
||||||
defined: defined,
|
|
||||||
id: id,
|
|
||||||
insert: insert,
|
|
||||||
map: map,
|
|
||||||
mapFilter: mapFilter,
|
|
||||||
of: of,
|
|
||||||
proj: proj
|
|
||||||
};
|
|
||||||
|
|
||||||
function compare(on) {
|
|
||||||
on = on || id;
|
|
||||||
return function(a, b) {
|
|
||||||
var va = on(a), vb = on(b);
|
|
||||||
return va < vb ? -1 : (va > vb ? 1 : 0)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function compose(f, g) {
|
|
||||||
return function() {
|
|
||||||
return f(g.apply(null, arguments));
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function defined(x) {
|
|
||||||
return x != undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
function id(x) {
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
function insert(obj, t, comparer, min, max) {
|
|
||||||
min = defined(min) ? min : 0;
|
|
||||||
max = defined(max) ? max : t.length;
|
|
||||||
comparer = comparer || compare();
|
|
||||||
if(max - min < 1) {
|
|
||||||
return min;
|
|
||||||
}
|
|
||||||
var avg = Math.floor((max + min) / 2);
|
|
||||||
if (compare(obj, t[avg]) < 0) {
|
|
||||||
return insert(obj, t, compare, min, avg);
|
|
||||||
} else {
|
|
||||||
return insert(obj, t, compare, avg+1, max);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function map(mapper, f) {
|
|
||||||
return function() {
|
|
||||||
var args = Array.prototype.map.call(arguments, mapper);
|
|
||||||
return f.apply(null, args);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function mapFilter(mapper, predicate) {
|
|
||||||
return function(array) {
|
|
||||||
return array.reduce(function(accumulator, elem) {
|
|
||||||
var v = mapper(elem);
|
|
||||||
return predicate(v) ? accumulator.concat(v) : accumulator;
|
|
||||||
}, []);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function of(o) {
|
|
||||||
return function(key) {return o[key];};
|
|
||||||
}
|
|
||||||
|
|
||||||
function proj(key) {
|
|
||||||
return function(o) {return o[key];};
|
|
||||||
}
|
|
||||||
}
|
|
128
src/UnitJS/Async.js
Normal file
128
src/UnitJS/Async.js
Normal file
|
@ -0,0 +1,128 @@
|
||||||
|
return {
|
||||||
|
apply: apply,
|
||||||
|
bind: bind,
|
||||||
|
fail: fail,
|
||||||
|
http: http,
|
||||||
|
map: map,
|
||||||
|
parallel: parallel,
|
||||||
|
run: run,
|
||||||
|
sequence: sequence,
|
||||||
|
wait: wait,
|
||||||
|
wrap: wrap
|
||||||
|
};
|
||||||
|
|
||||||
|
function apply(f, x) {
|
||||||
|
return function(g) {
|
||||||
|
g(f(x));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function bind() {
|
||||||
|
var m, steps, i;
|
||||||
|
if(arguments.length < 1) {
|
||||||
|
return wrap();
|
||||||
|
}
|
||||||
|
m = arguments[0];
|
||||||
|
steps = arguments;
|
||||||
|
i = 1;
|
||||||
|
return function(f) {
|
||||||
|
var step = function(x) {
|
||||||
|
if(i < steps.length) {
|
||||||
|
steps[i++](x)(step);
|
||||||
|
} else {
|
||||||
|
return f(x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m(step);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function fail(message) {
|
||||||
|
return function(f) {
|
||||||
|
console.log(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function map(mapper) {
|
||||||
|
return function(x) {
|
||||||
|
return function(f) {
|
||||||
|
f(mapper(x));
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function parallel() {
|
||||||
|
var threads = arguments;
|
||||||
|
var pending = threads.length;
|
||||||
|
var results = [];
|
||||||
|
var returned = [];
|
||||||
|
return function(f) {
|
||||||
|
var useResult = function(i) {
|
||||||
|
return function(x) {
|
||||||
|
if(!returned[i]) {
|
||||||
|
results[i] = x;
|
||||||
|
returned[i] = true;
|
||||||
|
pending--;
|
||||||
|
if(pending < 1) {
|
||||||
|
f(results);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
for(var i = 0; i < threads.length; i++) {
|
||||||
|
threads[i](useResult(i));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function run() {
|
||||||
|
var m;
|
||||||
|
if(arguments.length == 1) {
|
||||||
|
m = arguments[0];
|
||||||
|
} else {
|
||||||
|
m = sequence.apply(null, arguments);
|
||||||
|
}
|
||||||
|
m(function() {});
|
||||||
|
}
|
||||||
|
|
||||||
|
function sequence() {
|
||||||
|
var steps = arguments;
|
||||||
|
var i = 0;
|
||||||
|
return function(f) {
|
||||||
|
var step = function(x) {
|
||||||
|
if(i < steps.length) {
|
||||||
|
steps[i++](step);
|
||||||
|
} else {
|
||||||
|
f(x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
step();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function wait(delay) {
|
||||||
|
return function(f) {
|
||||||
|
setTimeout(f, delay);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function wrap(x) {
|
||||||
|
return function(f) {
|
||||||
|
f(x);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function http(query) {
|
||||||
|
return function(f) {
|
||||||
|
var xhr = new XMLHttpRequest();
|
||||||
|
xhr.addEventListener('load', function() {
|
||||||
|
f(this);
|
||||||
|
});
|
||||||
|
xhr.open(query.method, query.url);
|
||||||
|
if(query.method == 'POST') {
|
||||||
|
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
|
||||||
|
}
|
||||||
|
xhr.send(query.body);
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
52
src/UnitJS/Cache.js
Normal file
52
src/UnitJS/Cache.js
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
function Cache(loader) {
|
||||||
|
this.loader = loader;
|
||||||
|
this.loaded = {};
|
||||||
|
this.loading = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
Cache.prototype.get = function(key) {
|
||||||
|
return function(f) {
|
||||||
|
if(this.loaded[key] != undefined) {
|
||||||
|
f(this.loaded[key]);
|
||||||
|
} else {
|
||||||
|
this.startLoading(key);
|
||||||
|
this.loading[key].push(f);
|
||||||
|
this.loader(key)(this.store(key));
|
||||||
|
}
|
||||||
|
}.bind(this);
|
||||||
|
};
|
||||||
|
|
||||||
|
Cache.prototype.warmUp = function(key) {
|
||||||
|
if(this.loaded[key] == undefined) {
|
||||||
|
this.startLoading(key);
|
||||||
|
this.loader(key)(this.store(key));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Cache.prototype.startLoading = function(key) {
|
||||||
|
if(this.loading[key] == undefined) {
|
||||||
|
this.loading[key] = [];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Cache.prototype.store = function(key) {
|
||||||
|
return function(value) {
|
||||||
|
this.loaded[key] = value;
|
||||||
|
for(var i = 0; i < this.loading[key].length; i++) {
|
||||||
|
this.loading[key][i](value);
|
||||||
|
}
|
||||||
|
this.loading[key] = null;
|
||||||
|
}.bind(this);
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
make: make
|
||||||
|
};
|
||||||
|
|
||||||
|
function make(loader) {
|
||||||
|
var cache = new Cache(loader);
|
||||||
|
return {
|
||||||
|
get: cache.get.bind(cache),
|
||||||
|
warmUp: cache.warmUp.bind(cache)
|
||||||
|
};
|
||||||
|
}
|
36
src/UnitJS/Dom.js
Normal file
36
src/UnitJS/Dom.js
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
return {
|
||||||
|
clear: clear,
|
||||||
|
make: make
|
||||||
|
}
|
||||||
|
|
||||||
|
function clear(elem) {
|
||||||
|
while(elem.firstChild) {
|
||||||
|
elem.removeChild(elem.firstChild);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function make(tag, properties, children) {
|
||||||
|
var e = document.createElement(tag);
|
||||||
|
properties = properties || {};
|
||||||
|
children = children || [];
|
||||||
|
for(key in properties) {
|
||||||
|
var value = properties[key];
|
||||||
|
switch(key) {
|
||||||
|
case "class":
|
||||||
|
e.className = Array.isArray(value) ? value.join(' ') : value;
|
||||||
|
break;;
|
||||||
|
case "maxlength":
|
||||||
|
e.setAttribute("maxlength", value);
|
||||||
|
break;
|
||||||
|
case "onClick":
|
||||||
|
e.addEventListener("click", value);
|
||||||
|
break;;
|
||||||
|
default:
|
||||||
|
e[key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(var i = 0; i < children.length; i++) {
|
||||||
|
e.appendChild(children[i]);
|
||||||
|
}
|
||||||
|
return e;
|
||||||
|
}
|
72
src/UnitJS/Fun.js
Normal file
72
src/UnitJS/Fun.js
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
return {
|
||||||
|
compare: compare,
|
||||||
|
compose: compose,
|
||||||
|
defined: defined,
|
||||||
|
id: id,
|
||||||
|
insert: insert,
|
||||||
|
map: map,
|
||||||
|
mapFilter: mapFilter,
|
||||||
|
of: of,
|
||||||
|
proj: proj
|
||||||
|
};
|
||||||
|
|
||||||
|
function compare(on) {
|
||||||
|
on = on || id;
|
||||||
|
return function(a, b) {
|
||||||
|
var va = on(a), vb = on(b);
|
||||||
|
return va < vb ? -1 : (va > vb ? 1 : 0)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function compose(f, g) {
|
||||||
|
return function() {
|
||||||
|
return f(g.apply(null, arguments));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function defined(x) {
|
||||||
|
return x != undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
function id(x) {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
function insert(obj, t, comparer, min, max) {
|
||||||
|
min = defined(min) ? min : 0;
|
||||||
|
max = defined(max) ? max : t.length;
|
||||||
|
comparer = comparer || compare();
|
||||||
|
if(max - min < 1) {
|
||||||
|
return min;
|
||||||
|
}
|
||||||
|
var avg = Math.floor((max + min) / 2);
|
||||||
|
if (compare(obj, t[avg]) < 0) {
|
||||||
|
return insert(obj, t, compare, min, avg);
|
||||||
|
} else {
|
||||||
|
return insert(obj, t, compare, avg+1, max);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function map(mapper, f) {
|
||||||
|
return function() {
|
||||||
|
var args = Array.prototype.map.call(arguments, mapper);
|
||||||
|
return f.apply(null, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function mapFilter(mapper, predicate) {
|
||||||
|
return function(array) {
|
||||||
|
return array.reduce(function(accumulator, elem) {
|
||||||
|
var v = mapper(elem);
|
||||||
|
return predicate(v) ? accumulator.concat(v) : accumulator;
|
||||||
|
}, []);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function of(o) {
|
||||||
|
return function(key) {return o[key];};
|
||||||
|
}
|
||||||
|
|
||||||
|
function proj(key) {
|
||||||
|
return function(o) {return o[key];};
|
||||||
|
}
|
29
unit.js.tpl
29
unit.js.tpl
|
@ -2,15 +2,36 @@
|
||||||
|
|
||||||
indent()
|
indent()
|
||||||
{
|
{
|
||||||
local tabs="$(printf '\t%.0s' `seq 1 $1`)"
|
sed "s|^\(.\)|\t\1|"
|
||||||
sed "s|^|${tabs}|"
|
}
|
||||||
|
|
||||||
|
moduleName()
|
||||||
|
{
|
||||||
|
local fileName="${1##*/}"
|
||||||
|
printf "${fileName%.*}"
|
||||||
|
}
|
||||||
|
|
||||||
|
MODULES=""
|
||||||
|
for file in "${@}"
|
||||||
|
do
|
||||||
|
MODULES="${MODULES}:$(moduleName "${file}")"
|
||||||
|
done
|
||||||
|
MODULES="${MODULES#:}"
|
||||||
|
|
||||||
|
includeModule()
|
||||||
|
{
|
||||||
|
cat <<EOF
|
||||||
|
function $(moduleName "${1}")() {
|
||||||
|
$(cat "${1}" | indent)
|
||||||
|
}
|
||||||
|
EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
cat <<EOF
|
cat <<EOF
|
||||||
var unitJS = (function() {
|
var unitJS = (function() {
|
||||||
return {
|
return {
|
||||||
$(echo "${@}" | sed -e 's| |,\n|g' -e 's|\([^.\n]\+\)\.js|\u\1: \u\1|g' | indent 2)
|
$(printf "${MODULES}" | sed -e 's|:|,\n|g' -e 's|[^,\n]\+|&: &|g' | indent | indent)
|
||||||
};
|
};
|
||||||
$(cat "${@}" | indent 1)
|
$(for file in "${@}"; do includeModule "${file}"; done | indent)
|
||||||
})();
|
})();
|
||||||
EOF
|
EOF
|
||||||
|
|
Loading…
Reference in a new issue