forked from davidchambers/string-format
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.js
More file actions
89 lines (78 loc) · 2.79 KB
/
index.js
File metadata and controls
89 lines (78 loc) · 2.79 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
void function(global) {
'use strict';
// ValueError :: String -> Error
function ValueError(message) {
var err = new Error(message);
err.name = 'ValueError';
return err;
}
// create :: Object -> String,*... -> String
function create(transformers) {
return function(template) {
var args = Array.prototype.slice.call(arguments, 1);
var idx = 0;
var state = 'UNDEFINED';
return template.replace(
/([{}])\1|[{](.*?)(?:!(.+?))?[}]/g,
function(match, literal, _key, xf) {
if (literal != null) {
return literal;
}
var key = _key;
if (key.length > 0) {
if (state === 'IMPLICIT') {
throw ValueError('cannot switch from ' +
'implicit to explicit numbering');
}
state = 'EXPLICIT';
} else {
if (state === 'EXPLICIT') {
throw ValueError('cannot switch from ' +
'explicit to implicit numbering');
}
state = 'IMPLICIT';
key = String(idx);
idx += 1;
}
// 1. Split the key into a lookup path.
// 2. If the first path component is not an index, prepend '0'.
// 3. Reduce the lookup path to a single result. If the lookup
// succeeds the result is a singleton array containing the
// value at the lookup path; otherwise the result is [].
// 4. Unwrap the result by reducing with '' as the default value.
var path = key.split('.');
var value = (/^\d+$/.test(path[0]) ? path : ['0'].concat(path))
.reduce(function(maybe, key) {
return maybe.reduce(function(_, x) {
return x != null && key in Object(x) ?
[typeof x[key] === 'function' ? x[key]() : x[key]] :
[];
}, []);
}, [args])
.reduce(function(_, x) { return x; }, '');
if (xf == null) {
return value;
} else if (Object.prototype.hasOwnProperty.call(transformers, xf)) {
return transformers[xf](value);
} else {
throw ValueError('no transformer named "' + xf + '"');
}
}
);
};
}
// format :: String,*... -> String
var format = create({});
// format.create :: Object -> String,*... -> String
format.create = create;
// format.extend :: Object,Object -> ()
format.extend = function(prototype, transformers) {
var $format = create(transformers);
prototype.format = function() {
var args = Array.prototype.slice.call(arguments);
args.unshift(this);
return $format.apply(global, args);
};
};
module.exports = format;
}.call(this, this);