forked from sheetjs/sheetjs
version bump 0.9.1: dateNF + sign
- dateNF option for default date format override - general format renders undefined/null as empty string - ignore text elements when searching for decimal point - bubble negative sign to the front when format starts with text - fixes for eslint + closure - updated frac to 1.0.6 Issues: - fixes #10 h/t @adamgundy @SegFaultx64 @RichardCzechowski - fixes #15 h/t @wilg - fixes #25 h/t @dougschiller - fixes #26 h/t @rjmcguire
This commit is contained in:
parent
ecb4515847
commit
f335d310ac
19
.eslintrc
Normal file
19
.eslintrc
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"env": { "shared-node-browser":true },
|
||||
"globals": {},
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 3,
|
||||
},
|
||||
"plugins": [ "html", "json" ],
|
||||
"rules": {
|
||||
"no-use-before-define": [ 1, {
|
||||
"functions":false, "classes":true, "variables":false
|
||||
}],
|
||||
"no-bitwise": 0,
|
||||
"curly": 0,
|
||||
"comma-style": [ 2, "last" ],
|
||||
"no-trailing-spaces": 2,
|
||||
"semi": [ 2, "always" ],
|
||||
"comma-dangle": [ 2, "never" ]
|
||||
}
|
||||
}
|
23
.gitignore
vendored
23
.gitignore
vendored
@ -1,7 +1,28 @@
|
||||
node_modules/
|
||||
node_modules
|
||||
misc/coverage.html
|
||||
.vocrc
|
||||
v8.log
|
||||
tmp
|
||||
*.tgz
|
||||
*.[tT][xX][tT]
|
||||
*.[cC][sS][vV]
|
||||
*.[dD][iIbB][fF]
|
||||
*.[pP][rR][nN]
|
||||
*.[sS][lL][kK]
|
||||
*.socialcalc
|
||||
*.[xX][lL][sSwWcC]
|
||||
*.[xX][lL][sS][xXmMbB]
|
||||
*.[oO][dD][sS]
|
||||
*.[fF][oO][dD][sS]
|
||||
*.[xX][mM][lL]
|
||||
*.[uU][oO][sS]
|
||||
*.[wW][kKqQbB][S1234567890]
|
||||
*.[qQ][pP][wW]
|
||||
*.123
|
||||
*.htm
|
||||
*.html
|
||||
*.sheetjs
|
||||
*.exe
|
||||
perf.log
|
||||
ctest/test.js
|
||||
ctest/sauce*
|
||||
|
30
.npmignore
30
.npmignore
@ -1,8 +1,33 @@
|
||||
test/
|
||||
ctest/
|
||||
index.html
|
||||
misc/
|
||||
node_modules/
|
||||
misc/coverage.html
|
||||
node_modules
|
||||
*.tgz
|
||||
_book
|
||||
book.json
|
||||
tmp
|
||||
*.[tT][xX][tT]
|
||||
*.[cC][sS][vV]
|
||||
*.[dD][iIbB][fF]
|
||||
*.[pP][rR][nN]
|
||||
*.[sS][lL][kK]
|
||||
*.socialcalc
|
||||
*.[xX][lL][sSwWcC]
|
||||
*.[xX][lL][sS][xXmMbB]
|
||||
*.[oO][dD][sS]
|
||||
*.[fF][oO][dD][sS]
|
||||
*.[xX][mM][lL]
|
||||
*.[uU][oO][sS]
|
||||
*.[wW][kKqQbB][S1234567890]
|
||||
*.[qQ][pP][wW]
|
||||
*.123
|
||||
*.htm
|
||||
*.html
|
||||
*.sheetjs
|
||||
*.exe
|
||||
.gitignore
|
||||
.eslintrc
|
||||
.jshintrc
|
||||
Makefile
|
||||
.npmignore
|
||||
@ -14,4 +39,3 @@ bits/
|
||||
.vocrc
|
||||
v8.log
|
||||
perf.log
|
||||
ssf*.tgz
|
||||
|
23
Makefile
23
Makefile
@ -1,5 +1,8 @@
|
||||
SHELL=/bin/bash
|
||||
LIB=ssf
|
||||
REQS=
|
||||
ADDONS=
|
||||
AUXTARGETS=
|
||||
CMDS=bin/ssf.njs
|
||||
HTMLLINT=
|
||||
|
||||
@ -11,6 +14,7 @@ FLOWAUX=$(patsubst %.js,%.flow.js,$(AUXTARGETS))
|
||||
AUXSCPTS=
|
||||
FLOWTGTS=$(TARGET) $(AUXTARGETS) $(AUXSCPTS)
|
||||
UGLIFYOPTS=--support-ie8
|
||||
CLOSURE=/usr/local/lib/node_modules/google-closure-compiler/compiler.jar
|
||||
|
||||
## Main Targets
|
||||
|
||||
@ -37,8 +41,8 @@ clean: ## Remove targets and build artifacts
|
||||
test mocha: ## Run test suite
|
||||
mocha -R spec -t 30000
|
||||
|
||||
.PHONY: test_min
|
||||
test_min:
|
||||
.PHONY: test_misc
|
||||
test_misc:
|
||||
MINTEST=1 npm test
|
||||
|
||||
.PHONY: travis
|
||||
@ -47,18 +51,29 @@ travis: ## Run test suite with minimal output
|
||||
|
||||
.PHONY: ctest
|
||||
ctest:
|
||||
browserify -t brfs test/{exp,fraction,general,implied,oddities,utilities,comma}.js > ctest/test.js
|
||||
browserify -t brfs test/{dateNF,exp,fraction,general,implied,oddities,utilities,comma}.js > ctest/test.js
|
||||
|
||||
.PHONY: ctestserv
|
||||
ctestserv: ## Start a test server on port 8000
|
||||
@cd ctest && python -mSimpleHTTPServer
|
||||
|
||||
|
||||
## Code Checking
|
||||
|
||||
.PHONY: lint
|
||||
lint: $(TARGET) $(AUXTARGETS) ## Run jshint and jscs checks
|
||||
lint: $(TARGET) $(AUXTARGETS) ## Run eslint checks
|
||||
@eslint --ext .js,.njs,.json,.html,.htm $(TARGET) $(AUXTARGETS) $(CMDS) $(HTMLLINT) package.json bower.json
|
||||
if [ -e $(CLOSURE) ]; then java -jar $(CLOSURE) $(REQS) $(FLOWTARGET) --jscomp_warning=reportUnknownTypes >/dev/null; fi
|
||||
|
||||
.PHONY: old-lint
|
||||
old-lint: $(TARGET) $(AUXTARGETS) ## Run jshint and jscs checks
|
||||
@jshint --show-non-errors $(TARGET) $(AUXTARGETS)
|
||||
@jshint --show-non-errors test/
|
||||
@jshint --show-non-errors $(CMDS)
|
||||
@jshint --show-non-errors package.json
|
||||
@jshint --show-non-errors --extract=always $(HTMLLINT)
|
||||
@jscs $(TARGET) $(AUXTARGETS)
|
||||
if [ -e $(CLOSURE) ]; then java -jar $(CLOSURE) $(REQS) $(FLOWTARGET) --jscomp_warning=reportUnknownTypes >/dev/null; fi
|
||||
|
||||
.PHONY: flow
|
||||
flow: lint ## Run flow checker
|
||||
|
@ -1,4 +1,4 @@
|
||||
# SSF
|
||||
# [SheetJS SSF](http://sheetjs.com)
|
||||
|
||||
ssf (SpreadSheet Format) is a pure-JS library to format data using ECMA-376
|
||||
spreadsheet format codes (used in popular spreadsheet software packages).
|
||||
|
@ -1 +1 @@
|
||||
SSF.version = '0.9.0';
|
||||
SSF.version = '0.9.1';
|
||||
|
@ -1,35 +1,3 @@
|
||||
var table_fmt = {
|
||||
/*::[*/0/*::]*/: 'General',
|
||||
/*::[*/1/*::]*/: '0',
|
||||
/*::[*/2/*::]*/: '0.00',
|
||||
/*::[*/3/*::]*/: '#,##0',
|
||||
/*::[*/4/*::]*/: '#,##0.00',
|
||||
/*::[*/9/*::]*/: '0%',
|
||||
/*::[*/10/*::]*/: '0.00%',
|
||||
/*::[*/11/*::]*/: '0.00E+00',
|
||||
/*::[*/12/*::]*/: '# ?/?',
|
||||
/*::[*/13/*::]*/: '# ??/??',
|
||||
/*::[*/14/*::]*/: 'm/d/yy',
|
||||
/*::[*/15/*::]*/: 'd-mmm-yy',
|
||||
/*::[*/16/*::]*/: 'd-mmm',
|
||||
/*::[*/17/*::]*/: 'mmm-yy',
|
||||
/*::[*/18/*::]*/: 'h:mm AM/PM',
|
||||
/*::[*/19/*::]*/: 'h:mm:ss AM/PM',
|
||||
/*::[*/20/*::]*/: 'h:mm',
|
||||
/*::[*/21/*::]*/: 'h:mm:ss',
|
||||
/*::[*/22/*::]*/: 'm/d/yy h:mm',
|
||||
/*::[*/37/*::]*/: '#,##0 ;(#,##0)',
|
||||
/*::[*/38/*::]*/: '#,##0 ;[Red](#,##0)',
|
||||
/*::[*/39/*::]*/: '#,##0.00;(#,##0.00)',
|
||||
/*::[*/40/*::]*/: '#,##0.00;[Red](#,##0.00)',
|
||||
/*::[*/45/*::]*/: 'mm:ss',
|
||||
/*::[*/46/*::]*/: '[h]:mm:ss',
|
||||
/*::[*/47/*::]*/: 'mmss.0',
|
||||
/*::[*/48/*::]*/: '##0.0E+0',
|
||||
/*::[*/49/*::]*/: '@',
|
||||
/*::[*/56/*::]*/: '"上午/下午 "hh"時"mm"分"ss"秒 "',
|
||||
/*::[*/65535/*::]*/: 'General'
|
||||
};
|
||||
var days/*:Array<Array<string> >*/ = [
|
||||
['Sun', 'Sunday'],
|
||||
['Mon', 'Monday'],
|
||||
|
35
bits/25_table.js
Normal file
35
bits/25_table.js
Normal file
@ -0,0 +1,35 @@
|
||||
function init_table(t/*:any*/) {
|
||||
t[0]= 'General';
|
||||
t[1]= '0';
|
||||
t[2]= '0.00';
|
||||
t[3]= '#,##0';
|
||||
t[4]= '#,##0.00';
|
||||
t[9]= '0%';
|
||||
t[10]= '0.00%';
|
||||
t[11]= '0.00E+00';
|
||||
t[12]= '# ?/?';
|
||||
t[13]= '# ??/??';
|
||||
t[14]= 'm/d/yy';
|
||||
t[15]= 'd-mmm-yy';
|
||||
t[16]= 'd-mmm';
|
||||
t[17]= 'mmm-yy';
|
||||
t[18]= 'h:mm AM/PM';
|
||||
t[19]= 'h:mm:ss AM/PM';
|
||||
t[20]= 'h:mm';
|
||||
t[21]= 'h:mm:ss';
|
||||
t[22]= 'm/d/yy h:mm';
|
||||
t[37]= '#,##0 ;(#,##0)';
|
||||
t[38]= '#,##0 ;[Red](#,##0)';
|
||||
t[39]= '#,##0.00;(#,##0.00)';
|
||||
t[40]= '#,##0.00;[Red](#,##0.00)';
|
||||
t[45]= 'mm:ss';
|
||||
t[46]= '[h]:mm:ss';
|
||||
t[47]= 'mmss.0';
|
||||
t[48]= '##0.0E+0';
|
||||
t[49]= '@';
|
||||
t[56]= '"上午/下午 "hh"時"mm"分"ss"秒 "';
|
||||
t[65535]= 'General';
|
||||
}
|
||||
|
||||
var table_fmt = {};
|
||||
init_table(table_fmt);
|
@ -1,4 +1,4 @@
|
||||
function frac(x, D, mixed) {
|
||||
function frac(x/*:number*/, D/*:number*/, mixed/*:?boolean*/)/*:Array<number>*/ {
|
||||
var sgn = x < 0 ? -1 : 1;
|
||||
var B = x * sgn;
|
||||
var P_2 = 0, P_1 = 1, P = 0;
|
||||
@ -8,15 +8,13 @@ function frac(x, D, mixed) {
|
||||
A = Math.floor(B);
|
||||
P = A * P_1 + P_2;
|
||||
Q = A * Q_1 + Q_2;
|
||||
if((B - A) < 0.0000000005) break;
|
||||
if((B - A) < 0.00000005) break;
|
||||
B = 1 / (B - A);
|
||||
P_2 = P_1; P_1 = P;
|
||||
Q_2 = Q_1; Q_1 = Q;
|
||||
}
|
||||
if(Q > D) { Q = Q_1; P = P_1; }
|
||||
if(Q > D) { Q = Q_2; P = P_2; }
|
||||
if(Q > D) { if(Q_1 > D) { Q = Q_2; P = P_2; } else { Q = Q_1; P = P_1; } }
|
||||
if(!mixed) return [0, sgn * P, Q];
|
||||
if(Q===0) throw "Unexpected state: "+P+" "+P_1+" "+P_2+" "+Q+" "+Q_1+" "+Q_2;
|
||||
var q = Math.floor(sgn * P/Q);
|
||||
return [q, sgn*P - q*Q, Q];
|
||||
}
|
||||
|
@ -36,6 +36,8 @@ function general_fmt(v/*:any*/, opts/*:?any*/) {
|
||||
case 'string': return v;
|
||||
case 'boolean': return v ? "TRUE" : "FALSE";
|
||||
case 'number': return (v|0) === v ? general_fmt_int(v, opts) : general_fmt_num(v, opts);
|
||||
case 'undefined': return "";
|
||||
case 'object': if(v == null) return "";
|
||||
}
|
||||
throw new Error("unsupported value in General format: " + v);
|
||||
}
|
||||
|
@ -51,211 +51,15 @@ function hashq(str/*:string*/)/*:string*/ {
|
||||
}
|
||||
function rnd(val/*:number*/, d/*:number*/)/*:string*/ { var dd = Math.pow(10,d); return ""+(Math.round(val * dd)/dd); }
|
||||
function dec(val/*:number*/, d/*:number*/)/*:number*/ {
|
||||
if (d < ('' + Math.round((val-Math.floor(val))*Math.pow(10,d))).length) {
|
||||
return 0;
|
||||
}
|
||||
return Math.round((val-Math.floor(val))*Math.pow(10,d));
|
||||
if (d < ('' + Math.round((val-Math.floor(val))*Math.pow(10,d))).length) {
|
||||
return 0;
|
||||
}
|
||||
return Math.round((val-Math.floor(val))*Math.pow(10,d));
|
||||
}
|
||||
function carry(val/*:number*/, d/*:number*/)/*:number*/ {
|
||||
if (d < ('' + Math.round((val-Math.floor(val))*Math.pow(10,d))).length) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
if (d < ('' + Math.round((val-Math.floor(val))*Math.pow(10,d))).length) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
function flr(val/*:number*/)/*:string*/ { if(val < 2147483647 && val > -2147483648) return ""+(val >= 0 ? (val|0) : (val-1|0)); return ""+Math.floor(val); }
|
||||
function write_num_flt(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string*/ {
|
||||
if(type.charCodeAt(0) === 40 && !fmt.match(closeparen)) {
|
||||
var ffmt = fmt.replace(/\( */,"").replace(/ \)/,"").replace(/\)/,"");
|
||||
if(val >= 0) return write_num_flt('n', ffmt, val);
|
||||
return '(' + write_num_flt('n', ffmt, -val) + ')';
|
||||
}
|
||||
if(fmt.charCodeAt(fmt.length - 1) === 44) return write_num_cm(type, fmt, val);
|
||||
if(fmt.indexOf('%') !== -1) return write_num_pct(type, fmt, val);
|
||||
if(fmt.indexOf('E') !== -1) return write_num_exp(fmt, val);
|
||||
if(fmt.charCodeAt(0) === 36) return "$"+write_num_flt(type,fmt.substr(fmt.charAt(1)==' '?2:1),val);
|
||||
var o;
|
||||
var r/*:?Array<string>*/, ri, ff, aval = Math.abs(val), sign = val < 0 ? "-" : "";
|
||||
if(fmt.match(/^00+$/)) return sign + pad0r(aval,fmt.length);
|
||||
if(fmt.match(/^[#?]+$/)) {
|
||||
o = pad0r(val,0); if(o === "0") o = "";
|
||||
return o.length > fmt.length ? o : hashq(fmt.substr(0,fmt.length-o.length)) + o;
|
||||
}
|
||||
if((r = fmt.match(frac1))) return write_num_f1(r, aval, sign);
|
||||
if(fmt.match(/^#+0+$/)) return sign + pad0r(aval,fmt.length - fmt.indexOf("0"));
|
||||
if((r = fmt.match(dec1))) {
|
||||
// $FlowIgnore
|
||||
o = rnd(val, r[1].length).replace(/^([^\.]+)$/,"$1."+r[1]).replace(/\.$/,"."+r[1]).replace(/\.(\d*)$/,function($$, $1) { return "." + $1 + fill("0", /*::(*/r/*::||[""])*/[1].length-$1.length); });
|
||||
return fmt.indexOf("0.") !== -1 ? o : o.replace(/^0\./,".");
|
||||
}
|
||||
fmt = fmt.replace(/^#+([0.])/, "$1");
|
||||
if((r = fmt.match(/^(0*)\.(#*)$/))) {
|
||||
return sign + rnd(aval, r[2].length).replace(/\.(\d*[1-9])0*$/,".$1").replace(/^(-?\d*)$/,"$1.").replace(/^0\./,r[1].length?"0.":".");
|
||||
}
|
||||
if((r = fmt.match(/^#,##0(\.?)$/))) return sign + commaify(pad0r(aval,0));
|
||||
if((r = fmt.match(/^#,##0\.([#0]*0)$/))) {
|
||||
return val < 0 ? "-" + write_num_flt(type, fmt, -val) : commaify(""+(Math.floor(val) + carry(val, r[1].length))) + "." + pad0(dec(val, r[1].length),r[1].length);
|
||||
}
|
||||
if((r = fmt.match(/^#,#*,#0/))) return write_num_flt(type,fmt.replace(/^#,#*,/,""),val);
|
||||
if((r = fmt.match(/^([0#]+)(\\?-([0#]+))+$/))) {
|
||||
o = _strrev(write_num_flt(type, fmt.replace(/[\\-]/g,""), val));
|
||||
ri = 0;
|
||||
return _strrev(_strrev(fmt.replace(/\\/g,"")).replace(/[0#]/g,function(x){return ri<o.length?o.charAt(ri++):x==='0'?'0':"";}));
|
||||
}
|
||||
if(fmt.match(phone)) {
|
||||
o = write_num_flt(type, "##########", val);
|
||||
return "(" + o.substr(0,3) + ") " + o.substr(3, 3) + "-" + o.substr(6);
|
||||
}
|
||||
var oa = "";
|
||||
if((r = fmt.match(/^([#0?]+)( ?)\/( ?)([#0?]+)/))) {
|
||||
ri = Math.min(/*::String(*/r[4]/*::)*/.length,7);
|
||||
ff = frac(aval, Math.pow(10,ri)-1, false);
|
||||
o = "" + sign;
|
||||
oa = write_num("n", /*::String(*/r[1]/*::)*/, ff[1]);
|
||||
if(oa.charAt(oa.length-1) == " ") oa = oa.substr(0,oa.length-1) + "0";
|
||||
o += oa + /*::String(*/r[2]/*::)*/ + "/" + /*::String(*/r[3]/*::)*/;
|
||||
oa = rpad_(ff[2],ri);
|
||||
if(oa.length < r[4].length) oa = hashq(r[4].substr(r[4].length-oa.length)) + oa;
|
||||
o += oa;
|
||||
return o;
|
||||
}
|
||||
if((r = fmt.match(/^# ([#0?]+)( ?)\/( ?)([#0?]+)/))) {
|
||||
ri = Math.min(Math.max(r[1].length, r[4].length),7);
|
||||
ff = frac(aval, Math.pow(10,ri)-1, true);
|
||||
return sign + (ff[0]||(ff[1] ? "" : "0")) + " " + (ff[1] ? pad_(ff[1],ri) + r[2] + "/" + r[3] + rpad_(ff[2],ri): fill(" ", 2*ri+1 + r[2].length + r[3].length));
|
||||
}
|
||||
if((r = fmt.match(/^[#0?]+$/))) {
|
||||
o = pad0r(val, 0);
|
||||
if(fmt.length <= o.length) return o;
|
||||
return hashq(fmt.substr(0,fmt.length-o.length)) + o;
|
||||
}
|
||||
if((r = fmt.match(/^([#0?]+)\.([#0]+)$/))) {
|
||||
o = "" + val.toFixed(Math.min(r[2].length,10)).replace(/([^0])0+$/,"$1");
|
||||
ri = o.indexOf(".");
|
||||
var lres = fmt.indexOf(".") - ri, rres = fmt.length - o.length - lres;
|
||||
return hashq(fmt.substr(0,lres) + o + fmt.substr(fmt.length-rres));
|
||||
}
|
||||
if((r = fmt.match(/^00,000\.([#0]*0)$/))) {
|
||||
ri = dec(val, r[1].length);
|
||||
return val < 0 ? "-" + write_num_flt(type, fmt, -val) : commaify(flr(val)).replace(/^\d,\d{3}$/,"0$&").replace(/^\d*$/,function($$) { return "00," + ($$.length < 3 ? pad0(0,3-$$.length) : "") + $$; }) + "." + pad0(ri,r[1].length);
|
||||
}
|
||||
switch(fmt) {
|
||||
case "#,###": var x = commaify(pad0r(aval,0)); return x !== "0" ? sign + x : "";
|
||||
default:
|
||||
}
|
||||
throw new Error("unsupported format |" + fmt + "|");
|
||||
}
|
||||
function write_num_cm2(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string*/{
|
||||
var idx = fmt.length - 1;
|
||||
while(fmt.charCodeAt(idx-1) === 44) --idx;
|
||||
return write_num(type, fmt.substr(0,idx), val / Math.pow(10,3*(fmt.length-idx)));
|
||||
}
|
||||
function write_num_pct2(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string*/{
|
||||
var sfmt = fmt.replace(pct1,""), mul = fmt.length - sfmt.length;
|
||||
return write_num(type, sfmt, val * Math.pow(10,2*mul)) + fill("%",mul);
|
||||
}
|
||||
function write_num_exp2(fmt/*:string*/, val/*:number*/)/*:string*/{
|
||||
var o/*:string*/;
|
||||
var idx = fmt.indexOf("E") - fmt.indexOf(".") - 1;
|
||||
if(fmt.match(/^#+0.0E\+0$/)) {
|
||||
var period = fmt.indexOf("."); if(period === -1) period=fmt.indexOf('E');
|
||||
var ee = Math.floor(Math.log(Math.abs(val))*Math.LOG10E)%period;
|
||||
if(ee < 0) ee += period;
|
||||
o = (val/Math.pow(10,ee)).toPrecision(idx+1+(period+ee)%period);
|
||||
if(!o.match(/[Ee]/)) {
|
||||
var fakee = Math.floor(Math.log(Math.abs(val))*Math.LOG10E);
|
||||
if(o.indexOf(".") === -1) o = o.charAt(0) + "." + o.substr(1) + "E+" + (fakee - o.length+ee);
|
||||
else o += "E+" + (fakee - ee);
|
||||
o = o.replace(/\+-/,"-");
|
||||
}
|
||||
o = o.replace(/^([+-]?)(\d*)\.(\d*)[Ee]/,function($$,$1,$2,$3) { return $1 + $2 + $3.substr(0,(period+ee)%period) + "." + $3.substr(ee) + "E"; });
|
||||
} else o = val.toExponential(idx);
|
||||
if(fmt.match(/E\+00$/) && o.match(/e[+-]\d$/)) o = o.substr(0,o.length-1) + "0" + o.charAt(o.length-1);
|
||||
if(fmt.match(/E\-/) && o.match(/e\+/)) o = o.replace(/e\+/,"e");
|
||||
return o.replace("e","E");
|
||||
}
|
||||
function write_num_int(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string*/ {
|
||||
if(type.charCodeAt(0) === 40 && !fmt.match(closeparen)) {
|
||||
var ffmt = fmt.replace(/\( */,"").replace(/ \)/,"").replace(/\)/,"");
|
||||
if(val >= 0) return write_num_int('n', ffmt, val);
|
||||
return '(' + write_num_int('n', ffmt, -val) + ')';
|
||||
}
|
||||
if(fmt.charCodeAt(fmt.length - 1) === 44) return write_num_cm2(type, fmt, val);
|
||||
if(fmt.indexOf('%') !== -1) return write_num_pct2(type, fmt, val);
|
||||
if(fmt.indexOf('E') !== -1) return write_num_exp2(fmt, val);
|
||||
if(fmt.charCodeAt(0) === 36) return "$"+write_num_int(type,fmt.substr(fmt.charAt(1)==' '?2:1),val);
|
||||
var o;
|
||||
var r, ri, ff, aval = Math.abs(val), sign = val < 0 ? "-" : "";
|
||||
if(fmt.match(/^00+$/)) return sign + pad0(aval,fmt.length);
|
||||
if(fmt.match(/^[#?]+$/)) {
|
||||
o = (""+val); if(val === 0) o = "";
|
||||
return o.length > fmt.length ? o : hashq(fmt.substr(0,fmt.length-o.length)) + o;
|
||||
}
|
||||
if((r = fmt.match(frac1))) return write_num_f2(r, aval, sign);
|
||||
if(fmt.match(/^#+0+$/)) return sign + pad0(aval,fmt.length - fmt.indexOf("0"));
|
||||
if((r = fmt.match(dec1))) {
|
||||
/*:: if(!Array.isArray(r)) throw "unreachable"; */
|
||||
o = (""+val).replace(/^([^\.]+)$/,"$1."+r[1]).replace(/\.$/,"."+r[1]);
|
||||
o = o.replace(/\.(\d*)$/,function($$, $1) {
|
||||
/*:: if(!Array.isArray(r)) throw "unreachable"; */
|
||||
return "." + $1 + fill("0", r[1].length-$1.length); });
|
||||
return fmt.indexOf("0.") !== -1 ? o : o.replace(/^0\./,".");
|
||||
}
|
||||
fmt = fmt.replace(/^#+([0.])/, "$1");
|
||||
if((r = fmt.match(/^(0*)\.(#*)$/))) {
|
||||
return sign + (""+aval).replace(/\.(\d*[1-9])0*$/,".$1").replace(/^(-?\d*)$/,"$1.").replace(/^0\./,r[1].length?"0.":".");
|
||||
}
|
||||
if((r = fmt.match(/^#,##0(\.?)$/))) return sign + commaify((""+aval));
|
||||
if((r = fmt.match(/^#,##0\.([#0]*0)$/))) {
|
||||
return val < 0 ? "-" + write_num_int(type, fmt, -val) : commaify((""+val)) + "." + fill('0',r[1].length);
|
||||
}
|
||||
if((r = fmt.match(/^#,#*,#0/))) return write_num_int(type,fmt.replace(/^#,#*,/,""),val);
|
||||
if((r = fmt.match(/^([0#]+)(\\?-([0#]+))+$/))) {
|
||||
o = _strrev(write_num_int(type, fmt.replace(/[\\-]/g,""), val));
|
||||
ri = 0;
|
||||
return _strrev(_strrev(fmt.replace(/\\/g,"")).replace(/[0#]/g,function(x){return ri<o.length?o.charAt(ri++):x==='0'?'0':"";}));
|
||||
}
|
||||
if(fmt.match(phone)) {
|
||||
o = write_num_int(type, "##########", val);
|
||||
return "(" + o.substr(0,3) + ") " + o.substr(3, 3) + "-" + o.substr(6);
|
||||
}
|
||||
var oa = "";
|
||||
if((r = fmt.match(/^([#0?]+)( ?)\/( ?)([#0?]+)/))) {
|
||||
ri = Math.min(r[4].length,7);
|
||||
ff = frac(aval, Math.pow(10,ri)-1, false);
|
||||
o = "" + sign;
|
||||
oa = write_num("n", r[1], ff[1]);
|
||||
if(oa.charAt(oa.length-1) == " ") oa = oa.substr(0,oa.length-1) + "0";
|
||||
o += oa + r[2] + "/" + r[3];
|
||||
oa = rpad_(ff[2],ri);
|
||||
if(oa.length < r[4].length) oa = hashq(r[4].substr(r[4].length-oa.length)) + oa;
|
||||
o += oa;
|
||||
return o;
|
||||
}
|
||||
if((r = fmt.match(/^# ([#0?]+)( ?)\/( ?)([#0?]+)/))) {
|
||||
ri = Math.min(Math.max(r[1].length, r[4].length),7);
|
||||
ff = frac(aval, Math.pow(10,ri)-1, true);
|
||||
return sign + (ff[0]||(ff[1] ? "" : "0")) + " " + (ff[1] ? pad_(ff[1],ri) + r[2] + "/" + r[3] + rpad_(ff[2],ri): fill(" ", 2*ri+1 + r[2].length + r[3].length));
|
||||
}
|
||||
if((r = fmt.match(/^[#0?]+$/))) {
|
||||
o = "" + val;
|
||||
if(fmt.length <= o.length) return o;
|
||||
return hashq(fmt.substr(0,fmt.length-o.length)) + o;
|
||||
}
|
||||
if((r = fmt.match(/^([#0]+)\.([#0]+)$/))) {
|
||||
o = "" + val.toFixed(Math.min(r[2].length,10)).replace(/([^0])0+$/,"$1");
|
||||
ri = o.indexOf(".");
|
||||
var lres = fmt.indexOf(".") - ri, rres = fmt.length - o.length - lres;
|
||||
return hashq(fmt.substr(0,lres) + o + fmt.substr(fmt.length-rres));
|
||||
}
|
||||
if((r = fmt.match(/^00,000\.([#0]*0)$/))) {
|
||||
return val < 0 ? "-" + write_num_int(type, fmt, -val) : commaify(""+val).replace(/^\d,\d{3}$/,"0$&").replace(/^\d*$/,function($$) { return "00," + ($$.length < 3 ? pad0(0,3-$$.length) : "") + $$; }) + "." + pad0(0,r[1].length);
|
||||
}
|
||||
switch(fmt) {
|
||||
case "#,###": var x = commaify(""+aval); return x !== "0" ? sign + x : "";
|
||||
default:
|
||||
}
|
||||
throw new Error("unsupported format |" + fmt + "|");
|
||||
}
|
||||
return function write_num(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string*/ {
|
||||
return (val|0) === val ? write_num_int(type, fmt, val) : write_num_flt(type, fmt, val);
|
||||
};})();
|
||||
|
80
bits/63_numflt.js
Normal file
80
bits/63_numflt.js
Normal file
@ -0,0 +1,80 @@
|
||||
function write_num_flt(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string*/ {
|
||||
if(type.charCodeAt(0) === 40 && !fmt.match(closeparen)) {
|
||||
var ffmt = fmt.replace(/\( */,"").replace(/ \)/,"").replace(/\)/,"");
|
||||
if(val >= 0) return write_num_flt('n', ffmt, val);
|
||||
return '(' + write_num_flt('n', ffmt, -val) + ')';
|
||||
}
|
||||
if(fmt.charCodeAt(fmt.length - 1) === 44) return write_num_cm(type, fmt, val);
|
||||
if(fmt.indexOf('%') !== -1) return write_num_pct(type, fmt, val);
|
||||
if(fmt.indexOf('E') !== -1) return write_num_exp(fmt, val);
|
||||
if(fmt.charCodeAt(0) === 36) return "$"+write_num_flt(type,fmt.substr(fmt.charAt(1)==' '?2:1),val);
|
||||
var o;
|
||||
var r/*:?Array<string>*/, ri, ff, aval = Math.abs(val), sign = val < 0 ? "-" : "";
|
||||
if(fmt.match(/^00+$/)) return sign + pad0r(aval,fmt.length);
|
||||
if(fmt.match(/^[#?]+$/)) {
|
||||
o = pad0r(val,0); if(o === "0") o = "";
|
||||
return o.length > fmt.length ? o : hashq(fmt.substr(0,fmt.length-o.length)) + o;
|
||||
}
|
||||
if((r = fmt.match(frac1))) return write_num_f1(r, aval, sign);
|
||||
if(fmt.match(/^#+0+$/)) return sign + pad0r(aval,fmt.length - fmt.indexOf("0"));
|
||||
if((r = fmt.match(dec1))) {
|
||||
o = rnd(val, r[1].length).replace(/^([^\.]+)$/,"$1."+r[1]).replace(/\.$/,"."+r[1]).replace(/\.(\d*)$/,function($$, $1) { return "." + $1 + fill("0", /*::(*/r/*::||[""])*/[1].length-$1.length); });
|
||||
return fmt.indexOf("0.") !== -1 ? o : o.replace(/^0\./,".");
|
||||
}
|
||||
fmt = fmt.replace(/^#+([0.])/, "$1");
|
||||
if((r = fmt.match(/^(0*)\.(#*)$/))) {
|
||||
return sign + rnd(aval, r[2].length).replace(/\.(\d*[1-9])0*$/,".$1").replace(/^(-?\d*)$/,"$1.").replace(/^0\./,r[1].length?"0.":".");
|
||||
}
|
||||
if((r = fmt.match(/^#,##0(\.?)$/))) return sign + commaify(pad0r(aval,0));
|
||||
if((r = fmt.match(/^#,##0\.([#0]*0)$/))) {
|
||||
return val < 0 ? "-" + write_num_flt(type, fmt, -val) : commaify(""+(Math.floor(val) + carry(val, r[1].length))) + "." + pad0(dec(val, r[1].length),r[1].length);
|
||||
}
|
||||
if((r = fmt.match(/^#,#*,#0/))) return write_num_flt(type,fmt.replace(/^#,#*,/,""),val);
|
||||
if((r = fmt.match(/^([0#]+)(\\?-([0#]+))+$/))) {
|
||||
o = _strrev(write_num_flt(type, fmt.replace(/[\\-]/g,""), val));
|
||||
ri = 0;
|
||||
return _strrev(_strrev(fmt.replace(/\\/g,"")).replace(/[0#]/g,function(x){return ri<o.length?o.charAt(ri++):x==='0'?'0':"";}));
|
||||
}
|
||||
if(fmt.match(phone)) {
|
||||
o = write_num_flt(type, "##########", val);
|
||||
return "(" + o.substr(0,3) + ") " + o.substr(3, 3) + "-" + o.substr(6);
|
||||
}
|
||||
var oa = "";
|
||||
if((r = fmt.match(/^([#0?]+)( ?)\/( ?)([#0?]+)/))) {
|
||||
ri = Math.min(/*::String(*/r[4]/*::)*/.length,7);
|
||||
ff = frac(aval, Math.pow(10,ri)-1, false);
|
||||
o = "" + sign;
|
||||
oa = write_num("n", /*::String(*/r[1]/*::)*/, ff[1]);
|
||||
if(oa.charAt(oa.length-1) == " ") oa = oa.substr(0,oa.length-1) + "0";
|
||||
o += oa + /*::String(*/r[2]/*::)*/ + "/" + /*::String(*/r[3]/*::)*/;
|
||||
oa = rpad_(ff[2],ri);
|
||||
if(oa.length < r[4].length) oa = hashq(r[4].substr(r[4].length-oa.length)) + oa;
|
||||
o += oa;
|
||||
return o;
|
||||
}
|
||||
if((r = fmt.match(/^# ([#0?]+)( ?)\/( ?)([#0?]+)/))) {
|
||||
ri = Math.min(Math.max(r[1].length, r[4].length),7);
|
||||
ff = frac(aval, Math.pow(10,ri)-1, true);
|
||||
return sign + (ff[0]||(ff[1] ? "" : "0")) + " " + (ff[1] ? pad_(ff[1],ri) + r[2] + "/" + r[3] + rpad_(ff[2],ri): fill(" ", 2*ri+1 + r[2].length + r[3].length));
|
||||
}
|
||||
if((r = fmt.match(/^[#0?]+$/))) {
|
||||
o = pad0r(val, 0);
|
||||
if(fmt.length <= o.length) return o;
|
||||
return hashq(fmt.substr(0,fmt.length-o.length)) + o;
|
||||
}
|
||||
if((r = fmt.match(/^([#0?]+)\.([#0]+)$/))) {
|
||||
o = "" + val.toFixed(Math.min(r[2].length,10)).replace(/([^0])0+$/,"$1");
|
||||
ri = o.indexOf(".");
|
||||
var lres = fmt.indexOf(".") - ri, rres = fmt.length - o.length - lres;
|
||||
return hashq(fmt.substr(0,lres) + o + fmt.substr(fmt.length-rres));
|
||||
}
|
||||
if((r = fmt.match(/^00,000\.([#0]*0)$/))) {
|
||||
ri = dec(val, r[1].length);
|
||||
return val < 0 ? "-" + write_num_flt(type, fmt, -val) : commaify(flr(val)).replace(/^\d,\d{3}$/,"0$&").replace(/^\d*$/,function($$) { return "00," + ($$.length < 3 ? pad0(0,3-$$.length) : "") + $$; }) + "." + pad0(ri,r[1].length);
|
||||
}
|
||||
switch(fmt) {
|
||||
case "#,###": var x = commaify(pad0r(aval,0)); return x !== "0" ? sign + x : "";
|
||||
default:
|
||||
}
|
||||
throw new Error("unsupported format |" + fmt + "|");
|
||||
}
|
29
bits/65_numinth.js
Normal file
29
bits/65_numinth.js
Normal file
@ -0,0 +1,29 @@
|
||||
function write_num_cm2(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string*/{
|
||||
var idx = fmt.length - 1;
|
||||
while(fmt.charCodeAt(idx-1) === 44) --idx;
|
||||
return write_num(type, fmt.substr(0,idx), val / Math.pow(10,3*(fmt.length-idx)));
|
||||
}
|
||||
function write_num_pct2(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string*/{
|
||||
var sfmt = fmt.replace(pct1,""), mul = fmt.length - sfmt.length;
|
||||
return write_num(type, sfmt, val * Math.pow(10,2*mul)) + fill("%",mul);
|
||||
}
|
||||
function write_num_exp2(fmt/*:string*/, val/*:number*/)/*:string*/{
|
||||
var o/*:string*/;
|
||||
var idx = fmt.indexOf("E") - fmt.indexOf(".") - 1;
|
||||
if(fmt.match(/^#+0.0E\+0$/)) {
|
||||
var period = fmt.indexOf("."); if(period === -1) period=fmt.indexOf('E');
|
||||
var ee = Math.floor(Math.log(Math.abs(val))*Math.LOG10E)%period;
|
||||
if(ee < 0) ee += period;
|
||||
o = (val/Math.pow(10,ee)).toPrecision(idx+1+(period+ee)%period);
|
||||
if(!o.match(/[Ee]/)) {
|
||||
var fakee = Math.floor(Math.log(Math.abs(val))*Math.LOG10E);
|
||||
if(o.indexOf(".") === -1) o = o.charAt(0) + "." + o.substr(1) + "E+" + (fakee - o.length+ee);
|
||||
else o += "E+" + (fakee - ee);
|
||||
o = o.replace(/\+-/,"-");
|
||||
}
|
||||
o = o.replace(/^([+-]?)(\d*)\.(\d*)[Ee]/,function($$,$1,$2,$3) { return $1 + $2 + $3.substr(0,(period+ee)%period) + "." + $3.substr(ee) + "E"; });
|
||||
} else o = val.toExponential(idx);
|
||||
if(fmt.match(/E\+00$/) && o.match(/e[+-]\d$/)) o = o.substr(0,o.length-1) + "0" + o.charAt(o.length-1);
|
||||
if(fmt.match(/E\-/) && o.match(/e\+/)) o = o.replace(/e\+/,"e");
|
||||
return o.replace("e","E");
|
||||
}
|
83
bits/66_numint.js
Normal file
83
bits/66_numint.js
Normal file
@ -0,0 +1,83 @@
|
||||
function write_num_int(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string*/ {
|
||||
if(type.charCodeAt(0) === 40 && !fmt.match(closeparen)) {
|
||||
var ffmt = fmt.replace(/\( */,"").replace(/ \)/,"").replace(/\)/,"");
|
||||
if(val >= 0) return write_num_int('n', ffmt, val);
|
||||
return '(' + write_num_int('n', ffmt, -val) + ')';
|
||||
}
|
||||
if(fmt.charCodeAt(fmt.length - 1) === 44) return write_num_cm2(type, fmt, val);
|
||||
if(fmt.indexOf('%') !== -1) return write_num_pct2(type, fmt, val);
|
||||
if(fmt.indexOf('E') !== -1) return write_num_exp2(fmt, val);
|
||||
if(fmt.charCodeAt(0) === 36) return "$"+write_num_int(type,fmt.substr(fmt.charAt(1)==' '?2:1),val);
|
||||
var o;
|
||||
var r, ri, ff, aval = Math.abs(val), sign = val < 0 ? "-" : "";
|
||||
if(fmt.match(/^00+$/)) return sign + pad0(aval,fmt.length);
|
||||
if(fmt.match(/^[#?]+$/)) {
|
||||
o = (""+val); if(val === 0) o = "";
|
||||
return o.length > fmt.length ? o : hashq(fmt.substr(0,fmt.length-o.length)) + o;
|
||||
}
|
||||
if((r = fmt.match(frac1))) return write_num_f2(r, aval, sign);
|
||||
if(fmt.match(/^#+0+$/)) return sign + pad0(aval,fmt.length - fmt.indexOf("0"));
|
||||
if((r = fmt.match(dec1))) {
|
||||
/*:: if(!Array.isArray(r)) throw new Error("unreachable"); */
|
||||
o = (""+val).replace(/^([^\.]+)$/,"$1."+r[1]).replace(/\.$/,"."+r[1]);
|
||||
o = o.replace(/\.(\d*)$/,function($$, $1) {
|
||||
/*:: if(!Array.isArray(r)) throw new Error("unreachable"); */
|
||||
return "." + $1 + fill("0", r[1].length-$1.length); });
|
||||
return fmt.indexOf("0.") !== -1 ? o : o.replace(/^0\./,".");
|
||||
}
|
||||
fmt = fmt.replace(/^#+([0.])/, "$1");
|
||||
if((r = fmt.match(/^(0*)\.(#*)$/))) {
|
||||
return sign + (""+aval).replace(/\.(\d*[1-9])0*$/,".$1").replace(/^(-?\d*)$/,"$1.").replace(/^0\./,r[1].length?"0.":".");
|
||||
}
|
||||
if((r = fmt.match(/^#,##0(\.?)$/))) return sign + commaify((""+aval));
|
||||
if((r = fmt.match(/^#,##0\.([#0]*0)$/))) {
|
||||
return val < 0 ? "-" + write_num_int(type, fmt, -val) : commaify((""+val)) + "." + fill('0',r[1].length);
|
||||
}
|
||||
if((r = fmt.match(/^#,#*,#0/))) return write_num_int(type,fmt.replace(/^#,#*,/,""),val);
|
||||
if((r = fmt.match(/^([0#]+)(\\?-([0#]+))+$/))) {
|
||||
o = _strrev(write_num_int(type, fmt.replace(/[\\-]/g,""), val));
|
||||
ri = 0;
|
||||
return _strrev(_strrev(fmt.replace(/\\/g,"")).replace(/[0#]/g,function(x){return ri<o.length?o.charAt(ri++):x==='0'?'0':"";}));
|
||||
}
|
||||
if(fmt.match(phone)) {
|
||||
o = write_num_int(type, "##########", val);
|
||||
return "(" + o.substr(0,3) + ") " + o.substr(3, 3) + "-" + o.substr(6);
|
||||
}
|
||||
var oa = "";
|
||||
if((r = fmt.match(/^([#0?]+)( ?)\/( ?)([#0?]+)/))) {
|
||||
ri = Math.min(r[4].length,7);
|
||||
ff = frac(aval, Math.pow(10,ri)-1, false);
|
||||
o = "" + sign;
|
||||
oa = write_num("n", r[1], ff[1]);
|
||||
if(oa.charAt(oa.length-1) == " ") oa = oa.substr(0,oa.length-1) + "0";
|
||||
o += oa + r[2] + "/" + r[3];
|
||||
oa = rpad_(ff[2],ri);
|
||||
if(oa.length < r[4].length) oa = hashq(r[4].substr(r[4].length-oa.length)) + oa;
|
||||
o += oa;
|
||||
return o;
|
||||
}
|
||||
if((r = fmt.match(/^# ([#0?]+)( ?)\/( ?)([#0?]+)/))) {
|
||||
ri = Math.min(Math.max(r[1].length, r[4].length),7);
|
||||
ff = frac(aval, Math.pow(10,ri)-1, true);
|
||||
return sign + (ff[0]||(ff[1] ? "" : "0")) + " " + (ff[1] ? pad_(ff[1],ri) + r[2] + "/" + r[3] + rpad_(ff[2],ri): fill(" ", 2*ri+1 + r[2].length + r[3].length));
|
||||
}
|
||||
if((r = fmt.match(/^[#0?]+$/))) {
|
||||
o = "" + val;
|
||||
if(fmt.length <= o.length) return o;
|
||||
return hashq(fmt.substr(0,fmt.length-o.length)) + o;
|
||||
}
|
||||
if((r = fmt.match(/^([#0]+)\.([#0]+)$/))) {
|
||||
o = "" + val.toFixed(Math.min(r[2].length,10)).replace(/([^0])0+$/,"$1");
|
||||
ri = o.indexOf(".");
|
||||
var lres = fmt.indexOf(".") - ri, rres = fmt.length - o.length - lres;
|
||||
return hashq(fmt.substr(0,lres) + o + fmt.substr(fmt.length-rres));
|
||||
}
|
||||
if((r = fmt.match(/^00,000\.([#0]*0)$/))) {
|
||||
return val < 0 ? "-" + write_num_int(type, fmt, -val) : commaify(""+val).replace(/^\d,\d{3}$/,"0$&").replace(/^\d*$/,function($$) { return "00," + ($$.length < 3 ? pad0(0,3-$$.length) : "") + $$; }) + "." + pad0(0,r[1].length);
|
||||
}
|
||||
switch(fmt) {
|
||||
case "#,###": var x = commaify(""+aval); return x !== "0" ? sign + x : "";
|
||||
default:
|
||||
}
|
||||
throw new Error("unsupported format |" + fmt + "|");
|
||||
}
|
3
bits/69_numfoot.js
Normal file
3
bits/69_numfoot.js
Normal file
@ -0,0 +1,3 @@
|
||||
return function write_num(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string*/ {
|
||||
return (val|0) === val ? write_num_int(type, fmt, val) : write_num_flt(type, fmt, val);
|
||||
};})();
|
@ -26,13 +26,13 @@ function fmt_is_date(fmt/*:string*/)/*:boolean*/ {
|
||||
case '.':
|
||||
/* falls through */
|
||||
case '0': case '#':
|
||||
while(i < fmt.length && ("0#?.,E+-%".indexOf(c=fmt.charAt(++i)) > -1 || c=='\\' && fmt.charAt(i+1) == "-" && "0#".indexOf(fmt.charAt(i+2))>-1));
|
||||
while(i < fmt.length && ("0#?.,E+-%".indexOf(c=fmt.charAt(++i)) > -1 || c=='\\' && fmt.charAt(i+1) == "-" && "0#".indexOf(fmt.charAt(i+2))>-1)){}
|
||||
break;
|
||||
case '?': while(fmt.charAt(++i) === c); break;
|
||||
case '?': while(fmt.charAt(++i) === c){} break;
|
||||
case '*': ++i; if(fmt.charAt(i) == ' ' || fmt.charAt(i) == '*') ++i; break;
|
||||
case '(': case ')': ++i; break;
|
||||
case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
|
||||
while(i < fmt.length && "0123456789".indexOf(fmt.charAt(++i)) > -1); break;
|
||||
while(i < fmt.length && "0123456789".indexOf(fmt.charAt(++i)) > -1){} break;
|
||||
case ' ': ++i; break;
|
||||
default: ++i; break;
|
||||
}
|
||||
|
@ -46,7 +46,10 @@ function eval_fmt(fmt/*:string*/, v/*:any*/, opts/*:any*/, flen/*:number*/) {
|
||||
if(o.match(abstime)) {
|
||||
if(dt==null) { dt=parse_date_code(v, opts); if(dt==null) return ""; }
|
||||
out[out.length] = {t:'Z', v:o.toLowerCase()};
|
||||
} else { o=""; }
|
||||
} else if(o.indexOf("$") > -1) {
|
||||
o = (o.match(/\$([^-\[\]]*)/)||[])[1]||"$";
|
||||
if(!fmt_is_date(fmt)) out[out.length] = {t:'t',v:o};
|
||||
}
|
||||
break;
|
||||
/* Numbers */
|
||||
case '.':
|
||||
@ -82,7 +85,7 @@ function eval_fmt(fmt/*:string*/, v/*:any*/, opts/*:any*/, flen/*:number*/) {
|
||||
/* falls through */
|
||||
case 'd': case 'y': case 'M': case 'e': lst=out[i].t; break;
|
||||
case 'm': if(lst === 's') { out[i].t = 'M'; if(bt < 2) bt = 2; } break;
|
||||
case 'X': if(out[i].v === "B2");
|
||||
case 'X': /*if(out[i].v === "B2");*/
|
||||
break;
|
||||
case 'Z':
|
||||
if(bt < 1 && out[i].v.match(/[Hh]/)) bt = 1;
|
||||
@ -132,11 +135,20 @@ function eval_fmt(fmt/*:string*/, v/*:any*/, opts/*:any*/, flen/*:number*/) {
|
||||
}
|
||||
var vv = "", myv, ostr;
|
||||
if(nstr.length > 0) {
|
||||
myv = (v<0&&nstr.charCodeAt(0) === 45 ? -v : v); /* '-' */
|
||||
ostr = write_num(nstr.charCodeAt(0) === 40 ? '(' : 'n', nstr, myv); /* '(' */
|
||||
if(nstr.charCodeAt(0) == 40) /* '(' */ {
|
||||
myv = (v<0&&nstr.charCodeAt(0) === 45 ? -v : v);
|
||||
ostr = write_num('(', nstr, myv);
|
||||
} else {
|
||||
myv = (v<0 && flen > 1 ? -v : v);
|
||||
ostr = write_num('n', nstr, myv);
|
||||
if(myv < 0 && out[0] && out[0].t == 't') {
|
||||
ostr = ostr.substr(1);
|
||||
out[0].v = "-" + out[0].v;
|
||||
}
|
||||
}
|
||||
jj=ostr.length-1;
|
||||
var decpt = out.length;
|
||||
for(i=0; i < out.length; ++i) if(out[i] != null && out[i].v.indexOf(".") > -1) { decpt = i; break; }
|
||||
for(i=0; i < out.length; ++i) if(out[i] != null && out[i].t != 't' && out[i].v.indexOf(".") > -1) { decpt = i; break; }
|
||||
var lasti=out.length;
|
||||
if(decpt === out.length && ostr.indexOf("E") === -1) {
|
||||
for(i=out.length-1; i>= 0;--i) {
|
||||
|
@ -20,11 +20,18 @@ function choose_fmt(f/*:string*/, v) {
|
||||
return [l, ff];
|
||||
}
|
||||
function format(fmt/*:string|number*/,v/*:any*/,o/*:?any*/) {
|
||||
fixopts(o != null ? o : (o=[]));
|
||||
if(o == null) o = {};
|
||||
//fixopts(o != null ? o : (o=[]));
|
||||
var sfmt = "";
|
||||
switch(typeof fmt) {
|
||||
case "string": sfmt = fmt; break;
|
||||
case "number": sfmt = (o.table != null ? (o.table/*:any*/) : table_fmt)[fmt]; break;
|
||||
case "string":
|
||||
if(fmt == "m/d/yy" && o.dateNF) sfmt = o.dateNF;
|
||||
else sfmt = fmt;
|
||||
break;
|
||||
case "number":
|
||||
if(fmt == 14 && o.dateNF) sfmt = o.dateNF;
|
||||
else sfmt = (o.table != null ? (o.table/*:any*/) : table_fmt)[fmt];
|
||||
break;
|
||||
}
|
||||
if(isgeneral(sfmt,0)) return general_fmt(v, o);
|
||||
var f = choose_fmt(sfmt, v);
|
||||
|
@ -3,3 +3,4 @@ SSF.load = function load_entry(fmt/*:string*/, idx/*:number*/) { table_fmt[idx]
|
||||
SSF.format = format;
|
||||
SSF.get_table = function get_table() { return table_fmt; };
|
||||
SSF.load_table = function load_table(tbl/*:{[n:number]:string}*/) { for(var i=0; i!=0x0188; ++i) if(tbl[i] !== undefined) SSF.load(tbl[i], i); };
|
||||
SSF.init_table = init_table;
|
||||
|
113
index.html
113
index.html
@ -1,49 +1,70 @@
|
||||
<!doctype html>
|
||||
<!DOCTYPE html>
|
||||
<!-- ssf.js (C) 2013-present SheetJS http://sheetjs.com -->
|
||||
<!-- vim: set ts=2: -->
|
||||
<html>
|
||||
<head>
|
||||
<script src="ssf.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<b>SSF (Spreadsheet Number Format) Live Demo</b><br />
|
||||
<a href="https://github.com/SheetJS/ssf">Github Repo</a><br />
|
||||
<a href="https://github.com/SheetJS/ssf/issues">Issues? Something look weird? Click here and report an issue</a><br />
|
||||
<div>
|
||||
<p><b>Format code:</b> <input type="text" id="fmt" value="General"></p>
|
||||
<p><b>Value: </b> <input type="text" id="val" value="3.1415926535"></p>
|
||||
<p><b>Formatted Number:</b> <pre id="num"></pre></p>
|
||||
<p><b>Formatted Text</b> <pre id="txt"></pre></p>
|
||||
</div>
|
||||
</body>
|
||||
<script>
|
||||
var F = document.getElementById('fmt');
|
||||
var V = document.getElementById('val');
|
||||
var N = document.getElementById('num');
|
||||
var T = document.getElementById('txt');
|
||||
function update() {
|
||||
try { N.innerHTML = SSF.format(F.value, Number(V.value)); } catch(e) { N.innerHTML = e; }
|
||||
try { T.innerHTML = SSF.format(F.value, V.value); } catch(e) { T.innerHTML = e; }
|
||||
}
|
||||
if(F.addEventListener) {
|
||||
F.addEventListener('keyup', update);
|
||||
V.addEventListener('keyup', update);
|
||||
} else if(F.attachEvent) {
|
||||
F.attachEvent('onkeyup', update);
|
||||
V.attachEvent('onkeyup', update);
|
||||
} else {
|
||||
F.oninput = update;
|
||||
V.oninput = update;
|
||||
}
|
||||
update();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
var _gaq = _gaq || [];
|
||||
_gaq.push(['_setAccount', 'UA-36810333-1']);
|
||||
_gaq.push(['_trackPageview']);
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<title>SSF Live Demo</title>
|
||||
<style>
|
||||
a { text-decoration: none }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<pre>
|
||||
<b><a href="http://sheetjs.com">SSF (Spreadsheet Number Format) Live Demo</a></b>
|
||||
|
||||
(function() {
|
||||
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
|
||||
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
|
||||
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
|
||||
})();
|
||||
</script>
|
||||
<a href="https://github.com/SheetJS/ssf">Source Code Repo</a>
|
||||
<a href="https://github.com/SheetJS/ssf/issues">Issues? Something look weird? Click here and report an issue</a>
|
||||
</pre>
|
||||
<table>
|
||||
<tr><td><b>Format code:</b></td><td><input type="text" id="fmt" value="General"></td></tr>
|
||||
<tr><td><b>Value:</b></td><td><input type="text" id="val" value="3.1415926535"></td></tr>
|
||||
<tr><td colspan="2"> </td></tr>
|
||||
<tr><td><b>Formatted Number:</b></td><td><pre id="num"></pre></td></tr>
|
||||
<tr><td><b>Formatted Text</b></td><td><pre id="txt"></pre></td></tr>
|
||||
</table>
|
||||
<script src="ssf.js"></script>
|
||||
<script>
|
||||
/*jshint browser:true */
|
||||
/*global frac */
|
||||
var V = document.getElementById('val');
|
||||
var F = document.getElementById('fmt');
|
||||
var N = document.getElementById('num');
|
||||
var T = document.getElementById('txt');
|
||||
|
||||
function update() {
|
||||
try {
|
||||
N.innerHTML = SSF.format(F.value, Number(V.value));
|
||||
} catch(e) { N.innerHTML = e; }
|
||||
try {
|
||||
T.innerHTML = SSF.format(F.value, V.value);
|
||||
} catch(e) { T.innerHTML = e; }
|
||||
}
|
||||
|
||||
/* Bind to relevant events */
|
||||
if(F.addEventListener) {
|
||||
F.addEventListener('keyup', update);
|
||||
V.addEventListener('keyup', update);
|
||||
} else if(F.attachEvent) {
|
||||
F.attachEvent('onkeyup', update);
|
||||
V.attachEvent('onkeyup', update);
|
||||
} else {
|
||||
F.oninput = update;
|
||||
V.oninput = update;
|
||||
}
|
||||
|
||||
update();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
var _gaq = _gaq || [];
|
||||
_gaq.push(['_setAccount', 'UA-36810333-1']);
|
||||
_gaq.push(['_trackPageview']);
|
||||
|
||||
(function() {
|
||||
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
|
||||
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
|
||||
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ssf",
|
||||
"version": "0.9.0",
|
||||
"version": "0.9.1",
|
||||
"author": "SheetJS",
|
||||
"description": "Format data using ECMA-376 spreadsheet Format Codes",
|
||||
"keywords": [ "format", "sprintf", "spreadsheet" ],
|
||||
@ -11,7 +11,7 @@
|
||||
"dependencies": {
|
||||
"voc":"",
|
||||
"colors":"0.6.2",
|
||||
"frac":"0.3.1"
|
||||
"frac":"~1.0.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"mocha":"",
|
||||
|
142
ssf.flow.js
142
ssf.flow.js
@ -2,7 +2,7 @@
|
||||
/*jshint -W041 */
|
||||
var SSF = {};
|
||||
var make_ssf = function make_ssf(SSF){
|
||||
SSF.version = '0.9.0';
|
||||
SSF.version = '0.9.1';
|
||||
function _strrev(x/*:string*/)/*:string*/ { var o = "", i = x.length-1; while(i>=0) o += x.charAt(i--); return o; }
|
||||
function fill(c/*:string*/,l/*:number*/)/*:string*/ { var o = ""; while(o.length < l) o+=c; return o; }
|
||||
function pad0(v/*:any*/,d/*:number*/)/*:string*/{var t=""+v; return t.length>=d?t:fill('0',d-t.length)+t;}
|
||||
@ -23,38 +23,6 @@ function fixopts(o){
|
||||
for(var y = 0; y != opts_fmt.length; ++y) if(o[opts_fmt[y][0]]===undefined) o[opts_fmt[y][0]]=opts_fmt[y][1];
|
||||
}
|
||||
SSF.opts = opts_fmt;
|
||||
var table_fmt = {
|
||||
/*::[*/0/*::]*/: 'General',
|
||||
/*::[*/1/*::]*/: '0',
|
||||
/*::[*/2/*::]*/: '0.00',
|
||||
/*::[*/3/*::]*/: '#,##0',
|
||||
/*::[*/4/*::]*/: '#,##0.00',
|
||||
/*::[*/9/*::]*/: '0%',
|
||||
/*::[*/10/*::]*/: '0.00%',
|
||||
/*::[*/11/*::]*/: '0.00E+00',
|
||||
/*::[*/12/*::]*/: '# ?/?',
|
||||
/*::[*/13/*::]*/: '# ??/??',
|
||||
/*::[*/14/*::]*/: 'm/d/yy',
|
||||
/*::[*/15/*::]*/: 'd-mmm-yy',
|
||||
/*::[*/16/*::]*/: 'd-mmm',
|
||||
/*::[*/17/*::]*/: 'mmm-yy',
|
||||
/*::[*/18/*::]*/: 'h:mm AM/PM',
|
||||
/*::[*/19/*::]*/: 'h:mm:ss AM/PM',
|
||||
/*::[*/20/*::]*/: 'h:mm',
|
||||
/*::[*/21/*::]*/: 'h:mm:ss',
|
||||
/*::[*/22/*::]*/: 'm/d/yy h:mm',
|
||||
/*::[*/37/*::]*/: '#,##0 ;(#,##0)',
|
||||
/*::[*/38/*::]*/: '#,##0 ;[Red](#,##0)',
|
||||
/*::[*/39/*::]*/: '#,##0.00;(#,##0.00)',
|
||||
/*::[*/40/*::]*/: '#,##0.00;[Red](#,##0.00)',
|
||||
/*::[*/45/*::]*/: 'mm:ss',
|
||||
/*::[*/46/*::]*/: '[h]:mm:ss',
|
||||
/*::[*/47/*::]*/: 'mmss.0',
|
||||
/*::[*/48/*::]*/: '##0.0E+0',
|
||||
/*::[*/49/*::]*/: '@',
|
||||
/*::[*/56/*::]*/: '"上午/下午 "hh"時"mm"分"ss"秒 "',
|
||||
/*::[*/65535/*::]*/: 'General'
|
||||
};
|
||||
var days/*:Array<Array<string> >*/ = [
|
||||
['Sun', 'Sunday'],
|
||||
['Mon', 'Monday'],
|
||||
@ -78,7 +46,42 @@ var months/*:Array<Array<string> >*/ = [
|
||||
['N', 'Nov', 'November'],
|
||||
['D', 'Dec', 'December']
|
||||
];
|
||||
function frac(x, D, mixed) {
|
||||
function init_table(t/*:any*/) {
|
||||
t[0]= 'General';
|
||||
t[1]= '0';
|
||||
t[2]= '0.00';
|
||||
t[3]= '#,##0';
|
||||
t[4]= '#,##0.00';
|
||||
t[9]= '0%';
|
||||
t[10]= '0.00%';
|
||||
t[11]= '0.00E+00';
|
||||
t[12]= '# ?/?';
|
||||
t[13]= '# ??/??';
|
||||
t[14]= 'm/d/yy';
|
||||
t[15]= 'd-mmm-yy';
|
||||
t[16]= 'd-mmm';
|
||||
t[17]= 'mmm-yy';
|
||||
t[18]= 'h:mm AM/PM';
|
||||
t[19]= 'h:mm:ss AM/PM';
|
||||
t[20]= 'h:mm';
|
||||
t[21]= 'h:mm:ss';
|
||||
t[22]= 'm/d/yy h:mm';
|
||||
t[37]= '#,##0 ;(#,##0)';
|
||||
t[38]= '#,##0 ;[Red](#,##0)';
|
||||
t[39]= '#,##0.00;(#,##0.00)';
|
||||
t[40]= '#,##0.00;[Red](#,##0.00)';
|
||||
t[45]= 'mm:ss';
|
||||
t[46]= '[h]:mm:ss';
|
||||
t[47]= 'mmss.0';
|
||||
t[48]= '##0.0E+0';
|
||||
t[49]= '@';
|
||||
t[56]= '"上午/下午 "hh"時"mm"分"ss"秒 "';
|
||||
t[65535]= 'General';
|
||||
}
|
||||
|
||||
var table_fmt = {};
|
||||
init_table(table_fmt);
|
||||
function frac(x/*:number*/, D/*:number*/, mixed/*:?boolean*/)/*:Array<number>*/ {
|
||||
var sgn = x < 0 ? -1 : 1;
|
||||
var B = x * sgn;
|
||||
var P_2 = 0, P_1 = 1, P = 0;
|
||||
@ -88,15 +91,13 @@ function frac(x, D, mixed) {
|
||||
A = Math.floor(B);
|
||||
P = A * P_1 + P_2;
|
||||
Q = A * Q_1 + Q_2;
|
||||
if((B - A) < 0.0000000005) break;
|
||||
if((B - A) < 0.00000005) break;
|
||||
B = 1 / (B - A);
|
||||
P_2 = P_1; P_1 = P;
|
||||
Q_2 = Q_1; Q_1 = Q;
|
||||
}
|
||||
if(Q > D) { Q = Q_1; P = P_1; }
|
||||
if(Q > D) { Q = Q_2; P = P_2; }
|
||||
if(Q > D) { if(Q_1 > D) { Q = Q_2; P = P_2; } else { Q = Q_1; P = P_1; } }
|
||||
if(!mixed) return [0, sgn * P, Q];
|
||||
if(Q===0) throw "Unexpected state: "+P+" "+P_1+" "+P_2+" "+Q+" "+Q_1+" "+Q_2;
|
||||
var q = Math.floor(sgn * P/Q);
|
||||
return [q, sgn*P - q*Q, Q];
|
||||
}
|
||||
@ -138,6 +139,8 @@ function general_fmt(v/*:any*/, opts/*:?any*/) {
|
||||
case 'string': return v;
|
||||
case 'boolean': return v ? "TRUE" : "FALSE";
|
||||
case 'number': return (v|0) === v ? general_fmt_int(v, opts) : general_fmt_num(v, opts);
|
||||
case 'undefined': return "";
|
||||
case 'object': if(v == null) return "";
|
||||
}
|
||||
throw new Error("unsupported value in General format: " + v);
|
||||
}
|
||||
@ -311,16 +314,16 @@ function hashq(str/*:string*/)/*:string*/ {
|
||||
}
|
||||
function rnd(val/*:number*/, d/*:number*/)/*:string*/ { var dd = Math.pow(10,d); return ""+(Math.round(val * dd)/dd); }
|
||||
function dec(val/*:number*/, d/*:number*/)/*:number*/ {
|
||||
if (d < ('' + Math.round((val-Math.floor(val))*Math.pow(10,d))).length) {
|
||||
return 0;
|
||||
}
|
||||
return Math.round((val-Math.floor(val))*Math.pow(10,d));
|
||||
if (d < ('' + Math.round((val-Math.floor(val))*Math.pow(10,d))).length) {
|
||||
return 0;
|
||||
}
|
||||
return Math.round((val-Math.floor(val))*Math.pow(10,d));
|
||||
}
|
||||
function carry(val/*:number*/, d/*:number*/)/*:number*/ {
|
||||
if (d < ('' + Math.round((val-Math.floor(val))*Math.pow(10,d))).length) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
if (d < ('' + Math.round((val-Math.floor(val))*Math.pow(10,d))).length) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
function flr(val/*:number*/)/*:string*/ { if(val < 2147483647 && val > -2147483648) return ""+(val >= 0 ? (val|0) : (val-1|0)); return ""+Math.floor(val); }
|
||||
function write_num_flt(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string*/ {
|
||||
@ -343,7 +346,6 @@ function write_num_flt(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string
|
||||
if((r = fmt.match(frac1))) return write_num_f1(r, aval, sign);
|
||||
if(fmt.match(/^#+0+$/)) return sign + pad0r(aval,fmt.length - fmt.indexOf("0"));
|
||||
if((r = fmt.match(dec1))) {
|
||||
// $FlowIgnore
|
||||
o = rnd(val, r[1].length).replace(/^([^\.]+)$/,"$1."+r[1]).replace(/\.$/,"."+r[1]).replace(/\.(\d*)$/,function($$, $1) { return "." + $1 + fill("0", /*::(*/r/*::||[""])*/[1].length-$1.length); });
|
||||
return fmt.indexOf("0.") !== -1 ? o : o.replace(/^0\./,".");
|
||||
}
|
||||
@ -453,10 +455,10 @@ function write_num_int(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string
|
||||
if((r = fmt.match(frac1))) return write_num_f2(r, aval, sign);
|
||||
if(fmt.match(/^#+0+$/)) return sign + pad0(aval,fmt.length - fmt.indexOf("0"));
|
||||
if((r = fmt.match(dec1))) {
|
||||
/*:: if(!Array.isArray(r)) throw "unreachable"; */
|
||||
/*:: if(!Array.isArray(r)) throw new Error("unreachable"); */
|
||||
o = (""+val).replace(/^([^\.]+)$/,"$1."+r[1]).replace(/\.$/,"."+r[1]);
|
||||
o = o.replace(/\.(\d*)$/,function($$, $1) {
|
||||
/*:: if(!Array.isArray(r)) throw "unreachable"; */
|
||||
/*:: if(!Array.isArray(r)) throw new Error("unreachable"); */
|
||||
return "." + $1 + fill("0", r[1].length-$1.length); });
|
||||
return fmt.indexOf("0.") !== -1 ? o : o.replace(/^0\./,".");
|
||||
}
|
||||
@ -564,13 +566,13 @@ function fmt_is_date(fmt/*:string*/)/*:boolean*/ {
|
||||
case '.':
|
||||
/* falls through */
|
||||
case '0': case '#':
|
||||
while(i < fmt.length && ("0#?.,E+-%".indexOf(c=fmt.charAt(++i)) > -1 || c=='\\' && fmt.charAt(i+1) == "-" && "0#".indexOf(fmt.charAt(i+2))>-1));
|
||||
while(i < fmt.length && ("0#?.,E+-%".indexOf(c=fmt.charAt(++i)) > -1 || c=='\\' && fmt.charAt(i+1) == "-" && "0#".indexOf(fmt.charAt(i+2))>-1)){}
|
||||
break;
|
||||
case '?': while(fmt.charAt(++i) === c); break;
|
||||
case '?': while(fmt.charAt(++i) === c){} break;
|
||||
case '*': ++i; if(fmt.charAt(i) == ' ' || fmt.charAt(i) == '*') ++i; break;
|
||||
case '(': case ')': ++i; break;
|
||||
case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
|
||||
while(i < fmt.length && "0123456789".indexOf(fmt.charAt(++i)) > -1); break;
|
||||
while(i < fmt.length && "0123456789".indexOf(fmt.charAt(++i)) > -1){} break;
|
||||
case ' ': ++i; break;
|
||||
default: ++i; break;
|
||||
}
|
||||
@ -626,7 +628,10 @@ function eval_fmt(fmt/*:string*/, v/*:any*/, opts/*:any*/, flen/*:number*/) {
|
||||
if(o.match(abstime)) {
|
||||
if(dt==null) { dt=parse_date_code(v, opts); if(dt==null) return ""; }
|
||||
out[out.length] = {t:'Z', v:o.toLowerCase()};
|
||||
} else { o=""; }
|
||||
} else if(o.indexOf("$") > -1) {
|
||||
o = (o.match(/\$([^-\[\]]*)/)||[])[1]||"$";
|
||||
if(!fmt_is_date(fmt)) out[out.length] = {t:'t',v:o};
|
||||
}
|
||||
break;
|
||||
/* Numbers */
|
||||
case '.':
|
||||
@ -662,7 +667,7 @@ function eval_fmt(fmt/*:string*/, v/*:any*/, opts/*:any*/, flen/*:number*/) {
|
||||
/* falls through */
|
||||
case 'd': case 'y': case 'M': case 'e': lst=out[i].t; break;
|
||||
case 'm': if(lst === 's') { out[i].t = 'M'; if(bt < 2) bt = 2; } break;
|
||||
case 'X': if(out[i].v === "B2");
|
||||
case 'X': /*if(out[i].v === "B2");*/
|
||||
break;
|
||||
case 'Z':
|
||||
if(bt < 1 && out[i].v.match(/[Hh]/)) bt = 1;
|
||||
@ -712,11 +717,20 @@ function eval_fmt(fmt/*:string*/, v/*:any*/, opts/*:any*/, flen/*:number*/) {
|
||||
}
|
||||
var vv = "", myv, ostr;
|
||||
if(nstr.length > 0) {
|
||||
myv = (v<0&&nstr.charCodeAt(0) === 45 ? -v : v); /* '-' */
|
||||
ostr = write_num(nstr.charCodeAt(0) === 40 ? '(' : 'n', nstr, myv); /* '(' */
|
||||
if(nstr.charCodeAt(0) == 40) /* '(' */ {
|
||||
myv = (v<0&&nstr.charCodeAt(0) === 45 ? -v : v);
|
||||
ostr = write_num('(', nstr, myv);
|
||||
} else {
|
||||
myv = (v<0 && flen > 1 ? -v : v);
|
||||
ostr = write_num('n', nstr, myv);
|
||||
if(myv < 0 && out[0] && out[0].t == 't') {
|
||||
ostr = ostr.substr(1);
|
||||
out[0].v = "-" + out[0].v;
|
||||
}
|
||||
}
|
||||
jj=ostr.length-1;
|
||||
var decpt = out.length;
|
||||
for(i=0; i < out.length; ++i) if(out[i] != null && out[i].v.indexOf(".") > -1) { decpt = i; break; }
|
||||
for(i=0; i < out.length; ++i) if(out[i] != null && out[i].t != 't' && out[i].v.indexOf(".") > -1) { decpt = i; break; }
|
||||
var lasti=out.length;
|
||||
if(decpt === out.length && ostr.indexOf("E") === -1) {
|
||||
for(i=out.length-1; i>= 0;--i) {
|
||||
@ -804,11 +818,18 @@ function choose_fmt(f/*:string*/, v) {
|
||||
return [l, ff];
|
||||
}
|
||||
function format(fmt/*:string|number*/,v/*:any*/,o/*:?any*/) {
|
||||
fixopts(o != null ? o : (o=[]));
|
||||
if(o == null) o = {};
|
||||
//fixopts(o != null ? o : (o=[]));
|
||||
var sfmt = "";
|
||||
switch(typeof fmt) {
|
||||
case "string": sfmt = fmt; break;
|
||||
case "number": sfmt = (o.table != null ? (o.table/*:any*/) : table_fmt)[fmt]; break;
|
||||
case "string":
|
||||
if(fmt == "m/d/yy" && o.dateNF) sfmt = o.dateNF;
|
||||
else sfmt = fmt;
|
||||
break;
|
||||
case "number":
|
||||
if(fmt == 14 && o.dateNF) sfmt = o.dateNF;
|
||||
else sfmt = (o.table != null ? (o.table/*:any*/) : table_fmt)[fmt];
|
||||
break;
|
||||
}
|
||||
if(isgeneral(sfmt,0)) return general_fmt(v, o);
|
||||
var f = choose_fmt(sfmt, v);
|
||||
@ -822,6 +843,7 @@ SSF.load = function load_entry(fmt/*:string*/, idx/*:number*/) { table_fmt[idx]
|
||||
SSF.format = format;
|
||||
SSF.get_table = function get_table() { return table_fmt; };
|
||||
SSF.load_table = function load_table(tbl/*:{[n:number]:string}*/) { for(var i=0; i!=0x0188; ++i) if(tbl[i] !== undefined) SSF.load(tbl[i], i); };
|
||||
SSF.init_table = init_table;
|
||||
};
|
||||
make_ssf(SSF);
|
||||
/*global module */
|
||||
|
136
ssf.js
136
ssf.js
@ -2,7 +2,7 @@
|
||||
/*jshint -W041 */
|
||||
var SSF = {};
|
||||
var make_ssf = function make_ssf(SSF){
|
||||
SSF.version = '0.9.0';
|
||||
SSF.version = '0.9.1';
|
||||
function _strrev(x) { var o = "", i = x.length-1; while(i>=0) o += x.charAt(i--); return o; }
|
||||
function fill(c,l) { var o = ""; while(o.length < l) o+=c; return o; }
|
||||
function pad0(v,d){var t=""+v; return t.length>=d?t:fill('0',d-t.length)+t;}
|
||||
@ -23,38 +23,6 @@ function fixopts(o){
|
||||
for(var y = 0; y != opts_fmt.length; ++y) if(o[opts_fmt[y][0]]===undefined) o[opts_fmt[y][0]]=opts_fmt[y][1];
|
||||
}
|
||||
SSF.opts = opts_fmt;
|
||||
var table_fmt = {
|
||||
0: 'General',
|
||||
1: '0',
|
||||
2: '0.00',
|
||||
3: '#,##0',
|
||||
4: '#,##0.00',
|
||||
9: '0%',
|
||||
10: '0.00%',
|
||||
11: '0.00E+00',
|
||||
12: '# ?/?',
|
||||
13: '# ??/??',
|
||||
14: 'm/d/yy',
|
||||
15: 'd-mmm-yy',
|
||||
16: 'd-mmm',
|
||||
17: 'mmm-yy',
|
||||
18: 'h:mm AM/PM',
|
||||
19: 'h:mm:ss AM/PM',
|
||||
20: 'h:mm',
|
||||
21: 'h:mm:ss',
|
||||
22: 'm/d/yy h:mm',
|
||||
37: '#,##0 ;(#,##0)',
|
||||
38: '#,##0 ;[Red](#,##0)',
|
||||
39: '#,##0.00;(#,##0.00)',
|
||||
40: '#,##0.00;[Red](#,##0.00)',
|
||||
45: 'mm:ss',
|
||||
46: '[h]:mm:ss',
|
||||
47: 'mmss.0',
|
||||
48: '##0.0E+0',
|
||||
49: '@',
|
||||
56: '"上午/下午 "hh"時"mm"分"ss"秒 "',
|
||||
65535: 'General'
|
||||
};
|
||||
var days = [
|
||||
['Sun', 'Sunday'],
|
||||
['Mon', 'Monday'],
|
||||
@ -78,6 +46,41 @@ var months = [
|
||||
['N', 'Nov', 'November'],
|
||||
['D', 'Dec', 'December']
|
||||
];
|
||||
function init_table(t) {
|
||||
t[0]= 'General';
|
||||
t[1]= '0';
|
||||
t[2]= '0.00';
|
||||
t[3]= '#,##0';
|
||||
t[4]= '#,##0.00';
|
||||
t[9]= '0%';
|
||||
t[10]= '0.00%';
|
||||
t[11]= '0.00E+00';
|
||||
t[12]= '# ?/?';
|
||||
t[13]= '# ??/??';
|
||||
t[14]= 'm/d/yy';
|
||||
t[15]= 'd-mmm-yy';
|
||||
t[16]= 'd-mmm';
|
||||
t[17]= 'mmm-yy';
|
||||
t[18]= 'h:mm AM/PM';
|
||||
t[19]= 'h:mm:ss AM/PM';
|
||||
t[20]= 'h:mm';
|
||||
t[21]= 'h:mm:ss';
|
||||
t[22]= 'm/d/yy h:mm';
|
||||
t[37]= '#,##0 ;(#,##0)';
|
||||
t[38]= '#,##0 ;[Red](#,##0)';
|
||||
t[39]= '#,##0.00;(#,##0.00)';
|
||||
t[40]= '#,##0.00;[Red](#,##0.00)';
|
||||
t[45]= 'mm:ss';
|
||||
t[46]= '[h]:mm:ss';
|
||||
t[47]= 'mmss.0';
|
||||
t[48]= '##0.0E+0';
|
||||
t[49]= '@';
|
||||
t[56]= '"上午/下午 "hh"時"mm"分"ss"秒 "';
|
||||
t[65535]= 'General';
|
||||
}
|
||||
|
||||
var table_fmt = {};
|
||||
init_table(table_fmt);
|
||||
function frac(x, D, mixed) {
|
||||
var sgn = x < 0 ? -1 : 1;
|
||||
var B = x * sgn;
|
||||
@ -88,15 +91,13 @@ function frac(x, D, mixed) {
|
||||
A = Math.floor(B);
|
||||
P = A * P_1 + P_2;
|
||||
Q = A * Q_1 + Q_2;
|
||||
if((B - A) < 0.0000000005) break;
|
||||
if((B - A) < 0.00000005) break;
|
||||
B = 1 / (B - A);
|
||||
P_2 = P_1; P_1 = P;
|
||||
Q_2 = Q_1; Q_1 = Q;
|
||||
}
|
||||
if(Q > D) { Q = Q_1; P = P_1; }
|
||||
if(Q > D) { Q = Q_2; P = P_2; }
|
||||
if(Q > D) { if(Q_1 > D) { Q = Q_2; P = P_2; } else { Q = Q_1; P = P_1; } }
|
||||
if(!mixed) return [0, sgn * P, Q];
|
||||
if(Q===0) throw "Unexpected state: "+P+" "+P_1+" "+P_2+" "+Q+" "+Q_1+" "+Q_2;
|
||||
var q = Math.floor(sgn * P/Q);
|
||||
return [q, sgn*P - q*Q, Q];
|
||||
}
|
||||
@ -138,6 +139,8 @@ function general_fmt(v, opts) {
|
||||
case 'string': return v;
|
||||
case 'boolean': return v ? "TRUE" : "FALSE";
|
||||
case 'number': return (v|0) === v ? general_fmt_int(v, opts) : general_fmt_num(v, opts);
|
||||
case 'undefined': return "";
|
||||
case 'object': if(v == null) return "";
|
||||
}
|
||||
throw new Error("unsupported value in General format: " + v);
|
||||
}
|
||||
@ -310,16 +313,16 @@ function hashq(str) {
|
||||
}
|
||||
function rnd(val, d) { var dd = Math.pow(10,d); return ""+(Math.round(val * dd)/dd); }
|
||||
function dec(val, d) {
|
||||
if (d < ('' + Math.round((val-Math.floor(val))*Math.pow(10,d))).length) {
|
||||
return 0;
|
||||
}
|
||||
return Math.round((val-Math.floor(val))*Math.pow(10,d));
|
||||
if (d < ('' + Math.round((val-Math.floor(val))*Math.pow(10,d))).length) {
|
||||
return 0;
|
||||
}
|
||||
return Math.round((val-Math.floor(val))*Math.pow(10,d));
|
||||
}
|
||||
function carry(val, d) {
|
||||
if (d < ('' + Math.round((val-Math.floor(val))*Math.pow(10,d))).length) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
if (d < ('' + Math.round((val-Math.floor(val))*Math.pow(10,d))).length) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
function flr(val) { if(val < 2147483647 && val > -2147483648) return ""+(val >= 0 ? (val|0) : (val-1|0)); return ""+Math.floor(val); }
|
||||
function write_num_flt(type, fmt, val) {
|
||||
@ -342,7 +345,6 @@ function write_num_flt(type, fmt, val) {
|
||||
if((r = fmt.match(frac1))) return write_num_f1(r, aval, sign);
|
||||
if(fmt.match(/^#+0+$/)) return sign + pad0r(aval,fmt.length - fmt.indexOf("0"));
|
||||
if((r = fmt.match(dec1))) {
|
||||
// $FlowIgnore
|
||||
o = rnd(val, r[1].length).replace(/^([^\.]+)$/,"$1."+r[1]).replace(/\.$/,"."+r[1]).replace(/\.(\d*)$/,function($$, $1) { return "." + $1 + fill("0", r[1].length-$1.length); });
|
||||
return fmt.indexOf("0.") !== -1 ? o : o.replace(/^0\./,".");
|
||||
}
|
||||
@ -561,13 +563,13 @@ function fmt_is_date(fmt) {
|
||||
case '.':
|
||||
/* falls through */
|
||||
case '0': case '#':
|
||||
while(i < fmt.length && ("0#?.,E+-%".indexOf(c=fmt.charAt(++i)) > -1 || c=='\\' && fmt.charAt(i+1) == "-" && "0#".indexOf(fmt.charAt(i+2))>-1));
|
||||
while(i < fmt.length && ("0#?.,E+-%".indexOf(c=fmt.charAt(++i)) > -1 || c=='\\' && fmt.charAt(i+1) == "-" && "0#".indexOf(fmt.charAt(i+2))>-1)){}
|
||||
break;
|
||||
case '?': while(fmt.charAt(++i) === c); break;
|
||||
case '?': while(fmt.charAt(++i) === c){} break;
|
||||
case '*': ++i; if(fmt.charAt(i) == ' ' || fmt.charAt(i) == '*') ++i; break;
|
||||
case '(': case ')': ++i; break;
|
||||
case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
|
||||
while(i < fmt.length && "0123456789".indexOf(fmt.charAt(++i)) > -1); break;
|
||||
while(i < fmt.length && "0123456789".indexOf(fmt.charAt(++i)) > -1){} break;
|
||||
case ' ': ++i; break;
|
||||
default: ++i; break;
|
||||
}
|
||||
@ -623,7 +625,10 @@ function eval_fmt(fmt, v, opts, flen) {
|
||||
if(o.match(abstime)) {
|
||||
if(dt==null) { dt=parse_date_code(v, opts); if(dt==null) return ""; }
|
||||
out[out.length] = {t:'Z', v:o.toLowerCase()};
|
||||
} else { o=""; }
|
||||
} else if(o.indexOf("$") > -1) {
|
||||
o = (o.match(/\$([^-\[\]]*)/)||[])[1]||"$";
|
||||
if(!fmt_is_date(fmt)) out[out.length] = {t:'t',v:o};
|
||||
}
|
||||
break;
|
||||
/* Numbers */
|
||||
case '.':
|
||||
@ -659,7 +664,7 @@ function eval_fmt(fmt, v, opts, flen) {
|
||||
/* falls through */
|
||||
case 'd': case 'y': case 'M': case 'e': lst=out[i].t; break;
|
||||
case 'm': if(lst === 's') { out[i].t = 'M'; if(bt < 2) bt = 2; } break;
|
||||
case 'X': if(out[i].v === "B2");
|
||||
case 'X': /*if(out[i].v === "B2");*/
|
||||
break;
|
||||
case 'Z':
|
||||
if(bt < 1 && out[i].v.match(/[Hh]/)) bt = 1;
|
||||
@ -706,11 +711,20 @@ out[i].v = write_date(out[i].t.charCodeAt(0), out[i].v, dt, ss0);
|
||||
}
|
||||
var vv = "", myv, ostr;
|
||||
if(nstr.length > 0) {
|
||||
myv = (v<0&&nstr.charCodeAt(0) === 45 ? -v : v); /* '-' */
|
||||
ostr = write_num(nstr.charCodeAt(0) === 40 ? '(' : 'n', nstr, myv); /* '(' */
|
||||
if(nstr.charCodeAt(0) == 40) /* '(' */ {
|
||||
myv = (v<0&&nstr.charCodeAt(0) === 45 ? -v : v);
|
||||
ostr = write_num('(', nstr, myv);
|
||||
} else {
|
||||
myv = (v<0 && flen > 1 ? -v : v);
|
||||
ostr = write_num('n', nstr, myv);
|
||||
if(myv < 0 && out[0] && out[0].t == 't') {
|
||||
ostr = ostr.substr(1);
|
||||
out[0].v = "-" + out[0].v;
|
||||
}
|
||||
}
|
||||
jj=ostr.length-1;
|
||||
var decpt = out.length;
|
||||
for(i=0; i < out.length; ++i) if(out[i] != null && out[i].v.indexOf(".") > -1) { decpt = i; break; }
|
||||
for(i=0; i < out.length; ++i) if(out[i] != null && out[i].t != 't' && out[i].v.indexOf(".") > -1) { decpt = i; break; }
|
||||
var lasti=out.length;
|
||||
if(decpt === out.length && ostr.indexOf("E") === -1) {
|
||||
for(i=out.length-1; i>= 0;--i) {
|
||||
@ -798,11 +812,18 @@ function choose_fmt(f, v) {
|
||||
return [l, ff];
|
||||
}
|
||||
function format(fmt,v,o) {
|
||||
fixopts(o != null ? o : (o=[]));
|
||||
if(o == null) o = {};
|
||||
//fixopts(o != null ? o : (o=[]));
|
||||
var sfmt = "";
|
||||
switch(typeof fmt) {
|
||||
case "string": sfmt = fmt; break;
|
||||
case "number": sfmt = (o.table != null ? (o.table) : table_fmt)[fmt]; break;
|
||||
case "string":
|
||||
if(fmt == "m/d/yy" && o.dateNF) sfmt = o.dateNF;
|
||||
else sfmt = fmt;
|
||||
break;
|
||||
case "number":
|
||||
if(fmt == 14 && o.dateNF) sfmt = o.dateNF;
|
||||
else sfmt = (o.table != null ? (o.table) : table_fmt)[fmt];
|
||||
break;
|
||||
}
|
||||
if(isgeneral(sfmt,0)) return general_fmt(v, o);
|
||||
var f = choose_fmt(sfmt, v);
|
||||
@ -816,6 +837,7 @@ SSF.load = function load_entry(fmt, idx) { table_fmt[idx] = fmt; };
|
||||
SSF.format = format;
|
||||
SSF.get_table = function get_table() { return table_fmt; };
|
||||
SSF.load_table = function load_table(tbl) { for(var i=0; i!=0x0188; ++i) if(tbl[i] !== undefined) SSF.load(tbl[i], i); };
|
||||
SSF.init_table = init_table;
|
||||
};
|
||||
make_ssf(SSF);
|
||||
/*global module */
|
||||
|
16
test/dateNF.js
Normal file
16
test/dateNF.js
Normal file
@ -0,0 +1,16 @@
|
||||
/* vim: set ts=2: */
|
||||
/*jshint loopfunc:true, mocha:true, node:true */
|
||||
var SSF = require('../');
|
||||
var fs = require('fs'), assert = require('assert');
|
||||
describe('dateNF override', function() {
|
||||
it('should override format code 14', function() {
|
||||
assert.equal(SSF.format(14, 43880), "2/19/20");
|
||||
assert.equal(SSF.format(14, 43880, {dateNF:"yyyy-mm-dd"}), "2020-02-19");
|
||||
assert.equal(SSF.format(14, 43880, {dateNF:"dd/mm/yyyy"}), "19/02/2020");
|
||||
});
|
||||
it('should override format "m/d/yy"', function() {
|
||||
assert.equal(SSF.format('m/d/yy', 43880), "2/19/20");
|
||||
assert.equal(SSF.format('m/d/yy', 43880, {dateNF:"yyyy-mm-dd"}), "2020-02-19");
|
||||
assert.equal(SSF.format('m/d/yy', 43880, {dateNF:"dd/mm/yyyy"}), "19/02/2020");
|
||||
});
|
||||
});
|
@ -10,7 +10,7 @@ describe('General format', function() {
|
||||
assert.equal(SSF.format(d[1], d[0], {}), d[2]);
|
||||
});
|
||||
});
|
||||
it.skip('should handle special values', function() {
|
||||
it('should handle special values', function() {
|
||||
assert.equal(SSF.format("General", true), "TRUE");
|
||||
assert.equal(SSF.format("General", undefined), "");
|
||||
assert.equal(SSF.format("General", null), "");
|
||||
|
@ -31,7 +31,7 @@
|
||||
["#,##0.000000000", [1000000, "1,000,000.000000000"]],
|
||||
["#,###", [1, "1"], [-1, "-1"], [0,""], [12345.6789, "12,346"], ["TODO", "TODO"]],
|
||||
["#.##", [1, "1."], [-1, "-1."], [0,"."], ["sheetjs", "sheetjs"]],
|
||||
["0;0", [1.1, "1"], [-1.1, "-1"], [0,"0"], ["sheetjs", "sheetjs"]],
|
||||
["0;0", [1.1, "1"], [-1.1, "1"], [0,"0"], ["sheetjs", "sheetjs"]],
|
||||
["0.0", [1, "1.0"], [-1, "-1.0"], [0,"0.0"], ["sheetjs", "sheetjs"]],
|
||||
["0.00", [1.0001, "1.00"], [-1, "-1.00"], [0,"0.00"], ["sheetjs", "sheetjs"]],
|
||||
["0.000", [1, "1.000"], [-1, "-1.000"], [0,"0.000"], ["sheetjs", "sheetjs"]],
|
||||
@ -146,6 +146,14 @@
|
||||
["☃", [0], [1], [-1]],
|
||||
["#0#######", [12345, "012345"], [12345.4321, "012345"], [12345.6789, "012346"]],
|
||||
["##,##", [12345, "12,345", ""], [12345.4321, "12,345", ""], [12345.6789, "12,346", ""]],
|
||||
[0, [12345,"12345"], [4294967296.5, 4294967297]],
|
||||
[0, [12345,"12345"], [4294967296.5, "4294967297"]],
|
||||
["\"Rs.\"#,##0.00", [-51968287, "-Rs.51,968,287.00"], [2000000, "Rs.2,000,000.00"]],
|
||||
["$#.00", [3.14159, "$3.14"], [-3.14159, "-$3.14"]],
|
||||
["\"This is a \".00\"test\"000", [-3.14159, "-This is a 3.14test159"], [3.14159, "This is a 3.14test159"]],
|
||||
["[$INR]\\ #,##0.00", [3.14159, "INR 3.14"], [-3.14159, "-INR 3.14"]],
|
||||
["[$₹-4009]\\ #,##0.00", [3.14159, "₹ 3.14"], [-3.14159, "-₹ 3.14"]],
|
||||
["[$£-809]#,##0.0000;\\-[$£-809]#,##0.0000", [3.14159, "£3.1416"], [-3.14159, "-£3.1416"]],
|
||||
["\"-\"0.00", [3.14159, "-3.14"], [-3.14159, "--3.14"]],
|
||||
["[$-409]mmm\\-yy", [12345, "Oct-33"]],
|
||||
["\"foo\";\"bar\";\"baz\";\"qux\";\"foobar\"", [1], [0], [-1], ["sheetjs"]]
|
||||
]
|
||||
|
Loading…
Reference in New Issue
Block a user