]> iEval git - gruntmaster-page.git/blob - js/20-sprintf.js
Fix static mode
[gruntmaster-page.git] / js / 20-sprintf.js
1 (function(window) {
2 var re = {
3 not_string: /[^s]/,
4 number: /[dief]/,
5 text: /^[^\x25]+/,
6 modulo: /^\x25{2}/,
7 placeholder: /^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fiosuxX])/,
8 key: /^([a-z_][a-z_\d]*)/i,
9 key_access: /^\.([a-z_][a-z_\d]*)/i,
10 index_access: /^\[(\d+)\]/,
11 sign: /^[\+\-]/
12 }
13
14 function sprintf() {
15 var key = arguments[0], cache = sprintf.cache
16 if (!(cache[key] && cache.hasOwnProperty(key))) {
17 cache[key] = sprintf.parse(key)
18 }
19 return sprintf.format.call(null, cache[key], arguments)
20 }
21
22 sprintf.format = function(parse_tree, argv) {
23 var cursor = 1, tree_length = parse_tree.length, node_type = "", arg, output = [], i, k, match, pad, pad_character, pad_length, is_positive = true, sign = ""
24 for (i = 0; i < tree_length; i++) {
25 node_type = get_type(parse_tree[i])
26 if (node_type === "string") {
27 output[output.length] = parse_tree[i]
28 }
29 else if (node_type === "array") {
30 match = parse_tree[i] // convenience purposes only
31 if (match[2]) { // keyword argument
32 arg = argv[cursor]
33 for (k = 0; k < match[2].length; k++) {
34 if (!arg.hasOwnProperty(match[2][k])) {
35 throw new Error(sprintf("[sprintf] property '%s' does not exist", match[2][k]))
36 }
37 arg = arg[match[2][k]]
38 }
39 }
40 else if (match[1]) { // positional argument (explicit)
41 arg = argv[match[1]]
42 }
43 else { // positional argument (implicit)
44 arg = argv[cursor++]
45 }
46
47 if (get_type(arg) == "function") {
48 arg = arg()
49 }
50
51 if (re.not_string.test(match[8]) && (get_type(arg) != "number" && isNaN(arg))) {
52 throw new TypeError(sprintf("[sprintf] expecting number but found %s", get_type(arg)))
53 }
54
55 if (re.number.test(match[8])) {
56 is_positive = arg >= 0
57 }
58
59 switch (match[8]) {
60 case "b":
61 arg = arg.toString(2)
62 break
63 case "c":
64 arg = String.fromCharCode(arg)
65 break
66 case "d":
67 case "i":
68 arg = parseInt(arg, 10)
69 break
70 case "e":
71 arg = match[7] ? arg.toExponential(match[7]) : arg.toExponential()
72 break
73 case "f":
74 arg = match[7] ? parseFloat(arg).toFixed(match[7]) : parseFloat(arg)
75 break
76 case "o":
77 arg = arg.toString(8)
78 break
79 case "s":
80 arg = ((arg = String(arg)) && match[7] ? arg.substring(0, match[7]) : arg)
81 break
82 case "u":
83 arg = arg >>> 0
84 break
85 case "x":
86 arg = arg.toString(16)
87 break
88 case "X":
89 arg = arg.toString(16).toUpperCase()
90 break
91 }
92 if (re.number.test(match[8]) && (!is_positive || match[3])) {
93 sign = is_positive ? "+" : "-"
94 arg = arg.toString().replace(re.sign, "")
95 }
96 else {
97 sign = ""
98 }
99 pad_character = match[4] ? match[4] === "0" ? "0" : match[4].charAt(1) : " "
100 pad_length = match[6] - (sign + arg).length
101 pad = match[6] ? (pad_length > 0 ? str_repeat(pad_character, pad_length) : "") : ""
102 output[output.length] = match[5] ? sign + arg + pad : (pad_character === "0" ? sign + pad + arg : pad + sign + arg)
103 }
104 }
105 return output.join("")
106 }
107
108 sprintf.cache = {}
109
110 sprintf.parse = function(fmt) {
111 var _fmt = fmt, match = [], parse_tree = [], arg_names = 0
112 while (_fmt) {
113 if ((match = re.text.exec(_fmt)) !== null) {
114 parse_tree[parse_tree.length] = match[0]
115 }
116 else if ((match = re.modulo.exec(_fmt)) !== null) {
117 parse_tree[parse_tree.length] = "%"
118 }
119 else if ((match = re.placeholder.exec(_fmt)) !== null) {
120 if (match[2]) {
121 arg_names |= 1
122 var field_list = [], replacement_field = match[2], field_match = []
123 if ((field_match = re.key.exec(replacement_field)) !== null) {
124 field_list[field_list.length] = field_match[1]
125 while ((replacement_field = replacement_field.substring(field_match[0].length)) !== "") {
126 if ((field_match = re.key_access.exec(replacement_field)) !== null) {
127 field_list[field_list.length] = field_match[1]
128 }
129 else if ((field_match = re.index_access.exec(replacement_field)) !== null) {
130 field_list[field_list.length] = field_match[1]
131 }
132 else {
133 throw new SyntaxError("[sprintf] failed to parse named argument key")
134 }
135 }
136 }
137 else {
138 throw new SyntaxError("[sprintf] failed to parse named argument key")
139 }
140 match[2] = field_list
141 }
142 else {
143 arg_names |= 2
144 }
145 if (arg_names === 3) {
146 throw new Error("[sprintf] mixing positional and named placeholders is not (yet) supported")
147 }
148 parse_tree[parse_tree.length] = match
149 }
150 else {
151 throw new SyntaxError("[sprintf] unexpected placeholder")
152 }
153 _fmt = _fmt.substring(match[0].length)
154 }
155 return parse_tree
156 }
157
158 var vsprintf = function(fmt, argv, _argv) {
159 _argv = (argv || []).slice(0)
160 _argv.splice(0, 0, fmt)
161 return sprintf.apply(null, _argv)
162 }
163
164 /**
165 * helpers
166 */
167 function get_type(variable) {
168 return Object.prototype.toString.call(variable).slice(8, -1).toLowerCase()
169 }
170
171 function str_repeat(input, multiplier) {
172 return Array(multiplier + 1).join(input)
173 }
174
175 /**
176 * export to either browser or node.js
177 */
178 if (typeof exports !== "undefined") {
179 exports.sprintf = sprintf
180 exports.vsprintf = vsprintf
181 }
182 else {
183 window.sprintf = sprintf
184 window.vsprintf = vsprintf
185
186 if (typeof define === "function" && define.amd) {
187 define(function() {
188 return {
189 sprintf: sprintf,
190 vsprintf: vsprintf
191 }
192 })
193 }
194 }
195 })(typeof window === "undefined" ? this : window);
This page took 0.072629 seconds and 4 git commands to generate.