Repository: gentooboontoo/js-quantities Branch: master Commit: 7116174b9995 Files: 42 Total size: 571.5 KB Directory structure: gitextract_9tyqrl1_/ ├── .eslintrc ├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── LICENSE ├── Makefile ├── README.md ├── RELEASE ├── SpecRunner.html ├── bench/ │ ├── index.html │ └── main.js ├── bin/ │ ├── bench.rb │ ├── prepare-release.sh │ └── release.sh ├── build/ │ ├── quantities.js │ └── quantities.mjs ├── lib/ │ ├── JSLitmus.js │ ├── jasmine-3.4.0/ │ │ ├── boot.js │ │ ├── jasmine-html.js │ │ ├── jasmine.css │ │ └── jasmine.js │ └── require.js ├── package.json ├── spec/ │ ├── blns.json │ ├── quantitiesSpec.js │ └── support/ │ └── jasmine.json └── src/ ├── quantities/ │ ├── comparators.js │ ├── constructor.js │ ├── conversion.js │ ├── definitions.js │ ├── error.js │ ├── format.js │ ├── global-api.js │ ├── kind.js │ ├── nested-map.js │ ├── operators.js │ ├── parse.js │ ├── predicates.js │ ├── signature.js │ ├── temperature.js │ └── utils.js └── quantities.js ================================================ FILE CONTENTS ================================================ ================================================ FILE: .eslintrc ================================================ { "env": { "browser": true, "es6": true }, "globals": { "define": true, "module": true }, parserOptions: { "sourceType": "module" }, "rules": { "brace-style": [ "error", "stroustrup", { "allowSingleLine": true } ], "camelcase": [ "error", { "properties": "never" } ], "curly": [ "error", "all" ], "eqeqeq": "error", "eol-last": "error", "guard-for-in": "error", "indent": [ "error", 2, { "SwitchCase": 1 } ], "keyword-spacing": [ "error", {} ], "new-cap": 0, "no-implicit-coercion": [ "error", { "boolean": false, "string": true, "number": false } ], "no-bitwise": "error", "no-mixed-spaces-and-tabs": "error", "no-multiple-empty-lines": "error", "no-trailing-spaces": "error", "no-undef": "error", "no-unused-vars": "error", "no-with": "error", "quotes": [ "error", "double" ], "semi": [ "error", "always" ], "space-before-function-paren": [ "error", "never" ], "space-infix-ops": "error", "space-unary-ops": [ "error", { "nonwords": false, "words": true } ], "strict": [ "error", "function" ], "valid-jsdoc": "error", "wrap-iife": "error" } } ================================================ FILE: .gitignore ================================================ .envrc shell.nix src/.committed-quantities.js *.swp node_modules/ tags ================================================ FILE: .travis.yml ================================================ language: node_js node_js: - "node" - "lts/*" script: make test ================================================ FILE: CHANGELOG.md ================================================ Unreleased ---------- 1.8.0 / 2023-08-21 ------------------ ### Added * Add "Joules" alias * Add some parts-per notation units * Add metric ton symbol t * Add electronvolt * Add arcminute and arcsecond ### Fixed * Fix wrong quantity name for molar_concentration units 1.7.6 / 2020-12-06 ------------------ ### Added * Unit of acceleration `Gal` ### Fixed * Missing aliases for barrel-related units (#101) 1.7.5 / 2020-04-05 ------------------ * Update development dependencies * Use ESLint as linter 1.7.4 / 2019-06-26 ------------------ * Add Imperial Gallons, and Barrels (US Beer, Imperial Beer, Oil) * Add support for imperial version of fluid ounces and pints 1.7.3 / 2018-12-15 ------------------ * Fix some inconsistent resulting units when multiplying or dividing quantities (#94) 1.7.2 / 2018-03-31 ------------------ * Remove `module` from package definition (Fix #91) 1.7.1 / 2018-03-25 ------------------ * Add missing unit aliases 1.7.0 / 2017-08-23 ------------------ * Fix JS allocation failure for unrealistically large exponents * Add volt-ampere, volt-ampere-reactive and data mile definitions * Add redshift alias 1.6.6 / 2017-02-08 ------------------ * Report incompatible units in error message 1.6.5 / 2017-01-20 ------------------ * Fix main entrypoint in bower.json 1.6.4 / 2017-01-02 ------------------ * Fix infinite regex check 1.6.3 / 2016-09-22 ------------------ * Add missing kinds * Fix conversion from percentage to unitless quantity * Fix capacitance definition * Exclude `farad` from base units * Rename `mass concentration` to `density` 1.6.2 / 2016-04-13 ------------------ * Accept blank string as initialization value 1.6.1 / 2016-03-27 ------------------ * Fix definition of square foot * Add tablespoon `tbsp` alias * Add `Qty.version` property 1.6.0 / 2015-12-26 ------------------ * Add `Qty.getUnits` to return available units of a well-known kind * Add `Qty.getAliases` to return every alias of a specific unit * Allow to initialize a quantity with scalar and units as separate arguments * Rename `memory` kind to `information` * Add `information_rate` kind * Accept Wh and Ah as units * Fix hang when using water height pressure units * Add plural for fluid ounce * Fix `amu` and `dalton` definitions * Add `tb` as tablespoon alias * Add plural for `information` units * Minor fixes or improvements 1.5.0 / 2014-12-08 ------------------ * Add `Qty.getKinds` returning known kinds of units * Add µ symbol as micro prefix alias * Add Ω symbol as ohm unit alias * Minor internal improvements and fixes 1.4.2 / 2014-09-09 ------------------ * Fix plural for radian and add missing ones for time units * Add "gon" international standard symbol as gradian alias * Fix units of force * Allow whitespaces between sign and scalar and do not accept sign without scalar 1.4.1 / 2014-05-14 ------------------ * Use a little more robust to test string type and factorize it 1.4.0 / 2014-04-10 ------------------ * Directly convert array of values when using swiftConverter * Add support for bushel units 1.3.0 / 2014-03-05 ------------------ * Add Qty#format and accept custom formatters * Allow to call Qty() without new to create Qty instances (Qty could be used both as a constructor or as a factory) * Qty#toString only supports to be passed output units as single parameter. Former parameters are now deprecated but still supported to not introduce a breaking change * Add mc as alternate definition for prefix "micro" * Throw error with mmm as unit * Add rounding optimization 1.2.0 / 2013-12-17 ------------------ * Throw QtyError instead of plain string * Cache conversion results from Qty#to instead of Qty#toString * Fix point and pica unit definitions * Fix error when initializing a quantity with an empty string 1.1.2 / 2013-11-04 ------------------ * Fix rounding issue when converting 1 cm3 to mm3 * Do some code cleaning (it should not break public API) 1.1.1 / 2013-10-01 ------------------ * Fix Qty#toPrec() returning wrong result with some precision 1.1.0 / 2013-09-20 ------------------ * Add array converting method * Major speedup by means of some optimizations and refactoring 1.0.0 / 2013-07-30 ------------------ * First stable version ================================================ FILE: LICENSE ================================================ The MIT License (MIT) Copyright © 2006-2007 Kevin C. Olbrich Copyright © 2010-2016 LIM SAS (http://lim.eu) - Julien Sanchez Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: Makefile ================================================ SPEC_DIR := spec SPECFILES := $(shell find $(SPEC_DIR) -iname '*.js') SOURCE_DIR := src SOURCES := $(shell find $(SOURCE_DIR) -iname '*.js') LINTEDFILES := $(SOURCES) $(SPECFILES) BUILD_DIR := build ESM_FILE := $(BUILD_DIR)/quantities.mjs UMD_FILE := $(BUILD_DIR)/quantities.js DIST_FILES := $(ESM_FILE) $(UMD_FILE) BANNER := $(shell cat LICENSE) ROLLUP := npx rollup JASMINE := npx jasmine ESLINT := npx eslint build: $(DIST_FILES) $(UMD_FILE): $(SOURCES) $(ROLLUP) --file=$(UMD_FILE) \ --format=umd \ --name=Qty \ --banner="`echo '/*'; cat LICENSE; echo '*/'`" \ src/quantities.js $(ESM_FILE): $(SOURCES) $(ROLLUP) --file=$(ESM_FILE) \ --format=es \ --banner="`echo '/*'; cat LICENSE; echo '*/'`" \ src/quantities.js test: lint build $(JASMINE) lint: $(LINTEDFILES) $(ESLINT) $(LINTEDFILES) bench: bin/bench.rb clean: rm -f $(DIST_FILES) .PHONY: bench build clean lint test ================================================ FILE: README.md ================================================ # JS-quantities [](https://travis-ci.org/gentooboontoo/js-quantities) JS-quantities is originally a JavaScript port of Kevin Olbrich's library Ruby Units (http://github.com/olbrich/ruby-units). The library aims to simplify the handling of units for scientific calculations involving quantities. JS-quantities is built as UMD and ES modules and can be used with Node.js and browsers. It has **no dependencies**. ## Installation Install with `npm install js-quantities` or download latest release v1.8.0 as: * [UMD module](https://raw.github.com/gentooboontoo/js-quantities/v1.8.0/build/quantities.js) * [ES module](https://raw.github.com/gentooboontoo/js-quantities/v1.8.0/build/quantities.mjs) ## Usage ### Node.js ```javascript // As CommonJS module const Qty = require('js-quantities'); // As ES module import Qty from 'js-quantities'; ``` ### Browsers * UMD module could be included as is: ```html ``` In this case, it will define a global variable `Qty`. * With an AMD loader like [Require.JS](http://requirejs.org/): ```javascript define(['quantities'], function(Qty) { ... }); ``` * As ES module: ```html ``` ## Synopsis ### Creation Instances of quantities are made by means of `Qty()` method. `Qty` can both be used as a constructor (with new) or as a factory (without new): ```javascript qty = new Qty('23 ft'); // constructor qty = Qty('23 ft'); // factory ``` `Qty` constructor accepts strings, numbers and `Qty` instances as initializing values. If scalars and their respective units are available programmatically, the two argument signature may be useful: ```javascript qty = new Qty(124, 'cm'); // => 1.24 meter qty = Qty(124, 'cm'); // => 1.24 meter ``` For the sake of simplicity, one will use the factory way below but using `new Qty()` is equivalent. ```javascript qty = Qty('1m'); // => 1 meter qty = Qty('m'); // => 1 meter (scalar defaults to 1) qty = Qty('1 N*m'); qty = Qty('1 N m'); // * is optional qty = Qty('1 m/s'); qty = Qty('1 m^2/s^2'); qty = Qty('1 m^2 s^-2'); // negative powers qty = Qty('1 m2 s-2'); // ^ is optional qty = Qty('1 m^2 kg^2 J^2/s^2 A'); qty = Qty('1.5'); // unitless quantity qty = Qty(1.5); // number as initializing value qty = Qty('1 attoparsec/microfortnight'); qtyCopy = Qty(qty); // quantity could be copied when used as // initializing value ``` `Qty.parse` utility method is also provided to parse and create quantities from strings. Unlike the constructor, it will return `null` instead of throwing an error when parsing an invalid quantity. ```javascript Qty.parse('1 m'); // => 1 meter Qty.parse('foo') // => null ``` ### Available well-known kinds ```javascript Qty.getKinds(); // => Array of names of every well-known kind of units ``` ### Available units of a particular kind ```javascript Qty.getUnits('currency'); // => [ 'dollar', 'cents' ] // Or all alphabetically sorted Qty.getUnits(); // => [ 'acre','Ah','ampere','AMU','angstrom'] ``` ### Alternative names of a unit ```javascript Qty.getAliases('m'); // => [ 'm', 'meter', 'meters', 'metre', 'metres' ] ``` ### Quantity compatibility, kind and various queries ```javascript qty1.isCompatible(qty2); // => true or false qty.kind(); // => 'length', 'area', etc... qty.isUnitless(); // => true or false qty.isBase(); // => true if quantity is represented with base units ``` ### Conversion ```javascript qty.toBase(); // converts to SI units (10 cm => 0.1 m) (new instance) qty.toFloat(); // returns scalar of unitless quantity // (otherwise throws error) qty.to('m'); // converts quantity to meter if compatible // or throws an error (new instance) qty1.to(qty2); // converts quantity to same unit of qty2 if compatible // or throws an error (new instance) qty.inverse(); // converts quantity to its inverse // ('100 m/s' => '.01 s/m') // Inverses can be used, but there is no special checking to // rename the units Qty('10ohm').inverse() // '.1/ohm' // (not '.1S', although they are equivalent) // however, the 'to' command will convert between inverses also Qty('10ohm').to('S') // '.1S' ``` `Qty.swiftConverter()` is a fast way to efficiently convert large array of Number values. It configures a function accepting a value or an array of Number values to convert. ```javascript var convert = Qty.swiftConverter('m/h', 'ft/s'); // Configures converter // Converting single value var converted = convert(2500); // => 2.278.. // Converting large array of values var convertedSerie = convert([2500, 5000, ...]); // => [2.278.., 4.556.., ...] ``` The main drawback of this conversion method is that it does not take care of rounding issues. ### Comparison ```javascript qty1.eq(qty2); // => true if both quantities are equal (1m == 100cm => true) qty1.same(qty2); // => true if both quantities are same (1m == 100cm => false) qty1.lt(qty2); // => true if qty1 is stricty less than qty2 qty1.lte(qty2); // => true if qty1 is less than or equal to qty2 qty1.gt(qty2); // => true if qty1 is stricty greater than qty2 qty1.gte(qty2); // => true if qty1 is greater than or equal to qty2 qty1.compareTo(qty2); // => -1 if qty1 < qty2, // => 0 if qty1 == qty2, // => 1 if qty1 > qty2 ``` ### Operators * add(other): Add. other can be string or quantity. other should be unit compatible. * sub(other): Substract. other can be string or quantity. other should be unit compatible. * mul(other): Multiply. other can be string, number or quantity. * div(other): Divide. other can be string, number or quantity. ### Rounding `Qty#toPrec(precision)` : returns the nearest multiple of quantity passed as precision. ```javascript var qty = Qty('5.17 ft'); qty.toPrec('ft'); // => 5 ft qty.toPrec('0.5 ft'); // => 5 ft qty.toPrec('0.25 ft'); // => 5.25 ft qty.toPrec('0.1 ft'); // => 5.2 ft qty.toPrec('0.05 ft'); // => 5.15 ft qty.toPrec('0.01 ft'); // => 5.17 ft qty.toPrec('0.00001 ft'); // => 5.17 ft qty.toPrec('2 ft'); // => 6 ft qty.toPrec('2'); // => 6 ft var qty = Qty('6.3782 m'); qty.toPrec('dm'); // => 6.4 m qty.toPrec('cm'); // => 6.38 m qty.toPrec('mm'); // => 6.378 m qty.toPrec('5 cm'); // => 6.4 m qty.toPrec('10 m'); // => 10 m qty.toPrec(0.1); // => 6.3 m var qty = Qty('1.146 MPa'); qty.toPrec('0.1 bar'); // => 1.15 MPa ``` ### Formatting quantities `Qty#toString` returns a string using the canonical form of the quantity (that is it could be seamlessly reparsed by `Qty`). ```javascript var qty = Qty('1.146 MPa'); qty.toString(); // => '1.146 MPa' ``` As a shorthand, units could be passed to `Qty#toString` and is equivalent to successively call `Qty#to` then `Qty#toString`. ```javascript var qty = Qty('1.146 MPa'); qty.toString('bar'); // => '11.46 bar' qty.to('bar').toString(); // => '11.46 bar' ``` `Qty#toString` could also be used with any method from `Qty` to make some sort of formatting. For instance, one could use `Qty#toPrec` to fix the maximum number of decimals: ```javascript var qty = Qty('1.146 MPa'); qty.toPrec(0.1).toString(); // => '1.1 MPa' qty.to('bar').toPrec(0.1).toString(); // => '11.5 bar' ``` For advanced formatting needs as localization, specific rounding or any other custom customization, quantities can be transformed into strings through `Qty#format` according to optional target units and formatter. If target units are specified, the quantity is converted into them before formatting. Such a string is not intended to be reparsed to construct a new instance of `Qty` (unlike output of `Qty#toString`). If no formatter is specified, quantities are formatted according to default js-quantities' formatter and is equivalent to `Qty#toString`. ```javascript var qty = Qty('1.1234 m'); qty.format(); // same units, default formatter => '1.234 m' qty.format('cm'); // converted to 'cm', default formatter => '123.45 cm' ``` `Qty#format` could delegates formatting to a custom formatter if required. A formatter is a callback function accepting scalar and units as parameters and returning a formatted string representing the quantity. ```javascript var configurableRoundingFormatter = function(maxDecimals) { return function(scalar, units) { var pow = Math.pow(10, maxDecimals); var rounded = Math.round(scalar * pow) / pow; return rounded + ' ' + units; }; }; var qty = Qty('1.1234 m'); // same units, custom formatter => '1.12 m' qty.format(configurableRoundingFormatter(2)); // convert to 'cm', custom formatter => '123.4 cm' qty.format('cm', configurableRoundingFormatter(1)); ``` Custom formatter can be configured globally by setting `Qty.formatter`. ```javascript Qty.formatter = configurableRoundingFormatter(2); var qty = Qty('1.1234 m'); qty.format(); // same units, current default formatter => '1.12 m' ``` ### Temperatures Like ruby-units, JS-quantities makes a distinction between a temperature (which technically is a property) and degrees of temperature (which temperatures are measured in). Temperature units (i.e., 'tempK') can be converted back and forth, and will take into account the differences in the zero points of the various scales. Differential temperature (e.g., '100 degC') units behave like most other units. ```javascript Qty('37 tempC').to('tempF') // => 98.6 tempF ``` JS-quantities will throw an error if you attempt to create a temperature unit that would fall below absolute zero. Unit math on temperatures is fairly limited. ```javascript Qty('100 tempC').add('10 degC') // 110 tempC Qty('100 tempC').sub('10 degC') // 90 tempC Qty('100 tempC').add('50 tempC') // throws error Qty('100 tempC').sub('50 tempC') // 50 degC Qty('50 tempC').sub('100 tempC') // -50 degC Qty('100 tempC').mul(scalar) // 100*scalar tempC Qty('100 tempC').div(scalar) // 100/scalar tempC Qty('100 tempC').mul(qty) // throws error Qty('100 tempC').div(qty) // throws error Qty('100 tempC*unit') // throws error Qty('100 tempC/unit') // throws error Qty('100 unit/tempC') // throws error Qty('100 tempC').inverse() // throws error ``` ```javascript Qty('100 tempC').to('degC') // => 100 degC ``` This conversion references the 0 point on the scale of the temperature unit ```javascript Qty('100 degC').to('tempC') // => -173.15 tempC ``` These conversions are always interpreted as being relative to absolute zero. Conversions are probably better done like this... ```javascript Qty('0 tempC').add('100 degC') // => 100 tempC ``` ### Errors Every error thrown by JS-quantities is an instance of `Qty.Error`. ```javascript try { // code triggering an error inside JS-quantities } catch(e) { if(e instanceof Qty.Error) { // ... } else { // ... } } ``` ## Tests Tests are implemented with Jasmine (https://github.com/pivotal/jasmine). You could use both HTML and jasmine-node runners. To execute specs through HTML runner, just open `SpecRunner.html` file in a browser to execute them. To execute specs through `jasmine-node`, launch: make test ### Performance regression test There is a small benchmarking HTML page to spot performance regression between currently checked-out quantities.js and any committed version. Just execute: make bench then open http://0.0.0.0:3000/bench Checked-out version is benchmarked against HEAD by default but it could be changed by passing any commit SHA on the command line. Port (default 3000) is also configurable. make bench COMMIT=e0c7fc468 PORT=5000 ## TypeScript type declarations A TypeScript declaration file is published on [DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/js-quantities). It could be installed with `npm install @types/js-quantities`. ## Contribute Feedback and contributions are welcomed. Pull requests must pass tests and linting. Please make sure that `make test` and `make lint` return no errors before submitting. ================================================ FILE: RELEASE ================================================ 1.8.0 ================================================ FILE: SpecRunner.html ================================================