diff --git a/package.json b/package.json index 316b65f..e444f0f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ssf", - "version": "0.5.5", + "version": "0.5.6", "author": "SheetJS", "description": "pure-JS library to format data using ECMA-376 spreadsheet Format Codes", "keywords": [ "format", "sprintf", "spreadsheet" ], diff --git a/ssf.js b/ssf.js index da25f77..f776ee7 100644 --- a/ssf.js +++ b/ssf.js @@ -5,7 +5,7 @@ var _strrev = function(x) { return String(x).split("").reverse().join("");}; function fill(c,l) { return new Array(l+1).join(c); } function pad(v,d,c){var t=String(v);return t.length>=d?t:(fill(c||0,d-t.length)+t);} function rpad(v,d,c){var t=String(v);return t.length>=d?t:(t+fill(c||0,d-t.length));} -SSF.version = '0.5.5'; +SSF.version = '0.5.6'; /* Options */ var opts_fmt = {}; function fixopts(o){for(var y in opts_fmt) if(o[y]===undefined) o[y]=opts_fmt[y];} @@ -212,13 +212,19 @@ var write_num = function(type, fmt, val) { if(fmt.indexOf("E") > -1) { var idx = fmt.indexOf("E") - fmt.indexOf(".") - 1; if(fmt == '##0.0E+0') { - var period = fmt.length - 5; + var period = fmt.indexOf("."); if(period === -1) period=fmt.indexOf('E'); var ee = (Number(val.toExponential(0).substr(2+(val<0))))%period; + if(ee < 0) ee += period; o = (val/Math.pow(10,ee)).toPrecision(idx+1+(period+ee)%period); if(!o.match(/[Ee]/)) { var fakee = (Number(val.toExponential(0).substr(2+(val<0)))); if(o.indexOf(".") === -1) o = o[0] + "." + o.substr(1) + "E+" + (fakee - o.length+ee); - else throw "missing E |" + o; + else o += "E+" + (fakee - ee); + while(o.substr(0,2) === "0.") { + o = o[0] + o.substr(2,period) + "." + o.substr(2+period); + o = o.replace(/^0+([1-9])/,"$1").replace(/^0+\./,"0."); + } + o = o.replace(/\+-/,"-"); } o = o.replace(/^([+-]?)([0-9]*)\.([0-9]*)[Ee]/,function($$,$1,$2,$3) { return $1 + $2 + $3.substr(0,(period+ee)%period) + "." + $3.substr(ee) + "E"; }); } else o = val.toExponential(idx); @@ -233,6 +239,7 @@ var write_num = function(type, fmt, val) { var myn = (rnd - base*den), myd = den; return sign + (base?base:"") + " " + (myn === 0 ? fill(" ", r[1].length + 1 + r[4].length) : pad(myn,r[1].length," ") + r[2] + "/" + r[3] + pad(myd,r[4].length)); } + if(fmt.match(/^#+0+$/)) fmt = fmt.replace(/#/g,""); if(fmt.match(/^00+$/)) return (val<0?"-":"")+pad(Math.round(aval),fmt.length); if(fmt.match(/^[#?]+$/)) return String(Math.round(val)).replace(/^0$/,""); if((r = fmt.match(/^#*0+\.(0+)/))) { @@ -343,7 +350,7 @@ function eval_fmt(fmt, v, opts, flen) { out.push({t:'D', v:o}); break; case ' ': out.push({t:c,v:c}); ++i; break; default: - if(",$-+/():!^&'~{}<>=".indexOf(c) === -1) + if(",$-+/():!^&'~{}<>=€".indexOf(c) === -1) throw 'unrecognized character ' + fmt[i] + ' in ' + fmt; out.push({t:'t', v:c}); ++i; break; } @@ -367,7 +374,7 @@ function eval_fmt(fmt, v, opts, flen) { out[i].t = 't'; break; case 'n': case '(': case '?': var jj = i+1; - while(out[jj] && ("?D".indexOf(out[jj].t) > -1 || (" t".indexOf(out[jj].t) > -1 && "?t".indexOf((out[jj+1]||{}).t)>-1 && (out[jj+1].t == '?' || out[jj+1].v == '/')) || out[i].t == '(' && (out[jj].t == ')' || out[jj].t == 'n') || out[jj].t == 't' && (out[jj].v == '/' || out[jj].v == '$' || (out[jj].v == ' ' && (out[jj+1]||{}).t == '?')))) { + while(out[jj] && ("?D".indexOf(out[jj].t) > -1 || (" t".indexOf(out[jj].t) > -1 && "?t".indexOf((out[jj+1]||{}).t)>-1 && (out[jj+1].t == '?' || out[jj+1].v == '/')) || out[i].t == '(' && (out[jj].t == ')' || out[jj].t == 'n') || out[jj].t == 't' && (out[jj].v == '/' || '$€'.indexOf(out[jj].v) > -1 || (out[jj].v == ' ' && (out[jj+1]||{}).t == '?')))) { out[i].v += out[jj].v; delete out[jj]; ++jj; } diff --git a/ssf.md b/ssf.md index 6b00563..7049176 100644 --- a/ssf.md +++ b/ssf.md @@ -377,8 +377,9 @@ For the special case of engineering notation, "shift" the decimal: ``` if(fmt == '##0.0E+0') { - var period = fmt.length - 5; + var period = fmt.indexOf("."); if(period === -1) period=fmt.indexOf('E'); var ee = (Number(val.toExponential(0).substr(2+(val<0))))%period; + if(ee < 0) ee += period; o = (val/Math.pow(10,ee)).toPrecision(idx+1+(period+ee)%period); if(!o.match(/[Ee]/)) { ``` @@ -388,7 +389,12 @@ TODO: something reasonable ``` var fakee = (Number(val.toExponential(0).substr(2+(val<0)))); if(o.indexOf(".") === -1) o = o[0] + "." + o.substr(1) + "E+" + (fakee - o.length+ee); - else throw "missing E |" + o; + else o += "E+" + (fakee - ee); + while(o.substr(0,2) === "0.") { + o = o[0] + o.substr(2,period) + "." + o.substr(2+period); + o = o.replace(/^0+([1-9])/,"$1").replace(/^0+\./,"0."); + } + o = o.replace(/\+-/,"-"); } o = o.replace(/^([+-]?)([0-9]*)\.([0-9]*)[Ee]/,function($$,$1,$2,$3) { return $1 + $2 + $3.substr(0,(period+ee)%period) + "." + $3.substr(ee) + "E"; }); } else o = val.toExponential(idx); @@ -418,6 +424,7 @@ Fractions with known denominator are resolved by rounding: A few special general cases can be handled in a very dumb manner: ``` + if(fmt.match(/^#+0+$/)) fmt = fmt.replace(/#/g,""); if(fmt.match(/^00+$/)) return (val<0?"-":"")+pad(Math.round(aval),fmt.length); if(fmt.match(/^[#?]+$/)) return String(Math.round(val)).replace(/^0$/,""); if((r = fmt.match(/^#*0+\.(0+)/))) { @@ -638,7 +645,7 @@ The default magic characters are listed in subsubsections 18.8.30-31 of ECMA376: ``` case ' ': out.push({t:c,v:c}); ++i; break; default: - if(",$-+/():!^&'~{}<>=".indexOf(c) === -1) + if(",$-+/():!^&'~{}<>=€".indexOf(c) === -1) throw 'unrecognized character ' + fmt[i] + ' in ' + fmt; out.push({t:'t', v:c}); ++i; break; } @@ -662,7 +669,7 @@ The default magic characters are listed in subsubsections 18.8.30-31 of ECMA376: out[i].t = 't'; break; case 'n': case '(': case '?': var jj = i+1; - while(out[jj] && ("?D".indexOf(out[jj].t) > -1 || (" t".indexOf(out[jj].t) > -1 && "?t".indexOf((out[jj+1]||{}).t)>-1 && (out[jj+1].t == '?' || out[jj+1].v == '/')) || out[i].t == '(' && (out[jj].t == ')' || out[jj].t == 'n') || out[jj].t == 't' && (out[jj].v == '/' || out[jj].v == '$' || (out[jj].v == ' ' && (out[jj+1]||{}).t == '?')))) { + while(out[jj] && ("?D".indexOf(out[jj].t) > -1 || (" t".indexOf(out[jj].t) > -1 && "?t".indexOf((out[jj+1]||{}).t)>-1 && (out[jj+1].t == '?' || out[jj+1].v == '/')) || out[i].t == '(' && (out[jj].t == ')' || out[jj].t == 'n') || out[jj].t == 't' && (out[jj].v == '/' || '$€'.indexOf(out[jj].v) > -1 || (out[jj].v == ' ' && (out[jj+1]||{}).t == '?')))) { out[i].v += out[jj].v; delete out[jj]; ++jj; } @@ -960,7 +967,7 @@ coveralls: ```json>package.json { "name": "ssf", - "version": "0.5.5", + "version": "0.5.6", "author": "SheetJS", "description": "pure-JS library to format data using ECMA-376 spreadsheet Format Codes", "keywords": [ "format", "sprintf", "spreadsheet" ], diff --git a/test/exp.tsv b/test/exp.tsv index f7c420c..8d7c132 100644 --- a/test/exp.tsv +++ b/test/exp.tsv @@ -12,9 +12,9 @@ value #0.0E+0 ##0.0E+0 ###0.0E+0 ####0.0E+0 0.001234568 12.3E-4 1.2E-3 12.3E-4 123.5E-5 0.012345679 1.2E-2 12.3E-3 123.5E-4 1234.6E-5 0.123456789 12.3E-2 123.5E-3 1234.6E-4 12345.7E-5 -1.23456789 1.2E+0 |1.2E+0 1.2E+0 1.2E+0 -12.3456789 12.3E+0 |12.3E+0 12.3E+0 12.3E+0 -123.456789 1.2E+2 |123.5E+0 123.5E+0 123.5E+0 +1.23456789 1.2E+0 1.2E+0 1.2E+0 1.2E+0 +12.3456789 12.3E+0 12.3E+0 12.3E+0 12.3E+0 +123.456789 1.2E+2 123.5E+0 123.5E+0 123.5E+0 1234.56789 12.3E+2 1.2E+3 1234.6E+0 1234.6E+0 12345.6789 1.2E+4 12.3E+3 1.2E+4 12345.7E+0 123456.789 12.3E+4 123.5E+3 12.3E+4 1.2E+5 @@ -40,7 +40,7 @@ value #0.0E+0 ##0.0E+0 ###0.0E+0 ####0.0E+0 12345678900000000000000000 12.3E+24 12.3E+24 12.3E+24 1.2E+25 123456789000000000000000000 1.2E+26 123.5E+24 123.5E+24 12.3E+25 1234567890000000000000000000 12.3E+26 1.2E+27 1234.6E+24 123.5E+25 -12345678900000000000000000000 1.2E+28 12.3E+27 1.2E+28 |1234.6E+25 -123456789000000000000000000000 |12.3E+28 123.5E+27 |12.3E+28 |12345.7E+25 -1234567890000000000000000000000 1.2E+30 1.2E+30 |123.5E+28 1.2E+30 -12345678900000000000000000000000 |12.3E+30 12.3E+30 |1234.6E+28 |12.3E+30 +12345678900000000000000000000 1.2E+28 12.3E+27 1.2E+28 1234.6E+25 +123456789000000000000000000000 12.3E+28 123.5E+27 12.3E+28 12345.7E+25 +1234567890000000000000000000000 1.2E+30 1.2E+30 123.5E+28 1.2E+30 +12345678900000000000000000000000 12.3E+30 12.3E+30 1234.6E+28 12.3E+30 diff --git a/test/implied.json b/test/implied.json index ce5b3c6..d23ea16 100644 --- a/test/implied.json +++ b/test/implied.json @@ -1,6 +1,6 @@ [ [1234567890000, [ - [0, "1.23457E+12", true], + [0, "1.23457E+12"], [1, "1234567890000"], [2, "1234567890000.00"], [3, "1,234,567,890,000"], @@ -27,7 +27,7 @@ [46, ""], [47, ""], [48, "1.2E+12"], - [49, "1.23457E+12", true] + [49, "1.23457E+12"] ]], [123456789000, [ @@ -57,8 +57,8 @@ [45, ""], [46, ""], [47, ""], - [48, "123.5E+9", true], - [49, "1.23457E+11", true] + [48, "123.5E+9"], + [49, "1.23457E+11"] ]], [12345678900, [ @@ -336,7 +336,7 @@ [45, "57:47"], [46, "2962:57:47"], [47, "5746.6"], - [48, "123.5E+0", true], + [48, "123.5E+0"], [49, "123.456789"] ]], @@ -367,7 +367,7 @@ [45, "17:47"], [46, "296:17:47"], [47, "1746.7"], - [48, "12.3E+0", true], + [48, "12.3E+0"], [49, "12.3456789"] ]], @@ -398,7 +398,7 @@ [45, "37:47"], [46, "29:37:47"], [47, "3746.7"], - [48, "1.2E+0", true], + [48, "1.2E+0"], [49, "1.23456789"] ]], @@ -429,8 +429,8 @@ [45, "57:47"], [46, "2:57:47"], [47, "5746.7"], - [48, "123.5E-3", true], - [49, "0.123456789", true] + [48, "123.5E-3"], + [49, "0.123456789"] ]], [0.0123456789, [ @@ -460,8 +460,8 @@ [45, "17:47"], [46, "0:17:47"], [47, "1746.7"], - [48, "12.3E-3", true], - [49, "0.012345679", true] + [48, "12.3E-3"], + [49, "0.012345679"] ]], [0.00123456789, [ @@ -491,8 +491,8 @@ [45, "01:47"], [46, "0:01:47"], [47, "0146.7"], - [48, "1.2E-3", true], - [49, "0.001234568", true] + [48, "1.2E-3"], + [49, "0.001234568"] ]], [0.000123456789, [ @@ -522,8 +522,8 @@ [45, "00:11"], [46, "0:00:11"], [47, "0010.7"], - [48, "123.5E-6", true], - [49, "0.000123457", true] + [48, "123.5E-6"], + [49, "0.000123457"] ]], [0.0000123456789, [ @@ -553,8 +553,8 @@ [45, "00:01"], [46, "0:00:01"], [47, "0001.1"], - [48, "12.3E-6", true], - [49, "1.23457E-05", true] + [48, "12.3E-6"], + [49, "1.23457E-05"] ]], [0.00000123456789, [ @@ -584,8 +584,8 @@ [45, "00:00"], [46, "0:00:00"], [47, "0000.1"], - [48, "1.2E-6", true], - [49, "1.23457E-06", true] + [48, "1.2E-6"], + [49, "1.23457E-06"] ]], [0.000000123456789, [ @@ -615,8 +615,8 @@ [45, "00:00"], [46, "0:00:00"], [47, "0000.0"], - [48, "123.5E-9", true], - [49, "1.23457E-07", true] + [48, "123.5E-9"], + [49, "1.23457E-07"] ]], [0.0000000123456789, [ @@ -646,8 +646,8 @@ [45, "00:00"], [46, "0:00:00"], [47, "0000.0"], - [48, "12.3E-9", true], - [49, "1.23457E-08", true] + [48, "12.3E-9"], + [49, "1.23457E-08"] ]], [0.00000000123456789, [ @@ -677,8 +677,8 @@ [45, "00:00"], [46, "0:00:00"], [47, "0000.0"], - [48, "1.2E-9", true], - [49, "1.23457E-09", true] + [48, "1.2E-9"], + [49, "1.23457E-09"] ]], [0.000000000123456789, [ @@ -708,8 +708,8 @@ [45, "00:00"], [46, "0:00:00"], [47, "0000.0"], - [48, "123.5E-12", true], - [49, "1.23457E-10", true] + [48, "123.5E-12"], + [49, "1.23457E-10"] ]],