pulling ssf into main project [ci skip]

This commit is contained in:
SheetJS 2022-03-09 06:28:51 -05:00
commit b738e5d3f1
94 changed files with 2408184 additions and 0 deletions

1
packages/ssf-cli/.gitignore vendored Normal file

@ -0,0 +1 @@
node_modules/

@ -0,0 +1 @@
*.tgz

@ -0,0 +1,48 @@
# [SSF Command-Line Interface](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).
This CLI tool formats numbers from shell scripts and other command-line tools.
## Installation
With [npm](https://www.npmjs.org/package/ssf-cli):
```bash
$ npm install -g ssf-cli
```
## Usage
`ssf-cli` takes two arguments: the format string and the value to be formatted.
The value is formatted twice, once interpreting the value as a string and once
interpreting the value as a number, and both results are printed to standard
output, with a pipe character `|` after each value:
```bash
$ bin/ssf.njs "#,##0.00" 12345
12345|12,345.00|
$ bin/ssf.njs "0;0;0;:@:" 12345
:12345:|12345|
```
Extracting the values in a pipeline is straightforward with AWK:
```bash
$ bin/ssf.njs "#,##0.00" 12345 | awk -F\| '{print $2}'
12,345.00
```
## License
Please consult the attached LICENSE file for details. All rights not explicitly
granted by the Apache 2.0 license are reserved by the Original Author.
## Credits
Special thanks to [Garrett Luu](https://garrettluu.com/) for spinning off the
command from the SSF module.
[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/ssf?pixel)](https://github.com/SheetJS/ssf)

8
packages/ssf-cli/bin/ssf.njs Executable file

@ -0,0 +1,8 @@
#!/usr/bin/env node
/* ssf.js (C) 2013-present SheetJS -- http://sheetjs.com */
/* eslint-env node */
/* eslint no-console:0 */
/*jshint node:true */
var cli = require('../');
cli();

16
packages/ssf-cli/index.js Normal file

@ -0,0 +1,16 @@
/* ssf.js (C) 2013-present SheetJS -- http://sheetjs.com */
/* eslint-env node */
/* eslint no-console:0 */
/*jshint node:true */
var X = require('ssf');
function run() {
var argv = process.argv.slice(2);
if (argv.length < 2 || argv[0] == "-h" || argv[0] == "--help") {
console.error("usage: ssf-cli <format> <value>");
console.error("output: format_as_string|format_as_number|");
process.exit(0);
}
console.log(X.format(argv[0], argv[1]) + "|" + X.format(argv[0], +(argv[1])) + "|");
}
module.exports = run;

@ -0,0 +1,31 @@
{
"name": "ssf-cli",
"version": "1.1.0",
"author": "sheetjs",
"description": "Command-line interface for ssf",
"keywords": [
"format",
"sprintf",
"spreadsheet"
],
"main": "index.js",
"bin": {
"ssf-cli": "bin/ssf.njs"
},
"dependencies": {
"ssf": "^0.11.2"
},
"repository": {
"type": "git",
"url": "git://github.com/SheetJS/sheetjs.git",
"directory": "packages/ssf-cli"
},
"homepage": "http://sheetjs.com/",
"bugs": {
"url": "https://github.com/SheetJS/sheetjs/issues"
},
"license": "Apache-2.0",
"engines": {
"node": ">=0.8"
}
}

24
packages/ssf/.eslintrc Normal file

@ -0,0 +1,24 @@
{
"env": { "shared-node-browser":true },
"globals": {},
"parserOptions": {
"ecmaVersion": 3
},
"plugins": [ "html", "json" ],
"extends": "eslint:recommended",
"rules": {
"comma-style": [ 2, "last" ],
"comma-dangle": [ 2, "never" ],
"curly": 0,
"no-bitwise": 0,
"no-console": 0,
"no-control-regex": 0,
"no-empty": 0,
"no-trailing-spaces": 2,
"no-use-before-define": [ 1, {
"functions":false, "classes":true, "variables":false
}],
"no-useless-escape": 0,
"semi": [ 2, "always" ]
}
}

31
packages/ssf/.flowconfig Normal file

@ -0,0 +1,31 @@
[ignore]
.*/node_modules/.*
.*/dist/.*
.*/test/bits/.*
.*/test/.*
.*/ssf.js
.*/ssf_lc.js
.*/bits/.*
.*/ctest/.*
.*/misc/.*
.*/perf/.*
.*/tmp/.*
.*/tmp/.*
.*/demo/browser.js
.*/shim.js
[include]
ssf.flow.js
.*/bin/.*.njs
[libs]
misc/flow.js
misc/flowdeps.js
[options]
module.file_ext=.js
module.file_ext=.njs
module.ignore_non_literal_requires=true
suppress_comment= \\(.\\|\n\\)*\\$FlowIgnore

28
packages/ssf/.gitignore vendored Normal file

@ -0,0 +1,28 @@
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*

6
packages/ssf/.jscs.json Normal file

@ -0,0 +1,6 @@
{
"requireCommaBeforeLineBreak": true,
"disallowTrailingWhitespace": true,
"disallowTrailingComma": true
}

51
packages/ssf/.npmignore Normal file

@ -0,0 +1,51 @@
test/
ctest/
index.html
misc/
packages/
node_modules
*.tgz
_book
book.json
tmp
mocha.js
*.[tT][xX][tT]
*.[cC][sS][vV]
*.[dD][iIbB][fF]
*.[pP][rR][nN]
*.[sS][lL][kK]
*.socialcalc
*.[xX][lL][sSwWcCaAtTmM]
*.[xX][lL][sSaAtT][xXmMbB]
*.[oO][dD][sS]
*.[fF][oO][dD][sS]
*.[xX][mM][lL]
*.[uU][oO][sS]
*.[wW][kKqQbB][S1234567890]
*.[qQ][pP][wW]
*.[bB][iI][fF][fF][23458]
*.[rR][tT][fF]
*.[eE][tT][hH]
*.123
*.htm
*.html
*.sheetjs
*.exe
*.img
.gitignore
.gitattributes
.fossaignore
.spelling
.eslintrc
.jshintrc
Makefile
.npmignore
.jscs.json
.gitmodules
.travis.yml
.flowconfig
bits/
.vocrc
v8.log
perf.log
ssf.md

9
packages/ssf/.spelling Normal file

@ -0,0 +1,9 @@
# ssf.js (C) 2013-present SheetJS -- http://sheetjs.com
SheetJS
ssf
ECMA-376
xls
xlsb
npm

45
packages/ssf/.travis.yml Normal file

@ -0,0 +1,45 @@
language: node_js
dist: xenial
node_js:
- "14"
- "13"
- "12"
- "11"
- "10"
- "9"
- "8"
- "7"
- "6"
- "5"
- "4"
- "0.12"
- "0.10"
- "0.8"
matrix:
include:
- node_js: "14"
env: TZ="America/New_York"
- node_js: "12"
env: TZ="America/Los_Angeles"
- node_js: "10"
env: TZ="Europe/London"
- node_js: "8"
env: TZ="Europe/Berlin"
- node_js: "6"
env: TZ="Asia/Kolkata"
- node_js: "4"
env: TZ="Asia/Shanghai"
- node_js: "0.12"
env: TZ="Asia/Seoul"
before_install:
- "npm config set strict-ssl false"
- "./misc/node_version.sh"
- "npm install -g mocha@2.x voc"
- "npm install blanket"
- "npm install word"
- "npm install coveralls mocha-lcov-reporter"
install:
- npm install
after_success:
- "make coveralls"

201
packages/ssf/LICENSE Normal file

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright (C) 2013-present SheetJS LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

124
packages/ssf/Makefile Executable file

@ -0,0 +1,124 @@
SHELL=/bin/bash
LIB=ssf
REQS=
ADDONS=
AUXTARGETS=
CMDS=bin/ssf.njs
HTMLLINT=index.html
ULIB=$(shell echo $(LIB) | tr a-z A-Z)
DEPS=$(sort $(wildcard bits/*.js))
TARGET=$(LIB).js
FLOWTARGET=$(LIB).flow.js
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
.PHONY: all
all: $(TARGET) $(AUXTARGETS) $(AUXSCPTS) ## Build library and auxiliary scripts
$(FLOWTGTS): %.js : %.flow.js
node -e 'process.stdout.write(require("fs").readFileSync("$<","utf8").replace(/^[ \t]*\/\*[:#][^*]*\*\/\s*(\n)?/gm,"").replace(/\/\*[:#][^*]*\*\//gm,""))' > $@
$(FLOWTARGET): $(DEPS)
cat $^ | tr -d '\15\32' > $@
bits/01_version.js: package.json
echo "$(ULIB).version = '"`grep version package.json | awk '{gsub(/[^0-9a-z\.-]/,"",$$2); print $$2}'`"';" > $@
.PHONY: clean
clean: ## Remove targets and build artifacts
rm -f $(TARGET) $(FLOWTARGET)
.PHONY: git
git: ## show version string
@echo "$$(node -pe 'require("./package.json").version') (ssf)"
## Testing
.PHONY: test mocha
test mocha: ## Run test suite
mocha -R spec -t 30000
.PHONY: test_misc
test_misc:
MINTEST=1 mocha -R spec -t 30000
.PHONY: travis
travis: ## Run test suite with minimal output
mocha -R dot -t 30000
.PHONY: ctest
ctest: ## Build browser test fixtures
browserify -t brfs test/{comma,dateNF,dates,exp,fraction,general,implied,oddities,utilities,valid}.js > ctest/test.js
.PHONY: ctestserv
ctestserv: ## Start a test server on port 8000
@cd ctest && python -mSimpleHTTPServer
## Code Checking
.PHONY: fullint
fullint: lint old-lint tslint flow mdlint ## Run all checks
.PHONY: lint
lint: $(TARGET) $(AUXTARGETS) ## Run eslint checks
@eslint --ext .js,.njs,.json,.html,.htm $(TARGET) $(AUXTARGETS) $(CMDS) $(HTMLLINT) package.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 $(CMDS)
@jshint --show-non-errors package.json test/
@jshint --show-non-errors --extract=always $(HTMLLINT)
@jscs $(TARGET) $(AUXTARGETS) test/*.js
if [ -e $(CLOSURE) ]; then java -jar $(CLOSURE) $(REQS) $(FLOWTARGET) --jscomp_warning=reportUnknownTypes >/dev/null; fi
.PHONY: tslint
tslint: $(TARGET) ## Run typescript checks
#@npm install dtslint typescript
#@npm run-script dtslint
dtslint types
.PHONY: flow
flow: lint ## Run flow checker
@flow check --all --show-all-errors
.PHONY: cov
cov: misc/coverage.html ## Run coverage test
.PHONY: cov_min
cov_min:
MINTEST=1 make cov
misc/coverage.html: $(TARGET)
mocha --require blanket -R html-cov -t 20000 > $@
.PHONY: full_coveralls
full_coveralls:
mocha --require blanket --reporter mocha-lcov-reporter | ./node_modules/coveralls/bin/coveralls.js
.PHONY: coveralls
coveralls: ## Coverage Test + Send to coveralls.io
MINTEST=1 make full_coveralls
MDLINT=README.md
.PHONY: mdlint
mdlint: $(MDLINT) ## Check markdown documents
alex $^
mdspell -a -n -x -r --en-us $^
.PHONY: help
help:
@grep -hE '(^[a-zA-Z_-][ a-zA-Z_-]*:.*?|^#[#*])' $(MAKEFILE_LIST) | bash misc/help.sh
#* To show a spinner, append "-spin" to any target e.g. cov-spin
%-spin:
@make $* & bash misc/spin.sh $$!

119
packages/ssf/README.md Normal file

@ -0,0 +1,119 @@
# [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).
This is the community version. We also offer a pro version with additional
features like international support as well as dedicated support.
## Installation
With [npm](https://www.npmjs.org/package/ssf):
```bash
$ npm install ssf
```
In the browser:
```html
<script src="ssf.js"></script>
```
The browser exposes a variable `SSF`
When installed globally, npm installs a script `ssf` that renders the format
string with the given arguments. Running the script with `-h` displays help.
The script will manipulate `module.exports` if available . This is not always
desirable. To prevent the behavior, define `DO_NOT_EXPORT_SSF`.
## Usage
`SSF.format(fmt, val, opts)` formats `val` using the format `fmt`.
If `fmt` is a string, it will be parsed and evaluated. If `fmt` is a `number`,
the actual format will be the corresponding entry in the internal format table.
For a raw numeric format like `000`, the value should be passed as a string.
Date arguments are interpreted in the local time of the JS client.
The options argument may contain the following keys:
| Option Name | Default | Description |
| :---------- | :-----: | :--------------------------------------------------- |
| `date1904` | false | Use 1904 date system if true, 1900 system if false |
### Manipulating the Internal Format Table
Binary spreadsheet formats store cell formats in a table and reference by index.
This library uses a global table:
`SSF._table` is the underlying object, mapping numeric keys to format strings.
`SSF.load(fmt:string, idx:?number):number` assigns the format to the specified
index and returns the index. If the index is not specified, SSF will search the
space for an available format slot pick an unused slot. For compatibility with
the XLS and XLSB file formats, custom indices should be in the valid ranges
`5-8`, `23-26`, `41-44`, `63-66`, `164-382` (see `[MS-XLSB] 2.4.655 BrtFmt`)
`SSF.get_table()` gets the internal format table (number to format mapping).
`SSF.load_table(table)` sets the internal format table.
### Other Utilities
`SSF.parse_date_code(val:number, opts:?any)` parses `val`, returning an object:
```typescript
type SSFDate = {
D:number; /* number of whole days since relevant epoch, 0 <= D */
y:number; /* integral year portion, epoch_year <= y */
m:number; /* integral month portion, 1 <= m <= 12 */
d:number; /* integral day portion, subject to gregorian YMD constraints */
q:number; /* integral day of week (0=Sunday .. 6=Saturday) 0 <= q <= 6 */
T:number; /* number of seconds since midnight, 0 <= T < 86400 */
H:number; /* integral number of hours since midnight, 0 <= H < 24 */
M:number; /* integral number of minutes since the last hour, 0 <= M < 60 */
S:number; /* integral number of seconds since the last minute, 0 <= S < 60 */
u:number; /* sub-second part of time, 0 <= u < 1 */
}
```
`SSF.is_date(fmt:string):boolean` returns `true` if `fmt` encodes a date format.
## Examples
- [Basic Demo](http://oss.sheetjs.com/ssf/)
- [Custom Formats Builder](https://customformats.com)
## Related Packages
[`ssf-cli`](https://www.npmjs.com/package/ssf-cli) is a simple NodeJS command
line tool for formatting numbers.
## License
Please consult the attached LICENSE file for details. All rights not explicitly
granted by the Apache 2.0 license are reserved by the Original Author.
## References
- `ECMA-376`: Office Open XML File Formats
- `MS-XLS`: Excel Binary File Format (.xls) Structure Specification
- `MS-XLSB`: Excel (.xlsb) Binary File Format
## Badges
[![Sauce Test Status](https://saucelabs.com/browser-matrix/ssfjs.svg)](https://saucelabs.com/u/ssfjs)
[![Build Status](https://travis-ci.org/SheetJS/ssf.svg?branch=master)](https://travis-ci.org/SheetJS/ssf)
[![Coverage Status](http://img.shields.io/coveralls/SheetJS/ssf/master.svg)](https://coveralls.io/r/SheetJS/ssf?branch=master)
[![NPM Downloads](https://img.shields.io/npm/dt/ssf.svg)](https://npmjs.org/package/ssf)
[![Dependencies Status](https://david-dm.org/sheetjs/ssf/status.svg)](https://david-dm.org/sheetjs/ssf)
[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/ssf?pixel)](https://github.com/SheetJS/ssf)

@ -0,0 +1,6 @@
/* ssf.js (C) 2013-present SheetJS -- http://sheetjs.com */
/* vim: set ts=2: */
/*jshint -W041 */
/*:: declare var DO_NOT_EXPORT_SSF: any; */
var SSF/*:SSFModule*/ = ({}/*:any*/);
var make_ssf = function make_ssf(SSF/*:SSFModule*/){

@ -0,0 +1 @@
SSF.version = '0.11.2';

@ -0,0 +1,10 @@
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;}
function pad_(v/*:any*/,d/*:number*/)/*:string*/{var t=""+v;return t.length>=d?t:fill(' ',d-t.length)+t;}
function rpad_(v/*:any*/,d/*:number*/)/*:string*/{var t=""+v; return t.length>=d?t:t+fill(' ',d-t.length);}
function pad0r1(v/*:any*/,d/*:number*/)/*:string*/{var t=""+Math.round(v); return t.length>=d?t:fill('0',d-t.length)+t;}
function pad0r2(v/*:any*/,d/*:number*/)/*:string*/{var t=""+v; return t.length>=d?t:fill('0',d-t.length)+t;}
var p2_32 = Math.pow(2,32);
function pad0r(v/*:any*/,d/*:number*/)/*:string*/{if(v>p2_32||v<-p2_32) return pad0r1(v,d); var i = Math.round(v); return pad0r2(i,d); }
function isgeneral(s/*:string*/, i/*:?number*/)/*:boolean*/ { i = i || 0; return s.length >= 7 + i && (s.charCodeAt(i)|32) === 103 && (s.charCodeAt(i+1)|32) === 101 && (s.charCodeAt(i+2)|32) === 110 && (s.charCodeAt(i+3)|32) === 101 && (s.charCodeAt(i+4)|32) === 114 && (s.charCodeAt(i+5)|32) === 97 && (s.charCodeAt(i+6)|32) === 108; }

@ -0,0 +1,3 @@
/*::
type SSF_write_num = {(type:string, fmt:string, val:number):string};
*/

@ -0,0 +1,23 @@
var days/*:Array<Array<string> >*/ = [
['Sun', 'Sunday'],
['Mon', 'Monday'],
['Tue', 'Tuesday'],
['Wed', 'Wednesday'],
['Thu', 'Thursday'],
['Fri', 'Friday'],
['Sat', 'Saturday']
];
var months/*:Array<Array<string> >*/ = [
['J', 'Jan', 'January'],
['F', 'Feb', 'February'],
['M', 'Mar', 'March'],
['A', 'Apr', 'April'],
['M', 'May', 'May'],
['J', 'Jun', 'June'],
['J', 'Jul', 'July'],
['A', 'Aug', 'August'],
['S', 'Sep', 'September'],
['O', 'Oct', 'October'],
['N', 'Nov', 'November'],
['D', 'Dec', 'December']
];

@ -0,0 +1,34 @@
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"秒 "';
}
var table_fmt = {};
init_table(table_fmt);

@ -0,0 +1,55 @@
/* Defaults determined by systematically testing in Excel 2019 */
/* These formats appear to default to other formats in the table */
var default_map/*:Array<number>*/ = [];
var defi = 0;
// 5 -> 37 ... 8 -> 40
for(defi = 5; defi <= 8; ++defi) default_map[defi] = 32 + defi;
// 23 -> 0 ... 26 -> 0
for(defi = 23; defi <= 26; ++defi) default_map[defi] = 0;
// 27 -> 14 ... 31 -> 14
for(defi = 27; defi <= 31; ++defi) default_map[defi] = 14;
// 50 -> 14 ... 58 -> 14
for(defi = 50; defi <= 58; ++defi) default_map[defi] = 14;
// 59 -> 1 ... 62 -> 4
for(defi = 59; defi <= 62; ++defi) default_map[defi] = defi - 58;
// 67 -> 9 ... 68 -> 10
for(defi = 67; defi <= 68; ++defi) default_map[defi] = defi - 58;
// 72 -> 14 ... 75 -> 17
for(defi = 72; defi <= 75; ++defi) default_map[defi] = defi - 58;
// 69 -> 12 ... 71 -> 14
for(defi = 67; defi <= 68; ++defi) default_map[defi] = defi - 57;
// 76 -> 20 ... 78 -> 22
for(defi = 76; defi <= 78; ++defi) default_map[defi] = defi - 56;
// 79 -> 45 ... 81 -> 47
for(defi = 79; defi <= 81; ++defi) default_map[defi] = defi - 34;
// 82 -> 0 ... 65536 -> 0 (omitted)
/* These formats technically refer to Accounting formats with no equivalent */
var default_str/*:Array<string>*/ = [];
// 5 -- Currency, 0 decimal, black negative
default_str[5] = default_str[63] = '"$"#,##0_);\\("$"#,##0\\)';
// 6 -- Currency, 0 decimal, red negative
default_str[6] = default_str[64] = '"$"#,##0_);[Red]\\("$"#,##0\\)';
// 7 -- Currency, 2 decimal, black negative
default_str[7] = default_str[65] = '"$"#,##0.00_);\\("$"#,##0.00\\)';
// 8 -- Currency, 2 decimal, red negative
default_str[8] = default_str[66] = '"$"#,##0.00_);[Red]\\("$"#,##0.00\\)';
// 41 -- Accounting, 0 decimal, No Symbol
default_str[41] = '_(* #,##0_);_(* \\(#,##0\\);_(* "-"_);_(@_)';
// 42 -- Accounting, 0 decimal, $ Symbol
default_str[42] = '_("$"* #,##0_);_("$"* \\(#,##0\\);_("$"* "-"_);_(@_)';
// 43 -- Accounting, 2 decimal, No Symbol
default_str[43] = '_(* #,##0.00_);_(* \\(#,##0.00\\);_(* "-"??_);_(@_)';
// 44 -- Accounting, 2 decimal, $ Symbol
default_str[44] = '_("$"* #,##0.00_);_("$"* \\(#,##0.00\\);_("$"* "-"??_);_(@_)';

@ -0,0 +1,20 @@
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;
var Q_2 = 1, Q_1 = 0, Q = 0;
var A = Math.floor(B);
while(Q_1 < D) {
A = Math.floor(B);
P = A * P_1 + P_2;
Q = A * Q_1 + Q_2;
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) { if(Q_1 > D) { Q = Q_2; P = P_2; } else { Q = Q_1; P = P_1; } }
if(!mixed) return [0, sgn * P, Q];
var q = Math.floor(sgn * P/Q);
return [q, sgn*P - q*Q, Q];
}

@ -0,0 +1,40 @@
function parse_date_code(v/*:number*/,opts/*:?any*/,b2/*:?boolean*/) {
if(v > 2958465 || v < 0) return null;
var date = (v|0), time = Math.floor(86400 * (v - date)), dow=0;
var dout=[];
var out={D:date, T:time, u:86400*(v-date)-time,y:0,m:0,d:0,H:0,M:0,S:0,q:0};
if(Math.abs(out.u) < 1e-6) out.u = 0;
if(opts && opts.date1904) date += 1462;
if(out.u > 0.9999) {
out.u = 0;
if(++time == 86400) { out.T = time = 0; ++date; ++out.D; }
}
if(date === 60) {dout = b2 ? [1317,10,29] : [1900,2,29]; dow=3;}
else if(date === 0) {dout = b2 ? [1317,8,29] : [1900,1,0]; dow=6;}
else {
if(date > 60) --date;
/* 1 = Jan 1 1900 in Gregorian */
var d = new Date(1900, 0, 1);
d.setDate(d.getDate() + date - 1);
dout = [d.getFullYear(), d.getMonth()+1,d.getDate()];
dow = d.getDay();
if(date < 60) dow = (dow + 6) % 7;
if(b2) dow = fix_hijri(d, dout);
}
out.y = dout[0]; out.m = dout[1]; out.d = dout[2];
out.S = time % 60; time = Math.floor(time / 60);
out.M = time % 60; time = Math.floor(time / 60);
out.H = time;
out.q = dow;
return out;
}
SSF.parse_date_code = parse_date_code;
var basedate = new Date(1899, 11, 31, 0, 0, 0);
var dnthresh = basedate.getTime();
var base1904 = new Date(1900, 2, 1, 0, 0, 0);
function datenum_local(v/*:Date*/, date1904/*:?boolean*/)/*:number*/ {
var epoch = v.getTime();
if(date1904) epoch -= 1461*24*60*60*1000;
else if(v >= base1904) epoch += 24*60*60*1000;
return (epoch - (dnthresh + (v.getTimezoneOffset() - basedate.getTimezoneOffset()) * 60000)) / (24 * 60 * 60 * 1000);
}

@ -0,0 +1,71 @@
/* The longest 32-bit integer text is "-4294967296", exactly 11 chars */
function general_fmt_int(v/*:number*/)/*:string*/ { return v.toString(10); }
SSF._general_int = general_fmt_int;
/* ECMA-376 18.8.30 numFmt*/
/* Note: `toPrecision` uses standard form when prec > E and E >= -6 */
var general_fmt_num = (function make_general_fmt_num() {
var trailing_zeroes_and_decimal = /(?:\.0*|(\.\d*[1-9])0+)$/;
function strip_decimal(o/*:string*/)/*:string*/ {
return (o.indexOf(".") == -1) ? o : o.replace(trailing_zeroes_and_decimal, "$1");
}
/* General Exponential always shows 2 digits exp and trims the mantissa */
var mantissa_zeroes_and_decimal = /(?:\.0*|(\.\d*[1-9])0+)[Ee]/;
var exp_with_single_digit = /(E[+-])(\d)$/;
function normalize_exp(o/*:string*/)/*:string*/ {
if(o.indexOf("E") == -1) return o;
return o.replace(mantissa_zeroes_and_decimal,"$1E").replace(exp_with_single_digit,"$10$2");
}
/* exponent >= -9 and <= 9 */
function small_exp(v/*:number*/)/*:string*/ {
var w = (v<0?12:11);
var o = strip_decimal(v.toFixed(12)); if(o.length <= w) return o;
o = v.toPrecision(10); if(o.length <= w) return o;
return v.toExponential(5);
}
/* exponent >= 11 or <= -10 likely exponential */
function large_exp(v/*:number*/)/*:string*/ {
var o = strip_decimal(v.toFixed(11));
return (o.length > (v<0?12:11) || o === "0" || o === "-0") ? v.toPrecision(6) : o;
}
function general_fmt_num_base(v/*:number*/)/*:string*/ {
var V = Math.floor(Math.log(Math.abs(v))*Math.LOG10E), o;
if(V >= -4 && V <= -1) o = v.toPrecision(10+V);
else if(Math.abs(V) <= 9) o = small_exp(v);
else if(V === 10) o = v.toFixed(10).substr(0,12);
else o = large_exp(v);
return strip_decimal(normalize_exp(o.toUpperCase()));
}
return general_fmt_num_base;
})();
SSF._general_num = general_fmt_num;
/*
"General" rules:
- text is passed through ("@")
- booleans are rendered as TRUE/FALSE
- "up to 11 characters" displayed for numbers
- Default date format (code 14) used for Dates
TODO: technically the display depends on the width of the cell
*/
function general_fmt(v/*:any*/, opts/*:any*/) {
switch(typeof v) {
case 'string': return v;
case 'boolean': return v ? "TRUE" : "FALSE";
case 'number': return (v|0) === v ? v.toString(10) : general_fmt_num(v);
case 'undefined': return "";
case 'object':
if(v == null) return "";
if(v instanceof Date) return format(14, datenum_local(v, opts && opts.date1904), opts);
}
throw new Error("unsupported value in General format: " + v);
}
SSF._general = general_fmt;

@ -0,0 +1,7 @@
function fix_hijri(date/*:Date*/, o/*:[number, number, number]*/) {
/* TODO: properly adjust y/m/d and */
o[0] -= 581;
var dow = date.getDay();
if(date < 60) dow = (dow + 6) % 7;
return dow;
}

@ -0,0 +1 @@
var THAI_DIGITS = "\u0E50\u0E51\u0E52\u0E53\u0E54\u0E55\u0E56\u0E57\u0E58\u0E59".split("");

@ -0,0 +1,66 @@
/*jshint -W086 */
function write_date(type/*:number*/, fmt/*:string*/, val, ss0/*:?number*/)/*:string*/ {
var o="", ss=0, tt=0, y = val.y, out, outl = 0;
switch(type) {
case 98: /* 'b' buddhist year */
y = val.y + 543;
/* falls through */
case 121: /* 'y' year */
switch(fmt.length) {
case 1: case 2: out = y % 100; outl = 2; break;
default: out = y % 10000; outl = 4; break;
} break;
case 109: /* 'm' month */
switch(fmt.length) {
case 1: case 2: out = val.m; outl = fmt.length; break;
case 3: return months[val.m-1][1];
case 5: return months[val.m-1][0];
default: return months[val.m-1][2];
} break;
case 100: /* 'd' day */
switch(fmt.length) {
case 1: case 2: out = val.d; outl = fmt.length; break;
case 3: return days[val.q][0];
default: return days[val.q][1];
} break;
case 104: /* 'h' 12-hour */
switch(fmt.length) {
case 1: case 2: out = 1+(val.H+11)%12; outl = fmt.length; break;
default: throw 'bad hour format: ' + fmt;
} break;
case 72: /* 'H' 24-hour */
switch(fmt.length) {
case 1: case 2: out = val.H; outl = fmt.length; break;
default: throw 'bad hour format: ' + fmt;
} break;
case 77: /* 'M' minutes */
switch(fmt.length) {
case 1: case 2: out = val.M; outl = fmt.length; break;
default: throw 'bad minute format: ' + fmt;
} break;
case 115: /* 's' seconds */
if(fmt != 's' && fmt != 'ss' && fmt != '.0' && fmt != '.00' && fmt != '.000') throw 'bad second format: ' + fmt;
if(val.u === 0 && (fmt == "s" || fmt == "ss")) return pad0(val.S, fmt.length);
/*::if(!ss0) ss0 = 0; */
if(ss0 >= 2) tt = ss0 === 3 ? 1000 : 100;
else tt = ss0 === 1 ? 10 : 1;
ss = Math.round((tt)*(val.S + val.u));
if(ss >= 60*tt) ss = 0;
if(fmt === 's') return ss === 0 ? "0" : ""+ss/tt;
o = pad0(ss,2 + ss0);
if(fmt === 'ss') return o.substr(0,2);
return "." + o.substr(2,fmt.length-1);
case 90: /* 'Z' absolute time */
switch(fmt) {
case '[h]': case '[hh]': out = val.D*24+val.H; break;
case '[m]': case '[mm]': out = (val.D*24+val.H)*60+val.M; break;
case '[s]': case '[ss]': out = ((val.D*24+val.H)*60+val.M)*60+Math.round(val.S+val.u); break;
default: throw 'bad abstime format: ' + fmt;
} outl = fmt.length === 3 ? 1 : 2; break;
case 101: /* 'e' era */
out = y; outl = 1; break;
}
var outstr = outl > 0 ? pad0(out, outl) : "";
return outstr;
}
/*jshint +W086 */

@ -0,0 +1,7 @@
function commaify(s/*:string*/)/*:string*/ {
var w = 3;
if(s.length <= w) return s;
var j = (s.length % w), o = s.substr(0,j);
for(; j!=s.length; j+=w) o+=(o.length > 0 ? "," : "") + s.substr(j,w);
return o;
}

@ -0,0 +1 @@
var write_num/*:SSF_write_num*/ = (function make_write_num(){

@ -0,0 +1,5 @@
var pct1 = /%/g;
function write_num_pct(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);
}

@ -0,0 +1,69 @@
function write_num_cm(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_exp(fmt/*:string*/, val/*:number*/)/*:string*/{
var o/*:string*/;
var idx = fmt.indexOf("E") - fmt.indexOf(".") - 1;
if(fmt.match(/^#+0.0E\+0$/)) {
if(val == 0) return "0.0E+0";
else if(val < 0) return "-" + write_num_exp(fmt, -val);
var period = fmt.indexOf("."); if(period === -1) period=fmt.indexOf('E');
var ee = Math.floor(Math.log(val)*Math.LOG10E)%period;
if(ee < 0) ee += period;
o = (val/Math.pow(10,ee)).toPrecision(idx+1+(period+ee)%period);
if(o.indexOf("e") === -1) {
var fakee = Math.floor(Math.log(val)*Math.LOG10E);
if(o.indexOf(".") === -1) o = o.charAt(0) + "." + o.substr(1) + "E+" + (fakee - o.length+ee);
else o += "E+" + (fakee - ee);
while(o.substr(0,2) === "0.") {
o = o.charAt(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(/^([+-]?)(\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");
}
var frac1 = /# (\?+)( ?)\/( ?)(\d+)/;
function write_num_f1(r/*:Array<string>*/, aval/*:number*/, sign/*:string*/)/*:string*/ {
var den = parseInt(r[4],10), rr = Math.round(aval * den), base = Math.floor(rr/den);
var myn = (rr - base*den), myd = den;
return sign + (base === 0 ? "" : ""+base) + " " + (myn === 0 ? fill(" ", r[1].length + 1 + r[4].length) : pad_(myn,r[1].length) + r[2] + "/" + r[3] + pad0(myd,r[4].length));
}
function write_num_f2(r/*:Array<string>*/, aval/*:number*/, sign/*:string*/)/*:string*/ {
return sign + (aval === 0 ? "" : ""+aval) + fill(" ", r[1].length + 2 + r[4].length);
}
var dec1 = /^#*0*\.([0#]+)/;
var closeparen = /\).*[0#]/;
var phone = /\(###\) ###\\?-####/;
function hashq(str/*:string*/)/*:string*/ {
var o = "", cc;
for(var i = 0; i != str.length; ++i) switch((cc=str.charCodeAt(i))) {
case 35: break;
case 63: o+= " "; break;
case 48: o+= "0"; break;
default: o+= String.fromCharCode(cc);
}
return o;
}
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*/ {
var _frac = val - Math.floor(val), dd = Math.pow(10,d);
if (d < ('' + Math.round(_frac * dd)).length) return 0;
return Math.round(_frac * dd);
}
function carry(val/*:number*/, d/*:number*/)/*:number*/ {
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);
}

@ -0,0 +1,85 @@
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."+hashq(r[1])).replace(/\.$/,"."+hashq(r[1])).replace(/\.(\d*)$/,function($$, $1) { return "." + $1 + fill("0", hashq(/*::(*/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(/^#{1,3},##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 "###,##0.00": return write_num_flt(type, "#,##0.00", val);
case "###,###":
case "##,###":
case "#,###": var x = commaify(pad0r(aval,0)); return x !== "0" ? sign + x : "";
case "###,###.00": return write_num_flt(type, "###,##0.00",val).replace(/^0\./,".");
case "#,###.00": return write_num_flt(type, "#,##0.00",val).replace(/^0\./,".");
default:
}
throw new Error("unsupported format |" + fmt + "|");
}

@ -0,0 +1,31 @@
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$/)) {
if(val == 0) return "0.0E+0";
else if(val < 0) return "-" + write_num_exp2(fmt, -val);
var period = fmt.indexOf("."); if(period === -1) period=fmt.indexOf('E');
var ee = Math.floor(Math.log(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(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");
}

@ -0,0 +1,86 @@
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/*:?Array<string>*/, 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."+hashq(r[1])).replace(/\.$/,"."+hashq(r[1]));
o = o.replace(/\.(\d*)$/,function($$, $1) {
/*:: if(!Array.isArray(r)) throw new Error("unreachable"); */
return "." + $1 + fill("0", hashq(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(/^#{1,3},##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(/*::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 = "" + 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 "###,###":
case "##,###":
case "#,###": var x = commaify(""+aval); return x !== "0" ? sign + x : "";
default:
if(fmt.match(/\.[0#?]*$/)) return write_num_int(type, fmt.slice(0,fmt.lastIndexOf(".")), val) + hashq(fmt.slice(fmt.lastIndexOf(".")));
}
throw new Error("unsupported format |" + fmt + "|");
}

@ -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);
};})();

@ -0,0 +1,17 @@
function split_fmt(fmt/*:string*/)/*:Array<string>*/ {
var out/*:Array<string>*/ = [];
var in_str = false/*, cc*/;
for(var i = 0, j = 0; i < fmt.length; ++i) switch((/*cc=*/fmt.charCodeAt(i))) {
case 34: /* '"' */
in_str = !in_str; break;
case 95: case 42: case 92: /* '_' '*' '\\' */
++i; break;
case 59: /* ';' */
out[out.length] = fmt.substr(j,i-j);
j = i+1;
}
out[out.length] = fmt.substr(j);
if(in_str === true) throw new Error("Format |" + fmt + "| unterminated string ");
return out;
}
SSF._split = split_fmt;

@ -0,0 +1,43 @@
var abstime = /\[[HhMmSs\u0E0A\u0E19\u0E17]*\]/;
function fmt_is_date(fmt/*:string*/)/*:boolean*/ {
var i = 0, /*cc = 0,*/ c = "", o = "";
while(i < fmt.length) {
switch((c = fmt.charAt(i))) {
case 'G': if(isgeneral(fmt, i)) i+= 6; i++; break;
case '"': for(;(/*cc=*/fmt.charCodeAt(++i)) !== 34 && i < fmt.length;){/*empty*/} ++i; break;
case '\\': i+=2; break;
case '_': i+=2; break;
case '@': ++i; break;
case 'B': case 'b':
if(fmt.charAt(i+1) === "1" || fmt.charAt(i+1) === "2") return true;
/* falls through */
case 'M': case 'D': case 'Y': case 'H': case 'S': case 'E':
/* falls through */
case 'm': case 'd': case 'y': case 'h': case 's': case 'e': case 'g': return true;
case 'A': case 'a': case '上':
if(fmt.substr(i, 3).toUpperCase() === "A/P") return true;
if(fmt.substr(i, 5).toUpperCase() === "AM/PM") return true;
if(fmt.substr(i, 5).toUpperCase() === "上午/下午") return true;
++i; break;
case '[':
o = c;
while(fmt.charAt(i++) !== ']' && i < fmt.length) o += fmt.charAt(i);
if(o.match(abstime)) return true;
break;
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))){/* empty */}
break;
case '?': while(fmt.charAt(++i) === c){/* empty */} 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){/* empty */} break;
case ' ': ++i; break;
default: ++i; break;
}
}
return false;
}
SSF.is_date = fmt_is_date;

@ -0,0 +1,208 @@
function eval_fmt(fmt/*:string*/, v/*:any*/, opts/*:any*/, flen/*:number*/) {
var out = [], o = "", i = 0, c = "", lst='t', dt, j, cc;
var hr='H';
/* Tokenize */
while(i < fmt.length) {
switch((c = fmt.charAt(i))) {
case 'G': /* General */
if(!isgeneral(fmt, i)) throw new Error('unrecognized character ' + c + ' in ' +fmt);
out[out.length] = {t:'G', v:'General'}; i+=7; break;
case '"': /* Literal text */
for(o="";(cc=fmt.charCodeAt(++i)) !== 34 && i < fmt.length;) o += String.fromCharCode(cc);
out[out.length] = {t:'t', v:o}; ++i; break;
case '\\': var w = fmt.charAt(++i), t = (w === "(" || w === ")") ? w : 't';
out[out.length] = {t:t, v:w}; ++i; break;
case '_': out[out.length] = {t:'t', v:" "}; i+=2; break;
case '@': /* Text Placeholder */
out[out.length] = {t:'T', v:v}; ++i; break;
case 'B': case 'b':
if(fmt.charAt(i+1) === "1" || fmt.charAt(i+1) === "2") {
if(dt==null) { dt=parse_date_code(v, opts, fmt.charAt(i+1) === "2"); if(dt==null) return ""; }
out[out.length] = {t:'X', v:fmt.substr(i,2)}; lst = c; i+=2; break;
}
/* falls through */
case 'M': case 'D': case 'Y': case 'H': case 'S': case 'E':
c = c.toLowerCase();
/* falls through */
case 'm': case 'd': case 'y': case 'h': case 's': case 'e': case 'g':
if(v < 0) return "";
if(dt==null) { dt=parse_date_code(v, opts); if(dt==null) return ""; }
o = c; while(++i < fmt.length && fmt.charAt(i).toLowerCase() === c) o+=c;
if(c === 'm' && lst.toLowerCase() === 'h') c = 'M';
if(c === 'h') c = hr;
out[out.length] = {t:c, v:o}; lst = c; break;
case 'A': case 'a': case '上':
var q={t:c, v:c};
if(dt==null) dt=parse_date_code(v, opts);
if(fmt.substr(i, 3).toUpperCase() === "A/P") { if(dt!=null) q.v = dt.H >= 12 ? "P" : "A"; q.t = 'T'; hr='h';i+=3;}
else if(fmt.substr(i,5).toUpperCase() === "AM/PM") { if(dt!=null) q.v = dt.H >= 12 ? "PM" : "AM"; q.t = 'T'; i+=5; hr='h'; }
else if(fmt.substr(i,5).toUpperCase() === "上午/下午") { if(dt!=null) q.v = dt.H >= 12 ? "下午" : "上午"; q.t = 'T'; i+=5; hr='h'; }
else { q.t = "t"; ++i; }
if(dt==null && q.t === 'T') return "";
out[out.length] = q; lst = c; break;
case '[':
o = c;
while(fmt.charAt(i++) !== ']' && i < fmt.length) o += fmt.charAt(i);
if(o.slice(-1) !== ']') throw 'unterminated "[" block: |' + o + '|';
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()};
lst = o.charAt(1);
} else if(o.indexOf("$") > -1) {
o = (o.match(/\$([^-\[\]]*)/)||[])[1]||"$";
if(!fmt_is_date(fmt)) out[out.length] = {t:'t',v:o};
}
break;
/* Numbers */
case '.':
if(dt != null) {
o = c; while(++i < fmt.length && (c=fmt.charAt(i)) === "0") o += c;
out[out.length] = {t:'s', v:o}; break;
}
/* falls through */
case '0': case '#':
o = c; while(++i < fmt.length && "0#?.,E+-%".indexOf(c=fmt.charAt(i)) > -1) o += c;
out[out.length] = {t:'n', v:o}; break;
case '?':
o = c; while(fmt.charAt(++i) === c) o+=c;
out[out.length] = {t:c, v:o}; lst = c; break;
case '*': ++i; if(fmt.charAt(i) == ' ' || fmt.charAt(i) == '*') ++i; break; // **
case '(': case ')': out[out.length] = {t:(flen===1?'t':c), v:c}; ++i; break;
case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
o = c; while(i < fmt.length && "0123456789".indexOf(fmt.charAt(++i)) > -1) o+=fmt.charAt(i);
out[out.length] = {t:'D', v:o}; break;
case ' ': out[out.length] = {t:c, v:c}; ++i; break;
case '$': out[out.length] = {t:'t', v:'$'}; ++i; break;
default:
if(",$-+/():!^&'~{}<>=€acfijklopqrtuvwxzP".indexOf(c) === -1) throw new Error('unrecognized character ' + c + ' in ' + fmt);
out[out.length] = {t:'t', v:c}; ++i; break;
}
}
/* Scan for date/time parts */
var bt = 0, ss0 = 0, ssm;
for(i=out.length-1, lst='t'; i >= 0; --i) {
switch(out[i].t) {
case 'h': case 'H': out[i].t = hr; lst='h'; if(bt < 1) bt = 1; break;
case 's':
if((ssm=out[i].v.match(/\.0+$/))) ss0=Math.max(ss0,ssm[0].length-1);
if(bt < 3) bt = 3;
/* 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");*/
break;
case 'Z':
if(bt < 1 && out[i].v.match(/[Hh]/)) bt = 1;
if(bt < 2 && out[i].v.match(/[Mm]/)) bt = 2;
if(bt < 3 && out[i].v.match(/[Ss]/)) bt = 3;
}
}
/* time rounding depends on presence of minute / second / usec fields */
switch(bt) {
case 0: break;
case 1:
/*::if(!dt) break;*/
if(dt.u >= 0.5) { dt.u = 0; ++dt.S; }
if(dt.S >= 60) { dt.S = 0; ++dt.M; }
if(dt.M >= 60) { dt.M = 0; ++dt.H; }
break;
case 2:
/*::if(!dt) break;*/
if(dt.u >= 0.5) { dt.u = 0; ++dt.S; }
if(dt.S >= 60) { dt.S = 0; ++dt.M; }
break;
}
/* replace fields */
var nstr = "", jj;
for(i=0; i < out.length; ++i) {
switch(out[i].t) {
case 't': case 'T': case ' ': case 'D': break;
case 'X': out[i].v = ""; out[i].t = ";"; break;
case 'd': case 'm': case 'y': case 'h': case 'H': case 'M': case 's': case 'e': case 'b': case 'Z':
/*::if(!dt) throw "unreachable"; */
out[i].v = write_date(out[i].t.charCodeAt(0), out[i].v, dt, ss0);
out[i].t = 't'; break;
case 'n': case '?':
jj = i+1;
while(out[jj] != null && (
(c=out[jj].t) === "?" || c === "D" ||
((c === " " || c === "t") && out[jj+1] != null && (out[jj+1].t === '?' || out[jj+1].t === "t" && out[jj+1].v === '/')) ||
(out[i].t === '(' && (c === ' ' || c === 'n' || c === ')')) ||
(c === 't' && (out[jj].v === '/' || out[jj].v === ' ' && out[jj+1] != null && out[jj+1].t == '?'))
)) {
out[i].v += out[jj].v;
out[jj] = {v:"", t:";"}; ++jj;
}
nstr += out[i].v;
i = jj-1; break;
case 'G': out[i].t = 't'; out[i].v = general_fmt(v,opts); break;
}
}
var vv = "", myv, ostr;
if(nstr.length > 0) {
if(nstr.charCodeAt(0) == 40) /* '(' */ {
myv = (v<0&&nstr.charCodeAt(0) === 45 ? -v : v);
ostr = write_num('n', 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].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) {
if(out[i] == null || 'n?'.indexOf(out[i].t) === -1) continue;
if(jj>=out[i].v.length-1) { jj -= out[i].v.length; out[i].v = ostr.substr(jj+1, out[i].v.length); }
else if(jj < 0) out[i].v = "";
else { out[i].v = ostr.substr(0, jj+1); jj = -1; }
out[i].t = 't';
lasti = i;
}
if(jj>=0 && lasti<out.length) out[lasti].v = ostr.substr(0,jj+1) + out[lasti].v;
}
else if(decpt !== out.length && ostr.indexOf("E") === -1) {
jj = ostr.indexOf(".")-1;
for(i=decpt; i>= 0; --i) {
if(out[i] == null || 'n?'.indexOf(out[i].t) === -1) continue;
j=out[i].v.indexOf(".")>-1&&i===decpt?out[i].v.indexOf(".")-1:out[i].v.length-1;
vv = out[i].v.substr(j+1);
for(; j>=0; --j) {
if(jj>=0 && (out[i].v.charAt(j) === "0" || out[i].v.charAt(j) === "#")) vv = ostr.charAt(jj--) + vv;
}
out[i].v = vv;
out[i].t = 't';
lasti = i;
}
if(jj>=0 && lasti<out.length) out[lasti].v = ostr.substr(0,jj+1) + out[lasti].v;
jj = ostr.indexOf(".")+1;
for(i=decpt; i<out.length; ++i) {
if(out[i] == null || ('n?('.indexOf(out[i].t) === -1 && i !== decpt)) continue;
j=out[i].v.indexOf(".")>-1&&i===decpt?out[i].v.indexOf(".")+1:0;
vv = out[i].v.substr(0,j);
for(; j<out[i].v.length; ++j) {
if(jj<ostr.length) vv += ostr.charAt(jj++);
}
out[i].v = vv;
out[i].t = 't';
lasti = i;
}
}
}
for(i=0; i<out.length; ++i) if(out[i] != null && 'n?'.indexOf(out[i].t)>-1) {
myv = (flen >1 && v < 0 && i>0 && out[i-1].v === "-" ? -v:v);
out[i].v = write_num(out[i].t, out[i].v, myv);
out[i].t = 't';
}
var retval = "";
for(i=0; i !== out.length; ++i) if(out[i] != null) retval += out[i].v;
return retval;
}
SSF._eval = eval_fmt;

@ -0,0 +1,15 @@
var cfregex = /\[[=<>]/;
var cfregex2 = /\[(=|>[=]?|<[>=]?)(-?\d+(?:\.\d*)?)\]/;
function chkcond(v, rr) {
if(rr == null) return false;
var thresh = parseFloat(rr[2]);
switch(rr[1]) {
case "=": if(v == thresh) return true; break;
case ">": if(v > thresh) return true; break;
case "<": if(v < thresh) return true; break;
case "<>": if(v != thresh) return true; break;
case ">=": if(v >= thresh) return true; break;
case "<=": if(v <= thresh) return true; break;
}
return false;
}

@ -0,0 +1,44 @@
function choose_fmt(f/*:string*/, v/*:any*/) {
var fmt = split_fmt(f);
var l = fmt.length, lat = fmt[l-1].indexOf("@");
if(l<4 && lat>-1) --l;
if(fmt.length > 4) throw new Error("cannot find right format for |" + fmt.join("|") + "|");
if(typeof v !== "number") return [4, fmt.length === 4 || lat>-1?fmt[fmt.length-1]:"@"];
switch(fmt.length) {
case 1: fmt = lat>-1 ? ["General", "General", "General", fmt[0]] : [fmt[0], fmt[0], fmt[0], "@"]; break;
case 2: fmt = lat>-1 ? [fmt[0], fmt[0], fmt[0], fmt[1]] : [fmt[0], fmt[1], fmt[0], "@"]; break;
case 3: fmt = lat>-1 ? [fmt[0], fmt[1], fmt[0], fmt[2]] : [fmt[0], fmt[1], fmt[2], "@"]; break;
case 4: break;
}
var ff = v > 0 ? fmt[0] : v < 0 ? fmt[1] : fmt[2];
if(fmt[0].indexOf("[") === -1 && fmt[1].indexOf("[") === -1) return [l, ff];
if(fmt[0].match(cfregex) != null || fmt[1].match(cfregex) != null) {
var m1 = fmt[0].match(cfregex2);
var m2 = fmt[1].match(cfregex2);
return chkcond(v, m1) ? [l, fmt[0]] : chkcond(v, m2) ? [l, fmt[1]] : [l, fmt[m1 != null && m2 != null ? 2 : 1]];
}
return [l, ff];
}
function format(fmt/*:string|number*/,v/*:any*/,o/*:?any*/) {
if(o == null) o = {};
var sfmt = "";
switch(typeof fmt) {
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];
if(sfmt == null) sfmt = (o.table && o.table[default_map[fmt]]) || table_fmt[default_map[fmt]];
if(sfmt == null) sfmt = default_str[fmt] || "General";
break;
}
if(isgeneral(sfmt,0)) return general_fmt(v, o);
if(v instanceof Date) v = datenum_local(v, o.date1904);
var f = choose_fmt(sfmt, v);
if(isgeneral(f[1])) return general_fmt(v, o);
if(v === true) v = "TRUE"; else if(v === false) v = "FALSE";
else if(v === "" || v == null) return "";
return eval_fmt(f[1], v, o, f[0]);
}

@ -0,0 +1,17 @@
function load_entry(fmt/*:string*/, idx/*:?number*/)/*:number*/ {
if(typeof idx != 'number') {
idx = +idx || -1;
/*::if(typeof idx != 'number') return 0x188; */
for(var i = 0; i < 0x0188; ++i) {
/*::if(typeof idx != 'number') return 0x188; */
if(table_fmt[i] == undefined) { if(idx < 0) idx = i; continue; }
if(table_fmt[i] == fmt) { idx = i; break; }
}
/*::if(typeof idx != 'number') return 0x188; */
if(idx < 0) idx = 0x187;
}
/*::if(typeof idx != 'number') return 0x188; */
table_fmt[idx] = fmt;
return idx;
}
SSF.load = load_entry;

@ -0,0 +1,8 @@
SSF._table = table_fmt;
SSF.get_table = function get_table()/*:SSFTable*/ { return table_fmt; };
SSF.load_table = function load_table(tbl/*:SSFTable*/)/*:void*/ {
for(var i=0; i!=0x0188; ++i)
if(tbl[i] !== undefined) load_entry(tbl[i], i);
};
SSF.init_table = init_table;
SSF.format = format;

@ -0,0 +1,4 @@
};
make_ssf(SSF);
/*global module */
if(typeof module !== 'undefined' && typeof DO_NOT_EXPORT_SSF === 'undefined') module.exports = SSF;

@ -0,0 +1,33 @@
<!DOCTYPE html>
<html>
<head>
<title>SSF Test Runner</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="mocha.css" />
<link rel="icon" type="image/png" href="//oss.sheetjs.com/assets/img/logo.png" />
<style>
#t { font: 20px/1.5 "Helvetica Neue", Helvetica, Arial, sans-serif; margin: 0px 60px; font-weight: bold; }
#tt{ font: 16px/1.5 "Helvetica Neue", Helvetica, Arial, sans-serif; margin: 0px 60px; }
th { font: 16px/1.5 "Helvetica Neue", Helvetica, Arial, sans-serif; margin: 0px 60px; font-weight: bold; text-align: left; }
</style>
</head>
<body>
<h1 id="t">SSF Tests</h1>
<div id="mocha"></div>
<script src="shim.js"></script>
<script src="json2.js"></script>
<script src="mocha.js"></script>
<script>
window.initMochaPhantomJS && window.initMochaPhantomJS();
mocha.setup('bdd');
</script>
<script src="test.js"></script>
<script>
if(typeof mochaSaucePlease !== "undefined") mochaSaucePlease();
else if(window.mochaPhantomJS) mochaPhantomJS.run();
else mocha.run();
</script>
</body>
</html>

489
packages/ssf/ctest/json2.js Normal file

@ -0,0 +1,489 @@
/*
json2.js
2014-02-04
Public Domain.
NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
See http://www.JSON.org/js.html
This code should be minified before deployment.
See http://javascript.crockford.com/jsmin.html
USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
NOT CONTROL.
This file creates a global JSON object containing two methods: stringify
and parse.
JSON.stringify(value, replacer, space)
value any JavaScript value, usually an object or array.
replacer an optional parameter that determines how object
values are stringified for objects. It can be a
function or an array of strings.
space an optional parameter that specifies the indentation
of nested structures. If it is omitted, the text will
be packed without extra whitespace. If it is a number,
it will specify the number of spaces to indent at each
level. If it is a string (such as '\t' or '&nbsp;'),
it contains the characters used to indent at each level.
This method produces a JSON text from a JavaScript value.
When an object value is found, if the object contains a toJSON
method, its toJSON method will be called and the result will be
stringified. A toJSON method does not serialize: it returns the
value represented by the name/value pair that should be serialized,
or undefined if nothing should be serialized. The toJSON method
will be passed the key associated with the value, and this will be
bound to the value
For example, this would serialize Dates as ISO strings.
Date.prototype.toJSON = function (key) {
function f(n) {
// Format integers to have at least two digits.
return n < 10 ? '0' + n : n;
}
return this.getUTCFullYear() + '-' +
f(this.getUTCMonth() + 1) + '-' +
f(this.getUTCDate()) + 'T' +
f(this.getUTCHours()) + ':' +
f(this.getUTCMinutes()) + ':' +
f(this.getUTCSeconds()) + 'Z';
};
You can provide an optional replacer method. It will be passed the
key and value of each member, with this bound to the containing
object. The value that is returned from your method will be
serialized. If your method returns undefined, then the member will
be excluded from the serialization.
If the replacer parameter is an array of strings, then it will be
used to select the members to be serialized. It filters the results
such that only members with keys listed in the replacer array are
stringified.
Values that do not have JSON representations, such as undefined or
functions, will not be serialized. Such values in objects will be
dropped; in arrays they will be replaced with null. You can use
a replacer function to replace those with JSON values.
JSON.stringify(undefined) returns undefined.
The optional space parameter produces a stringification of the
value that is filled with line breaks and indentation to make it
easier to read.
If the space parameter is a non-empty string, then that string will
be used for indentation. If the space parameter is a number, then
the indentation will be that many spaces.
Example:
text = JSON.stringify(['e', {pluribus: 'unum'}]);
// text is '["e",{"pluribus":"unum"}]'
text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
// text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
text = JSON.stringify([new Date()], function (key, value) {
return this[key] instanceof Date ?
'Date(' + this[key] + ')' : value;
});
// text is '["Date(---current time---)"]'
JSON.parse(text, reviver)
This method parses a JSON text to produce an object or array.
It can throw a SyntaxError exception.
The optional reviver parameter is a function that can filter and
transform the results. It receives each of the keys and values,
and its return value is used instead of the original value.
If it returns what it received, then the structure is not modified.
If it returns undefined then the member is deleted.
Example:
// Parse the text. Values that look like ISO date strings will
// be converted to Date objects.
myData = JSON.parse(text, function (key, value) {
var a;
if (typeof value === 'string') {
a =
/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
if (a) {
return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
+a[5], +a[6]));
}
}
return value;
});
myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
var d;
if (typeof value === 'string' &&
value.slice(0, 5) === 'Date(' &&
value.slice(-1) === ')') {
d = new Date(value.slice(5, -1));
if (d) {
return d;
}
}
return value;
});
This is a reference implementation. You are free to copy, modify, or
redistribute.
*/
/*jslint evil: true, regexp: true */
/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
lastIndex, length, parse, prototype, push, replace, slice, stringify,
test, toJSON, toString, valueOf
*/
// Create a JSON object only if one does not already exist. We create the
// methods in a closure to avoid creating global variables.
if (typeof JSON !== 'object') {
JSON = {};
}
(function () {
'use strict';
function f(n) {
// Format integers to have at least two digits.
return n < 10 ? '0' + n : n;
}
if (typeof Date.prototype.toJSON !== 'function') {
Date.prototype.toJSON = function () {
return isFinite(this.valueOf())
? this.getUTCFullYear() + '-' +
f(this.getUTCMonth() + 1) + '-' +
f(this.getUTCDate()) + 'T' +
f(this.getUTCHours()) + ':' +
f(this.getUTCMinutes()) + ':' +
f(this.getUTCSeconds()) + 'Z'
: null;
};
String.prototype.toJSON =
Number.prototype.toJSON =
Boolean.prototype.toJSON = function () {
return this.valueOf();
};
}
var cx,
escapable,
gap,
indent,
meta,
rep;
function quote(string) {
// If the string contains no control characters, no quote characters, and no
// backslash characters, then we can safely slap some quotes around it.
// Otherwise we must also replace the offending characters with safe escape
// sequences.
escapable.lastIndex = 0;
return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
var c = meta[a];
return typeof c === 'string'
? c
: '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
}) + '"' : '"' + string + '"';
}
function str(key, holder) {
// Produce a string from holder[key].
var i, // The loop counter.
k, // The member key.
v, // The member value.
length,
mind = gap,
partial,
value = holder[key];
// If the value has a toJSON method, call it to obtain a replacement value.
if (value && typeof value === 'object' &&
typeof value.toJSON === 'function') {
value = value.toJSON(key);
}
// If we were called with a replacer function, then call the replacer to
// obtain a replacement value.
if (typeof rep === 'function') {
value = rep.call(holder, key, value);
}
// What happens next depends on the value's type.
switch (typeof value) {
case 'string':
return quote(value);
case 'number':
// JSON numbers must be finite. Encode non-finite numbers as null.
return isFinite(value) ? String(value) : 'null';
case 'boolean':
case 'null':
// If the value is a boolean or null, convert it to a string. Note:
// typeof null does not produce 'null'. The case is included here in
// the remote chance that this gets fixed someday.
return String(value);
// If the type is 'object', we might be dealing with an object or an array or
// null.
case 'object':
// Due to a specification blunder in ECMAScript, typeof null is 'object',
// so watch out for that case.
if (!value) {
return 'null';
}
// Make an array to hold the partial results of stringifying this object value.
gap += indent;
partial = [];
// Is the value an array?
if (Object.prototype.toString.apply(value) === '[object Array]') {
// The value is an array. Stringify every element. Use null as a placeholder
// for non-JSON values.
length = value.length;
for (i = 0; i < length; i += 1) {
partial[i] = str(i, value) || 'null';
}
// Join all of the elements together, separated with commas, and wrap them in
// brackets.
v = partial.length === 0
? '[]'
: gap
? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']'
: '[' + partial.join(',') + ']';
gap = mind;
return v;
}
// If the replacer is an array, use it to select the members to be stringified.
if (rep && typeof rep === 'object') {
length = rep.length;
for (i = 0; i < length; i += 1) {
if (typeof rep[i] === 'string') {
k = rep[i];
v = str(k, value);
if (v) {
partial.push(quote(k) + (gap ? ': ' : ':') + v);
}
}
}
} else {
// Otherwise, iterate through all of the keys in the object.
for (k in value) {
if (Object.prototype.hasOwnProperty.call(value, k)) {
v = str(k, value);
if (v) {
partial.push(quote(k) + (gap ? ': ' : ':') + v);
}
}
}
}
// Join all of the member texts together, separated with commas,
// and wrap them in braces.
v = partial.length === 0
? '{}'
: gap
? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}'
: '{' + partial.join(',') + '}';
gap = mind;
return v;
}
}
// If the JSON object does not yet have a stringify method, give it one.
if (typeof JSON.stringify !== 'function') {
escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
meta = { // table of character substitutions
'\b': '\\b',
'\t': '\\t',
'\n': '\\n',
'\f': '\\f',
'\r': '\\r',
'"' : '\\"',
'\\': '\\\\'
};
JSON.stringify = function (value, replacer, space) {
// The stringify method takes a value and an optional replacer, and an optional
// space parameter, and returns a JSON text. The replacer can be a function
// that can replace values, or an array of strings that will select the keys.
// A default replacer method can be provided. Use of the space parameter can
// produce text that is more easily readable.
var i;
gap = '';
indent = '';
// If the space parameter is a number, make an indent string containing that
// many spaces.
if (typeof space === 'number') {
for (i = 0; i < space; i += 1) {
indent += ' ';
}
// If the space parameter is a string, it will be used as the indent string.
} else if (typeof space === 'string') {
indent = space;
}
// If there is a replacer, it must be a function or an array.
// Otherwise, throw an error.
rep = replacer;
if (replacer && typeof replacer !== 'function' &&
(typeof replacer !== 'object' ||
typeof replacer.length !== 'number')) {
throw new Error('JSON.stringify');
}
// Make a fake root object containing our value under the key of ''.
// Return the result of stringifying the value.
return str('', {'': value});
};
}
// If the JSON object does not yet have a parse method, give it one.
if (typeof JSON.parse !== 'function') {
cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
JSON.parse = function (text, reviver) {
// The parse method takes a text and an optional reviver function, and returns
// a JavaScript value if the text is a valid JSON text.
var j;
function walk(holder, key) {
// The walk method is used to recursively walk the resulting structure so
// that modifications can be made.
var k, v, value = holder[key];
if (value && typeof value === 'object') {
for (k in value) {
if (Object.prototype.hasOwnProperty.call(value, k)) {
v = walk(value, k);
if (v !== undefined) {
value[k] = v;
} else {
delete value[k];
}
}
}
}
return reviver.call(holder, key, value);
}
// Parsing happens in four stages. In the first stage, we replace certain
// Unicode characters with escape sequences. JavaScript handles many characters
// incorrectly, either silently deleting them, or treating them as line endings.
text = String(text);
cx.lastIndex = 0;
if (cx.test(text)) {
text = text.replace(cx, function (a) {
return '\\u' +
('0000' + a.charCodeAt(0).toString(16)).slice(-4);
});
}
// In the second stage, we run the text against regular expressions that look
// for non-JSON patterns. We are especially concerned with '()' and 'new'
// because they can cause invocation, and '=' because it can cause mutation.
// But just to be safe, we want to reject all unexpected forms.
// We split the second stage into 4 regexp operations in order to work around
// crippling inefficiencies in IE's and Safari's regexp engines. First we
// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
// replace all simple value tokens with ']' characters. Third, we delete all
// open brackets that follow a colon or comma or that begin the text. Finally,
// we look to see that the remaining characters are only whitespace or ']' or
// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
if (/^[\],:{}\s]*$/
.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
.replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
// In the third stage we use the eval function to compile the text into a
// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
// in JavaScript: it can begin a block or an object literal. We wrap the text
// in parens to eliminate the ambiguity.
j = eval('(' + text + ')');
// In the optional fourth stage, we recursively walk the new structure, passing
// each name/value pair to a reviver function for possible transformation.
return typeof reviver === 'function'
? walk({'': j}, '')
: j;
}
// If the text is not JSON parseable, then a SyntaxError is thrown.
throw new SyntaxError('JSON.parse');
};
}
}());

@ -0,0 +1,260 @@
@charset "utf-8";
body {
margin:0;
}
#mocha {
font: 20px/1.5 "Helvetica Neue", Helvetica, Arial, sans-serif;
margin: 60px 50px;
}
#mocha ul, #mocha li {
margin: 0;
padding: 0;
}
#mocha ul {
list-style: none;
}
#mocha h1, #mocha h2 {
margin: 0;
}
#mocha h1 {
margin-top: 15px;
font-size: 1em;
font-weight: 200;
}
#mocha h1 a {
text-decoration: none;
color: inherit;
}
#mocha h1 a:hover {
text-decoration: underline;
}
#mocha .suite .suite h1 {
margin-top: 0;
font-size: .8em;
}
#mocha .hidden {
display: none;
}
#mocha h2 {
font-size: 12px;
font-weight: normal;
cursor: pointer;
}
#mocha .suite {
margin-left: 15px;
}
#mocha .test {
margin-left: 15px;
overflow: hidden;
}
#mocha .test.pending:hover h2::after {
content: '(pending)';
font-family: arial, sans-serif;
}
#mocha .test.pass.medium .duration {
background: #C09853;
}
#mocha .test.pass.slow .duration {
background: #B94A48;
}
#mocha .test.pass::before {
content: '✓';
font-size: 12px;
display: block;
float: left;
margin-right: 5px;
color: #00d6b2;
}
#mocha .test.pass .duration {
font-size: 9px;
margin-left: 5px;
padding: 2px 5px;
color: white;
-webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
-moz-box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
-ms-border-radius: 5px;
-o-border-radius: 5px;
border-radius: 5px;
}
#mocha .test.pass.fast .duration {
display: none;
}
#mocha .test.pending {
color: #0b97c4;
}
#mocha .test.pending::before {
content: '◦';
color: #0b97c4;
}
#mocha .test.fail {
color: #c00;
}
#mocha .test.fail pre {
color: black;
}
#mocha .test.fail::before {
content: '✖';
font-size: 12px;
display: block;
float: left;
margin-right: 5px;
color: #c00;
}
#mocha .test pre.error {
color: #c00;
max-height: 300px;
overflow: auto;
}
#mocha .test pre {
display: block;
float: left;
clear: left;
font: 12px/1.5 monaco, monospace;
margin: 5px;
padding: 15px;
border: 1px solid #eee;
border-bottom-color: #ddd;
-webkit-border-radius: 3px;
-webkit-box-shadow: 0 1px 3px #eee;
-moz-border-radius: 3px;
-moz-box-shadow: 0 1px 3px #eee;
border-radius: 3px;
}
#mocha .test h2 {
position: relative;
}
#mocha .test a.replay {
position: absolute;
top: 3px;
right: 0;
text-decoration: none;
vertical-align: middle;
display: block;
width: 15px;
height: 15px;
line-height: 15px;
text-align: center;
background: #eee;
font-size: 15px;
-moz-border-radius: 15px;
border-radius: 15px;
-webkit-transition: opacity 200ms;
-moz-transition: opacity 200ms;
transition: opacity 200ms;
opacity: 0.3;
color: #888;
}
#mocha .test:hover a.replay {
opacity: 1;
}
#mocha-report.pass .test.fail {
display: none;
}
#mocha-report.fail .test.pass {
display: none;
}
#mocha-report.pending .test.pass,
#mocha-report.pending .test.fail {
display: none;
}
#mocha-report.pending .test.pass.pending {
display: block;
}
#mocha-error {
color: #c00;
font-size: 1.5em;
font-weight: 100;
letter-spacing: 1px;
}
#mocha-stats {
position: fixed;
top: 15px;
right: 10px;
font-size: 12px;
margin: 0;
color: #888;
z-index: 1;
}
#mocha-stats .progress {
float: right;
padding-top: 0;
}
#mocha-stats em {
color: black;
}
#mocha-stats a {
text-decoration: none;
color: inherit;
}
#mocha-stats a:hover {
border-bottom: 1px solid #eee;
}
#mocha-stats li {
display: inline-block;
margin: 0 5px;
list-style: none;
padding-top: 11px;
}
#mocha-stats canvas {
width: 40px;
height: 40px;
}
#mocha code .comment { color: #ddd }
#mocha code .init { color: #2F6FAD }
#mocha code .string { color: #5890AD }
#mocha code .keyword { color: #8A6343 }
#mocha code .number { color: #2F6FAD }
@media screen and (max-device-width: 480px) {
#mocha {
margin: 60px 0px;
}
#mocha #stats {
position: absolute;
}
}

5554
packages/ssf/ctest/mocha.js Normal file

File diff suppressed because it is too large Load Diff

330
packages/ssf/ctest/shim.js Normal file

@ -0,0 +1,330 @@
// From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
if (!Object.keys) {
Object.keys = (function () {
var hasOwnProperty = Object.prototype.hasOwnProperty,
hasDontEnumBug = !({toString: null}).propertyIsEnumerable('toString'),
dontEnums = [
'toString',
'toLocaleString',
'valueOf',
'hasOwnProperty',
'isPrototypeOf',
'propertyIsEnumerable',
'constructor'
],
dontEnumsLength = dontEnums.length;
return function (obj) {
if (typeof obj !== 'object' && typeof obj !== 'function' || obj === null) throw new TypeError('Object.keys called on non-object');
var result = [];
for (var prop in obj) {
if (hasOwnProperty.call(obj, prop)) result.push(prop);
}
if (hasDontEnumBug) {
for (var i=0; i < dontEnumsLength; i++) {
if (hasOwnProperty.call(obj, dontEnums[i])) result.push(dontEnums[i]);
}
}
return result;
};
})();
}
// From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
if (!Array.prototype.filter)
{
Array.prototype.filter = function(fun /*, thisp */)
{
"use strict";
if (this == null)
throw new TypeError();
var t = Object(this);
var len = t.length >>> 0;
if (typeof fun != "function")
throw new TypeError();
var res = [];
var thisp = arguments[1];
for (var i = 0; i < len; i++)
{
if (i in t)
{
var val = t[i]; // in case fun mutates this
if (fun.call(thisp, val, i, t))
res.push(val);
}
}
return res;
};
}
// From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/Trim
if (!String.prototype.trim) {
String.prototype.trim = function () {
return this.replace(/^\s+|\s+$/g, '');
};
}
// From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach
if (!Array.prototype.forEach)
{
Array.prototype.forEach = function(fun /*, thisArg */)
{
"use strict";
if (this === void 0 || this === null)
throw new TypeError();
var t = Object(this);
var len = t.length >>> 0;
if (typeof fun !== "function")
throw new TypeError();
var thisArg = arguments.length >= 2 ? arguments[1] : void 0;
for (var i = 0; i < len; i++)
{
if (i in t)
fun.call(thisArg, t[i], i, t);
}
};
}
// Production steps of ECMA-262, Edition 5, 15.4.4.19
// Reference: http://es5.github.com/#x15.4.4.19
if (!Array.prototype.map) {
Array.prototype.map = function(callback, thisArg) {
var T, A, k;
if (this == null) {
throw new TypeError(" this is null or not defined");
}
// 1. Let O be the result of calling ToObject passing the |this| value as the argument.
var O = Object(this);
// 2. Let lenValue be the result of calling the Get internal method of O with the argument "length".
// 3. Let len be ToUint32(lenValue).
var len = O.length >>> 0;
// 4. If IsCallable(callback) is false, throw a TypeError exception.
// See: http://es5.github.com/#x9.11
if (typeof callback !== "function") {
throw new TypeError(callback + " is not a function");
}
// 5. If thisArg was supplied, let T be thisArg; else let T be undefined.
if (thisArg) {
T = thisArg;
}
// 6. Let A be a new array created as if by the expression new Array(len) where Array is
// the standard built-in constructor with that name and len is the value of len.
A = new Array(len);
// 7. Let k be 0
k = 0;
// 8. Repeat, while k < len
while(k < len) {
var kValue, mappedValue;
// a. Let Pk be ToString(k).
// This is implicit for LHS operands of the in operator
// b. Let kPresent be the result of calling the HasProperty internal method of O with argument Pk.
// This step can be combined with c
// c. If kPresent is true, then
if (k in O) {
// i. Let kValue be the result of calling the Get internal method of O with argument Pk.
kValue = O[ k ];
// ii. Let mappedValue be the result of calling the Call internal method of callback
// with T as the this value and argument list containing kValue, k, and O.
mappedValue = callback.call(T, kValue, k, O);
// iii. Call the DefineOwnProperty internal method of A with arguments
// Pk, Property Descriptor {Value: mappedValue, : true, Enumerable: true, Configurable: true},
// and false.
// In browsers that support Object.defineProperty, use the following:
// Object.defineProperty(A, Pk, { value: mappedValue, writable: true, enumerable: true, configurable: true });
// For best browser support, use the following:
A[ k ] = mappedValue;
}
// d. Increase k by 1.
k++;
}
// 9. return A
return A;
};
}
// From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf
if (!Array.prototype.indexOf) {
Array.prototype.indexOf = function (searchElement, fromIndex) {
if ( this === undefined || this === null ) {
throw new TypeError( '"this" is null or not defined' );
}
var length = this.length >>> 0; // Hack to convert object.length to a UInt32
fromIndex = +fromIndex || 0;
if (Math.abs(fromIndex) === Infinity) {
fromIndex = 0;
}
if (fromIndex < 0) {
fromIndex += length;
if (fromIndex < 0) {
fromIndex = 0;
}
}
for (;fromIndex < length; fromIndex++) {
if (this[fromIndex] === searchElement) {
return fromIndex;
}
}
return -1;
};
}
// Based on https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray
if (! Array.isArray) {
Array.isArray = function(obj) {
return Object.prototype.toString.call(obj) === "[object Array]";
};
}
// https://github.com/ttaubert/node-arraybuffer-slice
// (c) 2013 Tim Taubert <tim@timtaubert.de>
// arraybuffer-slice may be freely distributed under the MIT license.
"use strict";
if (typeof ArrayBuffer !== 'undefined' && !ArrayBuffer.prototype.slice) {
ArrayBuffer.prototype.slice = function (begin, end) {
begin = (begin|0) || 0;
var num = this.byteLength;
end = end === (void 0) ? num : (end|0);
// Handle negative values.
if (begin < 0) begin += num;
if (end < 0) end += num;
if (num === 0 || begin >= num || begin >= end) {
return new ArrayBuffer(0);
}
var length = Math.min(num - begin, end - begin);
var target = new ArrayBuffer(length);
var targetArray = new Uint8Array(target);
targetArray.set(new Uint8Array(this, begin, length));
return target;
};
}
// https://github.com/davidchambers/Base64.js
// (C) 2015 David Chambers
// Base64.js may be freely distributed under the Apache 2.0 License.
;(function () {
var object = typeof exports != 'undefined' ? exports : typeof self != 'undefined' ? self : eval("this");
var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
function InvalidCharacterError(message) {
this.message = message;
}
InvalidCharacterError.prototype = new Error;
InvalidCharacterError.prototype.name = 'InvalidCharacterError';
// encoder
// [https://gist.github.com/999166] by [https://github.com/nignag]
object.btoa || (
object.btoa = function (input) {
var str = String(input);
for (
// initialize result and counter
var block, charCode, idx = 0, map = chars, output = '';
// if the next str index does not exist:
// change the mapping table to "="
// check if d has no fractional digits
str.charAt(idx | 0) || (map = '=', idx % 1);
// "8 - idx % 1 * 8" generates the sequence 2, 4, 6, 8
output += map.charAt(63 & block >> 8 - idx % 1 * 8)
) {
charCode = str.charCodeAt(idx += 3/4);
if (charCode > 0xFF) {
throw new InvalidCharacterError("'btoa' failed: The string to be encoded contains characters outside of the Latin1 range.");
}
block = block << 8 | charCode;
}
return output;
});
// decoder
// [https://gist.github.com/1020396] by [https://github.com/atk]
object.atob || (
object.atob = function (input) {
var str = String(input).replace(new RegExp("=+$"), '');
if (str.length % 4 == 1) {
throw new InvalidCharacterError("'atob' failed: The string to be decoded is not correctly encoded.");
}
for (
// initialize result and counters
var bc = 0, bs, buffer, idx = 0, output = '';
// get next character
buffer = str.charAt(idx++);
// character found in table? initialize bit storage and add its ascii value;
~buffer && (bs = bc % 4 ? bs * 64 + buffer : buffer,
// and if not first of each 4 characters,
// convert the first 8 bits to one ascii character
bc++ % 4) ? output += String.fromCharCode(255 & bs >> (-2 * bc & 6)) : 0
) {
// try to find character in table (0-63, not found => -1)
buffer = chars.indexOf(buffer);
}
return output;
});
}());
// From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString
if (!Date.prototype.toISOString) {
(function() {
function pad(number) {
if (number < 10) {
return '0' + number;
}
return number;
}
Date.prototype.toISOString = function() {
return this.getUTCFullYear() +
'-' + pad(this.getUTCMonth() + 1) +
'-' + pad(this.getUTCDate()) +
'T' + pad(this.getUTCHours()) +
':' + pad(this.getUTCMinutes()) +
':' + pad(this.getUTCSeconds()) +
'.' + (this.getUTCMilliseconds() / 1000).toFixed(3).slice(2, 5) +
'Z';
};
}());
}

70
packages/ssf/index.html Normal file

@ -0,0 +1,70 @@
<!DOCTYPE html>
<!-- ssf.js (C) 2013-present SheetJS http://sheetjs.com -->
<!-- vim: set ts=2: -->
<html>
<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>
<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">&nbsp;</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 */
/*eslint-env browser */
/*eslint no-use-before-define:0 */
/*global SSF */
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; }
}
/* 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();
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>

31
packages/ssf/misc/flow.js Normal file

@ -0,0 +1,31 @@
/*# vim: set ts=2: */
/*::
type SSFTable = {[key:number|string]:string};
type SSFDate = {
D:number; T:number;
y:number; m:number; d:number; q:number;
H:number; M:number; S:number; u:number;
};
type SSFModule = {
format:(fmt:string|number, v:any, o:any)=>string;
is_date:(fmt:string)=>boolean;
parse_date_code:(v:number,opts:any)=>?SSFDate;
load:(fmt:string, idx:?number)=>number;
get_table:()=>SSFTable;
load_table:(table:any)=>void;
_table:SSFTable;
init_table:any;
_general_int:(v:number)=>string;
_general_num:(v:number)=>string;
_general:(v:number, o:?any)=>string;
_eval:any;
_split:any;
version:string;
};
*/

@ -0,0 +1,7 @@
/*# vim: set ts=2: */
/*::
declare module './' { declare module.exports:SSFModule; };
declare module '../' { declare module.exports:SSFModule; };
declare module 'ssf' { declare module.exports:SSFModule; };
*/

42
packages/ssf/misc/help.sh Executable file

@ -0,0 +1,42 @@
#!/bin/bash
# make_help.sh -- process listing of targets and special items in Makefile
# Copyright (C) 2016-present SheetJS
#
# usage in makefile: pipe the output of the following command:
# @grep -hE '(^[a-zA-Z_-][ a-zA-Z_-]*:.*?|^#[#*])' $(MAKEFILE_LIST)
#
# lines starting with "## " are treated as subtitles
# lines starting with "#* " are treated as plaintext comments
# multiple targets with "## " after the ":" are rendered as separate targets
# if the presumed default target is labeled, it will be assigned a unique color
awk '
BEGIN{recipes=0;}
!/#[#*] .*$/ {next;}
{multi=0; isrecipe=0;}
/^[^#]*:/ {isrecipe=1; ++recipes;}
/^[^ :]* .*:/ {multi=1}
multi==0 && isrecipe>0 { if(recipes > 1) print; else print $0, "[default]"; next}
isrecipe == 0 {print; next}
multi>0 {
k=split($0, msg, "##"); m=split($0, a, ":"); n=split(a[1], b, " ");
for(i=1; i<=n; ++i) print b[i] ":", "##" msg[2], (recipes==1 && i==1 ? "[default]" : "")
}
END {}
' | if [[ -t 1 ]]; then
awk '
BEGIN {FS = ":.*?## "}
{color=36}
/\[default\]/ {color=35}
NF==1 && /^##/ {color=34}
NF==1 && /^#\*/ {color=20; $1 = substr($1, 4)}
{printf "\033[" color "m%-20s\033[0m %s\n", $1, $2;}
END{}' -
else
awk '
BEGIN {FS = ":.*?## "}
/^#\* / {$1 = substr($1, 4)}
{printf "%-20s %s\n", $1, $2;}
END{}' -
fi

@ -0,0 +1,11 @@
#! /usr/bin/env bash
# This script will check the current version of node and install another version
# of npm if node is version 0.8
version=$(node --version)
if [[ $version =~ v0\.8\. ]]
then
npm install -g npm@4.3.0
fi

77
packages/ssf/misc/perf.js Normal file

@ -0,0 +1,77 @@
/* vim: set ts=2: */
/*jshint loopfunc:true */
var SSF = require('../');
var fs = require('fs')//, assert = require('assert');
var data = JSON.parse(fs.readFileSync('./test/oddities.json','utf8'));
var dates = fs.readFileSync('./test/dates.tsv','utf8').split("\n");
var date2 = fs.readFileSync('./test/cal.tsv', 'utf8').split("\n");
var times = fs.readFileSync('./test/times.tsv','utf8').split("\n");
function doit(data) {
/* Prevent Optimization */
/* Prevent Optimization */
/* Prevent Optimization */
/* Prevent Optimization */
/* Prevent Optimization */
/* Prevent Optimization */
/* Prevent Optimization */
/* Prevent Optimization */
/* Prevent Optimization */
/* Prevent Optimization */
/* Prevent Optimization */
/* Prevent Optimization */
/* Prevent Optimization */
/* Prevent Optimization */
/* Prevent Optimization */
/* Prevent Optimization */
/* Prevent Optimization */
/* Prevent Optimization */
/* Prevent Optimization */
/* Prevent Optimization */
/* Prevent Optimization */
var headers = data[0].split("\t");
for(var k = 1; k <= data.length; ++k) {
if(data[k] == null) return;
var d = data[k].replace(/#{255}/g,"").split("\t");
for(var w = 1; w < headers.length; ++w) {
var expected = d[w], actual = SSF.format(headers[w], parseFloat(d[0]), {});
}
}
}
function testit() {
/* Prevent Optimization */
/* Prevent Optimization */
/* Prevent Optimization */
/* Prevent Optimization */
/* Prevent Optimization */
/* Prevent Optimization */
/* Prevent Optimization */
/* Prevent Optimization */
/* Prevent Optimization */
/* Prevent Optimization */
/* Prevent Optimization */
/* Prevent Optimization */
/* Prevent Optimization */
/* Prevent Optimization */
/* Prevent Optimization */
/* Prevent Optimization */
/* Prevent Optimization */
/* Prevent Optimization */
/* Prevent Optimization */
/* Prevent Optimization */
doit(times.slice(0,4000));
doit(dates.slice(0,4000));
for(var i = 0; i != 1000; ++i) {
for(var k = 0; k != data.length; ++k) {
var d = data[k];
for(var j=1;j<d.length;++j) {
if(d[j].length == 2) {
var expected = d[j][1], actual = SSF.format(d[0], d[j][0], {});
//if(actual != expected) console.log(d[j]);
}
}
}
}
}
testit();

13
packages/ssf/misc/perf.sh Executable file

@ -0,0 +1,13 @@
#!/bin/bash
ARGS="--trace_opt --trace_deopt --trace_inlining --code_comments"
#ARGS="--trace_opt --trace_deopt --code_comments"
SCPT=misc/perf.js
echo 1
make && jshint --show-non-errors ssf.js && make lint &&
MINTEST=1 mocha -b && time node $SCPT && {
node $ARGS $SCPT > perf.log
node --prof $SCPT
echo 1; time node $SCPT >/dev/null
echo 1; time node $SCPT >/dev/null
} && grep disabled perf.log

@ -0,0 +1 @@
#include "ssf.flow.js"; var fmt = 10; var data = 123.456789; alert(SSF.format(fmt, data));

14
packages/ssf/misc/spin.sh Executable file

@ -0,0 +1,14 @@
#!/bin/bash
# spin.sh -- show a spinner (for coverage test)
# Copyright (C) 2014-present SheetJS
wpid=$1
delay=1
str="|/-\\"
while [ $(ps -a|awk '$1=='$wpid' {print $1}') ]; do
t=${str#?}
printf " [%c]" "$str"
str=$t${str%"$t"}
sleep $delay
printf "\b\b\b\b"
done

58
packages/ssf/package.json Normal file

@ -0,0 +1,58 @@
{
"name": "ssf",
"version": "0.11.2",
"author": "sheetjs",
"description": "Format data using ECMA-376 spreadsheet Format Codes",
"keywords": [
"format",
"sprintf",
"spreadsheet"
],
"main": "ssf.js",
"types": "types",
"dependencies": {
"frac":"~1.1.2"
},
"devDependencies": {
"@sheetjs/uglify-js":"~2.7.3",
"@types/node":"^8.0.7",
"blanket": "~1.2.3",
"dtslint": "^0.1.2",
"mocha": "~2.5.3",
"typescript": "2.2.0"
},
"repository": {
"type": "git",
"url": "git://github.com/SheetJS/sheetjs.git",
"directory": "packages/ssf"
},
"scripts": {
"test": "make test",
"build": "make",
"lint": "make fullint",
"dtslint": "dtslint types"
},
"config": {
"blanket": {
"pattern": "ssf.js"
}
},
"alex": {
"allow": [
"special",
"simple",
"just",
"crash",
"wtf",
"holes"
]
},
"homepage": "http://sheetjs.com/",
"bugs": {
"url": "https://github.com/SheetJS/sheetjs/issues"
},
"license": "Apache-2.0",
"engines": {
"node": ">=0.8"
}
}

980
packages/ssf/ssf.flow.js Normal file

@ -0,0 +1,980 @@
/* ssf.js (C) 2013-present SheetJS -- http://sheetjs.com */
/* vim: set ts=2: */
/*jshint -W041 */
/*:: declare var DO_NOT_EXPORT_SSF: any; */
var SSF/*:SSFModule*/ = ({}/*:any*/);
var make_ssf = function make_ssf(SSF/*:SSFModule*/){
SSF.version = '0.11.2';
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;}
function pad_(v/*:any*/,d/*:number*/)/*:string*/{var t=""+v;return t.length>=d?t:fill(' ',d-t.length)+t;}
function rpad_(v/*:any*/,d/*:number*/)/*:string*/{var t=""+v; return t.length>=d?t:t+fill(' ',d-t.length);}
function pad0r1(v/*:any*/,d/*:number*/)/*:string*/{var t=""+Math.round(v); return t.length>=d?t:fill('0',d-t.length)+t;}
function pad0r2(v/*:any*/,d/*:number*/)/*:string*/{var t=""+v; return t.length>=d?t:fill('0',d-t.length)+t;}
var p2_32 = Math.pow(2,32);
function pad0r(v/*:any*/,d/*:number*/)/*:string*/{if(v>p2_32||v<-p2_32) return pad0r1(v,d); var i = Math.round(v); return pad0r2(i,d); }
function isgeneral(s/*:string*/, i/*:?number*/)/*:boolean*/ { i = i || 0; return s.length >= 7 + i && (s.charCodeAt(i)|32) === 103 && (s.charCodeAt(i+1)|32) === 101 && (s.charCodeAt(i+2)|32) === 110 && (s.charCodeAt(i+3)|32) === 101 && (s.charCodeAt(i+4)|32) === 114 && (s.charCodeAt(i+5)|32) === 97 && (s.charCodeAt(i+6)|32) === 108; }
/*::
type SSF_write_num = {(type:string, fmt:string, val:number):string};
*/
var days/*:Array<Array<string> >*/ = [
['Sun', 'Sunday'],
['Mon', 'Monday'],
['Tue', 'Tuesday'],
['Wed', 'Wednesday'],
['Thu', 'Thursday'],
['Fri', 'Friday'],
['Sat', 'Saturday']
];
var months/*:Array<Array<string> >*/ = [
['J', 'Jan', 'January'],
['F', 'Feb', 'February'],
['M', 'Mar', 'March'],
['A', 'Apr', 'April'],
['M', 'May', 'May'],
['J', 'Jun', 'June'],
['J', 'Jul', 'July'],
['A', 'Aug', 'August'],
['S', 'Sep', 'September'],
['O', 'Oct', 'October'],
['N', 'Nov', 'November'],
['D', 'Dec', 'December']
];
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"秒 "';
}
var table_fmt = {};
init_table(table_fmt);
/* Defaults determined by systematically testing in Excel 2019 */
/* These formats appear to default to other formats in the table */
var default_map/*:Array<number>*/ = [];
var defi = 0;
// 5 -> 37 ... 8 -> 40
for(defi = 5; defi <= 8; ++defi) default_map[defi] = 32 + defi;
// 23 -> 0 ... 26 -> 0
for(defi = 23; defi <= 26; ++defi) default_map[defi] = 0;
// 27 -> 14 ... 31 -> 14
for(defi = 27; defi <= 31; ++defi) default_map[defi] = 14;
// 50 -> 14 ... 58 -> 14
for(defi = 50; defi <= 58; ++defi) default_map[defi] = 14;
// 59 -> 1 ... 62 -> 4
for(defi = 59; defi <= 62; ++defi) default_map[defi] = defi - 58;
// 67 -> 9 ... 68 -> 10
for(defi = 67; defi <= 68; ++defi) default_map[defi] = defi - 58;
// 72 -> 14 ... 75 -> 17
for(defi = 72; defi <= 75; ++defi) default_map[defi] = defi - 58;
// 69 -> 12 ... 71 -> 14
for(defi = 67; defi <= 68; ++defi) default_map[defi] = defi - 57;
// 76 -> 20 ... 78 -> 22
for(defi = 76; defi <= 78; ++defi) default_map[defi] = defi - 56;
// 79 -> 45 ... 81 -> 47
for(defi = 79; defi <= 81; ++defi) default_map[defi] = defi - 34;
// 82 -> 0 ... 65536 -> 0 (omitted)
/* These formats technically refer to Accounting formats with no equivalent */
var default_str/*:Array<string>*/ = [];
// 5 -- Currency, 0 decimal, black negative
default_str[5] = default_str[63] = '"$"#,##0_);\\("$"#,##0\\)';
// 6 -- Currency, 0 decimal, red negative
default_str[6] = default_str[64] = '"$"#,##0_);[Red]\\("$"#,##0\\)';
// 7 -- Currency, 2 decimal, black negative
default_str[7] = default_str[65] = '"$"#,##0.00_);\\("$"#,##0.00\\)';
// 8 -- Currency, 2 decimal, red negative
default_str[8] = default_str[66] = '"$"#,##0.00_);[Red]\\("$"#,##0.00\\)';
// 41 -- Accounting, 0 decimal, No Symbol
default_str[41] = '_(* #,##0_);_(* \\(#,##0\\);_(* "-"_);_(@_)';
// 42 -- Accounting, 0 decimal, $ Symbol
default_str[42] = '_("$"* #,##0_);_("$"* \\(#,##0\\);_("$"* "-"_);_(@_)';
// 43 -- Accounting, 2 decimal, No Symbol
default_str[43] = '_(* #,##0.00_);_(* \\(#,##0.00\\);_(* "-"??_);_(@_)';
// 44 -- Accounting, 2 decimal, $ Symbol
default_str[44] = '_("$"* #,##0.00_);_("$"* \\(#,##0.00\\);_("$"* "-"??_);_(@_)';
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;
var Q_2 = 1, Q_1 = 0, Q = 0;
var A = Math.floor(B);
while(Q_1 < D) {
A = Math.floor(B);
P = A * P_1 + P_2;
Q = A * Q_1 + Q_2;
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) { if(Q_1 > D) { Q = Q_2; P = P_2; } else { Q = Q_1; P = P_1; } }
if(!mixed) return [0, sgn * P, Q];
var q = Math.floor(sgn * P/Q);
return [q, sgn*P - q*Q, Q];
}
function parse_date_code(v/*:number*/,opts/*:?any*/,b2/*:?boolean*/) {
if(v > 2958465 || v < 0) return null;
var date = (v|0), time = Math.floor(86400 * (v - date)), dow=0;
var dout=[];
var out={D:date, T:time, u:86400*(v-date)-time,y:0,m:0,d:0,H:0,M:0,S:0,q:0};
if(Math.abs(out.u) < 1e-6) out.u = 0;
if(opts && opts.date1904) date += 1462;
if(out.u > 0.9999) {
out.u = 0;
if(++time == 86400) { out.T = time = 0; ++date; ++out.D; }
}
if(date === 60) {dout = b2 ? [1317,10,29] : [1900,2,29]; dow=3;}
else if(date === 0) {dout = b2 ? [1317,8,29] : [1900,1,0]; dow=6;}
else {
if(date > 60) --date;
/* 1 = Jan 1 1900 in Gregorian */
var d = new Date(1900, 0, 1);
d.setDate(d.getDate() + date - 1);
dout = [d.getFullYear(), d.getMonth()+1,d.getDate()];
dow = d.getDay();
if(date < 60) dow = (dow + 6) % 7;
if(b2) dow = fix_hijri(d, dout);
}
out.y = dout[0]; out.m = dout[1]; out.d = dout[2];
out.S = time % 60; time = Math.floor(time / 60);
out.M = time % 60; time = Math.floor(time / 60);
out.H = time;
out.q = dow;
return out;
}
SSF.parse_date_code = parse_date_code;
var basedate = new Date(1899, 11, 31, 0, 0, 0);
var dnthresh = basedate.getTime();
var base1904 = new Date(1900, 2, 1, 0, 0, 0);
function datenum_local(v/*:Date*/, date1904/*:?boolean*/)/*:number*/ {
var epoch = v.getTime();
if(date1904) epoch -= 1461*24*60*60*1000;
else if(v >= base1904) epoch += 24*60*60*1000;
return (epoch - (dnthresh + (v.getTimezoneOffset() - basedate.getTimezoneOffset()) * 60000)) / (24 * 60 * 60 * 1000);
}
/* The longest 32-bit integer text is "-4294967296", exactly 11 chars */
function general_fmt_int(v/*:number*/)/*:string*/ { return v.toString(10); }
SSF._general_int = general_fmt_int;
/* ECMA-376 18.8.30 numFmt*/
/* Note: `toPrecision` uses standard form when prec > E and E >= -6 */
var general_fmt_num = (function make_general_fmt_num() {
var trailing_zeroes_and_decimal = /(?:\.0*|(\.\d*[1-9])0+)$/;
function strip_decimal(o/*:string*/)/*:string*/ {
return (o.indexOf(".") == -1) ? o : o.replace(trailing_zeroes_and_decimal, "$1");
}
/* General Exponential always shows 2 digits exp and trims the mantissa */
var mantissa_zeroes_and_decimal = /(?:\.0*|(\.\d*[1-9])0+)[Ee]/;
var exp_with_single_digit = /(E[+-])(\d)$/;
function normalize_exp(o/*:string*/)/*:string*/ {
if(o.indexOf("E") == -1) return o;
return o.replace(mantissa_zeroes_and_decimal,"$1E").replace(exp_with_single_digit,"$10$2");
}
/* exponent >= -9 and <= 9 */
function small_exp(v/*:number*/)/*:string*/ {
var w = (v<0?12:11);
var o = strip_decimal(v.toFixed(12)); if(o.length <= w) return o;
o = v.toPrecision(10); if(o.length <= w) return o;
return v.toExponential(5);
}
/* exponent >= 11 or <= -10 likely exponential */
function large_exp(v/*:number*/)/*:string*/ {
var o = strip_decimal(v.toFixed(11));
return (o.length > (v<0?12:11) || o === "0" || o === "-0") ? v.toPrecision(6) : o;
}
function general_fmt_num_base(v/*:number*/)/*:string*/ {
var V = Math.floor(Math.log(Math.abs(v))*Math.LOG10E), o;
if(V >= -4 && V <= -1) o = v.toPrecision(10+V);
else if(Math.abs(V) <= 9) o = small_exp(v);
else if(V === 10) o = v.toFixed(10).substr(0,12);
else o = large_exp(v);
return strip_decimal(normalize_exp(o.toUpperCase()));
}
return general_fmt_num_base;
})();
SSF._general_num = general_fmt_num;
/*
"General" rules:
- text is passed through ("@")
- booleans are rendered as TRUE/FALSE
- "up to 11 characters" displayed for numbers
- Default date format (code 14) used for Dates
TODO: technically the display depends on the width of the cell
*/
function general_fmt(v/*:any*/, opts/*:any*/) {
switch(typeof v) {
case 'string': return v;
case 'boolean': return v ? "TRUE" : "FALSE";
case 'number': return (v|0) === v ? v.toString(10) : general_fmt_num(v);
case 'undefined': return "";
case 'object':
if(v == null) return "";
if(v instanceof Date) return format(14, datenum_local(v, opts && opts.date1904), opts);
}
throw new Error("unsupported value in General format: " + v);
}
SSF._general = general_fmt;
function fix_hijri(date/*:Date*/, o/*:[number, number, number]*/) {
/* TODO: properly adjust y/m/d and */
o[0] -= 581;
var dow = date.getDay();
if(date < 60) dow = (dow + 6) % 7;
return dow;
}
var THAI_DIGITS = "\u0E50\u0E51\u0E52\u0E53\u0E54\u0E55\u0E56\u0E57\u0E58\u0E59".split("");
/*jshint -W086 */
function write_date(type/*:number*/, fmt/*:string*/, val, ss0/*:?number*/)/*:string*/ {
var o="", ss=0, tt=0, y = val.y, out, outl = 0;
switch(type) {
case 98: /* 'b' buddhist year */
y = val.y + 543;
/* falls through */
case 121: /* 'y' year */
switch(fmt.length) {
case 1: case 2: out = y % 100; outl = 2; break;
default: out = y % 10000; outl = 4; break;
} break;
case 109: /* 'm' month */
switch(fmt.length) {
case 1: case 2: out = val.m; outl = fmt.length; break;
case 3: return months[val.m-1][1];
case 5: return months[val.m-1][0];
default: return months[val.m-1][2];
} break;
case 100: /* 'd' day */
switch(fmt.length) {
case 1: case 2: out = val.d; outl = fmt.length; break;
case 3: return days[val.q][0];
default: return days[val.q][1];
} break;
case 104: /* 'h' 12-hour */
switch(fmt.length) {
case 1: case 2: out = 1+(val.H+11)%12; outl = fmt.length; break;
default: throw 'bad hour format: ' + fmt;
} break;
case 72: /* 'H' 24-hour */
switch(fmt.length) {
case 1: case 2: out = val.H; outl = fmt.length; break;
default: throw 'bad hour format: ' + fmt;
} break;
case 77: /* 'M' minutes */
switch(fmt.length) {
case 1: case 2: out = val.M; outl = fmt.length; break;
default: throw 'bad minute format: ' + fmt;
} break;
case 115: /* 's' seconds */
if(fmt != 's' && fmt != 'ss' && fmt != '.0' && fmt != '.00' && fmt != '.000') throw 'bad second format: ' + fmt;
if(val.u === 0 && (fmt == "s" || fmt == "ss")) return pad0(val.S, fmt.length);
/*::if(!ss0) ss0 = 0; */
if(ss0 >= 2) tt = ss0 === 3 ? 1000 : 100;
else tt = ss0 === 1 ? 10 : 1;
ss = Math.round((tt)*(val.S + val.u));
if(ss >= 60*tt) ss = 0;
if(fmt === 's') return ss === 0 ? "0" : ""+ss/tt;
o = pad0(ss,2 + ss0);
if(fmt === 'ss') return o.substr(0,2);
return "." + o.substr(2,fmt.length-1);
case 90: /* 'Z' absolute time */
switch(fmt) {
case '[h]': case '[hh]': out = val.D*24+val.H; break;
case '[m]': case '[mm]': out = (val.D*24+val.H)*60+val.M; break;
case '[s]': case '[ss]': out = ((val.D*24+val.H)*60+val.M)*60+Math.round(val.S+val.u); break;
default: throw 'bad abstime format: ' + fmt;
} outl = fmt.length === 3 ? 1 : 2; break;
case 101: /* 'e' era */
out = y; outl = 1; break;
}
var outstr = outl > 0 ? pad0(out, outl) : "";
return outstr;
}
/*jshint +W086 */
function commaify(s/*:string*/)/*:string*/ {
var w = 3;
if(s.length <= w) return s;
var j = (s.length % w), o = s.substr(0,j);
for(; j!=s.length; j+=w) o+=(o.length > 0 ? "," : "") + s.substr(j,w);
return o;
}
var write_num/*:SSF_write_num*/ = (function make_write_num(){
var pct1 = /%/g;
function write_num_pct(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_cm(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_exp(fmt/*:string*/, val/*:number*/)/*:string*/{
var o/*:string*/;
var idx = fmt.indexOf("E") - fmt.indexOf(".") - 1;
if(fmt.match(/^#+0.0E\+0$/)) {
if(val == 0) return "0.0E+0";
else if(val < 0) return "-" + write_num_exp(fmt, -val);
var period = fmt.indexOf("."); if(period === -1) period=fmt.indexOf('E');
var ee = Math.floor(Math.log(val)*Math.LOG10E)%period;
if(ee < 0) ee += period;
o = (val/Math.pow(10,ee)).toPrecision(idx+1+(period+ee)%period);
if(o.indexOf("e") === -1) {
var fakee = Math.floor(Math.log(val)*Math.LOG10E);
if(o.indexOf(".") === -1) o = o.charAt(0) + "." + o.substr(1) + "E+" + (fakee - o.length+ee);
else o += "E+" + (fakee - ee);
while(o.substr(0,2) === "0.") {
o = o.charAt(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(/^([+-]?)(\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");
}
var frac1 = /# (\?+)( ?)\/( ?)(\d+)/;
function write_num_f1(r/*:Array<string>*/, aval/*:number*/, sign/*:string*/)/*:string*/ {
var den = parseInt(r[4],10), rr = Math.round(aval * den), base = Math.floor(rr/den);
var myn = (rr - base*den), myd = den;
return sign + (base === 0 ? "" : ""+base) + " " + (myn === 0 ? fill(" ", r[1].length + 1 + r[4].length) : pad_(myn,r[1].length) + r[2] + "/" + r[3] + pad0(myd,r[4].length));
}
function write_num_f2(r/*:Array<string>*/, aval/*:number*/, sign/*:string*/)/*:string*/ {
return sign + (aval === 0 ? "" : ""+aval) + fill(" ", r[1].length + 2 + r[4].length);
}
var dec1 = /^#*0*\.([0#]+)/;
var closeparen = /\).*[0#]/;
var phone = /\(###\) ###\\?-####/;
function hashq(str/*:string*/)/*:string*/ {
var o = "", cc;
for(var i = 0; i != str.length; ++i) switch((cc=str.charCodeAt(i))) {
case 35: break;
case 63: o+= " "; break;
case 48: o+= "0"; break;
default: o+= String.fromCharCode(cc);
}
return o;
}
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*/ {
var _frac = val - Math.floor(val), dd = Math.pow(10,d);
if (d < ('' + Math.round(_frac * dd)).length) return 0;
return Math.round(_frac * dd);
}
function carry(val/*:number*/, d/*:number*/)/*:number*/ {
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))) {
o = rnd(val, r[1].length).replace(/^([^\.]+)$/,"$1."+hashq(r[1])).replace(/\.$/,"."+hashq(r[1])).replace(/\.(\d*)$/,function($$, $1) { return "." + $1 + fill("0", hashq(/*::(*/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(/^#{1,3},##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 "###,##0.00": return write_num_flt(type, "#,##0.00", val);
case "###,###":
case "##,###":
case "#,###": var x = commaify(pad0r(aval,0)); return x !== "0" ? sign + x : "";
case "###,###.00": return write_num_flt(type, "###,##0.00",val).replace(/^0\./,".");
case "#,###.00": return write_num_flt(type, "#,##0.00",val).replace(/^0\./,".");
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$/)) {
if(val == 0) return "0.0E+0";
else if(val < 0) return "-" + write_num_exp2(fmt, -val);
var period = fmt.indexOf("."); if(period === -1) period=fmt.indexOf('E');
var ee = Math.floor(Math.log(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(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/*:?Array<string>*/, 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."+hashq(r[1])).replace(/\.$/,"."+hashq(r[1]));
o = o.replace(/\.(\d*)$/,function($$, $1) {
/*:: if(!Array.isArray(r)) throw new Error("unreachable"); */
return "." + $1 + fill("0", hashq(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(/^#{1,3},##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(/*::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 = "" + 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 "###,###":
case "##,###":
case "#,###": var x = commaify(""+aval); return x !== "0" ? sign + x : "";
default:
if(fmt.match(/\.[0#?]*$/)) return write_num_int(type, fmt.slice(0,fmt.lastIndexOf(".")), val) + hashq(fmt.slice(fmt.lastIndexOf(".")));
}
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);
};})();
function split_fmt(fmt/*:string*/)/*:Array<string>*/ {
var out/*:Array<string>*/ = [];
var in_str = false/*, cc*/;
for(var i = 0, j = 0; i < fmt.length; ++i) switch((/*cc=*/fmt.charCodeAt(i))) {
case 34: /* '"' */
in_str = !in_str; break;
case 95: case 42: case 92: /* '_' '*' '\\' */
++i; break;
case 59: /* ';' */
out[out.length] = fmt.substr(j,i-j);
j = i+1;
}
out[out.length] = fmt.substr(j);
if(in_str === true) throw new Error("Format |" + fmt + "| unterminated string ");
return out;
}
SSF._split = split_fmt;
var abstime = /\[[HhMmSs\u0E0A\u0E19\u0E17]*\]/;
function fmt_is_date(fmt/*:string*/)/*:boolean*/ {
var i = 0, /*cc = 0,*/ c = "", o = "";
while(i < fmt.length) {
switch((c = fmt.charAt(i))) {
case 'G': if(isgeneral(fmt, i)) i+= 6; i++; break;
case '"': for(;(/*cc=*/fmt.charCodeAt(++i)) !== 34 && i < fmt.length;){/*empty*/} ++i; break;
case '\\': i+=2; break;
case '_': i+=2; break;
case '@': ++i; break;
case 'B': case 'b':
if(fmt.charAt(i+1) === "1" || fmt.charAt(i+1) === "2") return true;
/* falls through */
case 'M': case 'D': case 'Y': case 'H': case 'S': case 'E':
/* falls through */
case 'm': case 'd': case 'y': case 'h': case 's': case 'e': case 'g': return true;
case 'A': case 'a': case '上':
if(fmt.substr(i, 3).toUpperCase() === "A/P") return true;
if(fmt.substr(i, 5).toUpperCase() === "AM/PM") return true;
if(fmt.substr(i, 5).toUpperCase() === "上午/下午") return true;
++i; break;
case '[':
o = c;
while(fmt.charAt(i++) !== ']' && i < fmt.length) o += fmt.charAt(i);
if(o.match(abstime)) return true;
break;
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))){/* empty */}
break;
case '?': while(fmt.charAt(++i) === c){/* empty */} 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){/* empty */} break;
case ' ': ++i; break;
default: ++i; break;
}
}
return false;
}
SSF.is_date = fmt_is_date;
function eval_fmt(fmt/*:string*/, v/*:any*/, opts/*:any*/, flen/*:number*/) {
var out = [], o = "", i = 0, c = "", lst='t', dt, j, cc;
var hr='H';
/* Tokenize */
while(i < fmt.length) {
switch((c = fmt.charAt(i))) {
case 'G': /* General */
if(!isgeneral(fmt, i)) throw new Error('unrecognized character ' + c + ' in ' +fmt);
out[out.length] = {t:'G', v:'General'}; i+=7; break;
case '"': /* Literal text */
for(o="";(cc=fmt.charCodeAt(++i)) !== 34 && i < fmt.length;) o += String.fromCharCode(cc);
out[out.length] = {t:'t', v:o}; ++i; break;
case '\\': var w = fmt.charAt(++i), t = (w === "(" || w === ")") ? w : 't';
out[out.length] = {t:t, v:w}; ++i; break;
case '_': out[out.length] = {t:'t', v:" "}; i+=2; break;
case '@': /* Text Placeholder */
out[out.length] = {t:'T', v:v}; ++i; break;
case 'B': case 'b':
if(fmt.charAt(i+1) === "1" || fmt.charAt(i+1) === "2") {
if(dt==null) { dt=parse_date_code(v, opts, fmt.charAt(i+1) === "2"); if(dt==null) return ""; }
out[out.length] = {t:'X', v:fmt.substr(i,2)}; lst = c; i+=2; break;
}
/* falls through */
case 'M': case 'D': case 'Y': case 'H': case 'S': case 'E':
c = c.toLowerCase();
/* falls through */
case 'm': case 'd': case 'y': case 'h': case 's': case 'e': case 'g':
if(v < 0) return "";
if(dt==null) { dt=parse_date_code(v, opts); if(dt==null) return ""; }
o = c; while(++i < fmt.length && fmt.charAt(i).toLowerCase() === c) o+=c;
if(c === 'm' && lst.toLowerCase() === 'h') c = 'M';
if(c === 'h') c = hr;
out[out.length] = {t:c, v:o}; lst = c; break;
case 'A': case 'a': case '上':
var q={t:c, v:c};
if(dt==null) dt=parse_date_code(v, opts);
if(fmt.substr(i, 3).toUpperCase() === "A/P") { if(dt!=null) q.v = dt.H >= 12 ? "P" : "A"; q.t = 'T'; hr='h';i+=3;}
else if(fmt.substr(i,5).toUpperCase() === "AM/PM") { if(dt!=null) q.v = dt.H >= 12 ? "PM" : "AM"; q.t = 'T'; i+=5; hr='h'; }
else if(fmt.substr(i,5).toUpperCase() === "上午/下午") { if(dt!=null) q.v = dt.H >= 12 ? "下午" : "上午"; q.t = 'T'; i+=5; hr='h'; }
else { q.t = "t"; ++i; }
if(dt==null && q.t === 'T') return "";
out[out.length] = q; lst = c; break;
case '[':
o = c;
while(fmt.charAt(i++) !== ']' && i < fmt.length) o += fmt.charAt(i);
if(o.slice(-1) !== ']') throw 'unterminated "[" block: |' + o + '|';
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()};
lst = o.charAt(1);
} else if(o.indexOf("$") > -1) {
o = (o.match(/\$([^-\[\]]*)/)||[])[1]||"$";
if(!fmt_is_date(fmt)) out[out.length] = {t:'t',v:o};
}
break;
/* Numbers */
case '.':
if(dt != null) {
o = c; while(++i < fmt.length && (c=fmt.charAt(i)) === "0") o += c;
out[out.length] = {t:'s', v:o}; break;
}
/* falls through */
case '0': case '#':
o = c; while(++i < fmt.length && "0#?.,E+-%".indexOf(c=fmt.charAt(i)) > -1) o += c;
out[out.length] = {t:'n', v:o}; break;
case '?':
o = c; while(fmt.charAt(++i) === c) o+=c;
out[out.length] = {t:c, v:o}; lst = c; break;
case '*': ++i; if(fmt.charAt(i) == ' ' || fmt.charAt(i) == '*') ++i; break; // **
case '(': case ')': out[out.length] = {t:(flen===1?'t':c), v:c}; ++i; break;
case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
o = c; while(i < fmt.length && "0123456789".indexOf(fmt.charAt(++i)) > -1) o+=fmt.charAt(i);
out[out.length] = {t:'D', v:o}; break;
case ' ': out[out.length] = {t:c, v:c}; ++i; break;
case '$': out[out.length] = {t:'t', v:'$'}; ++i; break;
default:
if(",$-+/():!^&'~{}<>=€acfijklopqrtuvwxzP".indexOf(c) === -1) throw new Error('unrecognized character ' + c + ' in ' + fmt);
out[out.length] = {t:'t', v:c}; ++i; break;
}
}
/* Scan for date/time parts */
var bt = 0, ss0 = 0, ssm;
for(i=out.length-1, lst='t'; i >= 0; --i) {
switch(out[i].t) {
case 'h': case 'H': out[i].t = hr; lst='h'; if(bt < 1) bt = 1; break;
case 's':
if((ssm=out[i].v.match(/\.0+$/))) ss0=Math.max(ss0,ssm[0].length-1);
if(bt < 3) bt = 3;
/* 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");*/
break;
case 'Z':
if(bt < 1 && out[i].v.match(/[Hh]/)) bt = 1;
if(bt < 2 && out[i].v.match(/[Mm]/)) bt = 2;
if(bt < 3 && out[i].v.match(/[Ss]/)) bt = 3;
}
}
/* time rounding depends on presence of minute / second / usec fields */
switch(bt) {
case 0: break;
case 1:
/*::if(!dt) break;*/
if(dt.u >= 0.5) { dt.u = 0; ++dt.S; }
if(dt.S >= 60) { dt.S = 0; ++dt.M; }
if(dt.M >= 60) { dt.M = 0; ++dt.H; }
break;
case 2:
/*::if(!dt) break;*/
if(dt.u >= 0.5) { dt.u = 0; ++dt.S; }
if(dt.S >= 60) { dt.S = 0; ++dt.M; }
break;
}
/* replace fields */
var nstr = "", jj;
for(i=0; i < out.length; ++i) {
switch(out[i].t) {
case 't': case 'T': case ' ': case 'D': break;
case 'X': out[i].v = ""; out[i].t = ";"; break;
case 'd': case 'm': case 'y': case 'h': case 'H': case 'M': case 's': case 'e': case 'b': case 'Z':
/*::if(!dt) throw "unreachable"; */
out[i].v = write_date(out[i].t.charCodeAt(0), out[i].v, dt, ss0);
out[i].t = 't'; break;
case 'n': case '?':
jj = i+1;
while(out[jj] != null && (
(c=out[jj].t) === "?" || c === "D" ||
((c === " " || c === "t") && out[jj+1] != null && (out[jj+1].t === '?' || out[jj+1].t === "t" && out[jj+1].v === '/')) ||
(out[i].t === '(' && (c === ' ' || c === 'n' || c === ')')) ||
(c === 't' && (out[jj].v === '/' || out[jj].v === ' ' && out[jj+1] != null && out[jj+1].t == '?'))
)) {
out[i].v += out[jj].v;
out[jj] = {v:"", t:";"}; ++jj;
}
nstr += out[i].v;
i = jj-1; break;
case 'G': out[i].t = 't'; out[i].v = general_fmt(v,opts); break;
}
}
var vv = "", myv, ostr;
if(nstr.length > 0) {
if(nstr.charCodeAt(0) == 40) /* '(' */ {
myv = (v<0&&nstr.charCodeAt(0) === 45 ? -v : v);
ostr = write_num('n', 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].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) {
if(out[i] == null || 'n?'.indexOf(out[i].t) === -1) continue;
if(jj>=out[i].v.length-1) { jj -= out[i].v.length; out[i].v = ostr.substr(jj+1, out[i].v.length); }
else if(jj < 0) out[i].v = "";
else { out[i].v = ostr.substr(0, jj+1); jj = -1; }
out[i].t = 't';
lasti = i;
}
if(jj>=0 && lasti<out.length) out[lasti].v = ostr.substr(0,jj+1) + out[lasti].v;
}
else if(decpt !== out.length && ostr.indexOf("E") === -1) {
jj = ostr.indexOf(".")-1;
for(i=decpt; i>= 0; --i) {
if(out[i] == null || 'n?'.indexOf(out[i].t) === -1) continue;
j=out[i].v.indexOf(".")>-1&&i===decpt?out[i].v.indexOf(".")-1:out[i].v.length-1;
vv = out[i].v.substr(j+1);
for(; j>=0; --j) {
if(jj>=0 && (out[i].v.charAt(j) === "0" || out[i].v.charAt(j) === "#")) vv = ostr.charAt(jj--) + vv;
}
out[i].v = vv;
out[i].t = 't';
lasti = i;
}
if(jj>=0 && lasti<out.length) out[lasti].v = ostr.substr(0,jj+1) + out[lasti].v;
jj = ostr.indexOf(".")+1;
for(i=decpt; i<out.length; ++i) {
if(out[i] == null || ('n?('.indexOf(out[i].t) === -1 && i !== decpt)) continue;
j=out[i].v.indexOf(".")>-1&&i===decpt?out[i].v.indexOf(".")+1:0;
vv = out[i].v.substr(0,j);
for(; j<out[i].v.length; ++j) {
if(jj<ostr.length) vv += ostr.charAt(jj++);
}
out[i].v = vv;
out[i].t = 't';
lasti = i;
}
}
}
for(i=0; i<out.length; ++i) if(out[i] != null && 'n?'.indexOf(out[i].t)>-1) {
myv = (flen >1 && v < 0 && i>0 && out[i-1].v === "-" ? -v:v);
out[i].v = write_num(out[i].t, out[i].v, myv);
out[i].t = 't';
}
var retval = "";
for(i=0; i !== out.length; ++i) if(out[i] != null) retval += out[i].v;
return retval;
}
SSF._eval = eval_fmt;
var cfregex = /\[[=<>]/;
var cfregex2 = /\[(=|>[=]?|<[>=]?)(-?\d+(?:\.\d*)?)\]/;
function chkcond(v, rr) {
if(rr == null) return false;
var thresh = parseFloat(rr[2]);
switch(rr[1]) {
case "=": if(v == thresh) return true; break;
case ">": if(v > thresh) return true; break;
case "<": if(v < thresh) return true; break;
case "<>": if(v != thresh) return true; break;
case ">=": if(v >= thresh) return true; break;
case "<=": if(v <= thresh) return true; break;
}
return false;
}
function choose_fmt(f/*:string*/, v/*:any*/) {
var fmt = split_fmt(f);
var l = fmt.length, lat = fmt[l-1].indexOf("@");
if(l<4 && lat>-1) --l;
if(fmt.length > 4) throw new Error("cannot find right format for |" + fmt.join("|") + "|");
if(typeof v !== "number") return [4, fmt.length === 4 || lat>-1?fmt[fmt.length-1]:"@"];
switch(fmt.length) {
case 1: fmt = lat>-1 ? ["General", "General", "General", fmt[0]] : [fmt[0], fmt[0], fmt[0], "@"]; break;
case 2: fmt = lat>-1 ? [fmt[0], fmt[0], fmt[0], fmt[1]] : [fmt[0], fmt[1], fmt[0], "@"]; break;
case 3: fmt = lat>-1 ? [fmt[0], fmt[1], fmt[0], fmt[2]] : [fmt[0], fmt[1], fmt[2], "@"]; break;
case 4: break;
}
var ff = v > 0 ? fmt[0] : v < 0 ? fmt[1] : fmt[2];
if(fmt[0].indexOf("[") === -1 && fmt[1].indexOf("[") === -1) return [l, ff];
if(fmt[0].match(cfregex) != null || fmt[1].match(cfregex) != null) {
var m1 = fmt[0].match(cfregex2);
var m2 = fmt[1].match(cfregex2);
return chkcond(v, m1) ? [l, fmt[0]] : chkcond(v, m2) ? [l, fmt[1]] : [l, fmt[m1 != null && m2 != null ? 2 : 1]];
}
return [l, ff];
}
function format(fmt/*:string|number*/,v/*:any*/,o/*:?any*/) {
if(o == null) o = {};
var sfmt = "";
switch(typeof fmt) {
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];
if(sfmt == null) sfmt = (o.table && o.table[default_map[fmt]]) || table_fmt[default_map[fmt]];
if(sfmt == null) sfmt = default_str[fmt] || "General";
break;
}
if(isgeneral(sfmt,0)) return general_fmt(v, o);
if(v instanceof Date) v = datenum_local(v, o.date1904);
var f = choose_fmt(sfmt, v);
if(isgeneral(f[1])) return general_fmt(v, o);
if(v === true) v = "TRUE"; else if(v === false) v = "FALSE";
else if(v === "" || v == null) return "";
return eval_fmt(f[1], v, o, f[0]);
}
function load_entry(fmt/*:string*/, idx/*:?number*/)/*:number*/ {
if(typeof idx != 'number') {
idx = +idx || -1;
/*::if(typeof idx != 'number') return 0x188; */
for(var i = 0; i < 0x0188; ++i) {
/*::if(typeof idx != 'number') return 0x188; */
if(table_fmt[i] == undefined) { if(idx < 0) idx = i; continue; }
if(table_fmt[i] == fmt) { idx = i; break; }
}
/*::if(typeof idx != 'number') return 0x188; */
if(idx < 0) idx = 0x187;
}
/*::if(typeof idx != 'number') return 0x188; */
table_fmt[idx] = fmt;
return idx;
}
SSF.load = load_entry;
SSF._table = table_fmt;
SSF.get_table = function get_table()/*:SSFTable*/ { return table_fmt; };
SSF.load_table = function load_table(tbl/*:SSFTable*/)/*:void*/ {
for(var i=0; i!=0x0188; ++i)
if(tbl[i] !== undefined) load_entry(tbl[i], i);
};
SSF.init_table = init_table;
SSF.format = format;
};
make_ssf(SSF);
/*global module */
if(typeof module !== 'undefined' && typeof DO_NOT_EXPORT_SSF === 'undefined') module.exports = SSF;

966
packages/ssf/ssf.js Normal file

@ -0,0 +1,966 @@
/* ssf.js (C) 2013-present SheetJS -- http://sheetjs.com */
/* vim: set ts=2: */
/*jshint -W041 */
var SSF = ({});
var make_ssf = function make_ssf(SSF){
SSF.version = '0.11.2';
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;}
function pad_(v,d){var t=""+v;return t.length>=d?t:fill(' ',d-t.length)+t;}
function rpad_(v,d){var t=""+v; return t.length>=d?t:t+fill(' ',d-t.length);}
function pad0r1(v,d){var t=""+Math.round(v); return t.length>=d?t:fill('0',d-t.length)+t;}
function pad0r2(v,d){var t=""+v; return t.length>=d?t:fill('0',d-t.length)+t;}
var p2_32 = Math.pow(2,32);
function pad0r(v,d){if(v>p2_32||v<-p2_32) return pad0r1(v,d); var i = Math.round(v); return pad0r2(i,d); }
function isgeneral(s, i) { i = i || 0; return s.length >= 7 + i && (s.charCodeAt(i)|32) === 103 && (s.charCodeAt(i+1)|32) === 101 && (s.charCodeAt(i+2)|32) === 110 && (s.charCodeAt(i+3)|32) === 101 && (s.charCodeAt(i+4)|32) === 114 && (s.charCodeAt(i+5)|32) === 97 && (s.charCodeAt(i+6)|32) === 108; }
var days = [
['Sun', 'Sunday'],
['Mon', 'Monday'],
['Tue', 'Tuesday'],
['Wed', 'Wednesday'],
['Thu', 'Thursday'],
['Fri', 'Friday'],
['Sat', 'Saturday']
];
var months = [
['J', 'Jan', 'January'],
['F', 'Feb', 'February'],
['M', 'Mar', 'March'],
['A', 'Apr', 'April'],
['M', 'May', 'May'],
['J', 'Jun', 'June'],
['J', 'Jul', 'July'],
['A', 'Aug', 'August'],
['S', 'Sep', 'September'],
['O', 'Oct', 'October'],
['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"秒 "';
}
var table_fmt = {};
init_table(table_fmt);
/* Defaults determined by systematically testing in Excel 2019 */
/* These formats appear to default to other formats in the table */
var default_map = [];
var defi = 0;
// 5 -> 37 ... 8 -> 40
for(defi = 5; defi <= 8; ++defi) default_map[defi] = 32 + defi;
// 23 -> 0 ... 26 -> 0
for(defi = 23; defi <= 26; ++defi) default_map[defi] = 0;
// 27 -> 14 ... 31 -> 14
for(defi = 27; defi <= 31; ++defi) default_map[defi] = 14;
// 50 -> 14 ... 58 -> 14
for(defi = 50; defi <= 58; ++defi) default_map[defi] = 14;
// 59 -> 1 ... 62 -> 4
for(defi = 59; defi <= 62; ++defi) default_map[defi] = defi - 58;
// 67 -> 9 ... 68 -> 10
for(defi = 67; defi <= 68; ++defi) default_map[defi] = defi - 58;
// 72 -> 14 ... 75 -> 17
for(defi = 72; defi <= 75; ++defi) default_map[defi] = defi - 58;
// 69 -> 12 ... 71 -> 14
for(defi = 67; defi <= 68; ++defi) default_map[defi] = defi - 57;
// 76 -> 20 ... 78 -> 22
for(defi = 76; defi <= 78; ++defi) default_map[defi] = defi - 56;
// 79 -> 45 ... 81 -> 47
for(defi = 79; defi <= 81; ++defi) default_map[defi] = defi - 34;
// 82 -> 0 ... 65536 -> 0 (omitted)
/* These formats technically refer to Accounting formats with no equivalent */
var default_str = [];
// 5 -- Currency, 0 decimal, black negative
default_str[5] = default_str[63] = '"$"#,##0_);\\("$"#,##0\\)';
// 6 -- Currency, 0 decimal, red negative
default_str[6] = default_str[64] = '"$"#,##0_);[Red]\\("$"#,##0\\)';
// 7 -- Currency, 2 decimal, black negative
default_str[7] = default_str[65] = '"$"#,##0.00_);\\("$"#,##0.00\\)';
// 8 -- Currency, 2 decimal, red negative
default_str[8] = default_str[66] = '"$"#,##0.00_);[Red]\\("$"#,##0.00\\)';
// 41 -- Accounting, 0 decimal, No Symbol
default_str[41] = '_(* #,##0_);_(* \\(#,##0\\);_(* "-"_);_(@_)';
// 42 -- Accounting, 0 decimal, $ Symbol
default_str[42] = '_("$"* #,##0_);_("$"* \\(#,##0\\);_("$"* "-"_);_(@_)';
// 43 -- Accounting, 2 decimal, No Symbol
default_str[43] = '_(* #,##0.00_);_(* \\(#,##0.00\\);_(* "-"??_);_(@_)';
// 44 -- Accounting, 2 decimal, $ Symbol
default_str[44] = '_("$"* #,##0.00_);_("$"* \\(#,##0.00\\);_("$"* "-"??_);_(@_)';
function frac(x, D, mixed) {
var sgn = x < 0 ? -1 : 1;
var B = x * sgn;
var P_2 = 0, P_1 = 1, P = 0;
var Q_2 = 1, Q_1 = 0, Q = 0;
var A = Math.floor(B);
while(Q_1 < D) {
A = Math.floor(B);
P = A * P_1 + P_2;
Q = A * Q_1 + Q_2;
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) { if(Q_1 > D) { Q = Q_2; P = P_2; } else { Q = Q_1; P = P_1; } }
if(!mixed) return [0, sgn * P, Q];
var q = Math.floor(sgn * P/Q);
return [q, sgn*P - q*Q, Q];
}
function parse_date_code(v,opts,b2) {
if(v > 2958465 || v < 0) return null;
var date = (v|0), time = Math.floor(86400 * (v - date)), dow=0;
var dout=[];
var out={D:date, T:time, u:86400*(v-date)-time,y:0,m:0,d:0,H:0,M:0,S:0,q:0};
if(Math.abs(out.u) < 1e-6) out.u = 0;
if(opts && opts.date1904) date += 1462;
if(out.u > 0.9999) {
out.u = 0;
if(++time == 86400) { out.T = time = 0; ++date; ++out.D; }
}
if(date === 60) {dout = b2 ? [1317,10,29] : [1900,2,29]; dow=3;}
else if(date === 0) {dout = b2 ? [1317,8,29] : [1900,1,0]; dow=6;}
else {
if(date > 60) --date;
/* 1 = Jan 1 1900 in Gregorian */
var d = new Date(1900, 0, 1);
d.setDate(d.getDate() + date - 1);
dout = [d.getFullYear(), d.getMonth()+1,d.getDate()];
dow = d.getDay();
if(date < 60) dow = (dow + 6) % 7;
if(b2) dow = fix_hijri(d, dout);
}
out.y = dout[0]; out.m = dout[1]; out.d = dout[2];
out.S = time % 60; time = Math.floor(time / 60);
out.M = time % 60; time = Math.floor(time / 60);
out.H = time;
out.q = dow;
return out;
}
SSF.parse_date_code = parse_date_code;
var basedate = new Date(1899, 11, 31, 0, 0, 0);
var dnthresh = basedate.getTime();
var base1904 = new Date(1900, 2, 1, 0, 0, 0);
function datenum_local(v, date1904) {
var epoch = v.getTime();
if(date1904) epoch -= 1461*24*60*60*1000;
else if(v >= base1904) epoch += 24*60*60*1000;
return (epoch - (dnthresh + (v.getTimezoneOffset() - basedate.getTimezoneOffset()) * 60000)) / (24 * 60 * 60 * 1000);
}
/* The longest 32-bit integer text is "-4294967296", exactly 11 chars */
function general_fmt_int(v) { return v.toString(10); }
SSF._general_int = general_fmt_int;
/* ECMA-376 18.8.30 numFmt*/
/* Note: `toPrecision` uses standard form when prec > E and E >= -6 */
var general_fmt_num = (function make_general_fmt_num() {
var trailing_zeroes_and_decimal = /(?:\.0*|(\.\d*[1-9])0+)$/;
function strip_decimal(o) {
return (o.indexOf(".") == -1) ? o : o.replace(trailing_zeroes_and_decimal, "$1");
}
/* General Exponential always shows 2 digits exp and trims the mantissa */
var mantissa_zeroes_and_decimal = /(?:\.0*|(\.\d*[1-9])0+)[Ee]/;
var exp_with_single_digit = /(E[+-])(\d)$/;
function normalize_exp(o) {
if(o.indexOf("E") == -1) return o;
return o.replace(mantissa_zeroes_and_decimal,"$1E").replace(exp_with_single_digit,"$10$2");
}
/* exponent >= -9 and <= 9 */
function small_exp(v) {
var w = (v<0?12:11);
var o = strip_decimal(v.toFixed(12)); if(o.length <= w) return o;
o = v.toPrecision(10); if(o.length <= w) return o;
return v.toExponential(5);
}
/* exponent >= 11 or <= -10 likely exponential */
function large_exp(v) {
var o = strip_decimal(v.toFixed(11));
return (o.length > (v<0?12:11) || o === "0" || o === "-0") ? v.toPrecision(6) : o;
}
function general_fmt_num_base(v) {
var V = Math.floor(Math.log(Math.abs(v))*Math.LOG10E), o;
if(V >= -4 && V <= -1) o = v.toPrecision(10+V);
else if(Math.abs(V) <= 9) o = small_exp(v);
else if(V === 10) o = v.toFixed(10).substr(0,12);
else o = large_exp(v);
return strip_decimal(normalize_exp(o.toUpperCase()));
}
return general_fmt_num_base;
})();
SSF._general_num = general_fmt_num;
/*
"General" rules:
- text is passed through ("@")
- booleans are rendered as TRUE/FALSE
- "up to 11 characters" displayed for numbers
- Default date format (code 14) used for Dates
TODO: technically the display depends on the width of the cell
*/
function general_fmt(v, opts) {
switch(typeof v) {
case 'string': return v;
case 'boolean': return v ? "TRUE" : "FALSE";
case 'number': return (v|0) === v ? v.toString(10) : general_fmt_num(v);
case 'undefined': return "";
case 'object':
if(v == null) return "";
if(v instanceof Date) return format(14, datenum_local(v, opts && opts.date1904), opts);
}
throw new Error("unsupported value in General format: " + v);
}
SSF._general = general_fmt;
function fix_hijri(date, o) {
/* TODO: properly adjust y/m/d and */
o[0] -= 581;
var dow = date.getDay();
if(date < 60) dow = (dow + 6) % 7;
return dow;
}
var THAI_DIGITS = "\u0E50\u0E51\u0E52\u0E53\u0E54\u0E55\u0E56\u0E57\u0E58\u0E59".split("");
/*jshint -W086 */
function write_date(type, fmt, val, ss0) {
var o="", ss=0, tt=0, y = val.y, out, outl = 0;
switch(type) {
case 98: /* 'b' buddhist year */
y = val.y + 543;
/* falls through */
case 121: /* 'y' year */
switch(fmt.length) {
case 1: case 2: out = y % 100; outl = 2; break;
default: out = y % 10000; outl = 4; break;
} break;
case 109: /* 'm' month */
switch(fmt.length) {
case 1: case 2: out = val.m; outl = fmt.length; break;
case 3: return months[val.m-1][1];
case 5: return months[val.m-1][0];
default: return months[val.m-1][2];
} break;
case 100: /* 'd' day */
switch(fmt.length) {
case 1: case 2: out = val.d; outl = fmt.length; break;
case 3: return days[val.q][0];
default: return days[val.q][1];
} break;
case 104: /* 'h' 12-hour */
switch(fmt.length) {
case 1: case 2: out = 1+(val.H+11)%12; outl = fmt.length; break;
default: throw 'bad hour format: ' + fmt;
} break;
case 72: /* 'H' 24-hour */
switch(fmt.length) {
case 1: case 2: out = val.H; outl = fmt.length; break;
default: throw 'bad hour format: ' + fmt;
} break;
case 77: /* 'M' minutes */
switch(fmt.length) {
case 1: case 2: out = val.M; outl = fmt.length; break;
default: throw 'bad minute format: ' + fmt;
} break;
case 115: /* 's' seconds */
if(fmt != 's' && fmt != 'ss' && fmt != '.0' && fmt != '.00' && fmt != '.000') throw 'bad second format: ' + fmt;
if(val.u === 0 && (fmt == "s" || fmt == "ss")) return pad0(val.S, fmt.length);
if(ss0 >= 2) tt = ss0 === 3 ? 1000 : 100;
else tt = ss0 === 1 ? 10 : 1;
ss = Math.round((tt)*(val.S + val.u));
if(ss >= 60*tt) ss = 0;
if(fmt === 's') return ss === 0 ? "0" : ""+ss/tt;
o = pad0(ss,2 + ss0);
if(fmt === 'ss') return o.substr(0,2);
return "." + o.substr(2,fmt.length-1);
case 90: /* 'Z' absolute time */
switch(fmt) {
case '[h]': case '[hh]': out = val.D*24+val.H; break;
case '[m]': case '[mm]': out = (val.D*24+val.H)*60+val.M; break;
case '[s]': case '[ss]': out = ((val.D*24+val.H)*60+val.M)*60+Math.round(val.S+val.u); break;
default: throw 'bad abstime format: ' + fmt;
} outl = fmt.length === 3 ? 1 : 2; break;
case 101: /* 'e' era */
out = y; outl = 1; break;
}
var outstr = outl > 0 ? pad0(out, outl) : "";
return outstr;
}
/*jshint +W086 */
function commaify(s) {
var w = 3;
if(s.length <= w) return s;
var j = (s.length % w), o = s.substr(0,j);
for(; j!=s.length; j+=w) o+=(o.length > 0 ? "," : "") + s.substr(j,w);
return o;
}
var write_num = (function make_write_num(){
var pct1 = /%/g;
function write_num_pct(type, fmt, val){
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_cm(type, fmt, val){
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_exp(fmt, val){
var o;
var idx = fmt.indexOf("E") - fmt.indexOf(".") - 1;
if(fmt.match(/^#+0.0E\+0$/)) {
if(val == 0) return "0.0E+0";
else if(val < 0) return "-" + write_num_exp(fmt, -val);
var period = fmt.indexOf("."); if(period === -1) period=fmt.indexOf('E');
var ee = Math.floor(Math.log(val)*Math.LOG10E)%period;
if(ee < 0) ee += period;
o = (val/Math.pow(10,ee)).toPrecision(idx+1+(period+ee)%period);
if(o.indexOf("e") === -1) {
var fakee = Math.floor(Math.log(val)*Math.LOG10E);
if(o.indexOf(".") === -1) o = o.charAt(0) + "." + o.substr(1) + "E+" + (fakee - o.length+ee);
else o += "E+" + (fakee - ee);
while(o.substr(0,2) === "0.") {
o = o.charAt(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(/^([+-]?)(\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");
}
var frac1 = /# (\?+)( ?)\/( ?)(\d+)/;
function write_num_f1(r, aval, sign) {
var den = parseInt(r[4],10), rr = Math.round(aval * den), base = Math.floor(rr/den);
var myn = (rr - base*den), myd = den;
return sign + (base === 0 ? "" : ""+base) + " " + (myn === 0 ? fill(" ", r[1].length + 1 + r[4].length) : pad_(myn,r[1].length) + r[2] + "/" + r[3] + pad0(myd,r[4].length));
}
function write_num_f2(r, aval, sign) {
return sign + (aval === 0 ? "" : ""+aval) + fill(" ", r[1].length + 2 + r[4].length);
}
var dec1 = /^#*0*\.([0#]+)/;
var closeparen = /\).*[0#]/;
var phone = /\(###\) ###\\?-####/;
function hashq(str) {
var o = "", cc;
for(var i = 0; i != str.length; ++i) switch((cc=str.charCodeAt(i))) {
case 35: break;
case 63: o+= " "; break;
case 48: o+= "0"; break;
default: o+= String.fromCharCode(cc);
}
return o;
}
function rnd(val, d) { var dd = Math.pow(10,d); return ""+(Math.round(val * dd)/dd); }
function dec(val, d) {
var _frac = val - Math.floor(val), dd = Math.pow(10,d);
if (d < ('' + Math.round(_frac * dd)).length) return 0;
return Math.round(_frac * dd);
}
function carry(val, d) {
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) {
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, 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."+hashq(r[1])).replace(/\.$/,"."+hashq(r[1])).replace(/\.(\d*)$/,function($$, $1) { return "." + $1 + fill("0", hashq(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(/^#{1,3},##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(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 = 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 "###,##0.00": return write_num_flt(type, "#,##0.00", val);
case "###,###":
case "##,###":
case "#,###": var x = commaify(pad0r(aval,0)); return x !== "0" ? sign + x : "";
case "###,###.00": return write_num_flt(type, "###,##0.00",val).replace(/^0\./,".");
case "#,###.00": return write_num_flt(type, "#,##0.00",val).replace(/^0\./,".");
default:
}
throw new Error("unsupported format |" + fmt + "|");
}
function write_num_cm2(type, fmt, val){
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, fmt, val){
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, val){
var o;
var idx = fmt.indexOf("E") - fmt.indexOf(".") - 1;
if(fmt.match(/^#+0.0E\+0$/)) {
if(val == 0) return "0.0E+0";
else if(val < 0) return "-" + write_num_exp2(fmt, -val);
var period = fmt.indexOf("."); if(period === -1) period=fmt.indexOf('E');
var ee = Math.floor(Math.log(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(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, fmt, val) {
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))) {
o = (""+val).replace(/^([^\.]+)$/,"$1."+hashq(r[1])).replace(/\.$/,"."+hashq(r[1]));
o = o.replace(/\.(\d*)$/,function($$, $1) {
return "." + $1 + fill("0", hashq(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(/^#{1,3},##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 "###,###":
case "##,###":
case "#,###": var x = commaify(""+aval); return x !== "0" ? sign + x : "";
default:
if(fmt.match(/\.[0#?]*$/)) return write_num_int(type, fmt.slice(0,fmt.lastIndexOf(".")), val) + hashq(fmt.slice(fmt.lastIndexOf(".")));
}
throw new Error("unsupported format |" + fmt + "|");
}
return function write_num(type, fmt, val) {
return (val|0) === val ? write_num_int(type, fmt, val) : write_num_flt(type, fmt, val);
};})();
function split_fmt(fmt) {
var out = [];
var in_str = false/*, cc*/;
for(var i = 0, j = 0; i < fmt.length; ++i) switch((/*cc=*/fmt.charCodeAt(i))) {
case 34: /* '"' */
in_str = !in_str; break;
case 95: case 42: case 92: /* '_' '*' '\\' */
++i; break;
case 59: /* ';' */
out[out.length] = fmt.substr(j,i-j);
j = i+1;
}
out[out.length] = fmt.substr(j);
if(in_str === true) throw new Error("Format |" + fmt + "| unterminated string ");
return out;
}
SSF._split = split_fmt;
var abstime = /\[[HhMmSs\u0E0A\u0E19\u0E17]*\]/;
function fmt_is_date(fmt) {
var i = 0, /*cc = 0,*/ c = "", o = "";
while(i < fmt.length) {
switch((c = fmt.charAt(i))) {
case 'G': if(isgeneral(fmt, i)) i+= 6; i++; break;
case '"': for(;(/*cc=*/fmt.charCodeAt(++i)) !== 34 && i < fmt.length;){/*empty*/} ++i; break;
case '\\': i+=2; break;
case '_': i+=2; break;
case '@': ++i; break;
case 'B': case 'b':
if(fmt.charAt(i+1) === "1" || fmt.charAt(i+1) === "2") return true;
/* falls through */
case 'M': case 'D': case 'Y': case 'H': case 'S': case 'E':
/* falls through */
case 'm': case 'd': case 'y': case 'h': case 's': case 'e': case 'g': return true;
case 'A': case 'a': case '上':
if(fmt.substr(i, 3).toUpperCase() === "A/P") return true;
if(fmt.substr(i, 5).toUpperCase() === "AM/PM") return true;
if(fmt.substr(i, 5).toUpperCase() === "上午/下午") return true;
++i; break;
case '[':
o = c;
while(fmt.charAt(i++) !== ']' && i < fmt.length) o += fmt.charAt(i);
if(o.match(abstime)) return true;
break;
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))){/* empty */}
break;
case '?': while(fmt.charAt(++i) === c){/* empty */} 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){/* empty */} break;
case ' ': ++i; break;
default: ++i; break;
}
}
return false;
}
SSF.is_date = fmt_is_date;
function eval_fmt(fmt, v, opts, flen) {
var out = [], o = "", i = 0, c = "", lst='t', dt, j, cc;
var hr='H';
/* Tokenize */
while(i < fmt.length) {
switch((c = fmt.charAt(i))) {
case 'G': /* General */
if(!isgeneral(fmt, i)) throw new Error('unrecognized character ' + c + ' in ' +fmt);
out[out.length] = {t:'G', v:'General'}; i+=7; break;
case '"': /* Literal text */
for(o="";(cc=fmt.charCodeAt(++i)) !== 34 && i < fmt.length;) o += String.fromCharCode(cc);
out[out.length] = {t:'t', v:o}; ++i; break;
case '\\': var w = fmt.charAt(++i), t = (w === "(" || w === ")") ? w : 't';
out[out.length] = {t:t, v:w}; ++i; break;
case '_': out[out.length] = {t:'t', v:" "}; i+=2; break;
case '@': /* Text Placeholder */
out[out.length] = {t:'T', v:v}; ++i; break;
case 'B': case 'b':
if(fmt.charAt(i+1) === "1" || fmt.charAt(i+1) === "2") {
if(dt==null) { dt=parse_date_code(v, opts, fmt.charAt(i+1) === "2"); if(dt==null) return ""; }
out[out.length] = {t:'X', v:fmt.substr(i,2)}; lst = c; i+=2; break;
}
/* falls through */
case 'M': case 'D': case 'Y': case 'H': case 'S': case 'E':
c = c.toLowerCase();
/* falls through */
case 'm': case 'd': case 'y': case 'h': case 's': case 'e': case 'g':
if(v < 0) return "";
if(dt==null) { dt=parse_date_code(v, opts); if(dt==null) return ""; }
o = c; while(++i < fmt.length && fmt.charAt(i).toLowerCase() === c) o+=c;
if(c === 'm' && lst.toLowerCase() === 'h') c = 'M';
if(c === 'h') c = hr;
out[out.length] = {t:c, v:o}; lst = c; break;
case 'A': case 'a': case '上':
var q={t:c, v:c};
if(dt==null) dt=parse_date_code(v, opts);
if(fmt.substr(i, 3).toUpperCase() === "A/P") { if(dt!=null) q.v = dt.H >= 12 ? "P" : "A"; q.t = 'T'; hr='h';i+=3;}
else if(fmt.substr(i,5).toUpperCase() === "AM/PM") { if(dt!=null) q.v = dt.H >= 12 ? "PM" : "AM"; q.t = 'T'; i+=5; hr='h'; }
else if(fmt.substr(i,5).toUpperCase() === "上午/下午") { if(dt!=null) q.v = dt.H >= 12 ? "下午" : "上午"; q.t = 'T'; i+=5; hr='h'; }
else { q.t = "t"; ++i; }
if(dt==null && q.t === 'T') return "";
out[out.length] = q; lst = c; break;
case '[':
o = c;
while(fmt.charAt(i++) !== ']' && i < fmt.length) o += fmt.charAt(i);
if(o.slice(-1) !== ']') throw 'unterminated "[" block: |' + o + '|';
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()};
lst = o.charAt(1);
} else if(o.indexOf("$") > -1) {
o = (o.match(/\$([^-\[\]]*)/)||[])[1]||"$";
if(!fmt_is_date(fmt)) out[out.length] = {t:'t',v:o};
}
break;
/* Numbers */
case '.':
if(dt != null) {
o = c; while(++i < fmt.length && (c=fmt.charAt(i)) === "0") o += c;
out[out.length] = {t:'s', v:o}; break;
}
/* falls through */
case '0': case '#':
o = c; while(++i < fmt.length && "0#?.,E+-%".indexOf(c=fmt.charAt(i)) > -1) o += c;
out[out.length] = {t:'n', v:o}; break;
case '?':
o = c; while(fmt.charAt(++i) === c) o+=c;
out[out.length] = {t:c, v:o}; lst = c; break;
case '*': ++i; if(fmt.charAt(i) == ' ' || fmt.charAt(i) == '*') ++i; break; // **
case '(': case ')': out[out.length] = {t:(flen===1?'t':c), v:c}; ++i; break;
case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
o = c; while(i < fmt.length && "0123456789".indexOf(fmt.charAt(++i)) > -1) o+=fmt.charAt(i);
out[out.length] = {t:'D', v:o}; break;
case ' ': out[out.length] = {t:c, v:c}; ++i; break;
case '$': out[out.length] = {t:'t', v:'$'}; ++i; break;
default:
if(",$-+/():!^&'~{}<>=€acfijklopqrtuvwxzP".indexOf(c) === -1) throw new Error('unrecognized character ' + c + ' in ' + fmt);
out[out.length] = {t:'t', v:c}; ++i; break;
}
}
/* Scan for date/time parts */
var bt = 0, ss0 = 0, ssm;
for(i=out.length-1, lst='t'; i >= 0; --i) {
switch(out[i].t) {
case 'h': case 'H': out[i].t = hr; lst='h'; if(bt < 1) bt = 1; break;
case 's':
if((ssm=out[i].v.match(/\.0+$/))) ss0=Math.max(ss0,ssm[0].length-1);
if(bt < 3) bt = 3;
/* 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");*/
break;
case 'Z':
if(bt < 1 && out[i].v.match(/[Hh]/)) bt = 1;
if(bt < 2 && out[i].v.match(/[Mm]/)) bt = 2;
if(bt < 3 && out[i].v.match(/[Ss]/)) bt = 3;
}
}
/* time rounding depends on presence of minute / second / usec fields */
switch(bt) {
case 0: break;
case 1:
if(dt.u >= 0.5) { dt.u = 0; ++dt.S; }
if(dt.S >= 60) { dt.S = 0; ++dt.M; }
if(dt.M >= 60) { dt.M = 0; ++dt.H; }
break;
case 2:
if(dt.u >= 0.5) { dt.u = 0; ++dt.S; }
if(dt.S >= 60) { dt.S = 0; ++dt.M; }
break;
}
/* replace fields */
var nstr = "", jj;
for(i=0; i < out.length; ++i) {
switch(out[i].t) {
case 't': case 'T': case ' ': case 'D': break;
case 'X': out[i].v = ""; out[i].t = ";"; break;
case 'd': case 'm': case 'y': case 'h': case 'H': case 'M': case 's': case 'e': case 'b': case 'Z':
out[i].v = write_date(out[i].t.charCodeAt(0), out[i].v, dt, ss0);
out[i].t = 't'; break;
case 'n': case '?':
jj = i+1;
while(out[jj] != null && (
(c=out[jj].t) === "?" || c === "D" ||
((c === " " || c === "t") && out[jj+1] != null && (out[jj+1].t === '?' || out[jj+1].t === "t" && out[jj+1].v === '/')) ||
(out[i].t === '(' && (c === ' ' || c === 'n' || c === ')')) ||
(c === 't' && (out[jj].v === '/' || out[jj].v === ' ' && out[jj+1] != null && out[jj+1].t == '?'))
)) {
out[i].v += out[jj].v;
out[jj] = {v:"", t:";"}; ++jj;
}
nstr += out[i].v;
i = jj-1; break;
case 'G': out[i].t = 't'; out[i].v = general_fmt(v,opts); break;
}
}
var vv = "", myv, ostr;
if(nstr.length > 0) {
if(nstr.charCodeAt(0) == 40) /* '(' */ {
myv = (v<0&&nstr.charCodeAt(0) === 45 ? -v : v);
ostr = write_num('n', 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].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) {
if(out[i] == null || 'n?'.indexOf(out[i].t) === -1) continue;
if(jj>=out[i].v.length-1) { jj -= out[i].v.length; out[i].v = ostr.substr(jj+1, out[i].v.length); }
else if(jj < 0) out[i].v = "";
else { out[i].v = ostr.substr(0, jj+1); jj = -1; }
out[i].t = 't';
lasti = i;
}
if(jj>=0 && lasti<out.length) out[lasti].v = ostr.substr(0,jj+1) + out[lasti].v;
}
else if(decpt !== out.length && ostr.indexOf("E") === -1) {
jj = ostr.indexOf(".")-1;
for(i=decpt; i>= 0; --i) {
if(out[i] == null || 'n?'.indexOf(out[i].t) === -1) continue;
j=out[i].v.indexOf(".")>-1&&i===decpt?out[i].v.indexOf(".")-1:out[i].v.length-1;
vv = out[i].v.substr(j+1);
for(; j>=0; --j) {
if(jj>=0 && (out[i].v.charAt(j) === "0" || out[i].v.charAt(j) === "#")) vv = ostr.charAt(jj--) + vv;
}
out[i].v = vv;
out[i].t = 't';
lasti = i;
}
if(jj>=0 && lasti<out.length) out[lasti].v = ostr.substr(0,jj+1) + out[lasti].v;
jj = ostr.indexOf(".")+1;
for(i=decpt; i<out.length; ++i) {
if(out[i] == null || ('n?('.indexOf(out[i].t) === -1 && i !== decpt)) continue;
j=out[i].v.indexOf(".")>-1&&i===decpt?out[i].v.indexOf(".")+1:0;
vv = out[i].v.substr(0,j);
for(; j<out[i].v.length; ++j) {
if(jj<ostr.length) vv += ostr.charAt(jj++);
}
out[i].v = vv;
out[i].t = 't';
lasti = i;
}
}
}
for(i=0; i<out.length; ++i) if(out[i] != null && 'n?'.indexOf(out[i].t)>-1) {
myv = (flen >1 && v < 0 && i>0 && out[i-1].v === "-" ? -v:v);
out[i].v = write_num(out[i].t, out[i].v, myv);
out[i].t = 't';
}
var retval = "";
for(i=0; i !== out.length; ++i) if(out[i] != null) retval += out[i].v;
return retval;
}
SSF._eval = eval_fmt;
var cfregex = /\[[=<>]/;
var cfregex2 = /\[(=|>[=]?|<[>=]?)(-?\d+(?:\.\d*)?)\]/;
function chkcond(v, rr) {
if(rr == null) return false;
var thresh = parseFloat(rr[2]);
switch(rr[1]) {
case "=": if(v == thresh) return true; break;
case ">": if(v > thresh) return true; break;
case "<": if(v < thresh) return true; break;
case "<>": if(v != thresh) return true; break;
case ">=": if(v >= thresh) return true; break;
case "<=": if(v <= thresh) return true; break;
}
return false;
}
function choose_fmt(f, v) {
var fmt = split_fmt(f);
var l = fmt.length, lat = fmt[l-1].indexOf("@");
if(l<4 && lat>-1) --l;
if(fmt.length > 4) throw new Error("cannot find right format for |" + fmt.join("|") + "|");
if(typeof v !== "number") return [4, fmt.length === 4 || lat>-1?fmt[fmt.length-1]:"@"];
switch(fmt.length) {
case 1: fmt = lat>-1 ? ["General", "General", "General", fmt[0]] : [fmt[0], fmt[0], fmt[0], "@"]; break;
case 2: fmt = lat>-1 ? [fmt[0], fmt[0], fmt[0], fmt[1]] : [fmt[0], fmt[1], fmt[0], "@"]; break;
case 3: fmt = lat>-1 ? [fmt[0], fmt[1], fmt[0], fmt[2]] : [fmt[0], fmt[1], fmt[2], "@"]; break;
case 4: break;
}
var ff = v > 0 ? fmt[0] : v < 0 ? fmt[1] : fmt[2];
if(fmt[0].indexOf("[") === -1 && fmt[1].indexOf("[") === -1) return [l, ff];
if(fmt[0].match(cfregex) != null || fmt[1].match(cfregex) != null) {
var m1 = fmt[0].match(cfregex2);
var m2 = fmt[1].match(cfregex2);
return chkcond(v, m1) ? [l, fmt[0]] : chkcond(v, m2) ? [l, fmt[1]] : [l, fmt[m1 != null && m2 != null ? 2 : 1]];
}
return [l, ff];
}
function format(fmt,v,o) {
if(o == null) o = {};
var sfmt = "";
switch(typeof fmt) {
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];
if(sfmt == null) sfmt = (o.table && o.table[default_map[fmt]]) || table_fmt[default_map[fmt]];
if(sfmt == null) sfmt = default_str[fmt] || "General";
break;
}
if(isgeneral(sfmt,0)) return general_fmt(v, o);
if(v instanceof Date) v = datenum_local(v, o.date1904);
var f = choose_fmt(sfmt, v);
if(isgeneral(f[1])) return general_fmt(v, o);
if(v === true) v = "TRUE"; else if(v === false) v = "FALSE";
else if(v === "" || v == null) return "";
return eval_fmt(f[1], v, o, f[0]);
}
function load_entry(fmt, idx) {
if(typeof idx != 'number') {
idx = +idx || -1;
for(var i = 0; i < 0x0188; ++i) {
if(table_fmt[i] == undefined) { if(idx < 0) idx = i; continue; }
if(table_fmt[i] == fmt) { idx = i; break; }
}
if(idx < 0) idx = 0x187;
}
table_fmt[idx] = fmt;
return idx;
}
SSF.load = load_entry;
SSF._table = table_fmt;
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) load_entry(tbl[i], i);
};
SSF.init_table = init_table;
SSF.format = format;
};
make_ssf(SSF);
/*global module */
if(typeof module !== 'undefined' && typeof DO_NOT_EXPORT_SSF === 'undefined') module.exports = SSF;

1507
packages/ssf/ssf.md Normal file

File diff suppressed because it is too large Load Diff

1048576
packages/ssf/test/cal.tsv Normal file

File diff suppressed because it is too large Load Diff

@ -0,0 +1,21 @@
/* vim: set ts=2: */
/*jshint loopfunc:true, mocha:true, node:true */
var SSF = require('../');
var fs = require('fs');
var data = fs.readFileSync('./test/comma.tsv','utf8').split("\n");
function doit(w, headers) {
it(headers[w], function() {
for(var j=1;j<data.length;++j) {
if(!data[j]) continue;
var d = data[j].replace(/#{255}/g,"").split("\t");
var expected = d[w].replace("|", ""), actual;
try { actual = SSF.format(headers[w], Number(d[0]), {}); } catch(e) { }
if(actual != expected && d[w][0] !== "|") throw new Error([actual, expected, w, headers[w],d[0],d].join("|"));
}
});
}
describe('comma formats', function() {
var headers = data[0].split("\t");
for(var w = 1; w < headers.length; ++w) doit(w, headers);
});

@ -0,0 +1,16 @@
value #.0000,,, #.0000,, #.0000, #,##0.0 ###,##0 ###,### #,###.00
0.99 .0000 .0000 .0010 1.0 1 1 .99
1.2345 .0000 .0000 .0012 1.2 1 1 1.23
12.345 .0000 .0000 .0123 12.3 12 12 12.35
123.456 .0000 .0001 .1235 123.5 123 123 123.46
1234 .0000 .0012 1.2340 1,234.0 1,234 1,234 1,234.00
12345 .0000 .0123 12.3450 12,345.0 12,345 12,345 12,345.00
123456 .0001 .1235 123.4560 123,456.0 123,456 123,456 123,456.00
1234567 .0012 1.2346 1234.5670 1,234,567.0 1,234,567 1,234,567 1,234,567.00
12345678 .0123 12.3457 12345.6780 12,345,678.0 12,345,678 12,345,678 12,345,678.00
123456789 .1235 123.4568 123456.7890 123,456,789.0 123,456,789 123,456,789 123,456,789.00
1234567890 1.2346 1234.5679 1234567.8900 1,234,567,890.0 1,234,567,890 1,234,567,890 1,234,567,890.00
12345678901 12.3457 12345.6789 12345678.9010 12,345,678,901.0 12,345,678,901 12,345,678,901 12,345,678,901.00
123456789012 123.4568 123456.7890 123456789.0120 123,456,789,012.0 123,456,789,012 123,456,789,012 123,456,789,012.00
4321 .0000 .0043 4.3210 4,321.0 4,321 4,321 4,321.00
4321234 .0043 4.3212 4321.2340 4,321,234.0 4,321,234 4,321,234 4,321,234.00
1 value #.0000,,, #.0000,, #.0000, #,##0.0 ###,##0 ###,### #,###.00
2 0.99 .0000 .0000 .0010 1.0 1 1 .99
3 1.2345 .0000 .0000 .0012 1.2 1 1 1.23
4 12.345 .0000 .0000 .0123 12.3 12 12 12.35
5 123.456 .0000 .0001 .1235 123.5 123 123 123.46
6 1234 .0000 .0012 1.2340 1,234.0 1,234 1,234 1,234.00
7 12345 .0000 .0123 12.3450 12,345.0 12,345 12,345 12,345.00
8 123456 .0001 .1235 123.4560 123,456.0 123,456 123,456 123,456.00
9 1234567 .0012 1.2346 1234.5670 1,234,567.0 1,234,567 1,234,567 1,234,567.00
10 12345678 .0123 12.3457 12345.6780 12,345,678.0 12,345,678 12,345,678 12,345,678.00
11 123456789 .1235 123.4568 123456.7890 123,456,789.0 123,456,789 123,456,789 123,456,789.00
12 1234567890 1.2346 1234.5679 1234567.8900 1,234,567,890.0 1,234,567,890 1,234,567,890 1,234,567,890.00
13 12345678901 12.3457 12345.6789 12345678.9010 12,345,678,901.0 12,345,678,901 12,345,678,901 12,345,678,901.00
14 123456789012 123.4568 123456.7890 123456789.0120 123,456,789,012.0 123,456,789,012 123,456,789,012 123,456,789,012.00
15 4321 .0000 .0043 4.3210 4,321.0 4,321 4,321 4,321.00
16 4321234 .0043 4.3212 4321.2340 4,321,234.0 4,321,234 4,321,234 4,321,234.00

38
packages/ssf/test/date.js Normal file

@ -0,0 +1,38 @@
/* vim: set ts=2: */
/*jshint -W041 */
/*jshint loopfunc:true, mocha:true, node:true */
var SSF = require('../');
var fs = require('fs'), assert = require('assert');
var dates = fs.readFileSync('./test/dates.tsv','utf8').split("\n");
var date2 = fs.readFileSync('./test/cal.tsv', 'utf8').split("\n");
var times = fs.readFileSync('./test/times.tsv','utf8').split("\n");
function doit(data) {
var step = Math.ceil(data.length/100), i = 1;
var headers = data[0].split("\t");
for(var j = 0; j <= 100; ++j) it(String(j), function() {
for(var k = 0; k <= step; ++k,++i) {
if(data[i] == null || data[i].length < 3) return;
var d = data[i].replace(/#{255}/g,"").split("\t");
for(var w = 1; w < headers.length; ++w) {
var expected = d[w], actual = SSF.format(headers[w], parseFloat(d[0]), {});
if(actual != expected) throw new Error([actual, expected, w, headers[w],d[0],d,i].join("|"));
actual = SSF.format(headers[w].toUpperCase(), parseFloat(d[0]), {});
if(actual != expected) throw new Error([actual, expected, w, headers[w].toUpperCase(),d[0],d,i].join("|"));
}
}
});
}
describe('time formats', function() {
doit(process.env.MINTEST ? times.slice(0,4000) : times);
});
describe('date formats', function() {
doit(process.env.MINTEST ? dates.slice(0,4000) : dates);
if(0) doit(process.env.MINTEST ? date2.slice(0,1000) : date2);
it('should fail for bad formats', function() {
var bad = [];
var chk = function(fmt){ return function(){ SSF.format(fmt,0); }; };
bad.forEach(function(fmt){assert.throws(chk(fmt));});
});
});

@ -0,0 +1,22 @@
[
["new Date(1900,0,1)", "1900-01-01 00:00:00", false],
["new Date(1900,1,1)", "1900-02-01 00:00:00", false],
["new Date(1900,2,1)", "1900-03-01 00:00:00", false],
["new Date(1900,3,1)", "1900-04-01 00:00:00", false],
["new Date(2000,0,1)", "2000-01-01 00:00:00", false],
["new Date(2000,1,1)", "2000-02-01 00:00:00", false],
["new Date(2000,2,1)", "2000-03-01 00:00:00", false],
["new Date(2000,3,1)", "2000-04-01 00:00:00", false],
["new Date(2000,0,1)", "2000-01-01 00:00:00", true],
["new Date(2000,1,3)", "2000-02-03 00:00:00", true],
["new Date(2000,2,5)", "2000-03-05 00:00:00", true],
["new Date(2000,3,7)", "2000-04-07 00:00:00", true],
["new Date(2100,0,1)", "2100-01-01 00:00:00", false],
["new Date(2100,1,1)", "2100-02-01 00:00:00", false],
["new Date(2100,2,1)", "2100-03-01 00:00:00", false],
["new Date(2100,3,1)", "2100-04-01 00:00:00", false],
["new Date(2100,0,1)", "2100-01-01 00:00:00", true],
["new Date(2100,1,3)", "2100-02-03 00:00:00", true],
["new Date(2100,2,5)", "2100-03-05 00:00:00", true],
["new Date(2100,3,7)", "2100-04-07 00:00:00", true]
]

@ -0,0 +1,50 @@
/* vim: set ts=2: */
/*jshint loopfunc:true, mocha:true, node:true */
/*eslint-env mocha, node */
var SSF = require('../');
var 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");
});
});
describe('asian formats', function() {
it('上午/下午 (AM/PM)', function() {
assert.equal(SSF.format('上午/下午', 0), '上午');
assert.equal(SSF.format('上午/下午', 0.25), '上午');
assert.equal(SSF.format('上午/下午', 0.49), '上午');
assert.equal(SSF.format('上午/下午', 0.5), '下午');
assert.equal(SSF.format('上午/下午', 0.51), '下午');
assert.equal(SSF.format('上午/下午', 0.99), '下午');
assert.equal(SSF.format('上午/下午', 1), '上午');
});
it('bb (buddhist)', function() {
[
[12345,
[ 'yyyy', '1933'],
[ 'eeee', '1933'],
[ 'bbbb', '2476'],
//[ 'ปปปป', '๒๔๗๖'],
[ 'b2yyyy', '1352'],
[ 'b2eeee', '1352'],
[ 'b2bbbb', '1895'],
//[ 'b2ปปปป', '๑๘๙๕']
]
].forEach(function(row) {
row.slice(1).forEach(function(fmt) {
assert.equal(SSF.format(fmt[0], row[0]), fmt[1]);
});
});
});
it.skip('thai fields', function() {
SSF.format('\u0E27/\u0E14/\u0E1B\u0E1B\u0E1B\u0E1B \u0E0A\u0E0A:\u0E19\u0E19:\u0E17\u0E17', 12345.67);
assert.equal(SSF.format('\u0E27/\u0E14/\u0E1B\u0E1B\u0E1B\u0E1B \u0E0A\u0E0A:\u0E19\u0E19:\u0E17\u0E17', 12345.67), "๑๘/๑๐/๒๔๗๖ ๑๖:๐๔:๔๘");
});
});

@ -0,0 +1,12 @@
/* vim: set ts=2: */
/*jshint -W041 */
/*jshint loopfunc:true, mocha:true, node:true, evil:true */
var SSF = require('../');
var fs = require('fs'), assert = require('assert');
var data = JSON.parse(fs.readFileSync('./test/date.json','utf8'));
describe('date values', function() {
it('should roundtrip dates', function() { data.forEach(function(d) {
assert.equal(SSF.format("yyyy-mm-dd HH:MM:SS", eval(d[0]), {date1904:!!d[2]}), d[1]);
}); });
});

295849
packages/ssf/test/dates.tsv Normal file

File diff suppressed because it is too large Load Diff

21
packages/ssf/test/exp.js Normal file

@ -0,0 +1,21 @@
/* vim: set ts=2: */
/*jshint loopfunc:true, mocha:true, node:true */
var SSF = require('../');
var fs = require('fs');
var data = fs.readFileSync('./test/exp.tsv','utf8').split("\n");
function doit(d, headers) {
it(d[0], function() {
for(var w = 1; w < headers.length; ++w) {
var expected = d[w].replace("|", ""), actual;
try { actual = SSF.format(headers[w], parseFloat(d[0]), {}); } catch(e) { }
if(actual != expected && d[w].charAt(0) !== "|") throw new Error([actual, expected, w, headers[w],d[0],d].join("|"));
}
});
}
describe('exponential formats', function() {
var headers = data[0].split("\t");
for(var j=1;j<data.length;++j) {
if(!data[j]) return;
doit(data[j].replace(/#{255}/g,"").split("\t"), headers);
}
});

46
packages/ssf/test/exp.tsv Normal file

@ -0,0 +1,46 @@
value #0.0E+0 ##0.0E+0 ###0.0E+0 ####0.0E+0
1.23457E-13 12.3E-14 123.5E-15 1234.6E-16 123.5E-15
1.23457E-12 1.2E-12 1.2E-12 1.2E-12 1234.6E-15
1.23457E-11 12.3E-12 12.3E-12 12.3E-12 12345.7E-15
1.23457E-10 1.2E-10 123.5E-12 123.5E-12 1.2E-10
1.23457E-09 12.3E-10 1.2E-9 1234.6E-12 12.3E-10
1.23457E-08 1.2E-8 12.3E-9 1.2E-8 123.5E-10
0.000000123457 12.3E-8 123.5E-9 12.3E-8 1234.6E-10
0.00000123457 1.2E-6 1.2E-6 123.5E-8 12345.7E-10
0.0000123457 12.3E-6 12.3E-6 1234.6E-8 1.2E-5
0.000123457 1.2E-4 123.5E-6 1.2E-4 12.3E-5
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
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
1234567.89 1.2E+6 1.2E+6 123.5E+4 12.3E+5
12345678.9 12.3E+6 12.3E+6 |1234.6E+4 123.5E+5
123456789 1.2E+8 123.5E+6 1.2E+8 1234.6E+5
1234567890 12.3E+8 1.2E+9 12.3E+8 |12345.7E+5
12345678900 1.2E+10 12.3E+9 123.5E+8 1.2E+10
123456789000 12.3E+10 123.5E+9 1234.6E+8 12.3E+10
1234567890000 1.2E+12 1.2E+12 1.2E+12 123.5E+10
12345678900000 12.3E+12 12.3E+12 12.3E+12 1234.6E+10
123456789000000 1.2E+14 123.5E+12 123.5E+12 12345.7E+10
1234567890000000 12.3E+14 1.2E+15 1234.6E+12 1.2E+15
12345678900000000 1.2E+16 12.3E+15 1.2E+16 12.3E+15
123456789000000000 12.3E+16 123.5E+15 12.3E+16 123.5E+15
1234567890000000000 1.2E+18 1.2E+18 123.5E+16 1234.6E+15
12345678900000000000 12.3E+18 12.3E+18 1234.6E+16 12345.7E+15
123456789000000000000 1.2E+20 123.5E+18 1.2E+20 1.2E+20
1234567890000000000000 12.3E+20 1.2E+21 12.3E+20 12.3E+20
12345678900000000000000 1.2E+22 12.3E+21 123.5E+20 123.5E+20
123456789000000000000000 12.3E+22 123.5E+21 1234.6E+20 1234.6E+20
1234567890000000000000000 1.2E+24 1.2E+24 1.2E+24 12345.7E+20
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
1 value #0.0E+0 ##0.0E+0 ###0.0E+0 ####0.0E+0
2 1.23457E-13 12.3E-14 123.5E-15 1234.6E-16 123.5E-15
3 1.23457E-12 1.2E-12 1.2E-12 1.2E-12 1234.6E-15
4 1.23457E-11 12.3E-12 12.3E-12 12.3E-12 12345.7E-15
5 1.23457E-10 1.2E-10 123.5E-12 123.5E-12 1.2E-10
6 1.23457E-09 12.3E-10 1.2E-9 1234.6E-12 12.3E-10
7 1.23457E-08 1.2E-8 12.3E-9 1.2E-8 123.5E-10
8 0.000000123457 12.3E-8 123.5E-9 12.3E-8 1234.6E-10
9 0.00000123457 1.2E-6 1.2E-6 123.5E-8 12345.7E-10
10 0.0000123457 12.3E-6 12.3E-6 1234.6E-8 1.2E-5
11 0.000123457 1.2E-4 123.5E-6 1.2E-4 12.3E-5
12 0.001234568 12.3E-4 1.2E-3 12.3E-4 123.5E-5
13 0.012345679 1.2E-2 12.3E-3 123.5E-4 1234.6E-5
14 0.123456789 12.3E-2 123.5E-3 1234.6E-4 12345.7E-5
15 1.23456789 1.2E+0 1.2E+0 1.2E+0 1.2E+0
16 12.3456789 12.3E+0 12.3E+0 12.3E+0 12.3E+0
17 123.456789 1.2E+2 123.5E+0 123.5E+0 123.5E+0
18 1234.56789 |12.3E+2 1.2E+3 1234.6E+0 1234.6E+0
19 12345.6789 1.2E+4 12.3E+3 1.2E+4 12345.7E+0
20 123456.789 12.3E+4 123.5E+3 12.3E+4 1.2E+5
21 1234567.89 1.2E+6 1.2E+6 123.5E+4 12.3E+5
22 12345678.9 12.3E+6 12.3E+6 |1234.6E+4 123.5E+5
23 123456789 1.2E+8 123.5E+6 1.2E+8 1234.6E+5
24 1234567890 12.3E+8 1.2E+9 12.3E+8 |12345.7E+5
25 12345678900 1.2E+10 12.3E+9 123.5E+8 1.2E+10
26 123456789000 12.3E+10 123.5E+9 1234.6E+8 12.3E+10
27 1234567890000 1.2E+12 1.2E+12 1.2E+12 123.5E+10
28 12345678900000 12.3E+12 12.3E+12 12.3E+12 1234.6E+10
29 123456789000000 1.2E+14 123.5E+12 123.5E+12 12345.7E+10
30 1234567890000000 12.3E+14 1.2E+15 1234.6E+12 1.2E+15
31 12345678900000000 1.2E+16 12.3E+15 1.2E+16 12.3E+15
32 123456789000000000 12.3E+16 123.5E+15 12.3E+16 123.5E+15
33 1234567890000000000 1.2E+18 1.2E+18 123.5E+16 1234.6E+15
34 12345678900000000000 12.3E+18 12.3E+18 1234.6E+16 12345.7E+15
35 123456789000000000000 1.2E+20 123.5E+18 1.2E+20 1.2E+20
36 1234567890000000000000 12.3E+20 1.2E+21 12.3E+20 12.3E+20
37 12345678900000000000000 1.2E+22 12.3E+21 123.5E+20 123.5E+20
38 123456789000000000000000 12.3E+22 123.5E+21 1234.6E+20 1234.6E+20
39 1234567890000000000000000 1.2E+24 1.2E+24 1.2E+24 12345.7E+20
40 12345678900000000000000000 12.3E+24 12.3E+24 12.3E+24 1.2E+25
41 123456789000000000000000000 1.2E+26 123.5E+24 123.5E+24 12.3E+25
42 1234567890000000000000000000 12.3E+26 1.2E+27 1234.6E+24 123.5E+25
43 12345678900000000000000000000 1.2E+28 12.3E+27 1.2E+28 1234.6E+25
44 123456789000000000000000000000 12.3E+28 123.5E+27 12.3E+28 12345.7E+25
45 1234567890000000000000000000000 1.2E+30 1.2E+30 123.5E+28 1.2E+30
46 12345678900000000000000000000000 12.3E+30 12.3E+30 1234.6E+28 12.3E+30

@ -0,0 +1,15 @@
/* vim: set ts=2: */
/*jshint loopfunc:true, mocha:true, node:true */
var SSF = require('../');
var fs = require('fs'), assert = require('assert');
var data = JSON.parse(fs.readFileSync('./test/fraction.json','utf8'));
var skip = [];
describe('fractional formats', function() {
data.forEach(function(d) {
it(d[1]+" for "+d[0], skip.indexOf(d[1]) > -1 ? null : function(){
var expected = d[2], actual = SSF.format(d[1], d[0], {});
//var r = actual.match(/(-?)\d* *\d+\/\d+/);
assert.equal(actual, expected);
});
});
});

@ -0,0 +1,121 @@
[
[1, "# ?/?", "1 "],
[-1.2, "# ?/?", "-1 1/5"],
[12.3, "# ?/?", "12 1/3"],
[-12.34, "# ?/?", "-12 1/3"],
[123.45, "# ?/?", "123 4/9"],
[-123.456, "# ?/?", "-123 1/2"],
[1234.567, "# ?/?", "1234 4/7"],
[-1234.5678, "# ?/?", "-1234 4/7"],
[12345.6789, "# ?/?", "12345 2/3"],
[-12345.67891, "# ?/?", "-12345 2/3"],
[1, "# ??/??", "1 "],
[-1.2, "# ??/??", "-1 1/5 "],
[12.3, "# ??/??", "12 3/10"],
[-12.34, "# ??/??", "-12 17/50"],
[123.45, "# ??/??", "123 9/20"],
[-123.456, "# ??/??", "-123 26/57"],
[1234.567, "# ??/??", "1234 55/97"],
[-1234.5678, "# ??/??", "-1234 46/81"],
[12345.6789, "# ??/??", "12345 55/81"],
[-12345.67891, "# ??/??", "-12345 55/81"],
[1, "# ???/???", "1 "],
[-1.2, "# ???/???", "-1 1/5 "],
[12.3, "# ???/???", "12 3/10 "],
[-12.34, "# ???/???", "-12 17/50 "],
[123.45, "# ???/???", "123 9/20 "],
[-123.456, "# ???/???", "-123 57/125"],
[1234.567, "# ???/???", "1234 55/97 "],
[-1234.5678, "# ???/???", "-1234 67/118"],
[12345.6789, "# ???/???", "12345 74/109"],
[-12345.67891, "# ???/???", "-12345 573/844"],
[1, "# ?/2", "1 "],
[-1.2, "# ?/2", "-1 "],
[12.3, "# ?/2", "12 1/2"],
[-12.34, "# ?/2", "-12 1/2"],
[123.45, "# ?/2", "123 1/2"],
[-123.456, "# ?/2", "-123 1/2"],
[1234.567, "# ?/2", "1234 1/2"],
[-1234.5678, "# ?/2", "-1234 1/2"],
[12345.6789, "# ?/2", "12345 1/2"],
[-12345.67891, "# ?/2", "-12345 1/2"],
[1, "# ?/4", "1 "],
[-1.2, "# ?/4", "-1 1/4"],
[12.3, "# ?/4", "12 1/4"],
[-12.34, "# ?/4", "-12 1/4"],
[123.45, "# ?/4", "123 2/4"],
[-123.456, "# ?/4", "-123 2/4"],
[1234.567, "# ?/4", "1234 2/4"],
[-1234.5678, "# ?/4", "-1234 2/4"],
[12345.6789, "# ?/4", "12345 3/4"],
[-12345.67891, "# ?/4", "-12345 3/4"],
[1, "# ?/8", "1 "],
[-1.2, "# ?/8", "-1 2/8"],
[12.3, "# ?/8", "12 2/8"],
[-12.34, "# ?/8", "-12 3/8"],
[123.45, "# ?/8", "123 4/8"],
[-123.456, "# ?/8", "-123 4/8"],
[1234.567, "# ?/8", "1234 5/8"],
[-1234.5678, "# ?/8", "-1234 5/8"],
[12345.6789, "# ?/8", "12345 5/8"],
[-12345.67891, "# ?/8", "-12345 5/8"],
[1, "# ??/16", "1 "],
[-1.2, "# ??/16", "-1 3/16"],
[12.3, "# ??/16", "12 5/16"],
[-12.34, "# ??/16", "-12 5/16"],
[123.45, "# ??/16", "123 7/16"],
[-123.456, "# ??/16", "-123 7/16"],
[1234.567, "# ??/16", "1234 9/16"],
[-1234.5678, "# ??/16", "-1234 9/16"],
[12345.6789, "# ??/16", "12345 11/16"],
[-12345.67891, "# ??/16", "-12345 11/16"],
[1, "# ?/10", "1 "],
[-1.2, "# ?/10", "-1 2/10"],
[12.3, "# ?/10", "12 3/10"],
[-12.34, "# ?/10", "-12 3/10"],
[123.45, "# ?/10", "123 5/10"],
[-123.456, "# ?/10", "-123 5/10"],
[1234.567, "# ?/10", "1234 6/10"],
[-1234.5678, "# ?/10", "-1234 6/10"],
[12345.6789, "# ?/10", "12345 7/10"],
[-12345.67891, "# ?/10", "-12345 7/10"],
[1, "# ??/100", "1 "],
[-1.2, "# ??/100", "-1 20/100"],
[12.3, "# ??/100", "12 30/100"],
[-12.34, "# ??/100", "-12 34/100"],
[123.45, "# ??/100", "123 45/100"],
[-123.456, "# ??/100", "-123 46/100"],
[1234.567, "# ??/100", "1234 57/100"],
[-1234.5678, "# ??/100", "-1234 57/100"],
[12345.6789, "# ??/100", "12345 68/100"],
[-12345.67891, "# ??/100", "-12345 68/100"],
[1, "??/??", " 1/1 "],
[-1.2, "??/??", "- 6/5 "],
[12.3, "??/??", "123/10"],
[-12.34, "??/??", "-617/50"],
[123.45, "??/??", "2469/20"],
[-123.456, "??/??", "-7037/57"],
[1234.567, "??/??", "119753/97"],
[-1234.5678, "??/??", "-100000/81"],
[12345.6789, "??/??", "1000000/81"],
[-12345.67891, "??/??", "-1000000/81"],
[0.3, "# ?/?", " 2/7"],
[1.3, "# ?/?", "1 1/3"],
[2.3, "# ?/?", "2 2/7"],
[0.123251512342345, "# ??/?????????", " 480894/3901729"],
[0.123251512342345, "# ?? / ?????????", " 480894 / 3901729"],
[0, "0", "0"]
]

@ -0,0 +1,26 @@
/* vim: set ts=2: */
/*jshint loopfunc:true, mocha:true, node:true */
var SSF = require('../');
var fs = require('fs'), assert = require('assert');
var data = JSON.parse(fs.readFileSync('./test/general.json','utf8'));
var skip = [];
describe('General format', function() {
data.forEach(function(d) {
it(d[1]+" for "+d[0], skip.indexOf(d[1]) > -1 ? null : function(){
assert.equal(SSF.format(d[1], d[0], {}), d[2]);
});
});
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), "");
});
it('should handle dates', function() {
assert.equal(SSF.format("General", new Date(2017, 1, 19)), "2/19/17");
assert.equal(SSF.format("General", new Date(2017, 1, 19), {date1904:true}), "2/19/17");
assert.equal(SSF.format("General", new Date(1901, 0, 1)), "1/1/01");
if(SSF.format("General", new Date(1901, 0, 1), {date1904:true}) == "1/1/01") throw new Error("date1904 invalid date");
assert.equal(SSF.format("General", new Date(1904, 0, 1)), "1/1/04");
assert.equal(SSF.format("General", new Date(1904, 0, 1), {date1904:true}), "1/1/04");
});
});

@ -0,0 +1,516 @@
[
[1.234567E-14, 0, "1.23457E-14"],
[1.234567E-13, 0, "1.23457E-13"],
[1.234567E-12, 0, "1.23457E-12"],
[1.234567E-11, 0, "1.23457E-11"],
[1.234567E-10, 0, "1.23457E-10"],
[1.234567E-9, 0, "1.23457E-09"],
[1.234567E-8, 0, "1.23457E-08"],
[1.234567E-7, 0, "1.23457E-07"],
[1.234567E-6, 0, "1.23457E-06"],
[1.234567E-5, 0, "1.23457E-05"],
[1.234567E-4, 0, "0.000123457"],
[1.234567E-3, 0, "0.001234567"],
[1.234567E-2, 0, "0.01234567"],
[1.234567E-1, 0, "0.1234567"],
[1.234567E0, 0, "1.234567"],
[1.234567E1, 0, "12.34567"],
[1.234567E2, 0, "123.4567"],
[1.234567E3, 0, "1234.567"],
[1.234567E4, 0, "12345.67"],
[1.234567E5, 0, "123456.7"],
[1.234567E6, 0, "1234567"],
[1.234567E7, 0, "12345670"],
[1.234567E8, 0, "123456700"],
[1.234567E9, 0, "1234567000"],
[1.234567E10, 0, "12345670000"],
[1.234567E11, 0, "1.23457E+11"],
[1.234567E12, 0, "1.23457E+12"],
[1.234567E13, 0, "1.23457E+13"],
[1.234567E14, 0, "1.23457E+14"],
[0.00000000000001, 0, "1E-14"],
[0.0000000000001, 0, "1E-13"],
[0.000000000001, 0, "1E-12"],
[0.00000000001, 0, "1E-11"],
[0.0000000001, 0, "1E-10"],
[0.000000001, 0, "0.000000001"],
[0.00000001, 0, "0.00000001"],
[0.0000001, 0, "0.0000001"],
[0.000001, 0, "0.000001"],
[0.00001, 0, "0.00001"],
[0.0001, 0, "0.0001"],
[0.001, 0, "0.001"],
[0.01, 0, "0.01"],
[0.1, 0, "0.1"],
[1, 0, "1"],
[10, 0, "10"],
[100, 0, "100"],
[1000, 0, "1000"],
[10000, 0, "10000"],
[100000, 0, "100000"],
[1000000, 0, "1000000"],
[10000000, 0, "10000000"],
[100000000, 0, "100000000"],
[1000000000, 0, "1000000000"],
[10000000000, 0, "10000000000"],
[100000000000, 0, "1E+11"],
[1000000000000, 0, "1E+12"],
[10000000000000, 0, "1E+13"],
[100000000000000, 0, "1E+14"],
[0.000000000000012, 0, "1.2E-14"],
[0.00000000000012, 0, "1.2E-13"],
[0.0000000000012, 0, "1.2E-12"],
[0.000000000012, 0, "1.2E-11"],
[0.00000000012, 0, "1.2E-10"],
[0.0000000012, 0, "1.2E-09"],
[0.000000012, 0, "0.000000012"],
[0.00000012, 0, "0.00000012"],
[0.0000012, 0, "0.0000012"],
[0.000012, 0, "0.000012"],
[0.00012, 0, "0.00012"],
[0.0012, 0, "0.0012"],
[0.012, 0, "0.012"],
[0.12, 0, "0.12"],
[1.2, 0, "1.2"],
[12, 0, "12"],
[120, 0, "120"],
[1200, 0, "1200"],
[12000, 0, "12000"],
[120000, 0, "120000"],
[1200000, 0, "1200000"],
[12000000, 0, "12000000"],
[120000000, 0, "120000000"],
[1200000000, 0, "1200000000"],
[12000000000, 0, "12000000000"],
[120000000000, 0, "1.2E+11"],
[1200000000000, 0, "1.2E+12"],
[12000000000000, 0, "1.2E+13"],
[120000000000000, 0, "1.2E+14"],
[0.0000000000000123, 0, "1.23E-14"],
[0.000000000000123, 0, "1.23E-13"],
[0.00000000000123, 0, "1.23E-12"],
[0.0000000000123, 0, "1.23E-11"],
[0.000000000123, 0, "1.23E-10"],
[0.00000000123, 0, "1.23E-09"],
[0.0000000123, 0, "1.23E-08"],
[0.000000123, 0, "0.000000123"],
[0.00000123, 0, "0.00000123"],
[0.0000123, 0, "0.0000123"],
[0.000123, 0, "0.000123"],
[0.00123, 0, "0.00123"],
[0.0123, 0, "0.0123"],
[0.123, 0, "0.123"],
[1.23, 0, "1.23"],
[12.3, 0, "12.3"],
[123, 0, "123"],
[1230, 0, "1230"],
[12300, 0, "12300"],
[123000, 0, "123000"],
[1230000, 0, "1230000"],
[12300000, 0, "12300000"],
[123000000, 0, "123000000"],
[1230000000, 0, "1230000000"],
[12300000000, 0, "12300000000"],
[123000000000, 0, "1.23E+11"],
[1230000000000, 0, "1.23E+12"],
[12300000000000, 0, "1.23E+13"],
[123000000000000, 0, "1.23E+14"],
[0.00000000000001234, 0, "1.234E-14"],
[0.0000000000001234, 0, "1.234E-13"],
[0.000000000001234, 0, "1.234E-12"],
[0.00000000001234, 0, "1.234E-11"],
[0.0000000001234, 0, "1.234E-10"],
[0.000000001234, 0, "1.234E-09"],
[0.00000001234, 0, "1.234E-08"],
[0.0000001234, 0, "1.234E-07"],
[0.000001234, 0, "0.000001234"],
[0.00001234, 0, "0.00001234"],
[0.0001234, 0, "0.0001234"],
[0.001234, 0, "0.001234"],
[0.01234, 0, "0.01234"],
[0.1234, 0, "0.1234"],
[1.234, 0, "1.234"],
[12.34, 0, "12.34"],
[123.4, 0, "123.4"],
[1234, 0, "1234"],
[12340, 0, "12340"],
[123400, 0, "123400"],
[1234000, 0, "1234000"],
[12340000, 0, "12340000"],
[123400000, 0, "123400000"],
[1234000000, 0, "1234000000"],
[12340000000, 0, "12340000000"],
[123400000000, 0, "1.234E+11"],
[1234000000000, 0, "1.234E+12"],
[12340000000000, 0, "1.234E+13"],
[123400000000000, 0, "1.234E+14"],
[0.000000000000012345, 0, "1.2345E-14"],
[0.00000000000012345, 0, "1.2345E-13"],
[0.0000000000012345, 0, "1.2345E-12"],
[0.000000000012345, 0, "1.2345E-11"],
[0.00000000012345, 0, "1.2345E-10"],
[0.0000000012345, 0, "1.2345E-09"],
[0.000000012345, 0, "1.2345E-08"],
[0.00000012345, 0, "1.2345E-07"],
[0.0000012345, 0, "1.2345E-06"],
[0.000012345, 0, "0.000012345"],
[0.00012345, 0, "0.00012345"],
[0.0012345, 0, "0.0012345"],
[0.012345, 0, "0.012345"],
[0.12345, 0, "0.12345"],
[1.2345, 0, "1.2345"],
[12.345, 0, "12.345"],
[123.45, 0, "123.45"],
[1234.5, 0, "1234.5"],
[12345, 0, "12345"],
[123450, 0, "123450"],
[1234500, 0, "1234500"],
[12345000, 0, "12345000"],
[123450000, 0, "123450000"],
[1234500000, 0, "1234500000"],
[12345000000, 0, "12345000000"],
[123450000000, 0, "1.2345E+11"],
[1234500000000, 0, "1.2345E+12"],
[12345000000000, 0, "1.2345E+13"],
[123450000000000, 0, "1.2345E+14"],
[0.0000000000000123456, 0, "1.23456E-14"],
[0.000000000000123456, 0, "1.23456E-13"],
[0.00000000000123456, 0, "1.23456E-12"],
[0.0000000000123456, 0, "1.23456E-11"],
[0.000000000123456, 0, "1.23456E-10"],
[0.00000000123456, 0, "1.23456E-09"],
[0.0000000123456, 0, "1.23456E-08"],
[0.000000123456, 0, "1.23456E-07"],
[0.00000123456, 0, "1.23456E-06"],
[0.0000123456, 0, "1.23456E-05"],
[0.000123456, 0, "0.000123456"],
[0.00123456, 0, "0.00123456"],
[0.0123456, 0, "0.0123456"],
[0.123456, 0, "0.123456"],
[1.23456, 0, "1.23456"],
[12.3456, 0, "12.3456"],
[123.456, 0, "123.456"],
[1234.56, 0, "1234.56"],
[12345.6, 0, "12345.6"],
[123456, 0, "123456"],
[1234560, 0, "1234560"],
[12345600, 0, "12345600"],
[123456000, 0, "123456000"],
[1234560000, 0, "1234560000"],
[12345600000, 0, "12345600000"],
[123456000000, 0, "1.23456E+11"],
[1234560000000, 0, "1.23456E+12"],
[12345600000000, 0, "1.23456E+13"],
[123456000000000, 0, "1.23456E+14"],
[0.00000000000001234567, 0, "1.23457E-14"],
[0.0000000000001234567, 0, "1.23457E-13"],
[0.000000000001234567, 0, "1.23457E-12"],
[0.00000000001234567, 0, "1.23457E-11"],
[0.0000000001234567, 0, "1.23457E-10"],
[0.000000001234567, 0, "1.23457E-09"],
[0.00000001234567, 0, "1.23457E-08"],
[0.0000001234567, 0, "1.23457E-07"],
[0.000001234567, 0, "1.23457E-06"],
[0.00001234567, 0, "1.23457E-05"],
[0.0001234567, 0, "0.000123457"],
[0.001234567, 0, "0.001234567"],
[0.01234567, 0, "0.01234567"],
[0.1234567, 0, "0.1234567"],
[1.234567, 0, "1.234567"],
[12.34567, 0, "12.34567"],
[123.4567, 0, "123.4567"],
[1234.567, 0, "1234.567"],
[12345.67, 0, "12345.67"],
[123456.7, 0, "123456.7"],
[1234567, 0, "1234567"],
[12345670, 0, "12345670"],
[123456700, 0, "123456700"],
[1234567000, 0, "1234567000"],
[12345670000, 0, "12345670000"],
[123456700000, 0, "1.23457E+11"],
[1234567000000, 0, "1.23457E+12"],
[12345670000000, 0, "1.23457E+13"],
[123456700000000, 0, "1.23457E+14"],
[0.000000000000012345678, 0, "1.23457E-14"],
[0.00000000000012345678, 0, "1.23457E-13"],
[0.0000000000012345678, 0, "1.23457E-12"],
[0.000000000012345678, 0, "1.23457E-11"],
[0.00000000012345678, 0, "1.23457E-10"],
[0.0000000012345678, 0, "1.23457E-09"],
[0.000000012345678, 0, "1.23457E-08"],
[0.00000012345678, 0, "1.23457E-07"],
[0.0000012345678, 0, "1.23457E-06"],
[0.000012345678, 0, "1.23457E-05"],
[0.00012345678, 0, "0.000123457"],
[0.0012345678, 0, "0.001234568"],
[0.012345678, 0, "0.012345678"],
[0.12345678, 0, "0.12345678"],
[1.2345678, 0, "1.2345678"],
[12.345678, 0, "12.345678"],
[123.45678, 0, "123.45678"],
[1234.5678, 0, "1234.5678"],
[12345.678, 0, "12345.678"],
[123456.78, 0, "123456.78"],
[1234567.8, 0, "1234567.8"],
[12345678, 0, "12345678"],
[123456780, 0, "123456780"],
[1234567800, 0, "1234567800"],
[12345678000, 0, "12345678000"],
[123456780000, 0, "1.23457E+11"],
[1234567800000, 0, "1.23457E+12"],
[12345678000000, 0, "1.23457E+13"],
[123456780000000, 0, "1.23457E+14"],
[0.0000000000000123456789, 0, "1.23457E-14"],
[0.000000000000123456789, 0, "1.23457E-13"],
[0.00000000000123456789, 0, "1.23457E-12"],
[0.0000000000123456789, 0, "1.23457E-11"],
[0.000000000123456789, 0, "1.23457E-10"],
[0.00000000123456789, 0, "1.23457E-09"],
[0.0000000123456789, 0, "1.23457E-08"],
[0.000000123456789, 0, "1.23457E-07"],
[0.00000123456789, 0, "1.23457E-06"],
[0.0000123456789, 0, "1.23457E-05"],
[0.000123456789, 0, "0.000123457"],
[0.00123456789, 0, "0.001234568"],
[0.0123456789, 0, "0.012345679"],
[0.123456789, 0, "0.123456789"],
[1.23456789, 0, "1.23456789"],
[12.3456789, 0, "12.3456789"],
[123.456789, 0, "123.456789"],
[1234.56789, 0, "1234.56789"],
[12345.6789, 0, "12345.6789"],
[123456.789, 0, "123456.789"],
[1234567.89, 0, "1234567.89"],
[12345678.9, 0, "12345678.9"],
[123456789, 0, "123456789"],
[1234567890, 0, "1234567890"],
[12345678900, 0, "12345678900"],
[123456789000, 0, "1.23457E+11"],
[1234567890000, 0, "1.23457E+12"],
[12345678900000, 0, "1.23457E+13"],
[123456789000000, 0, "1.23457E+14"],
[0.00000000000001234567891, 0, "1.23457E-14"],
[0.0000000000001234567891, 0, "1.23457E-13"],
[0.000000000001234567891, 0, "1.23457E-12"],
[0.00000000001234567891, 0, "1.23457E-11"],
[0.0000000001234567891, 0, "1.23457E-10"],
[0.000000001234567891, 0, "1.23457E-09"],
[0.00000001234567891, 0, "1.23457E-08"],
[0.0000001234567891, 0, "1.23457E-07"],
[0.000001234567891, 0, "1.23457E-06"],
[0.00001234567891, 0, "1.23457E-05"],
[0.0001234567891, 0, "0.000123457"],
[0.001234567891, 0, "0.001234568"],
[0.01234567891, 0, "0.012345679"],
[0.1234567891, 0, "0.123456789"],
[1.234567891, 0, "1.234567891"],
[12.34567891, 0, "12.34567891"],
[123.4567891, 0, "123.4567891"],
[1234.567891, 0, "1234.567891"],
[12345.67891, 0, "12345.67891"],
[123456.7891, 0, "123456.7891"],
[1234567.891, 0, "1234567.891"],
[12345678.91, 0, "12345678.91"],
[123456789.1, 0, "123456789.1"],
[1234567891, 0, "1234567891"],
[12345678910, 0, "12345678910"],
[123456789100, 0, "1.23457E+11"],
[1234567891000, 0, "1.23457E+12"],
[12345678910000, 0, "1.23457E+13"],
[123456789100000, 0, "1.23457E+14"],
[0.000000000000012345678912, 0, "1.23457E-14"],
[0.00000000000012345678912, 0, "1.23457E-13"],
[0.0000000000012345678912, 0, "1.23457E-12"],
[0.000000000012345678912, 0, "1.23457E-11"],
[0.00000000012345678912, 0, "1.23457E-10"],
[0.0000000012345678912, 0, "1.23457E-09"],
[0.000000012345678912, 0, "1.23457E-08"],
[0.00000012345678912, 0, "1.23457E-07"],
[0.0000012345678912, 0, "1.23457E-06"],
[0.000012345678912, 0, "1.23457E-05"],
[0.00012345678912, 0, "0.000123457"],
[0.0012345678912, 0, "0.001234568"],
[0.012345678912, 0, "0.012345679"],
[0.12345678912, 0, "0.123456789"],
[1.2345678912, 0, "1.234567891"],
[12.345678912, 0, "12.34567891"],
[123.45678912, 0, "123.4567891"],
[1234.5678912, 0, "1234.567891"],
[12345.678912, 0, "12345.67891"],
[123456.78912, 0, "123456.7891"],
[1234567.8912, 0, "1234567.891"],
[12345678.912, 0, "12345678.91"],
[123456789.12, 0, "123456789.1"],
[1234567891.2, 0, "1234567891"],
[12345678912, 0, "12345678912"],
[123456789120, 0, "1.23457E+11"],
[1234567891200, 0, "1.23457E+12"],
[12345678912000, 0, "1.23457E+13"],
[123456789120000, 0, "1.23457E+14"],
[0.0000000000000123456789123, 0, "1.23457E-14"],
[0.000000000000123456789123, 0, "1.23457E-13"],
[0.00000000000123456789123, 0, "1.23457E-12"],
[0.0000000000123456789123, 0, "1.23457E-11"],
[0.000000000123456789123, 0, "1.23457E-10"],
[0.00000000123456789123, 0, "1.23457E-09"],
[0.0000000123456789123, 0, "1.23457E-08"],
[0.000000123456789123, 0, "1.23457E-07"],
[0.00000123456789123, 0, "1.23457E-06"],
[0.0000123456789123, 0, "1.23457E-05"],
[0.000123456789123, 0, "0.000123457"],
[0.00123456789123, 0, "0.001234568"],
[0.0123456789123, 0, "0.012345679"],
[0.123456789123, 0, "0.123456789"],
[1.23456789123, 0, "1.234567891"],
[12.3456789123, 0, "12.34567891"],
[123.456789123, 0, "123.4567891"],
[1234.56789123, 0, "1234.567891"],
[12345.6789123, 0, "12345.67891"],
[123456.789123, 0, "123456.7891"],
[1234567.89123, 0, "1234567.891"],
[12345678.9123, 0, "12345678.91"],
[123456789.123, 0, "123456789.1"],
[1234567891.23, 0, "1234567891"],
[12345678912.3, 0, "12345678912"],
[123456789123, 0, "1.23457E+11"],
[1234567891230, 0, "1.23457E+12"],
[12345678912300, 0, "1.23457E+13"],
[123456789123000, 0, "1.23457E+14"],
[0.00000000000001234567891234, 0, "1.23457E-14"],
[0.0000000000001234567891234, 0, "1.23457E-13"],
[0.000000000001234567891234, 0, "1.23457E-12"],
[0.00000000001234567891234, 0, "1.23457E-11"],
[0.0000000001234567891234, 0, "1.23457E-10"],
[0.000000001234567891234, 0, "1.23457E-09"],
[0.00000001234567891234, 0, "1.23457E-08"],
[0.0000001234567891234, 0, "1.23457E-07"],
[0.000001234567891234, 0, "1.23457E-06"],
[0.00001234567891234, 0, "1.23457E-05"],
[0.0001234567891234, 0, "0.000123457"],
[0.001234567891234, 0, "0.001234568"],
[0.01234567891234, 0, "0.012345679"],
[0.1234567891234, 0, "0.123456789"],
[1.234567891234, 0, "1.234567891"],
[12.34567891234, 0, "12.34567891"],
[123.4567891234, 0, "123.4567891"],
[1234.567891234, 0, "1234.567891"],
[12345.67891234, 0, "12345.67891"],
[123456.7891234, 0, "123456.7891"],
[1234567.891234, 0, "1234567.891"],
[12345678.91234, 0, "12345678.91"],
[123456789.1234, 0, "123456789.1"],
[1234567891.234, 0, "1234567891"],
[12345678912.34, 0, "12345678912"],
[123456789123.4, 0, "1.23457E+11"],
[1234567891234, 0, "1.23457E+12"],
[12345678912340, 0, "1.23457E+13"],
[123456789123400, 0, "1.23457E+14"],
[0.000000000000012345678912345, 0, "1.23457E-14"],
[0.00000000000012345678912345, 0, "1.23457E-13"],
[0.0000000000012345678912345, 0, "1.23457E-12"],
[0.000000000012345678912345, 0, "1.23457E-11"],
[0.00000000012345678912345, 0, "1.23457E-10"],
[0.0000000012345678912345, 0, "1.23457E-09"],
[0.000000012345678912345, 0, "1.23457E-08"],
[0.00000012345678912345, 0, "1.23457E-07"],
[0.0000012345678912345, 0, "1.23457E-06"],
[0.000012345678912345, 0, "1.23457E-05"],
[0.00012345678912345, 0, "0.000123457"],
[0.0012345678912345, 0, "0.001234568"],
[0.012345678912345, 0, "0.012345679"],
[0.12345678912345, 0, "0.123456789"],
[1.2345678912345, 0, "1.234567891"],
[12.345678912345, 0, "12.34567891"],
[123.45678912345, 0, "123.4567891"],
[1234.5678912345, 0, "1234.567891"],
[12345.678912345, 0, "12345.67891"],
[123456.78912345, 0, "123456.7891"],
[1234567.8912345, 0, "1234567.891"],
[12345678.912345, 0, "12345678.91"],
[123456789.12345, 0, "123456789.1"],
[1234567891.2345, 0, "1234567891"],
[12345678912.345, 0, "12345678912"],
[123456789123.45, 0, "1.23457E+11"],
[1234567891234.5, 0, "1.23457E+12"],
[12345678912345, 0, "1.23457E+13"],
[123456789123450, 0, "1.23457E+14"],
[0.0000000000000123456789123456, 0, "1.23457E-14"],
[0.000000000000123456789123456, 0, "1.23457E-13"],
[0.00000000000123456789123456, 0, "1.23457E-12"],
[0.0000000000123456789123456, 0, "1.23457E-11"],
[0.000000000123456789123456, 0, "1.23457E-10"],
[0.00000000123456789123456, 0, "1.23457E-09"],
[0.0000000123456789123456, 0, "1.23457E-08"],
[0.000000123456789123456, 0, "1.23457E-07"],
[0.00000123456789123456, 0, "1.23457E-06"],
[0.0000123456789123456, 0, "1.23457E-05"],
[0.000123456789123456, 0, "0.000123457"],
[0.00123456789123456, 0, "0.001234568"],
[0.0123456789123456, 0, "0.012345679"],
[0.123456789123456, 0, "0.123456789"],
[1.23456789123456, 0, "1.234567891"],
[12.3456789123456, 0, "12.34567891"],
[123.456789123456, 0, "123.4567891"],
[1234.56789123456, 0, "1234.567891"],
[12345.6789123456, 0, "12345.67891"],
[123456.789123456, 0, "123456.7891"],
[1234567.89123456, 0, "1234567.891"],
[12345678.9123456, 0, "12345678.91"],
[123456789.123456, 0, "123456789.1"],
[1234567891.23456, 0, "1234567891"],
[12345678912.3456, 0, "12345678912"],
[123456789123.456, 0, "1.23457E+11"],
[1234567891234.56, 0, "1.23457E+12"],
[12345678912345.6, 0, "1.23457E+13"],
[123456789123456, 0, "1.23457E+14"],
[-0.00000000000001234567, 0, "-1.23457E-14"],
[-0.0000000000001234567, 0, "-1.23457E-13"],
[-0.000000000001234567, 0, "-1.23457E-12"],
[-0.00000000001234567, 0, "-1.23457E-11"],
[-0.0000000001234567, 0, "-1.23457E-10"],
[-0.000000001234567, 0, "-1.23457E-09"],
[-0.00000001234567, 0, "-1.23457E-08"],
[-0.0000001234567, 0, "-1.23457E-07"],
[-0.000001234567, 0, "-1.23457E-06"],
[-0.00001234567, 0, "-1.23457E-05"],
[-0.0001234567, 0, "-0.000123457"],
[-0.001234567, 0, "-0.001234567"],
[-0.01234567, 0, "-0.01234567"],
[-0.1234567, 0, "-0.1234567"],
[-1.234567, 0, "-1.234567"],
[-12.34567, 0, "-12.34567"],
[-123.4567, 0, "-123.4567"],
[-1234.567, 0, "-1234.567"],
[-12345.67, 0, "-12345.67"],
[-123456.7, 0, "-123456.7"],
[-1234567, 0, "-1234567"],
[-12345670, 0, "-12345670"],
[-123456700, 0, "-123456700"],
[-1234567000, 0, "-1234567000"],
[-12345670000, 0, "-12345670000"],
[-123456700000, 0, "-1.23457E+11"],
[-1234567000000, 0, "-1.23457E+12"],
[-12345670000000, 0, "-1.23457E+13"],
[-123456700000000, 0, "-1.23457E+14"],
[true, 0, "TRUE"],
[false, 0, "FALSE"],
["sheetjs", 0, "sheetjs"]
]

@ -0,0 +1,17 @@
/* vim: set ts=2: */
/*jshint loopfunc:true, mocha:true, node:true */
var SSF = require('../');
var fs = require('fs'), assert = require('assert');
var data = JSON.parse(fs.readFileSync('./test/implied.json','utf8'));
var skip = [];
function doit(d) {
d[1].forEach(function(r){if(r.length === 2)assert.equal(SSF.format(r[0],d[0]),r[1]);});
}
describe('implied formats', function() {
data.forEach(function(d) {
if(d.length == 2) it(String(d[0]), function() { doit(d); });
else it(d[1]+" for "+d[0], skip.indexOf(d[1]) > -1 ? null : function(){
assert.equal(SSF.format(d[1], d[0], {}), d[2]);
});
});
});

@ -0,0 +1,756 @@
[
[1234567890000, [
[0, "1.23457E+12"],
[1, "1234567890000"],
[2, "1234567890000.00"],
[3, "1,234,567,890,000"],
[4, "1,234,567,890,000.00"],
[9, "123456789000000%"],
[10, "123456789000000.00%"],
[11, "1.23E+12"],
[12, "1234567890000 "],
[13, "1234567890000 "],
[14, ""],
[15, ""],
[16, ""],
[17, ""],
[18, ""],
[19, ""],
[20, ""],
[21, ""],
[22, ""],
[37, "1,234,567,890,000 "],
[38, "1,234,567,890,000 "],
[39, "1,234,567,890,000.00"],
[40, "1,234,567,890,000.00"],
[45, ""],
[46, ""],
[47, ""],
[48, "1.2E+12"],
[49, "1.23457E+12"]
]],
[123456789000, [
[0, "1.23457E+11"],
[1, "123456789000"],
[2, "123456789000.00"],
[3, "123,456,789,000"],
[4, "123,456,789,000.00"],
[9, "12345678900000%"],
[10, "12345678900000.00%"],
[11, "1.23E+11"],
[12, "123456789000 "],
[13, "123456789000 "],
[14, ""],
[15, ""],
[16, ""],
[17, ""],
[18, ""],
[19, ""],
[20, ""],
[21, ""],
[22, ""],
[37, "123,456,789,000 "],
[38, "123,456,789,000 "],
[39, "123,456,789,000.00"],
[40, "123,456,789,000.00"],
[45, ""],
[46, ""],
[47, ""],
[48, "123.5E+9"],
[49, "1.23457E+11"]
]],
[12345678900, [
[0, "12345678900"],
[1, "12345678900"],
[2, "12345678900.00"],
[3, "12,345,678,900"],
[4, "12,345,678,900.00"],
[9, "1234567890000%"],
[10, "1234567890000.00%"],
[11, "1.23E+10"],
[12, "12345678900 "],
[13, "12345678900 "],
[14, ""],
[15, ""],
[16, ""],
[17, ""],
[18, ""],
[19, ""],
[20, ""],
[21, ""],
[22, ""],
[37, "12,345,678,900 "],
[38, "12,345,678,900 "],
[39, "12,345,678,900.00"],
[40, "12,345,678,900.00"],
[45, ""],
[46, ""],
[47, ""],
[48, "12.3E+9"],
[49, "12345678900"]
]],
[1234567890, [
[0, "1234567890"],
[1, "1234567890"],
[2, "1234567890.00"],
[3, "1,234,567,890"],
[4, "1,234,567,890.00"],
[9, "123456789000%"],
[10, "123456789000.00%"],
[11, "1.23E+09"],
[12, "1234567890 "],
[13, "1234567890 "],
[14, ""],
[15, ""],
[16, ""],
[17, ""],
[18, ""],
[19, ""],
[20, ""],
[21, ""],
[22, ""],
[37, "1,234,567,890 "],
[38, "1,234,567,890 "],
[39, "1,234,567,890.00"],
[40, "1,234,567,890.00"],
[45, ""],
[46, ""],
[47, ""],
[48, "1.2E+9"],
[49, "1234567890"]
]],
[123456789, [
[0, "123456789"],
[1, "123456789"],
[2, "123456789.00"],
[3, "123,456,789"],
[4, "123,456,789.00"],
[9, "12345678900%"],
[10, "12345678900.00%"],
[11, "1.23E+08"],
[12, "123456789 "],
[13, "123456789 "],
[14, ""],
[15, ""],
[16, ""],
[17, ""],
[18, ""],
[19, ""],
[20, ""],
[21, ""],
[22, ""],
[37, "123,456,789 "],
[38, "123,456,789 "],
[39, "123,456,789.00"],
[40, "123,456,789.00"],
[45, ""],
[46, ""],
[47, ""],
[48, "123.5E+6"],
[49, "123456789"]
]],
[12345678.9, [
[0, "12345678.9"],
[1, "12345679"],
[2, "12345678.90"],
[3, "12,345,679"],
[4, "12,345,678.90"],
[9, "1234567890%"],
[10, "1234567890.00%"],
[11, "1.23E+07"],
[12, "12345679 "],
[13, "12345678 9/10"],
[14, ""],
[15, ""],
[16, ""],
[17, ""],
[18, ""],
[19, ""],
[20, ""],
[21, ""],
[22, ""],
[37, "12,345,679 "],
[38, "12,345,679 "],
[39, "12,345,678.90"],
[40, "12,345,678.90"],
[45, ""],
[46, ""],
[47, ""],
[48, "12.3E+6"],
[49, "12345678.9"]
]],
[1234567.89, [
[0, "1234567.89"],
[1, "1234568"],
[2, "1234567.89"],
[3, "1,234,568"],
[4, "1,234,567.89"],
[9, "123456789%"],
[10, "123456789.00%"],
[11, "1.23E+06"],
[12, "1234567 8/9"],
[13, "1234567 8/9 "],
[14, "2/15/80"],
[15, "15-Feb-80"],
[16, "15-Feb"],
[17, "Feb-80"],
[18, "9:21 PM"],
[19, "9:21:36 PM"],
[20, "21:21"],
[21, "21:21:36"],
[22, "2/15/80 21:21"],
[37, "1,234,568 "],
[38, "1,234,568 "],
[39, "1,234,567.89"],
[40, "1,234,567.89"],
[45, "21:36"],
[46, "29629629:21:36"],
[47, "2136.0"],
[48, "1.2E+6"],
[49, "1234567.89"]
]],
[123456.789, [
[0, "123456.789"],
[1, "123457"],
[2, "123456.79"],
[3, "123,457"],
[4, "123,456.79"],
[9, "12345679%"],
[10, "12345678.90%"],
[11, "1.23E+05"],
[12, "123456 4/5"],
[13, "123456 15/19"],
[14, "1/3/38"],
[15, "3-Jan-38"],
[16, "3-Jan"],
[17, "Jan-38"],
[18, "6:56 PM"],
[19, "6:56:10 PM"],
[20, "18:56"],
[21, "18:56:10"],
[22, "1/3/38 18:56"],
[37, "123,457 "],
[38, "123,457 "],
[39, "123,456.79"],
[40, "123,456.79"],
[45, "56:10"],
[46, "2962962:56:10"],
[47, "5609.6"],
[48, "123.5E+3"],
[49, "123456.789"]
]],
[12345.6789, [
[0, "12345.6789"],
[1, "12346"],
[2, "12345.68"],
[3, "12,346"],
[4, "12,345.68"],
[9, "1234568%"],
[10, "1234567.89%"],
[11, "1.23E+04"],
[12, "12345 2/3"],
[13, "12345 55/81"],
[14, "10/18/33"],
[15, "18-Oct-33"],
[16, "18-Oct"],
[17, "Oct-33"],
[18, "4:17 PM"],
[19, "4:17:37 PM"],
[20, "16:17"],
[21, "16:17:37"],
[22, "10/18/33 16:17"],
[37, "12,346 "],
[38, "12,346 "],
[39, "12,345.68"],
[40, "12,345.68"],
[45, "17:37"],
[46, "296296:17:37"],
[47, "1737.0"],
[48, "12.3E+3"],
[49, "12345.6789"]
]],
[1234.56789, [
[0, "1234.56789"],
[1, "1235"],
[2, "1234.57"],
[3, "1,235"],
[4, "1,234.57"],
[9, "123457%"],
[10, "123456.79%"],
[11, "1.23E+03"],
[12, "1234 4/7"],
[13, "1234 46/81"],
[14, "5/18/03"],
[15, "18-May-03"],
[16, "18-May"],
[17, "May-03"],
[18, "1:37 PM"],
[19, "1:37:46 PM"],
[20, "13:37"],
[21, "13:37:46"],
[22, "5/18/03 13:37"],
[37, "1,235 "],
[38, "1,235 "],
[39, "1,234.57"],
[40, "1,234.57"],
[45, "37:46"],
[46, "29629:37:46"],
[47, "3745.7"],
[48, "1.2E+3"],
[49, "1234.56789"]
]],
[123.456789, [
[0, "123.456789"],
[1, "123"],
[2, "123.46"],
[3, "123"],
[4, "123.46"],
[9, "12346%"],
[10, "12345.68%"],
[11, "1.23E+02"],
[12, "123 1/2"],
[13, "123 37/81"],
[14, "5/2/00"],
[15, "2-May-00"],
[16, "2-May"],
[17, "May-00"],
[18, "10:57 AM"],
[19, "10:57:47 AM"],
[20, "10:57"],
[21, "10:57:47"],
[22, "5/2/00 10:57"],
[37, "123 "],
[38, "123 "],
[39, "123.46"],
[40, "123.46"],
[45, "57:47"],
[46, "2962:57:47"],
[47, "5746.6"],
[48, "123.5E+0"],
[49, "123.456789"]
]],
[12.3456789, [
[0, "12.3456789"],
[1, "12"],
[2, "12.35"],
[3, "12"],
[4, "12.35"],
[9, "1235%"],
[10, "1234.57%"],
[11, "1.23E+01"],
[12, "12 1/3"],
[13, "12 28/81"],
[14, "1/12/00"],
[15, "12-Jan-00"],
[16, "12-Jan"],
[17, "Jan-00"],
[18, "8:17 AM"],
[19, "8:17:47 AM"],
[20, "8:17"],
[21, "8:17:47"],
[22, "1/12/00 8:17"],
[37, "12 "],
[38, "12 "],
[39, "12.35"],
[40, "12.35"],
[45, "17:47"],
[46, "296:17:47"],
[47, "1746.7"],
[48, "12.3E+0"],
[49, "12.3456789"]
]],
[1.23456789, [
[0, "1.23456789"],
[1, "1"],
[2, "1.23"],
[3, "1"],
[4, "1.23"],
[9, "123%"],
[10, "123.46%"],
[11, "1.23E+00"],
[12, "1 1/4"],
[13, "1 19/81"],
[14, "1/1/00"],
[15, "1-Jan-00"],
[16, "1-Jan"],
[17, "Jan-00"],
[18, "5:37 AM"],
[19, "5:37:47 AM"],
[20, "5:37"],
[21, "5:37:47"],
[22, "1/1/00 5:37"],
[37, "1 "],
[38, "1 "],
[39, "1.23"],
[40, "1.23"],
[45, "37:47"],
[46, "29:37:47"],
[47, "3746.7"],
[48, "1.2E+0"],
[49, "1.23456789"]
]],
[0.123456789, [
[0, "0.123456789"],
[1, "0"],
[2, "0.12"],
[3, "0"],
[4, "0.12"],
[9, "12%"],
[10, "12.35%"],
[11, "1.23E-01"],
[12, " 1/8"],
[13, " 10/81"],
[14, "1/0/00"],
[15, "0-Jan-00"],
[16, "0-Jan"],
[17, "Jan-00"],
[18, "2:57 AM"],
[19, "2:57:47 AM"],
[20, "2:57"],
[21, "2:57:47"],
[22, "1/0/00 2:57"],
[37, "0 "],
[38, "0 "],
[39, "0.12"],
[40, "0.12"],
[45, "57:47"],
[46, "2:57:47"],
[47, "5746.7"],
[48, "123.5E-3"],
[49, "0.123456789"]
]],
[0.0123456789, [
[0, "0.012345679"],
[1, "0"],
[2, "0.01"],
[3, "0"],
[4, "0.01"],
[9, "1%"],
[10, "1.23%"],
[11, "1.23E-02"],
[12, "0 "],
[13, " 1/81"],
[14, "1/0/00"],
[15, "0-Jan-00"],
[16, "0-Jan"],
[17, "Jan-00"],
[18, "12:17 AM"],
[19, "12:17:47 AM"],
[20, "0:17"],
[21, "0:17:47"],
[22, "1/0/00 0:17"],
[37, "0 "],
[38, "0 "],
[39, "0.01"],
[40, "0.01"],
[45, "17:47"],
[46, "0:17:47"],
[47, "1746.7"],
[48, "12.3E-3"],
[49, "0.012345679"]
]],
[0.00123456789, [
[0, "0.001234568"],
[1, "0"],
[2, "0.00"],
[3, "0"],
[4, "0.00"],
[9, "0%"],
[10, "0.12%"],
[11, "1.23E-03"],
[12, "0 "],
[13, "0 "],
[14, "1/0/00"],
[15, "0-Jan-00"],
[16, "0-Jan"],
[17, "Jan-00"],
[18, "12:01 AM"],
[19, "12:01:47 AM"],
[20, "0:01"],
[21, "0:01:47"],
[22, "1/0/00 0:01"],
[37, "0 "],
[38, "0 "],
[39, "0.00"],
[40, "0.00"],
[45, "01:47"],
[46, "0:01:47"],
[47, "0146.7"],
[48, "1.2E-3"],
[49, "0.001234568"]
]],
[0.000123456789, [
[0, "0.000123457"],
[1, "0"],
[2, "0.00"],
[3, "0"],
[4, "0.00"],
[9, "0%"],
[10, "0.01%"],
[11, "1.23E-04"],
[12, "0 "],
[13, "0 "],
[14, "1/0/00"],
[15, "0-Jan-00"],
[16, "0-Jan"],
[17, "Jan-00"],
[18, "12:00 AM"],
[19, "12:00:11 AM"],
[20, "0:00"],
[21, "0:00:11"],
[22, "1/0/00 0:00"],
[37, "0 "],
[38, "0 "],
[39, "0.00"],
[40, "0.00"],
[45, "00:11"],
[46, "0:00:11"],
[47, "0010.7"],
[48, "123.5E-6"],
[49, "0.000123457"]
]],
[0.0000123456789, [
[0, "1.23457E-05"],
[1, "0"],
[2, "0.00"],
[3, "0"],
[4, "0.00"],
[9, "0%"],
[10, "0.00%"],
[11, "1.23E-05"],
[12, "0 "],
[13, "0 "],
[14, "1/0/00"],
[15, "0-Jan-00"],
[16, "0-Jan"],
[17, "Jan-00"],
[18, "12:00 AM"],
[19, "12:00:01 AM"],
[20, "0:00"],
[21, "0:00:01"],
[22, "1/0/00 0:00"],
[37, "0 "],
[38, "0 "],
[39, "0.00"],
[40, "0.00"],
[45, "00:01"],
[46, "0:00:01"],
[47, "0001.1"],
[48, "12.3E-6"],
[49, "1.23457E-05"]
]],
[0.00000123456789, [
[0, "1.23457E-06"],
[1, "0"],
[2, "0.00"],
[3, "0"],
[4, "0.00"],
[9, "0%"],
[10, "0.00%"],
[11, "1.23E-06"],
[12, "0 "],
[13, "0 "],
[14, "1/0/00"],
[15, "0-Jan-00"],
[16, "0-Jan"],
[17, "Jan-00"],
[18, "12:00 AM"],
[19, "12:00:00 AM"],
[20, "0:00"],
[21, "0:00:00"],
[22, "1/0/00 0:00"],
[37, "0 "],
[38, "0 "],
[39, "0.00"],
[40, "0.00"],
[45, "00:00"],
[46, "0:00:00"],
[47, "0000.1"],
[48, "1.2E-6"],
[49, "1.23457E-06"]
]],
[0.000000123456789, [
[0, "1.23457E-07"],
[1, "0"],
[2, "0.00"],
[3, "0"],
[4, "0.00"],
[9, "0%"],
[10, "0.00%"],
[11, "1.23E-07"],
[12, "0 "],
[13, "0 "],
[14, "1/0/00"],
[15, "0-Jan-00"],
[16, "0-Jan"],
[17, "Jan-00"],
[18, "12:00 AM"],
[19, "12:00:00 AM"],
[20, "0:00"],
[21, "0:00:00"],
[22, "1/0/00 0:00"],
[37, "0 "],
[38, "0 "],
[39, "0.00"],
[40, "0.00"],
[45, "00:00"],
[46, "0:00:00"],
[47, "0000.0"],
[48, "123.5E-9"],
[49, "1.23457E-07"]
]],
[0.0000000123456789, [
[0, "1.23457E-08"],
[1, "0"],
[2, "0.00"],
[3, "0"],
[4, "0.00"],
[9, "0%"],
[10, "0.00%"],
[11, "1.23E-08"],
[12, "0 "],
[13, "0 "],
[14, "1/0/00"],
[15, "0-Jan-00"],
[16, "0-Jan"],
[17, "Jan-00"],
[18, "12:00 AM"],
[19, "12:00:00 AM"],
[20, "0:00"],
[21, "0:00:00"],
[22, "1/0/00 0:00"],
[37, "0 "],
[38, "0 "],
[39, "0.00"],
[40, "0.00"],
[45, "00:00"],
[46, "0:00:00"],
[47, "0000.0"],
[48, "12.3E-9"],
[49, "1.23457E-08"]
]],
[0.00000000123456789, [
[0, "1.23457E-09"],
[1, "0"],
[2, "0.00"],
[3, "0"],
[4, "0.00"],
[9, "0%"],
[10, "0.00%"],
[11, "1.23E-09"],
[12, "0 "],
[13, "0 "],
[14, "1/0/00"],
[15, "0-Jan-00"],
[16, "0-Jan"],
[17, "Jan-00"],
[18, "12:00 AM"],
[19, "12:00:00 AM"],
[20, "0:00"],
[21, "0:00:00"],
[22, "1/0/00 0:00"],
[37, "0 "],
[38, "0 "],
[39, "0.00"],
[40, "0.00"],
[45, "00:00"],
[46, "0:00:00"],
[47, "0000.0"],
[48, "1.2E-9"],
[49, "1.23457E-09"]
]],
[0.000000000123456789, [
[0, "1.23457E-10"],
[1, "0"],
[2, "0.00"],
[3, "0"],
[4, "0.00"],
[9, "0%"],
[10, "0.00%"],
[11, "1.23E-10"],
[12, "0 "],
[13, "0 "],
[14, "1/0/00"],
[15, "0-Jan-00"],
[16, "0-Jan"],
[17, "Jan-00"],
[18, "12:00 AM"],
[19, "12:00:00 AM"],
[20, "0:00"],
[21, "0:00:00"],
[22, "1/0/00 0:00"],
[37, "0 "],
[38, "0 "],
[39, "0.00"],
[40, "0.00"],
[45, "00:00"],
[46, "0:00:00"],
[47, "0000.0"],
[48, "123.5E-12"],
[49, "1.23457E-10"]
]],
[-12345.6789, [
[0, "-12345.6789"],
[1, "-12346"],
[2, "-12345.68"],
[3, "-12,346"],
[4, "-12,345.68"],
[9, "-1234568%"],
[10, "-1234567.89%"],
[11, "-1.23E+04"],
[12, "-12345 2/3"],
[13, "-12345 55/81"],
[14, ""],
[15, ""],
[16, ""],
[17, ""],
[18, ""],
[19, ""],
[20, ""],
[21, ""],
[22, ""],
[37, "(12,346)"],
[38, "(12,346)"],
[39, "(12,345.68)"],
[40, "(12,345.68)"],
[45, ""],
[46, ""],
[47, ""],
[48, "-12.3E+3"],
[49, "-12345.6789"]
]],
[11.666666666666666, 0, "11.66666667"],
[5.057996968497839, 0, "5.057996968"],
[4.380353866983808, 0, "4.380353867"],
[12.333333333333343, 0, "12.33333333"],
[-0.000006211546860868111, 0, "-6.21155E-06"],
[12345.67876, 47, "1724.9"],
[0, 0, "0"]
]

40
packages/ssf/test/implied.njs Executable file

@ -0,0 +1,40 @@
#!/usr/bin/env node
var ssf = require("../");
var val = 12345.6789;
console.log(val);
[
"0", // 1
"0.00", // 2
"#,##0", // 3
"#,##0.00", // 4
"0%", // 9
"0.00%", // 10
"0.00E+00", // 11
"# ?/?", // 12
"# ??/??", // 13
"m/d/yy", // 14
"d-mmm-yy", // 15
"d-mmm", // 16
"mmm-yy", // 17
"h:mm AM/PM", // 18
"h:mm:ss AM/PM", // 19
"h:mm", // 20
"h:mm:ss", // 21
"m/d/yy h:mm", // 22
"#,##0 ;(#,##0)", // 37
"#,##0 ;[Red](#,##0)", // 38
"#,##0.00;(#,##0.00)", // 39
"#,##0.00;[Red](#,##0.00)", // 40
"mm:ss", // 45
"[h]:mm:ss", // 46
"mmss.0", // 47
"##0.0E+0", // 48
"@", // 49
"General" // 0
].forEach(function(x) {
try {
console.log(x + "|" + ssf.format(x,val,{}));
} catch (e) { }
});

@ -0,0 +1,447 @@
[
["General", false],
["yyyy", true],
["\" Excellent\"", false],
["\" Fair\"", false],
["\" Good\"", false],
["\" Poor\"", false],
["\" Very Good\"", false],
["\"$\"#,##0", false],
["\"$\"#,##0.00", false],
["\"$\"#,##0.00_);[Red]\\(\"$\"#,##0.00\\)", false],
["\"$\"#,##0.00_);\\(\"$\"#,##0.00\\)", false],
["\"$\"#,##0;[Red]\\-\"$\"#,##0", false],
["\"$\"#,##0_);[Red]\\(\"$\"#,##0\\)", false],
["\"$\"#,##0_);\\(\"$\"#,##0\\)", false],
["\"Haha!\"\\ @\\ \"Yeah!\"", false],
["\"TRUE\";\"TRUE\";\"FALSE\"", false],
["\"True\";\"True\";\"False\";@", false],
["\"Years: \"0", false],
["\"Yes\";\"Yes\";\"No\";@", false],
["\"kl \"hh:mm:ss;@", true],
["\"£\"#,##0.00", false],
["\"£\"#,##0;[Red]\\-\"£\"#,##0", false],
["\"€\"#,##0.00", false],
["\"€\"\\ #,##0.00_-", false],
["\"上午/下午 \"hh\"時\"mm\"分\"ss\"秒 \"", true],
["\"¥\"#,##0.00;\"¥\"\\-#,##0.00", false],
["#", false],
["# ?/?", false],
["# ??/??", false],
["#\" \"?/?", false],
["#\" \"??/??", false],
["#\"abded\"\\ ??/??", false],
["###0.00;-###0.00", false],
["###0;-###0", false],
["##0.0E+0", false],
["#,##0", false],
["#,##0 ;(#,##0)", false],
["#,##0 ;[Red](#,##0)", false],
["#,##0\"р.\";[Red]\\-#,##0\"р.\"", false],
["#,##0.0", false],
["#,##0.00", false],
["#,##0.00 \"<22>\"", false],
["#,##0.00 €;-#,##0.00 €", false],
["#,##0.00\"р.\";[Red]\\-#,##0.00\"р.\"", false],
["#,##0.000", false],
["#,##0.0000", false],
["#,##0.00000", false],
["#,##0.000000", false],
["#,##0.0000000", false],
["#,##0.00000000", false],
["#,##0.000000000", false],
["#,##0.00000000;[Red]#,##0.00000000", false],
["#,##0.0000_ ", false],
["#,##0.000_ ", false],
["#,##0.000_);\\(#,##0.000\\)", false],
["#,##0.00;(#,##0.00)", false],
["#,##0.00;(#,##0.00);0.00", false],
["#,##0.00;[Red](#,##0.00)", false],
["#,##0.00;[Red]\\(#,##0.00\\)", false],
["#,##0.00;\\(#,##0.00\\)", false],
["#,##0.00[$₹-449]_);\\(#,##0.00[$₹-449]\\)", false],
["#,##0.00\\ \"р.\"", false],
["#,##0.00\\ \"р.\";[Red]\\-#,##0.00\\ \"р.\"", false],
["#,##0.00\\ [$€-407]", false],
["#,##0.00\\ [$€-40C]", false],
["#,##0.00_);\\(#,##0.00\\)", false],
["#,##0.00_р_.;[Red]\\-#,##0.00_р_.", false],
["#,##0.00_р_.;\\-#,##0.00_р_.", false],
["#,##0.0;[Red]#,##0.0", false],
["#,##0.0_ ;\\-#,##0.0\\ ", false],
["#,##0.0_);[Red]\\(#,##0.0\\)", false],
["#,##0.0_);\\(#,##0.0\\)", false],
["#,##0;\\-#,##0;0", false],
["#,##0\\ \"р.\";[Red]\\-#,##0\\ \"р.\"", false],
["#,##0\\ \"р.\";\\-#,##0\\ \"р.\"", false],
["#,##0\\ ;[Red]\\(#,##0\\)", false],
["#,##0\\ ;\\(#,##0\\)", false],
["#,##0_ ", false],
["#,##0_ ;[Red]\\-#,##0\\ ", false],
["#,##0_);[Red]\\(#,##0\\)", false],
["#,##0_р_.;[Red]\\-#,##0_р_.", false],
["#,##0_р_.;\\-#,##0_р_.", false],
["#.0000,,", false],
["#0", false],
["#0.00", false],
["#0.0000", false],
["#\\ ?/10", false],
["#\\ ?/2", false],
["#\\ ?/4", false],
["#\\ ?/8", false],
["#\\ ?/?", false],
["#\\ ??/100", false],
["#\\ ??/100;[Red]\\(#\\ ??/16\\)", false],
["#\\ ??/16", false],
["#\\ ??/??", false],
["#\\ ??/?????????", false],
["#\\ ???/???", false],
["**\\ #,###,#00,000.00,**", false],
["0", false],
["0\"abde\".0\"??\"000E+00", false],
["0%", false],
["0.0", false],
["0.0%", false],
["0.00", false],
["0.00\"°\"", false],
["0.00%", false],
["0.000", false],
["0.000%", false],
["0.0000", false],
["0.000000", false],
["0.00000000", false],
["0.000000000", false],
["0.000000000%", false],
["0.00000000000", false],
["0.000000000000000", false],
["0.00000000E+00", false],
["0.0000E+00", false],
["0.00;[Red]0.00", false],
["0.00E+00", false],
["0.00_);[Red]\\(0.00\\)", false],
["0.00_);\\(0.00\\)", false],
["0.0_ ", false],
["00.00.00.000", false],
["00.000%", false],
["0000", false],
["00000", false],
["00000000", false],
["000000000", false],
["00000\\-0000", false],
["00000\\-00000", false],
["000\\-00\\-0000", false],
["0;[Red]0", false],
["0\\-00000\\-00000\\-0", false],
["0_);[Red]\\(0\\)", false],
["0_);\\(0\\)", false],
["@", false],
["A/P", true],
["AM/PM", true],
["AM/PMh\"時\"mm\"分\"ss\"秒\";@", true],
["D", true],
["DD", true],
["DD/MM/YY;@", true],
["DD/MM/YYYY", true],
["DD/MM/YYYY;@", true],
["DDD", true],
["DDDD", true],
["DDDD\", \"MMMM\\ DD\", \"YYYY", true],
["GENERAL", false],
["General", false],
["H", true],
["H:MM:SS\\ AM/PM", true],
["HH:MM", true],
["HH:MM:SS\\ AM/PM", true],
["HHM", true],
["HHMM", true],
["HH[MM]", true],
["HH[M]", true],
["M/D/YYYY", true],
["M/D/YYYY\\ H:MM", true],
["MM/DD/YY", true],
["S", true],
["SS", true],
["YY", true],
["YYM", true],
["YYMM", true],
["YYMMM", true],
["YYMMMM", true],
["YYMMMMM", true],
["YYYY", true],
["YYYY-MM-DD HH:MM:SS", true],
["YYYY\\-MM\\-DD", true],
["[$$-409]#,##0", false],
["[$$-409]#,##0.00", false],
["[$$-409]#,##0.00_);[Red]\\([$$-409]#,##0.00\\)", false],
["[$$-C09]#,##0.00", false],
["[$-100042A]h:mm:ss\\ AM/PM;@", true],
["[$-1010409]0.000%", false],
["[$-1010409]General", false],
["[$-1010409]d/m/yyyy\\ h:mm\\ AM/PM;@", true],
["[$-1010409]dddd, mmmm dd, yyyy", true],
["[$-1010409]m/d/yyyy", true],
["[$-1409]h:mm:ss\\ AM/PM;@", true],
["[$-2000000]h:mm:ss;@", true],
["[$-2010401]d/mm/yyyy\\ h:mm\\ AM/PM;@", true],
["[$-4000439]h:mm:ss\\ AM/PM;@", true],
["[$-4010439]d/m/yyyy\\ h:mm\\ AM/PM;@", true],
["[$-409]AM/PM\\ hh:mm:ss;@", true],
["[$-409]d/m/yyyy\\ hh:mm;@", true],
["[$-409]d\\-mmm;@", true],
["[$-409]d\\-mmm\\-yy;@", true],
["[$-409]d\\-mmm\\-yyyy;@", true],
["[$-409]dd/mm/yyyy\\ hh:mm;@", true],
["[$-409]dd\\-mmm\\-yy;@", true],
["[$-409]h:mm:ss\\ AM/PM;@", true],
["[$-409]h:mm\\ AM/PM;@", true],
["[$-409]m/d/yy\\ h:mm\\ AM/PM;@", true],
["[$-409]mmm\\-yy;@", true],
["[$-409]mmmm\\ d\\,\\ yyyy;@", true],
["[$-409]mmmm\\-yy;@", true],
["[$-409]mmmmm;@", true],
["[$-409]mmmmm\\-yy;@", true],
["[$-40E]h\\ \"óra\"\\ m\\ \"perckor\"\\ AM/PM;@", true],
["[$-412]AM/PM\\ h\"시\"\\ mm\"분\"\\ ss\"초\";@", true],
["[$-41C]h:mm:ss\\.AM/PM;@", true],
["[$-449]hh:mm:ss\\ AM/PM;@", true],
["[$-44E]hh:mm:ss\\ AM/PM;@", true],
["[$-44F]hh:mm:ss\\ AM/PM;@", true],
["[$-D000409]h:mm\\ AM/PM;@", true],
["[$-D010000]d/mm/yyyy\\ h:mm\\ \"น.\";@", true],
["[$-F400]h:mm:ss\\ AM/PM", true],
["[$-F800]dddd\\,\\ mmmm\\ dd\\,\\ yyyy", true],
["[$AUD]\\ #,##0.00", false],
["[$RD$-1C0A]#,##0.00;[Red]\\-[$RD$-1C0A]#,##0.00", false],
["[$SFr.-810]\\ #,##0.00_);[Red]\\([$SFr.-810]\\ #,##0.00\\)", false],
["[$£-809]#,##0.00;[Red][$£-809]#,##0.00", false],
["[$¥-411]#,##0.00", false],
["[$¥-804]#,##0.00", false],
["[<0]\"\";0%", false],
["[<=9999999]###\\-####;\\(###\\)\\ ###\\-####", false],
["[=0]?;#,##0.00", false],
["[=0]?;0%", false],
["[=0]?;[<4.16666666666667][hh]:mm:ss;[hh]:mm", true],
["[>999999]#,,\"M\";[>999]#,\"K\";#", false],
["[>999999]#.000,,\"M\";[>999]#.000,\"K\";#.000", false],
["[>=100000]0.000\\ \\\";[Red]0.000\\ \\<\\ \\>\\ \\\"\\ \\&\\ \\'\\ ", false],
["[>=100000]0.000\\ \\<;[Red]0.000\\ \\>", false],
["[BLACK]@", false],
["[BLUE]GENERAL", false],
["[Black]@", false],
["[Blue]General", false],
["[CYAN]@", false],
["[Cyan]@", false],
["[DBNum1][$-804]AM/PMh\"时\"mm\"分\";@", true],
["[DBNum1][$-804]General", false],
["[DBNum1][$-804]h\"时\"mm\"分\";@", true],
["[ENG][$-1004]dddd\\,\\ d\\ mmmm\\,\\ yyyy;@", true],
["[ENG][$-101040D]d\\ mmmm\\ yyyy;@", true],
["[ENG][$-101042A]d\\ mmmm\\ yyyy;@", true],
["[ENG][$-140C]dddd\\ \"YeahWoo!\"\\ ddd\\ mmmm\\ yyyy;@", true],
["[ENG][$-2C0A]dddd\\ d\" de \"mmmm\" de \"yyyy;@", true],
["[ENG][$-402]dd\\ mmmm\\ yyyy\\ \"г.\";@", true],
["[ENG][$-403]dddd\\,\\ d\" / \"mmmm\" / \"yyyy;@", true],
["[ENG][$-405]d\\.\\ mmmm\\ yyyy;@", true],
["[ENG][$-408]d\\ mmmm\\ yyyy;@", true],
["[ENG][$-409]d\\-mmm;@", true],
["[ENG][$-409]d\\-mmm\\-yy;@", true],
["[ENG][$-409]d\\-mmm\\-yyyy;@", true],
["[ENG][$-409]dd\\-mmm\\-yy;@", true],
["[ENG][$-409]mmm\\-yy;@", true],
["[ENG][$-409]mmmm\\ d\\,\\ yyyy;@", true],
["[ENG][$-409]mmmm\\-yy;@", true],
["[ENG][$-40B]d\\.\\ mmmm\\t\\a\\ yyyy;@", true],
["[ENG][$-40C]d/mmm/yyyy;@", true],
["[ENG][$-40E]yyyy/\\ mmmm\\ d\\.;@", true],
["[ENG][$-40F]dd\\.\\ mmmm\\ yyyy;@", true],
["[ENG][$-410]d\\ mmmm\\ yyyy;@", true],
["[ENG][$-415]d\\ mmmm\\ yyyy;@", true],
["[ENG][$-416]d\\ \\ mmmm\\,\\ yyyy;@", true],
["[ENG][$-418]d\\ mmmm\\ yyyy;@", true],
["[ENG][$-41A]d\\.\\ mmmm\\ yyyy\\.;@", true],
["[ENG][$-41B]d\\.\\ mmmm\\ yyyy;@", true],
["[ENG][$-41D]\"den \"\\ d\\ mmmm\\ yyyy;@", true],
["[ENG][$-420]dddd\\,\\ dd\\ mmmm\\,\\ yyyy;@", true],
["[ENG][$-421]dd\\ mmmm\\ yyyy;@", true],
["[ENG][$-424]dddd\\,\\ d\\.\\ mmmm\\ yyyy;@", true],
["[ENG][$-425]dddd\\,\\ d\\.\\ mmmm\\ yyyy;@", true],
["[ENG][$-426]dddd\\,\\ yyyy\". gada \"d\\.\\ mmmm;@", true],
["[ENG][$-427]yyyy\\ \"m.\"\\ mmmm\\ d\\ \"d.\";@", true],
["[ENG][$-42B]dddd\\,\\ d\\ mmmm\\ yyyy;@", true],
["[ENG][$-42C]d\\ mmmm\\ yyyy;@", true],
["[ENG][$-42D]yyyy\"(e)ko\"\\ mmmm\"ren\"\\ d\"a\";@", true],
["[ENG][$-42F]dddd\\,\\ dd\\ mmmm\\ yyyy;@", true],
["[ENG][$-437]yyyy\\ \\წ\\ლ\\ი\\ს\\ dd\\ mm\\,\\ dddd;@", true],
["[ENG][$-438]d\\.\\ mmmm\\ yyyy;@", true],
["[ENG][$-43F]d\\ mmmm\\ yyyy\\ \"ж.\";@", true],
["[ENG][$-444]d\\ mmmm\\ yyyy;@", true],
["[ENG][$-449]dd\\ mmmm\\ yyyy;@", true],
["[ENG][$-44E]d\\ mmmm\\ yyyy;@", true],
["[ENG][$-44F]dd\\ mmmm\\ yyyy\\ dddd;@", true],
["[ENG][$-457]dd\\ mmmm\\ yyyy;@", true],
["[ENG][$-813]dddd\\ d\\ mmmm\\ yyyy;@", true],
["[ENG][$-81A]dddd\\,\\ d\\.\\ mmmm\\ yyyy;@", true],
["[ENG][$-82C]d\\ mmmm\\ yyyy;@", true],
["[ENG][$-843]yyyy\\ \"й\"\"и\"\"л\"\\ d/mmmm;@", true],
["[ENG][$-C07]dddd\\,\\ dd\\.\\ mmmm\\ yyyy;@", true],
["[ENG][$-FC19]yyyy\\,\\ dd\\ mmmm;@", true],
["[ENG][$-FC22]d\\ mmmm\\ yyyy\" р.\";@", true],
["[ENG][$-FC23]d\\ mmmm\\ yyyy;@", true],
["[GREEN]#,###", false],
["[Green]#,###", false],
["[HH]", true],
["[HIJ][$-2060401]d/mm/yyyy\\ h:mm\\ AM/PM;@", true],
["[HIJ][$-2060401]d\\ mmmm\\ yyyy;@", true],
["[H]", true],
["[JPN][$-411]gggyy\"年\"m\"月\"d\"日\"\\ dddd;@", true],
["[MAGENTA]0.00", false],
["[Magenta]0.00", false],
["[RED]#.##", false],
["[Red]#.##", false],
["[Red][<-25]General;[Blue][>25]General;[Green]General;[Yellow]General\\ ", false],
["[Red][<=-25]General;[Blue][>=25]General;[Green]General;[Yellow]General", false],
["[Red][<>50]General;[Blue]000", false],
["[Red][=50]General;[Blue]000", false],
["[SS]", true],
["[S]", true],
["[TWN][DBNum1][$-404]y\"年\"m\"月\"d\"日\";@", true],
["[WHITE]0.0", false],
["[White]0.0", false],
["[YELLOW]@", false],
["[Yellow]@", false],
["[h]", true],
["[h]:mm:ss", true],
["[h]:mm:ss;@", true],
["[h]\\.mm\" Uhr \";@", true],
["[hh]", true],
["[s]", true],
["[ss]", true],
["\\#\\r\\e\\c", false],
["\\$#,##0_);[Red]\\\"($\\\"#,##0\\)", false],
["\\$0.00", false],
["\\C\\O\\B\\ \\o\\n\\ @", false],
["\\C\\R\\O\\N\\T\\A\\B\\ \\o\\n\\ @", false],
["\\R\\e\\s\\u\\l\\t\\ \\o\\n\\ @", false],
["\\S\\Q\\L\\ \\:\\ @", false],
["\\S\\Q\\L\\ \\R\\e\\q\\u\\e\\s\\t\\ \\f\\o\\r\\ @", false],
["\\c\\c\\c?????0\"aaaa\"0\"bbbb\"000000.00%", false],
["\\u\\n\\t\\i\\l\\ h:mm;@", true],
["_ * #,##0.00_)[$﷼-429]_ ;_ * \\(#,##0.00\\)[$﷼-429]_ ;_ * \"-\"??_)[$﷼-429]_ ;_ @_ ", false],
["_ * #,##0_ ;_ * \\-#,##0_ ;[Red]_ * \"-\"_ ;_ @_ ", false],
["_(\"$\"* #,##0.00_);_(\"$\"* \\(#,##0.00\\);_(\"$\"* \"-\"??_);_(@_)", false],
["_(\"$\"* #,##0_);_(\"$\"* \\(#,##0\\);_(\"$\"* \"-\"??_);_(@_)", false],
["_(\"$\"* #,##0_);_(\"$\"* \\(#,##0\\);_(\"$\"* \"-\"_);_(@_)", false],
["_(* #,##0.0000_);_(* \\(#,##0.0000\\);_(* \"-\"??_);_(@_)", false],
["_(* #,##0.000_);_(* \\(#,##0.000\\);_(* \"-\"??_);_(@_)", false],
["_(* #,##0.00_);_(* \\(#,##0.00\\);_(* \"-\"??_);_(@_)", false],
["_(* #,##0.0_);_(* \\(#,##0.0\\);_(* \"-\"??_);_(@_)", false],
["_(* #,##0_);_(* \\(#,##0\\);_(* \"-\"??_);_(@_)", false],
["_(* #,##0_);_(* \\(#,##0\\);_(* \"-\"_);_(@_)", false],
["_([$ANG]\\ * #,##0.0_);_([$ANG]\\ * \\(#,##0.0\\);_([$ANG]\\ * \"-\"?_);_(@_)", false],
["_-\"€\"\\ * #,##0.00_-;_-\"€\"\\ * #,##0.00\\-;_-\"€\"\\ * \"-\"??_-;_-@_-", false],
["_-* #,##0.00\" TL\"_-;\\-* #,##0.00\" TL\"_-;_-* \\-??\" TL\"_-;_-@_-", false],
["_-* #,##0.00\" €\"_-;\\-* #,##0.00\" €\"_-;_-* \\-??\" €\"_-;_-@_-", false],
["_-* #,##0.00\\ \"р.\"_-;\\-* #,##0.00\\ \"р.\"_-;_-* \"-\"??\\ \"р.\"_-;_-@_-", false],
["_-* #,##0.00\\ \"€\"_-;\\-* #,##0.00\\ \"€\"_-;_-* \"-\"??\\ \"€\"_-;_-@_-", false],
["_-* #,##0.00\\ [$€-407]_-;\\-* #,##0.00\\ [$€-407]_-;_-* \\-??\\ [$€-407]_-;_-@_-", false],
["_-* #,##0.0\\ _F_-;\\-* #,##0.0\\ _F_-;_-* \"-\"??\\ _F_-;_-@_-", false],
["_-* #,##0\\ \"€\"_-;\\-* #,##0\\ \"€\"_-;_-* \"-\"\\ \"€\"_-;_-@_-", false],
["_-* #,##0_-;\\-* #,##0_-;_-* \"-\"??_-;_-@_-", false],
["_-\\$* #,##0.0_ ;_-\\$* \\-#,##0.0\\ ;_-\\$* \"-\"?_ ;_-@_ ", false],
["d", true],
["d-mmm", true],
["d-mmm-yy", true],
["d/m", true],
["d/m/yy;@", true],
["d/m/yyyy;@", true],
["d/mm/yy;@", true],
["d/mm/yyyy;@", true],
["d\\-mmm", true],
["d\\-mmm\\-yyyy", true],
["dd", true],
["dd\"-\"mmm\"-\"yyyy", true],
["dd/m/yyyy", true],
["dd/mm/yy", true],
["dd/mm/yy;@", true],
["dd/mm/yy\\ hh:mm", true],
["dd/mm/yyyy", true],
["dd/mm/yyyy\\ hh:mm:ss", true],
["dd/mmm", true],
["dd\\-mm\\-yy", true],
["dd\\-mmm\\-yy", true],
["dd\\-mmm\\-yyyy\\ hh:mm:ss.000", true],
["dd\/mm\/yy", true],
["dd\/mm\/yyyy", true],
["ddd", true],
["dddd", true],
["dddd, mmmm dd, yyyy", true],
["h", true],
["h\"时\"mm\"分\"ss\"秒\";@", true],
["h\"時\"mm\"分\"ss\"秒\";@", true],
["h:mm", true],
["h:mm AM/PM", true],
["h:mm:ss", true],
["h:mm:ss AM/PM", true],
["h:mm:ss;@", true],
["h:mm;@", true],
["h\\.mm\" Uhr \";@", true],
["h\\.mm\" h\";@", true],
["h\\.mm\" u.\";@", true],
["hh\":\"mm AM/PM", true],
["hh:mm:ss", true],
["hh:mm:ss\\ AM/PM", true],
["hh\\.mm\" h\";@", true],
["hhm", true],
["hhmm", true],
["m\"月\"d\"日\"", true],
["m/d/yy", true],
["m/d/yy h:mm", true],
["m/d/yy;@", true],
["m/d/yy\\ h:mm", true],
["m/d/yy\\ h:mm;@", true],
["m/d/yyyy", true],
["m/d/yyyy;@", true],
["m/d/yyyy\\ h:mm:ss;@", true],
["m/d;@", true],
["m\/d\/yyyy", true],
["mm/dd", true],
["mm/dd/yy", true],
["mm/dd/yy;@", true],
["mm/dd/yyyy", true],
["mm:ss", true],
["mm:ss.0;@", true],
["mmm d, yyyy", true],
["mmm\" \"d\", \"yyyy", true],
["mmm-yy", true],
["mmm-yy;@", true],
["mmm/yy", true],
["mmm\\-yy", true],
["mmm\\-yy;@", true],
["mmm\\-yyyy", true],
["mmmm\\ d\\,\\ yyyy", true],
["mmmm\\ yyyy", true],
["mmss.0", true],
["s", true],
["ss", true],
["yy", true],
["yy/mm/dd", true],
["yy\\.mm\\.dd", true],
["yym", true],
["yymm", true],
["yymmm", true],
["yymmmm", true],
["yymmmmm", true],
["yyyy", true],
["yyyy\"년\"\\ m\"월\"\\ d\"일\";@", true],
["yyyy-m-d h:mm AM/PM", true],
["yyyy-mm-dd", true],
["yyyy/mm/dd", true],
["yyyy\\-m\\-d\\ hh:mm:ss", true],
["yyyy\\-mm\\-dd", true],
["yyyy\\-mm\\-dd;@", true],
["yyyy\\-mm\\-dd\\ h:mm", true],
["yyyy\\-mm\\-dd\\Thh:mm", true],
["yyyy\\-mm\\-dd\\Thhmmss.000", true],
["###,##0", false],
["#,###.00", false]
]

@ -0,0 +1,57 @@
/* vim: set ts=2: */
/*jshint loopfunc:true, mocha:true, node:true */
/*eslint-env mocha, node */
var SSF = require('../');
var assert = require('assert');
/* {format, data:[[value, result]]} */
var data = [
{
format: '"$"#,##0_);\\("$"#,##0\\);"-"',
data: [
[10000, "$10,000 "],
[9000.98, "$9,001 "],
[100, "$100 "],
[50.02, "$50 "],
[1, "$1 "],
[0.1, "$0 "],
[0.01, "$0 "],
[0, "-"],
[-10000, "($10,000)"],
[-9000.98, "($9,001)"],
[-100, "($100)"],
[-50.02, "($50)"],
[-1, "($1)"],
[-0.1, "($0)"],
[-0.01, "($0)"]
]
},
{
format: '(#,##0.00)',
data: [
[-12345.6789, "-(12,345.68)"]
]
},
{
format: '#,##0.00;\\(#,##0.00\\)',
data: [
[-12345.6789, "(12,345.68)"]
]
},
{
format: '[<=9999999]###\\-####;(###) ###\\-####',
data: [
[2813308004, '(281) 330-8004']
]
}
];
describe("negatives", function() {
data.forEach(function(row) {
it(row.format, function() {
row.data.forEach(function(r) {
assert.equal(SSF.format(row.format, r[0]), r[1]);
});
});
});
});

@ -0,0 +1,22 @@
/* vim: set ts=2: */
/*jshint loopfunc:true, mocha:true, node:true */
var SSF = require('../');
var fs = require('fs'), assert = require('assert');
var data = JSON.parse(fs.readFileSync('./test/oddities.json','utf8'));
describe('oddities', function() {
data.forEach(function(d) {
it(String(d[0]), function(){
for(var j=1;j<d.length;++j) {
if(d[j].length == 2) {
var expected = d[j][1], actual = SSF.format(d[0], d[j][0], {});
assert.equal(actual, expected);
} else if(d[j][2] !== "#") assert.throws(function() { SSF.format(d[0], d[j][0]); });
}
});
});
it('should fail for bad formats', function() {
var bad = ['##,##'];
var chk = function(fmt){ return function(){ SSF.format(fmt,0); }; };
bad.forEach(function(fmt){assert.throws(chk(fmt));});
});
});

@ -0,0 +1,180 @@
[
["\"foo\";\"bar\";\"baz\";\"qux\"",
[1, "foo"], [-1, "bar"], [0, "baz"], ["sheetjs", "qux"]
],
["\"foo\";\"bar\";\"baz\"",
[1, "foo"], [-1, "bar"], [0, "baz"], ["sheetjs", "sheetjs"]
],
["\"foo\";\"bar\";@",
[1, "foo"], [-1, "bar"], [0, "foo"], ["sheetjs", "sheetjs"]
],
["\"foo\";\"bar\"",
[1, "foo"], [-1, "bar"], [0, "foo"], ["sheetjs", "sheetjs"]
],
["@@", [1, "1"], [-1, "-1"], [0, "0"], ["sheetjs", "sheetjssheetjs"]],
["[Blue]General", [1, "1"], [-1, "-1"], [0, "0"], ["sheetjs", "sheetjs"]],
["[Blue]G3neral", [1], [-1], [0], ["TODO","TODO"]],
["A\"TODO\"", [1, "ATODO"], [-1, "ATODO"], [0, "ATODO"], ["TODO","TODO"]],
["r", [1,"r"], [-1,"-r","#"], [0,"r"], ["sheetjs","sheetjs"]],
["((;@", [1,"(("], [0,"(("], ["foo","foo"]],
["\\r", [1, "r"], [-1, "r"], [0, "r"], ["TODO","TODO"]],
["_($* #,##0_);_($* (#,##0);_($* \"-\"_);_(@_)", [1, " $1 "], [-1, " $(1)"], [0," $- "], ["TODO", " TODO "], ["",""]],
["#0.#", [0,"0."], [1,"1."], [12,"12."], [12.34, "12.3"], [-1.23, "-1.2"]],
["#,##0.0", [1,"1.0"], [-1,"-1.0"], [0,"0.0"], ["TODO","TODO"]],
["#,##0.00", [1,"1.00"], [-1,"-1.00"], [0,"0.00"], ["TODO","TODO"]],
["#,##0.000", [1,"1.000"], [-1,"-1.000"], [0,"0.000"], ["TODO","TODO"]],
["#,##0.0000", [1,"1.0000"], [-1,"-1.0000"], [0,"0.0000"], ["TODO","TODO"]],
["#,##0.00000", [1000000, "1,000,000.00000"]],
["#,##0.000000", [1000000, "1,000,000.000000"]],
["#,##0.0000000", [1000000, "1,000,000.0000000"]],
["#,##0.00000000", [1000000, "1,000,000.00000000"]],
["#,##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.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"]],
["0.0000", [1, "1.0000"], [-1, "-1.0000"], [0,"0.0000"], ["sheetjs", "sheetjs"]],
["hh:mm AM/PM", [0.7, "04:48 PM"]],
["hhh:mm AM/PM", [0.7]],
["hhh:mmm:sss", [0.7]],
["hh:mmm:sss", [0.7]],
["hh:mm:sss", [0.7]],
["hh:mm:ss.000", [0.7,"16:48:00.000"], [0.70707,"16:58:10.848"]],
["hh.000", [0.70707, "16.848"]],
["hh .00", [0.70707, "16 .85"]],
["hh .0", [0.70707, "16 .8"]],
["hh .00 .000", [0.70707, "16 .84 .848"]],
["[hhh]", [0.7]],
["[", [0.7]],
["A/P", [0.7, "P"]],
["e", [0.7, "1900"]],
["123", [0.7, "123"], [0, "123"], ["sheetjs", "sheetjs"]],
["0.##", [1,"1."], [-1,"-1."], [0, "0."], [1.1, "1.1"], [-1.2, "-1.2"], [1000000000000.01, "1000000000000.01"], [-1000.01, "-1000.01"], [0.1, "0.1"], [1.007, "1.01"], [-1.008, "-1.01"]],
["** #,###,#00,000.00,**",
[1.2345, " 00,000.00"],
[12.345, " 00,000.01"],
[123.45, " 00,000.12"],
[1234.56, " 00,001.23"],
[12345.67, " 00,012.35"],
[123456.78, " 00,123.46"],
[1234567.89, " 01,234.57"],
[12345681.9, " 12,345.68"],
[123456822, " 123,456.82"],
[1234568223, " 1,234,568.22"],
[12345682233, " 12,345,682.23"],
[123456822333, " 123,456,822.33"],
[1234568223333, " 1,234,568,223.33"],
[12345682233333, " 12,345,682,233.33"],
[123456822333333, " 123,456,822,333.33"],
[1234568223333330, " 1,234,568,223,333.33"],
[12345682233333300, " 12,345,682,233,333.30"],
[123456822333333000, " 123,456,822,333,333.00", "#"],
[1234568223333330000, " 1,234,568,223,333,330.00"],
[12345682233333300000, " 12,345,682,233,333,300.00"],
[123456822333333000000, " 123,456,822,333,333,000.00"],
[1234568223333330000000, " 1,234,568,223,333,330,000.00"]
],
["00,000.00,", [12345, "00,012.35"] ],
["00,000.00", [12345, "12,345.00"] ],
["000#0#0#0##00##00##0#########", [12345, "0000000000012345"] ],
["##0.0E+0",
[1, "1.0E+0"],
[12, "12.0E+0"],
[123, "123.0E+0"],
[1234, "1.2E+3"],
[12345, "12.3E+3"],
[123456, "123.5E+3"],
[1234567, "1.2E+6"],
[12345678, "12.3E+6"],
[123456789, "123.5E+6"]
],
["0#######0.##0##0######00######0",
[12.3456789, "012.3456789000"],
[123456789, "123456789.00000"]
],
["###\\###\\##0.00",
[0.00101, "##0.00"],
[0.0101, "##0.01"],
[0.101, "##0.10"],
[1.01, "##1.01"],
[10.1, "##10.10"],
[101, "#1#01.00"],
[1010, "#10#10.00"],
[10100, "1#01#00.00"],
[101000, "10#10#00.00"],
[1010000, "101#00#00.00"],
[10100000, "1010#00#00.00"],
[101000000, "10100#00#00.00"],
[123456789.01, "12345#67#89.01"]
],
["###\\\\###\\\\##\\0.00",
[0.00101, "\\\\0.00"],
[0.0101, "\\\\0.01"],
[0.101, "\\\\0.10"],
[1.01, "\\\\10.01"],
[10.1, "\\\\100.10"],
[101, "\\1\\010.00"],
[1010, "\\10\\100.00"],
[10100, "\\101\\000.00"],
[101000, "1\\010\\000.00"],
[1010000, "10\\100\\000.00"],
[10100000, "101\\000\\000.00"],
[101000000, "1010\\000\\000.00"],
[123456789.01, "1234\\567\\890.01"]
],
["0.0#",
[12345.0, "12345.0"],
[1234.5, "1234.5"],
[123.45, "123.45"],
[12.345, "12.35"],
[1.2345, "1.23"],
[0.12345, "0.12"],
[0.012345, "0.01"],
[0.0012345, "0.0"],
[0.00012345, "0.0"],
[15.04, "15.04"],
[15.06, "15.06"]
],
["###\\\\###\\\\##\\0", [12345.6789, "\\123\\460"]],
["00000-0000", [941051630, "94105-1630"], [12345.6789, "00001-2346"]],
["000-00-0000", [123456789, "123-45-6789"]],
["00000\\-0000", [941051630, "94105-1630"]],
["000\\-00\\-0000", [123456789, "123-45-6789"]],
["??/??", [12.3456789, "1000/81"], [0.00001, " 0/1 "]],
["# ??/??", [12.3456789, "12 28/81"]],
["#??/??", [12.3456789, "1000/81"]],
["#0#00??/??", [12.3456789, "01000/81"]],
["[<=9999999]###-####;(###) ###-####", [8675309, "867-5309"],[2813308004, "(281) 330-8004"], [2018675309, "(201) 867-5309"]],
["[<=9999999]###\\-####;(###) ###\\-####", [8675309, "867-5309"],[2813308004, "(281) 330-8004"]],
["[Red][<-25]General;[Blue][>25]General;[Green]General;[Yellow]General", [50, "50"],[26, "26"],[25,"25"],[1,"1"],[0,"0"],[-1,"-1"],[-25,"-25"],[-26,"26","#"],[-50.1,"50","#"], ["foo","foo"],["bar","bar"]],
["[Red][<=-25]General;[Blue][>=25]General;[Green]General;[Yellow]General", [50, "50"],[26, "26"],[25,"25"],[1,"1"],[0,"0"],[-1,"-1"],[-25,"-25"],[-26.1,"26","#"],[-50,"50","#"], ["foo","foo"],["bar","bar"]],
["[Red]General ;[Blue]General\\ ;[Green]Generalp;[Yellow]General'", [50, "50 "],[0,"0p"],[-25,"-25 "],["foo","foo'"]],
["[Red][=50]General;[Blue]000", [50, "50"], [51, "051"], [49, "049"]],
["[Red][<>50]General;[Blue]000", [50, "050"], [51, "51"], [49, "49"]],
["b", [1,"43"], [1000,"45"], [10000,"70"]],
["B2yyyymmdd", [0,"13170829"], [1000,"13200624","#"], [10000,"13451117","#"]],
["☃", [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"]],
["\"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"]],
["\\,##.??;\\(#,###.??\\);0", [15,",15. ","#"], [14.3453453,",14.35","#"], [12.1,",12.1 ","#"], [0,"0","#"], [-15,"(15. )","#"], [-14.3453453,"(14.35)","#"], [-12.1,"(12.1 )","#"], [1,",1. ","#"]],
["\"£\"#.####;-\"£\"#.####", [3.141592654, "£3.1416"], [-3.141592654, "-£3.1416"]],
["[h]:mm:ss;@", [2.9999999999999996, "72:00:00"]],
["hh:mm:ss AM/PM", [0.5, "12:00:00 PM"]],
["hh:mm:ss am/pm", [0.5, "12:00:00 PM"]],
["hh:mm:ss AM/P", [0.5, "12:00:00 A1/P"]],
["hh:mm:ss am/p", [0.5, "12:00:00 a1/p"]],
["\"foo\";\"bar\";\"baz\";\"qux\";\"foobar\"", [1], [0], [-1], ["sheetjs"]]
]

1048576
packages/ssf/test/times.tsv Normal file

File diff suppressed because it is too large Load Diff

@ -0,0 +1,10 @@
/* vim: set ts=2: */
/*jshint loopfunc:true, mocha:true, node:true */
var SSF = require('../');
var fs = require('fs'), assert = require('assert');
var is_date = JSON.parse(fs.readFileSync('./test/is_date.json','utf8'));
describe('utilities', function() {
it('correctly determines if formats are dates', function() {
is_date.forEach(function(d) { assert.equal(SSF.is_date(d[0]), d[1], d[0]); });
});
});

@ -0,0 +1,19 @@
/* vim: set ts=2: */
/*jshint loopfunc:true, mocha:true, node:true */
var SSF = require('../');
var fs = require('fs');
var data = fs.readFileSync('./test/valid.tsv','utf8').split("\n");
var _data = [0, 1, -2, 3.45, -67.89, "foo"];
function doit(d) {
it(d[0], function() {
for(var w = 0; w < _data.length; ++w) {
SSF.format(d[0], _data[w]);
}
});
}
describe('valid formats', function() {
for(var j=0;j<data.length;++j) {
if(!data[j]) return;
doit(data[j].replace(/#{255}/g,"").split("\t"));
}
});

442
packages/ssf/test/valid.tsv Normal file

@ -0,0 +1,442 @@
" Excellent"
" Fair"
" Good"
" Poor"
" Very Good"
"$"#,##0
"$"#,##0.00
"$"#,##0.00_);[Red]\("$"#,##0.00\)
"$"#,##0.00_);\("$"#,##0.00\)
"$"#,##0;[Red]\-"$"#,##0
"$"#,##0_);[Red]\("$"#,##0\)
"$"#,##0_);\("$"#,##0\)
"Haha!"\ @\ "Yeah!"
"TRUE";"TRUE";"FALSE"
"True";"True";"False";@
"Years: "0
"Yes";"Yes";"No";@
"kl "hh:mm:ss;@
"£"#,##0.00
"£"#,##0;[Red]\-"£"#,##0
"€"#,##0.00
"€"\ #,##0.00_-
"上午/下午 "hh"時"mm"分"ss"秒 "
"¥"#,##0.00;"¥"\-#,##0.00
#
# ?/?
# ??/??
#" "?/?
#" "??/??
#"abded"\ ??/??
###0.00;-###0.00
###0;-###0
##0.0E+0
#,##0
#,##0 ;(#,##0)
#,##0 ;[Red](#,##0)
#,##0"р.";[Red]\-#,##0"р."
#,##0.0
#,##0.00
#,##0.00 "<22>"
#,##0.00 €;-#,##0.00 €
#,##0.00"р.";[Red]\-#,##0.00"р."
#,##0.000
#,##0.0000
#,##0.00000
#,##0.000000
#,##0.0000000
#,##0.00000000
#,##0.000000000
#,##0.00000000;[Red]#,##0.00000000
#,##0.0000_
#,##0.000_
#,##0.000_);\(#,##0.000\)
#,##0.00;(#,##0.00)
#,##0.00;(#,##0.00);0.00
#,##0.00;[Red](#,##0.00)
#,##0.00;[Red]\(#,##0.00\)
#,##0.00;\(#,##0.00\)
#,##0.00[$₹-449]_);\(#,##0.00[$₹-449]\)
#,##0.00\ "р."
#,##0.00\ "р.";[Red]\-#,##0.00\ "р."
#,##0.00\ [$€-407]
#,##0.00\ [$€-40C]
#,##0.00_);\(#,##0.00\)
#,##0.00_р_.;[Red]\-#,##0.00_р_.
#,##0.00_р_.;\-#,##0.00_р_.
#,##0.0;[Red]#,##0.0
#,##0.0_ ;\-#,##0.0\
#,##0.0_);[Red]\(#,##0.0\)
#,##0.0_);\(#,##0.0\)
#,##0;\-#,##0;0
#,##0\ "р.";[Red]\-#,##0\ "р."
#,##0\ "р.";\-#,##0\ "р."
#,##0\ ;[Red]\(#,##0\)
#,##0\ ;\(#,##0\)
#,##0_
#,##0_ ;[Red]\-#,##0\
#,##0_);[Red]\(#,##0\)
#,##0_р_.;[Red]\-#,##0_р_.
#,##0_р_.;\-#,##0_р_.
#.0000,,
#0
#0.00
#0.0000
#\ ?/10
#\ ?/2
#\ ?/4
#\ ?/8
#\ ?/?
#\ ??/100
#\ ??/100;[Red]\(#\ ??/16\)
#\ ??/16
#\ ??/??
#\ ??/?????????
#\ ???/???
**\ #,###,#00,000.00,**
0
0"abde".0"??"000E+00
0%
0.0
0.0%
0.00
0.00"°"
0.00%
0.000
0.000%
0.0000
0.000000
0.00000000
0.000000000
0.000000000%
0.00000000000
0.000000000000000
0.00000000E+00
0.0000E+00
0.00;[Red]0.00
0.00E+00
0.00_);[Red]\(0.00\)
0.00_);\(0.00\)
0.0_
00.00.00.000
00.000%
0000
00000
00000000
000000000
00000\-0000
00000\-00000
000\-00\-0000
0;[Red]0
0\-00000\-00000\-0
0_);[Red]\(0\)
0_);\(0\)
@
A/P
AM/PM
AM/PMh"時"mm"分"ss"秒";@
D
DD
DD/MM/YY;@
DD/MM/YYYY
DD/MM/YYYY;@
DDD
DDDD
DDDD", "MMMM\ DD", "YYYY
GENERAL
General
H
H:MM:SS\ AM/PM
HH:MM
HH:MM:SS\ AM/PM
HHM
HHMM
HH[MM]
HH[M]
M/D/YYYY
M/D/YYYY\ H:MM
MM/DD/YY
S
SS
YY
YYM
YYMM
YYMMM
YYMMMM
YYMMMMM
YYYY
YYYY-MM-DD HH:MM:SS
YYYY\-MM\-DD
[$$-409]#,##0
[$$-409]#,##0.00
[$$-409]#,##0.00_);[Red]\([$$-409]#,##0.00\)
[$$-C09]#,##0.00
[$-100042A]h:mm:ss\ AM/PM;@
[$-1010409]0.000%
[$-1010409]General
[$-1010409]d/m/yyyy\ h:mm\ AM/PM;@
[$-1010409]dddd, mmmm dd, yyyy
[$-1010409]m/d/yyyy
[$-1409]h:mm:ss\ AM/PM;@
[$-2000000]h:mm:ss;@
[$-2010401]d/mm/yyyy\ h:mm\ AM/PM;@
[$-4000439]h:mm:ss\ AM/PM;@
[$-4010439]d/m/yyyy\ h:mm\ AM/PM;@
[$-409]AM/PM\ hh:mm:ss;@
[$-409]d/m/yyyy\ hh:mm;@
[$-409]d\-mmm;@
[$-409]d\-mmm\-yy;@
[$-409]d\-mmm\-yyyy;@
[$-409]dd/mm/yyyy\ hh:mm;@
[$-409]dd\-mmm\-yy;@
[$-409]h:mm:ss\ AM/PM;@
[$-409]h:mm\ AM/PM;@
[$-409]m/d/yy\ h:mm\ AM/PM;@
[$-409]mmm\-yy;@
[$-409]mmmm\ d\,\ yyyy;@
[$-409]mmmm\-yy;@
[$-409]mmmmm;@
[$-409]mmmmm\-yy;@
[$-40E]h\ "óra"\ m\ "perckor"\ AM/PM;@
[$-412]AM/PM\ h"시"\ mm"분"\ ss"초";@
[$-41C]h:mm:ss\.AM/PM;@
[$-449]hh:mm:ss\ AM/PM;@
[$-44E]hh:mm:ss\ AM/PM;@
[$-44F]hh:mm:ss\ AM/PM;@
[$-D000409]h:mm\ AM/PM;@
[$-D010000]d/mm/yyyy\ h:mm\ "น.";@
[$-F400]h:mm:ss\ AM/PM
[$-F800]dddd\,\ mmmm\ dd\,\ yyyy
[$AUD]\ #,##0.00
[$RD$-1C0A]#,##0.00;[Red]\-[$RD$-1C0A]#,##0.00
[$SFr.-810]\ #,##0.00_);[Red]\([$SFr.-810]\ #,##0.00\)
[$£-809]#,##0.00;[Red][$£-809]#,##0.00
[$¥-411]#,##0.00
[$¥-804]#,##0.00
[<0]"";0%
[<=9999999]###\-####;\(###\)\ ###\-####
[=0]?;#,##0.00
[=0]?;0%
[=0]?;[<4.16666666666667][hh]:mm:ss;[hh]:mm
[>999999]#,,"M";[>999]#,"K";#
[>999999]#.000,,"M";[>999]#.000,"K";#.000
[>=100000]0.000\ \";[Red]0.000\ \<\ \>\ \"\ \&\ \'\
[>=100000]0.000\ \<;[Red]0.000\ \>
[BLACK]@
[BLUE]GENERAL
[Black]@
[Blue]General
[CYAN]@
[Cyan]@
[DBNum1][$-804]AM/PMh"时"mm"分";@
[DBNum1][$-804]General
[DBNum1][$-804]h"时"mm"分";@
[ENG][$-1004]dddd\,\ d\ mmmm\,\ yyyy;@
[ENG][$-101040D]d\ mmmm\ yyyy;@
[ENG][$-101042A]d\ mmmm\ yyyy;@
[ENG][$-140C]dddd\ "YeahWoo!"\ ddd\ mmmm\ yyyy;@
[ENG][$-2C0A]dddd\ d" de "mmmm" de "yyyy;@
[ENG][$-402]dd\ mmmm\ yyyy\ "г.";@
[ENG][$-403]dddd\,\ d" / "mmmm" / "yyyy;@
[ENG][$-405]d\.\ mmmm\ yyyy;@
[ENG][$-408]d\ mmmm\ yyyy;@
[ENG][$-409]d\-mmm;@
[ENG][$-409]d\-mmm\-yy;@
[ENG][$-409]d\-mmm\-yyyy;@
[ENG][$-409]dd\-mmm\-yy;@
[ENG][$-409]mmm\-yy;@
[ENG][$-409]mmmm\ d\,\ yyyy;@
[ENG][$-409]mmmm\-yy;@
[ENG][$-40B]d\.\ mmmm\t\a\ yyyy;@
[ENG][$-40C]d/mmm/yyyy;@
[ENG][$-40E]yyyy/\ mmmm\ d\.;@
[ENG][$-40F]dd\.\ mmmm\ yyyy;@
[ENG][$-410]d\ mmmm\ yyyy;@
[ENG][$-415]d\ mmmm\ yyyy;@
[ENG][$-416]d\ \ mmmm\,\ yyyy;@
[ENG][$-418]d\ mmmm\ yyyy;@
[ENG][$-41A]d\.\ mmmm\ yyyy\.;@
[ENG][$-41B]d\.\ mmmm\ yyyy;@
[ENG][$-41D]"den "\ d\ mmmm\ yyyy;@
[ENG][$-420]dddd\,\ dd\ mmmm\,\ yyyy;@
[ENG][$-421]dd\ mmmm\ yyyy;@
[ENG][$-424]dddd\,\ d\.\ mmmm\ yyyy;@
[ENG][$-425]dddd\,\ d\.\ mmmm\ yyyy;@
[ENG][$-426]dddd\,\ yyyy". gada "d\.\ mmmm;@
[ENG][$-427]yyyy\ "m."\ mmmm\ d\ "d.";@
[ENG][$-42B]dddd\,\ d\ mmmm\ yyyy;@
[ENG][$-42C]d\ mmmm\ yyyy;@
[ENG][$-42D]yyyy"(e)ko"\ mmmm"ren"\ d"a";@
[ENG][$-42F]dddd\,\ dd\ mmmm\ yyyy;@
[ENG][$-437]yyyy\ \წ\ლ\ი\ს\ dd\ mm\,\ dddd;@
[ENG][$-438]d\.\ mmmm\ yyyy;@
[ENG][$-43F]d\ mmmm\ yyyy\ "ж.";@
[ENG][$-444]d\ mmmm\ yyyy;@
[ENG][$-449]dd\ mmmm\ yyyy;@
[ENG][$-44E]d\ mmmm\ yyyy;@
[ENG][$-44F]dd\ mmmm\ yyyy\ dddd;@
[ENG][$-457]dd\ mmmm\ yyyy;@
[ENG][$-813]dddd\ d\ mmmm\ yyyy;@
[ENG][$-81A]dddd\,\ d\.\ mmmm\ yyyy;@
[ENG][$-82C]d\ mmmm\ yyyy;@
[ENG][$-843]yyyy\ "й""и""л"\ d/mmmm;@
[ENG][$-C07]dddd\,\ dd\.\ mmmm\ yyyy;@
[ENG][$-FC19]yyyy\,\ dd\ mmmm;@
[ENG][$-FC22]d\ mmmm\ yyyy" р.";@
[ENG][$-FC23]d\ mmmm\ yyyy;@
[GREEN]#,###
[Green]#,###
[HH]
[HIJ][$-2060401]d/mm/yyyy\ h:mm\ AM/PM;@
[HIJ][$-2060401]d\ mmmm\ yyyy;@
[H]
[JPN][$-411]gggyy"年"m"月"d"日"\ dddd;@
[MAGENTA]0.00
[Magenta]0.00
[RED]#.##
[Red]#.##
[Red][<-25]General;[Blue][>25]General;[Green]General;[Yellow]General\
[Red][<=-25]General;[Blue][>=25]General;[Green]General;[Yellow]General
[Red][<>50]General;[Blue]000
[Red][=50]General;[Blue]000
[SS]
[S]
[TWN][DBNum1][$-404]y"年"m"月"d"日";@
[WHITE]0.0
[White]0.0
[YELLOW]@
[Yellow]@
[h]
[h]:mm:ss
[h]:mm:ss;@
[h]\.mm" Uhr ";@
[hh]
[s]
[ss]
\#\r\e\c
\$#,##0_);[Red]"($"#,##0\)
\$0.00
\C\O\B\ \o\n\ @
\C\R\O\N\T\A\B\ \o\n\ @
\R\e\s\u\l\t\ \o\n\ @
\S\Q\L\ \:\ @
\S\Q\L\ \R\e\q\u\e\s\t\ \f\o\r\ @
\c\c\c?????0"aaaa"0"bbbb"000000.00%
\u\n\t\i\l\ h:mm;@
_ "¥"* #,##0.00_ "Positive";_ "¥"* \-#,##0.00_ ;_ "¥"* "-"??_ "Negtive";_ @_ \ "Zero"
_ * #,##0.00_)[$﷼-429]_ ;_ * \(#,##0.00\)[$﷼-429]_ ;_ * "-"??_)[$﷼-429]_ ;_ @_
_ * #,##0_ ;_ * \-#,##0_ ;[Red]_ * "-"_ ;_ @_
_("$"* #,##0.00_);_("$"* \(#,##0.00\);_("$"* "-"??_);_(@_)
_("$"* #,##0_);_("$"* \(#,##0\);_("$"* "-"??_);_(@_)
_("$"* #,##0_);_("$"* \(#,##0\);_("$"* "-"_);_(@_)
_(* #,##0.0000_);_(* \(#,##0.0000\);_(* "-"??_);_(@_)
_(* #,##0.000_);_(* \(#,##0.000\);_(* "-"??_);_(@_)
_(* #,##0.00_);_(* \(#,##0.00\);_(* "-"??_);_(@_)
_(* #,##0.0_);_(* \(#,##0.0\);_(* "-"??_);_(@_)
_(* #,##0_);_(* \(#,##0\);_(* "-"??_);_(@_)
_(* #,##0_);_(* \(#,##0\);_(* "-"_);_(@_)
_([$ANG]\ * #,##0.0_);_([$ANG]\ * \(#,##0.0\);_([$ANG]\ * "-"?_);_(@_)
_-"€"\ * #,##0.00_-;_-"€"\ * #,##0.00\-;_-"€"\ * "-"??_-;_-@_-
_-* #,##0.00" TL"_-;\-* #,##0.00" TL"_-;_-* \-??" TL"_-;_-@_-
_-* #,##0.00" €"_-;\-* #,##0.00" €"_-;_-* \-??" €"_-;_-@_-
_-* #,##0.00\ "р."_-;\-* #,##0.00\ "р."_-;_-* "-"??\ "р."_-;_-@_-
_-* #,##0.00\ "€"_-;\-* #,##0.00\ "€"_-;_-* "-"??\ "€"_-;_-@_-
_-* #,##0.00\ [$€-407]_-;\-* #,##0.00\ [$€-407]_-;_-* \-??\ [$€-407]_-;_-@_-
_-* #,##0.0\ _F_-;\-* #,##0.0\ _F_-;_-* "-"??\ _F_-;_-@_-
_-* #,##0\ "€"_-;\-* #,##0\ "€"_-;_-* "-"\ "€"_-;_-@_-
_-* #,##0_-;\-* #,##0_-;_-* "-"??_-;_-@_-
_-\$* #,##0.0_ ;_-\$* \-#,##0.0\ ;_-\$* "-"?_ ;_-@_
d
d-mmm
d-mmm-yy
d/m
d/m/yy;@
d/m/yyyy;@
d/mm/yy;@
d/mm/yyyy;@
d\-mmm
d\-mmm\-yyyy
dd
dd"-"mmm"-"yyyy
dd/m/yyyy
dd/mm/yy
dd/mm/yy;@
dd/mm/yy\ hh:mm
dd/mm/yyyy
dd/mm/yyyy\ hh:mm:ss
dd/mmm
dd\-mm\-yy
dd\-mmm\-yy
dd\-mmm\-yyyy\ hh:mm:ss.000
dd\/mm\/yy
dd\/mm\/yyyy
ddd
dddd
dddd, mmmm dd, yyyy
h
h"时"mm"分"ss"秒";@
h"時"mm"分"ss"秒";@
h:mm
h:mm AM/PM
h:mm:ss
h:mm:ss AM/PM
h:mm:ss;@
h:mm;@
h\.mm" Uhr ";@
h\.mm" h";@
h\.mm" u.";@
hh":"mm AM/PM
hh:mm:ss
hh:mm:ss\ AM/PM
hh\.mm" h";@
hhm
hhmm
m"月"d"日"
m/d/yy
m/d/yy h:mm
m/d/yy;@
m/d/yy\ h:mm
m/d/yy\ h:mm;@
m/d/yyyy
m/d/yyyy;@
m/d/yyyy\ h:mm:ss;@
m/d;@
m\/d\/yyyy
mm/dd
mm/dd/yy
mm/dd/yy;@
mm/dd/yyyy
mm:ss
mm:ss.0;@
mmm d, yyyy
mmm" "d", "yyyy
mmm-yy
mmm-yy;@
mmm/yy
mmm\-yy
mmm\-yy;@
mmm\-yyyy
mmmm\ d\,\ yyyy
mmmm\ yyyy
mmss.0
s
ss
yy
yy/mm/dd
yy\.mm\.dd
yym
yymm
yymmm
yymmmm
yymmmmm
yyyy
yyyy"년"\ m"월"\ d"일";@
yyyy-m-d h:mm AM/PM
yyyy-mm-dd
yyyy/mm/dd
yyyy\-m\-d\ hh:mm:ss
yyyy\-mm\-dd
yyyy\-mm\-dd;@
yyyy\-mm\-dd\ h:mm
yyyy\-mm\-dd\Thh:mm
yyyy\-mm\-dd\Thhmmss.000
Can't render this file because it contains an unexpected character in line 6 and column 3.

@ -0,0 +1,5 @@
Makefile
*ssf*.ts
doc.ts
write.ts
tslint.json

13
packages/ssf/types/bin_ssf.ts Executable file

@ -0,0 +1,13 @@
/* ssf.js (C) 2013-present SheetJS -- http://sheetjs.com */
/* eslint-env node */
/* eslint no-console:0 */
/*jshint node:true */
/// <reference types="../node_modules/@types/node/" />
import X = require('ssf');
const argv = process.argv.slice(2);
if(argv.length < 2 || argv[0] === "-h" || argv[0] === "--help") {
console.error("usage: ssf <format> <value>");
console.error("output: format_as_string|format_as_number|");
process.exit(0);
}
console.log(X.format(argv[0],argv[1]) + "|" + X.format(argv[0],+(argv[1])) + "|");

56
packages/ssf/types/index.d.ts vendored Normal file

@ -0,0 +1,56 @@
/* ssf.js (C) 2013-present SheetJS -- http://sheetjs.com */
// TypeScript Version: 2.2
/** Version string */
export const version: string;
/** Render value using format string or code */
export function format(fmt: string|number, val: any, opts?: any): string;
/** Load format string */
export function load(fmt: string, idx?: number): number;
/** Test if the format is a Date format */
export function is_date(fmt: string): boolean;
/** Format Table */
export interface SSF$Table {
[key: number]: string;
[key: string]: string;
}
/** Get format table */
export function get_table(): SSF$Table;
/** Set format table */
export function load_table(tbl: SSF$Table): void;
/** Parsed date */
export interface SSF$Date {
/** number of whole days since relevant epoch, 0 <= D */
D: number;
/** integral year portion, epoch_year <= y */
y: number;
/** integral month portion, 1 <= m <= 12 */
m: number;
/** integral day portion, subject to gregorian YMD constraints */
d: number;
/** integral day of week (0=Sunday .. 6=Saturday) 0 <= q <= 6 */
q: number;
/** number of seconds since midnight, 0 <= T < 86400 */
T: number;
/** integral number of hours since midnight, 0 <= H < 24 */
H: number;
/** integral number of minutes since the last hour, 0 <= M < 60 */
M: number;
/** integral number of seconds since the last minute, 0 <= S < 60 */
S: number;
/** sub-second part of time, 0 <= u < 1 */
u: number;
}
/** Parse numeric date code */
export function parse_date_code(v: number, opts?: any): SSF$Date;

@ -0,0 +1,16 @@
import { format, load, get_table, load_table, parse_date_code, is_date, SSF$Table, SSF$Date } from 'ssf';
const t1: string = format("General", 123.456);
const t2: string = format(0, 234.567);
const t3: string = format("@", "1234.567");
load('"This is "0.00', 70);
load('"This is "0');
const tbl: SSF$Table = get_table();
load_table(tbl);
const date: SSF$Date = parse_date_code(43150);
const sum: number = date.D + date.T + date.y + date.m + date.d + date.H + date.M + date.S + date.q + date.u;
const isdate: boolean = is_date("YYYY-MM-DD");

@ -0,0 +1,15 @@
{
"compilerOptions": {
"module": "commonjs",
"lib": [ "es5" ],
"noImplicitAny": true,
"noImplicitThis": true,
"strictNullChecks": false,
"baseUrl": ".",
"paths": { "ssf": ["."] },
"types": [],
"noEmit": true,
"strictFunctionTypes": true,
"forceConsistentCasingInFileNames": true
}
}

@ -0,0 +1,18 @@
{
"extends": "dtslint/dtslint.json",
"rules": {
"no-implicit-dependencies": false,
"whitespace": false,
"no-sparse-arrays": false,
"only-arrow-functions": false,
"no-consecutive-blank-lines": false,
"prefer-conditional-expression": false,
"one-variable-per-declaration": false,
"strict-export-declare-modifiers": false,
"no-redundant-jsdoc": false,
"no-any-union": false,
"no-unnecessary-generics": false,
"no-unnecessary-type-assertion": false,
"prefer-template": false
}
}