├── .eslintrc.json ├── .github ├── eslint.json └── workflows │ └── node.js.yml ├── .gitignore ├── LICENSE ├── README.md ├── locale ├── ar-001.json ├── ar-AE.json ├── ar-BH.json ├── ar-DJ.json ├── ar-DZ.json ├── ar-EG.json ├── ar-EH.json ├── ar-ER.json ├── ar-IL.json ├── ar-IQ.json ├── ar-JO.json ├── ar-KM.json ├── ar-KW.json ├── ar-LB.json ├── ar-LY.json ├── ar-MA.json ├── ar-MR.json ├── ar-OM.json ├── ar-PS.json ├── ar-QA.json ├── ar-SA.json ├── ar-SD.json ├── ar-SO.json ├── ar-SS.json ├── ar-SY.json ├── ar-TD.json ├── ar-TN.json ├── ar-YE.json ├── ca-ES.json ├── cs-CZ.json ├── da-DK.json ├── de-CH.json ├── de-DE.json ├── en-CA.json ├── en-GB.json ├── en-IE.json ├── en-IN.json ├── en-US.json ├── es-BO.json ├── es-ES.json ├── es-MX.json ├── fi-FI.json ├── fr-CA.json ├── fr-FR.json ├── he-IL.json ├── hu-HU.json ├── it-IT.json ├── ja-JP.json ├── ko-KR.json ├── mk-MK.json ├── nl-NL.json ├── pl-PL.json ├── pt-BR.json ├── pt-PT.json ├── ru-RU.json ├── sl-SI.json ├── sv-SE.json ├── uk-UA.json └── zh-CN.json ├── package.json ├── rollup.config.js ├── src ├── defaultLocale.js ├── exponent.js ├── formatDecimal.js ├── formatGroup.js ├── formatNumerals.js ├── formatPrefixAuto.js ├── formatRounded.js ├── formatSpecifier.js ├── formatTrim.js ├── formatTypes.js ├── identity.js ├── index.js ├── locale.js ├── precisionFixed.js ├── precisionPrefix.js └── precisionRound.js ├── test ├── .eslintrc.json ├── arabicLocale-test.js ├── defaultLocale-test.js ├── format-test.js ├── format-trim-test.js ├── format-type-%-test.js ├── format-type-b-test.js ├── format-type-c-test.js ├── format-type-d-test.js ├── format-type-e-test.js ├── format-type-f-test.js ├── format-type-g-test.js ├── format-type-n-test.js ├── format-type-none-test.js ├── format-type-o-test.js ├── format-type-p-test.js ├── format-type-r-test.js ├── format-type-s-test.js ├── format-type-x-test.js ├── formatPrefix-test.js ├── formatSpecifier-test.js ├── locale-test.js ├── precisionFixed-test.js ├── precisionPrefix-test.js └── precisionRound-test.js └── yarn.lock /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "eslint:recommended", 3 | "parserOptions": { 4 | "sourceType": "module", 5 | "ecmaVersion": 8 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /.github/eslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "problemMatcher": [ 3 | { 4 | "owner": "eslint-compact", 5 | "pattern": [ 6 | { 7 | "regexp": "^(.+):\\sline\\s(\\d+),\\scol\\s(\\d+),\\s(Error|Warning|Info)\\s-\\s(.+)\\s\\((.+)\\)$", 8 | "file": 1, 9 | "line": 2, 10 | "column": 3, 11 | "severity": 4, 12 | "message": 5, 13 | "code": 6 14 | } 15 | ] 16 | } 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /.github/workflows/node.js.yml: -------------------------------------------------------------------------------- 1 | # https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions 2 | 3 | name: Node.js CI 4 | 5 | on: 6 | push: 7 | branches: [ main ] 8 | pull_request: 9 | branches: [ main ] 10 | 11 | jobs: 12 | build: 13 | 14 | runs-on: ubuntu-latest 15 | 16 | strategy: 17 | matrix: 18 | node-version: [14.x] 19 | 20 | steps: 21 | - uses: actions/checkout@v2 22 | - name: Use Node.js ${{ matrix.node-version }} 23 | uses: actions/setup-node@v1 24 | with: 25 | node-version: ${{ matrix.node-version }} 26 | - run: yarn --frozen-lockfile 27 | - run: | 28 | echo ::add-matcher::.github/eslint.json 29 | yarn run eslint src test --format=compact 30 | - run: yarn test 31 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.sublime-workspace 2 | .DS_Store 3 | dist/ 4 | node_modules 5 | npm-debug.log 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2010-2021 Mike Bostock 2 | 3 | Permission to use, copy, modify, and/or distribute this software for any purpose 4 | with or without fee is hereby granted, provided that the above copyright notice 5 | and this permission notice appear in all copies. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 8 | REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 9 | FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 10 | INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS 11 | OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 12 | TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF 13 | THIS SOFTWARE. 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # d3-format 2 | 3 | 4 | 5 | This module formats numbers for human consumption, with a consistent output allowing comparison. Grouped digits, currencies, scientific notation… 6 | 7 | ## Resources 8 | 9 | - [Documentation](https://d3js.org/d3-format) 10 | - [Examples](https://observablehq.com/collection/@d3/d3-format) 11 | - [Releases](https://github.com/d3/d3-format/releases) 12 | - [Getting help](https://d3js.org/community) 13 | -------------------------------------------------------------------------------- /locale/ar-001.json: -------------------------------------------------------------------------------- 1 | { 2 | "decimal": "\u066b", 3 | "thousands": "\u066c", 4 | "grouping": [3], 5 | "currency": ["", ""], 6 | "numerals" : ["\u0660", "\u0661", "\u0662", "\u0663", "\u0664", "\u0665", "\u0666", "\u0667", "\u0668", "\u0669"] 7 | } 8 | -------------------------------------------------------------------------------- /locale/ar-AE.json: -------------------------------------------------------------------------------- 1 | { 2 | "decimal": "\u066b", 3 | "thousands": "\u066c", 4 | "grouping": [3], 5 | "currency": ["", " \u062f\u002e\u0625\u002e"], 6 | "numerals" : ["\u0660", "\u0661", "\u0662", "\u0663", "\u0664", "\u0665", "\u0666", "\u0667", "\u0668", "\u0669"] 7 | } 8 | -------------------------------------------------------------------------------- /locale/ar-BH.json: -------------------------------------------------------------------------------- 1 | { 2 | "decimal": "\u066b", 3 | "thousands": "\u066c", 4 | "grouping": [3], 5 | "currency": ["", " \u062f\u002e\u0628\u002e"], 6 | "numerals" : ["\u0660", "\u0661", "\u0662", "\u0663", "\u0664", "\u0665", "\u0666", "\u0667", "\u0668", "\u0669"] 7 | } 8 | -------------------------------------------------------------------------------- /locale/ar-DJ.json: -------------------------------------------------------------------------------- 1 | { 2 | "decimal": "\u066b", 3 | "thousands": "\u066c", 4 | "grouping": [3], 5 | "currency": ["\u200f\u0046\u0064\u006a ", ""], 6 | "numerals" : ["\u0660", "\u0661", "\u0662", "\u0663", "\u0664", "\u0665", "\u0666", "\u0667", "\u0668", "\u0669"] 7 | } 8 | -------------------------------------------------------------------------------- /locale/ar-DZ.json: -------------------------------------------------------------------------------- 1 | { 2 | "decimal": "\u002c", 3 | "thousands": "\u002e", 4 | "grouping": [3], 5 | "currency": ["\u062f\u002e\u062c\u002e ", ""] 6 | } 7 | -------------------------------------------------------------------------------- /locale/ar-EG.json: -------------------------------------------------------------------------------- 1 | { 2 | "decimal": "\u066b", 3 | "thousands": "\u066c", 4 | "grouping": [3], 5 | "currency": ["", " \u062c\u002e\u0645\u002e"], 6 | "numerals" : ["\u0660", "\u0661", "\u0662", "\u0663", "\u0664", "\u0665", "\u0666", "\u0667", "\u0668", "\u0669"] 7 | } 8 | -------------------------------------------------------------------------------- /locale/ar-EH.json: -------------------------------------------------------------------------------- 1 | { 2 | "decimal": "\u002e", 3 | "thousands": "\u002c", 4 | "grouping": [3], 5 | "currency": ["\u062f\u002e\u0645\u002e ", ""] 6 | } 7 | -------------------------------------------------------------------------------- /locale/ar-ER.json: -------------------------------------------------------------------------------- 1 | { 2 | "decimal": "\u066b", 3 | "thousands": "\u066c", 4 | "grouping": [3], 5 | "currency": ["\u004e\u0066\u006b ", ""], 6 | "numerals" : ["\u0660", "\u0661", "\u0662", "\u0663", "\u0664", "\u0665", "\u0666", "\u0667", "\u0668", "\u0669"] 7 | } 8 | -------------------------------------------------------------------------------- /locale/ar-IL.json: -------------------------------------------------------------------------------- 1 | { 2 | "decimal": "\u066b", 3 | "thousands": "\u066c", 4 | "grouping": [3], 5 | "currency": ["\u20aa ", ""], 6 | "numerals" : ["\u0660", "\u0661", "\u0662", "\u0663", "\u0664", "\u0665", "\u0666", "\u0667", "\u0668", "\u0669"] 7 | } 8 | -------------------------------------------------------------------------------- /locale/ar-IQ.json: -------------------------------------------------------------------------------- 1 | { 2 | "decimal": "\u066b", 3 | "thousands": "\u066c", 4 | "grouping": [3], 5 | "currency": ["", " \u062f\u002e\u0639\u002e"], 6 | "numerals" : ["\u0660", "\u0661", "\u0662", "\u0663", "\u0664", "\u0665", "\u0666", "\u0667", "\u0668", "\u0669"] 7 | } 8 | -------------------------------------------------------------------------------- /locale/ar-JO.json: -------------------------------------------------------------------------------- 1 | { 2 | "decimal": "\u066b", 3 | "thousands": "\u066c", 4 | "grouping": [3], 5 | "currency": ["", " \u062f\u002e\u0623\u002e"], 6 | "numerals" : ["\u0660", "\u0661", "\u0662", "\u0663", "\u0664", "\u0665", "\u0666", "\u0667", "\u0668", "\u0669"] 7 | } 8 | -------------------------------------------------------------------------------- /locale/ar-KM.json: -------------------------------------------------------------------------------- 1 | { 2 | "decimal": "\u066b", 3 | "thousands": "\u066c", 4 | "grouping": [3], 5 | "currency": ["", " \u0641\u002e\u062c\u002e\u0642\u002e"], 6 | "numerals" : ["\u0660", "\u0661", "\u0662", "\u0663", "\u0664", "\u0665", "\u0666", "\u0667", "\u0668", "\u0669"] 7 | } 8 | -------------------------------------------------------------------------------- /locale/ar-KW.json: -------------------------------------------------------------------------------- 1 | { 2 | "decimal": "\u066b", 3 | "thousands": "\u066c", 4 | "grouping": [3], 5 | "currency": ["", " \u062f\u002e\u0643\u002e"], 6 | "numerals" : ["\u0660", "\u0661", "\u0662", "\u0663", "\u0664", "\u0665", "\u0666", "\u0667", "\u0668", "\u0669"] 7 | } 8 | -------------------------------------------------------------------------------- /locale/ar-LB.json: -------------------------------------------------------------------------------- 1 | { 2 | "decimal": "\u066b", 3 | "thousands": "\u066c", 4 | "grouping": [3], 5 | "currency": ["", " \u0644\u002e\u0644\u002e"], 6 | "numerals" : ["\u0660", "\u0661", "\u0662", "\u0663", "\u0664", "\u0665", "\u0666", "\u0667", "\u0668", "\u0669"] 7 | } 8 | -------------------------------------------------------------------------------- /locale/ar-LY.json: -------------------------------------------------------------------------------- 1 | { 2 | "decimal": "\u002c", 3 | "thousands": "\u002e", 4 | "grouping": [3], 5 | "currency": ["\u062f\u002e\u0644\u002e ", ""] 6 | } 7 | -------------------------------------------------------------------------------- /locale/ar-MA.json: -------------------------------------------------------------------------------- 1 | { 2 | "decimal": "\u002c", 3 | "thousands": "\u002e", 4 | "grouping": [3], 5 | "currency": ["\u062f\u002e\u0645\u002e ", ""] 6 | } 7 | -------------------------------------------------------------------------------- /locale/ar-MR.json: -------------------------------------------------------------------------------- 1 | { 2 | "decimal": "\u066b", 3 | "thousands": "\u066c", 4 | "grouping": [3], 5 | "currency": ["", " \u0623\u002e\u0645\u002e"], 6 | "numerals" : ["\u0660", "\u0661", "\u0662", "\u0663", "\u0664", "\u0665", "\u0666", "\u0667", "\u0668", "\u0669"] 7 | } 8 | -------------------------------------------------------------------------------- /locale/ar-OM.json: -------------------------------------------------------------------------------- 1 | { 2 | "decimal": "\u066b", 3 | "thousands": "\u066c", 4 | "grouping": [3], 5 | "currency": ["", " \u0631\u002e\u0639\u002e"], 6 | "numerals" : ["\u0660", "\u0661", "\u0662", "\u0663", "\u0664", "\u0665", "\u0666", "\u0667", "\u0668", "\u0669"] 7 | } 8 | -------------------------------------------------------------------------------- /locale/ar-PS.json: -------------------------------------------------------------------------------- 1 | { 2 | "decimal": "\u066b", 3 | "thousands": "\u066c", 4 | "grouping": [3], 5 | "currency": ["\u20aa ", ""], 6 | "numerals" : ["\u0660", "\u0661", "\u0662", "\u0663", "\u0664", "\u0665", "\u0666", "\u0667", "\u0668", "\u0669"] 7 | } 8 | -------------------------------------------------------------------------------- /locale/ar-QA.json: -------------------------------------------------------------------------------- 1 | { 2 | "decimal": "\u066b", 3 | "thousands": "\u066c", 4 | "grouping": [3], 5 | "currency": ["", " \u0631\u002e\u0642\u002e"], 6 | "numerals" : ["\u0660", "\u0661", "\u0662", "\u0663", "\u0664", "\u0665", "\u0666", "\u0667", "\u0668", "\u0669"] 7 | } 8 | -------------------------------------------------------------------------------- /locale/ar-SA.json: -------------------------------------------------------------------------------- 1 | { 2 | "decimal": "\u066b", 3 | "thousands": "\u066c", 4 | "grouping": [3], 5 | "currency": ["", " \u0631\u002e\u0633\u002e"], 6 | "numerals" : ["\u0660", "\u0661", "\u0662", "\u0663", "\u0664", "\u0665", "\u0666", "\u0667", "\u0668", "\u0669"] 7 | } 8 | -------------------------------------------------------------------------------- /locale/ar-SD.json: -------------------------------------------------------------------------------- 1 | { 2 | "decimal": "\u066b", 3 | "thousands": "\u066c", 4 | "grouping": [3], 5 | "currency": ["", " \u062c\u002e\u0633\u002e"], 6 | "numerals" : ["\u0660", "\u0661", "\u0662", "\u0663", "\u0664", "\u0665", "\u0666", "\u0667", "\u0668", "\u0669"] 7 | } 8 | -------------------------------------------------------------------------------- /locale/ar-SO.json: -------------------------------------------------------------------------------- 1 | { 2 | "decimal": "\u066b", 3 | "thousands": "\u066c", 4 | "grouping": [3], 5 | "currency": ["\u200f\u0053 ", ""], 6 | "numerals" : ["\u0660", "\u0661", "\u0662", "\u0663", "\u0664", "\u0665", "\u0666", "\u0667", "\u0668", "\u0669"] 7 | } 8 | -------------------------------------------------------------------------------- /locale/ar-SS.json: -------------------------------------------------------------------------------- 1 | { 2 | "decimal": "\u066b", 3 | "thousands": "\u066c", 4 | "grouping": [3], 5 | "currency": ["\u00a3 ", ""], 6 | "numerals" : ["\u0660", "\u0661", "\u0662", "\u0663", "\u0664", "\u0665", "\u0666", "\u0667", "\u0668", "\u0669"] 7 | } 8 | -------------------------------------------------------------------------------- /locale/ar-SY.json: -------------------------------------------------------------------------------- 1 | { 2 | "decimal": "\u066b", 3 | "thousands": "\u066c", 4 | "grouping": [3], 5 | "currency": ["", " \u0644\u002e\u0633\u002e"], 6 | "numerals" : ["\u0660", "\u0661", "\u0662", "\u0663", "\u0664", "\u0665", "\u0666", "\u0667", "\u0668", "\u0669"] 7 | } 8 | -------------------------------------------------------------------------------- /locale/ar-TD.json: -------------------------------------------------------------------------------- 1 | { 2 | "decimal": "\u066b", 3 | "thousands": "\u066c", 4 | "grouping": [3], 5 | "currency": ["\u200f\u0046\u0043\u0046\u0041 ", ""], 6 | "numerals" : ["\u0660", "\u0661", "\u0662", "\u0663", "\u0664", "\u0665", "\u0666", "\u0667", "\u0668", "\u0669"] 7 | } 8 | -------------------------------------------------------------------------------- /locale/ar-TN.json: -------------------------------------------------------------------------------- 1 | { 2 | "decimal": "\u002c", 3 | "thousands": "\u002e", 4 | "grouping": [3], 5 | "currency": ["\u062f\u002e\u062a\u002e ", ""] 6 | } 7 | -------------------------------------------------------------------------------- /locale/ar-YE.json: -------------------------------------------------------------------------------- 1 | { 2 | "decimal": "\u066b", 3 | "thousands": "\u066c", 4 | "grouping": [3], 5 | "currency": ["", " \u0631\u002e\u0649\u002e"], 6 | "numerals" : ["\u0660", "\u0661", "\u0662", "\u0663", "\u0664", "\u0665", "\u0666", "\u0667", "\u0668", "\u0669"] 7 | } 8 | -------------------------------------------------------------------------------- /locale/ca-ES.json: -------------------------------------------------------------------------------- 1 | { 2 | "decimal": ",", 3 | "thousands": ".", 4 | "grouping": [3], 5 | "currency": ["", "\u00a0€"] 6 | } 7 | -------------------------------------------------------------------------------- /locale/cs-CZ.json: -------------------------------------------------------------------------------- 1 | { 2 | "decimal": ",", 3 | "thousands": "\u00a0", 4 | "grouping": [3], 5 | "currency": ["", "\u00a0Kč"] 6 | } 7 | -------------------------------------------------------------------------------- /locale/da-DK.json: -------------------------------------------------------------------------------- 1 | { 2 | "decimal": ",", 3 | "thousands": ".", 4 | "grouping": [3], 5 | "currency": ["", " kr"] 6 | } 7 | -------------------------------------------------------------------------------- /locale/de-CH.json: -------------------------------------------------------------------------------- 1 | { 2 | "decimal": ",", 3 | "thousands": "'", 4 | "grouping": [3], 5 | "currency": ["", "\u00a0CHF"] 6 | } 7 | -------------------------------------------------------------------------------- /locale/de-DE.json: -------------------------------------------------------------------------------- 1 | { 2 | "decimal": ",", 3 | "thousands": ".", 4 | "grouping": [3], 5 | "currency": ["", "\u00a0€"] 6 | } 7 | -------------------------------------------------------------------------------- /locale/en-CA.json: -------------------------------------------------------------------------------- 1 | { 2 | "decimal": ".", 3 | "thousands": ",", 4 | "grouping": [3], 5 | "currency": ["$", ""] 6 | } 7 | -------------------------------------------------------------------------------- /locale/en-GB.json: -------------------------------------------------------------------------------- 1 | { 2 | "decimal": ".", 3 | "thousands": ",", 4 | "grouping": [3], 5 | "currency": ["£", ""] 6 | } 7 | -------------------------------------------------------------------------------- /locale/en-IE.json: -------------------------------------------------------------------------------- 1 | { 2 | "decimal": ".", 3 | "thousands": ",", 4 | "grouping": [3], 5 | "currency": ["€", ""] 6 | } 7 | -------------------------------------------------------------------------------- /locale/en-IN.json: -------------------------------------------------------------------------------- 1 | { 2 | "decimal": ".", 3 | "thousands": ",", 4 | "grouping": [3, 2, 2, 2, 2, 2, 2, 2, 2, 2], 5 | "currency": ["₹", ""] 6 | } 7 | -------------------------------------------------------------------------------- /locale/en-US.json: -------------------------------------------------------------------------------- 1 | { 2 | "decimal": ".", 3 | "thousands": ",", 4 | "grouping": [3], 5 | "currency": ["$", ""] 6 | } 7 | -------------------------------------------------------------------------------- /locale/es-BO.json: -------------------------------------------------------------------------------- 1 | { 2 | "decimal": ",", 3 | "thousands": ".", 4 | "grouping": [3], 5 | "currency": ["Bs\u00a0", ""], 6 | "percent": "\u202f%" 7 | } 8 | -------------------------------------------------------------------------------- /locale/es-ES.json: -------------------------------------------------------------------------------- 1 | { 2 | "decimal": ",", 3 | "thousands": ".", 4 | "grouping": [3], 5 | "currency": ["", "\u00a0€"] 6 | } 7 | -------------------------------------------------------------------------------- /locale/es-MX.json: -------------------------------------------------------------------------------- 1 | { 2 | "decimal": ".", 3 | "thousands": ",", 4 | "grouping": [3], 5 | "currency": ["$", ""] 6 | } 7 | -------------------------------------------------------------------------------- /locale/fi-FI.json: -------------------------------------------------------------------------------- 1 | { 2 | "decimal": ",", 3 | "thousands": "\u00a0", 4 | "grouping": [3], 5 | "currency": ["", "\u00a0€"] 6 | } 7 | -------------------------------------------------------------------------------- /locale/fr-CA.json: -------------------------------------------------------------------------------- 1 | { 2 | "decimal": ",", 3 | "thousands": "\u00a0", 4 | "grouping": [3], 5 | "currency": ["", "$"] 6 | } 7 | -------------------------------------------------------------------------------- /locale/fr-FR.json: -------------------------------------------------------------------------------- 1 | { 2 | "decimal": ",", 3 | "thousands": "\u00a0", 4 | "grouping": [3], 5 | "currency": ["", "\u00a0€"], 6 | "percent": "\u202f%" 7 | } 8 | -------------------------------------------------------------------------------- /locale/he-IL.json: -------------------------------------------------------------------------------- 1 | { 2 | "decimal": ".", 3 | "thousands": ",", 4 | "grouping": [3], 5 | "currency": ["₪", ""] 6 | } 7 | -------------------------------------------------------------------------------- /locale/hu-HU.json: -------------------------------------------------------------------------------- 1 | { 2 | "decimal": ",", 3 | "thousands": "\u00a0", 4 | "grouping": [3], 5 | "currency": ["", "\u00a0Ft"] 6 | } 7 | -------------------------------------------------------------------------------- /locale/it-IT.json: -------------------------------------------------------------------------------- 1 | { 2 | "decimal": ",", 3 | "thousands": ".", 4 | "grouping": [3], 5 | "currency": ["€", ""] 6 | } 7 | -------------------------------------------------------------------------------- /locale/ja-JP.json: -------------------------------------------------------------------------------- 1 | { 2 | "decimal": ".", 3 | "thousands": ",", 4 | "grouping": [3], 5 | "currency": ["", "円"] 6 | } 7 | -------------------------------------------------------------------------------- /locale/ko-KR.json: -------------------------------------------------------------------------------- 1 | { 2 | "decimal": ".", 3 | "thousands": ",", 4 | "grouping": [3], 5 | "currency": ["₩", ""] 6 | } 7 | -------------------------------------------------------------------------------- /locale/mk-MK.json: -------------------------------------------------------------------------------- 1 | { 2 | "decimal": ",", 3 | "thousands": ".", 4 | "grouping": [3], 5 | "currency": ["", "\u00a0ден."] 6 | } 7 | -------------------------------------------------------------------------------- /locale/nl-NL.json: -------------------------------------------------------------------------------- 1 | { 2 | "decimal": ",", 3 | "thousands": ".", 4 | "grouping": [3], 5 | "currency": ["€\u00a0", ""] 6 | } 7 | -------------------------------------------------------------------------------- /locale/pl-PL.json: -------------------------------------------------------------------------------- 1 | { 2 | "decimal": ",", 3 | "thousands": ".", 4 | "grouping": [3], 5 | "currency": ["", "zł"] 6 | } 7 | -------------------------------------------------------------------------------- /locale/pt-BR.json: -------------------------------------------------------------------------------- 1 | { 2 | "decimal": ",", 3 | "thousands": ".", 4 | "grouping": [3], 5 | "currency": ["R$", ""] 6 | } 7 | -------------------------------------------------------------------------------- /locale/pt-PT.json: -------------------------------------------------------------------------------- 1 | { 2 | "decimal": ",", 3 | "thousands": "\u00a0", 4 | "grouping": [3], 5 | "currency": ["", "\u00a0€"] 6 | } 7 | -------------------------------------------------------------------------------- /locale/ru-RU.json: -------------------------------------------------------------------------------- 1 | { 2 | "decimal": ",", 3 | "thousands": "\u00a0", 4 | "grouping": [3], 5 | "currency": ["", "\u00a0\u20bd"] 6 | } 7 | -------------------------------------------------------------------------------- /locale/sl-SI.json: -------------------------------------------------------------------------------- 1 | { 2 | "decimal": ",", 3 | "thousands": ".", 4 | "grouping": [3], 5 | "currency": ["", "\u00a0€"] 6 | } 7 | -------------------------------------------------------------------------------- /locale/sv-SE.json: -------------------------------------------------------------------------------- 1 | { 2 | "decimal": ",", 3 | "thousands": "\u00a0", 4 | "grouping": [3], 5 | "currency": ["", " kr"] 6 | } 7 | -------------------------------------------------------------------------------- /locale/uk-UA.json: -------------------------------------------------------------------------------- 1 | { 2 | "decimal": ",", 3 | "thousands": "\u00a0", 4 | "grouping": [3], 5 | "currency": ["", "\u00a0₴."] 6 | } 7 | -------------------------------------------------------------------------------- /locale/zh-CN.json: -------------------------------------------------------------------------------- 1 | { 2 | "decimal": ".", 3 | "thousands": ",", 4 | "grouping": [3], 5 | "currency": ["¥", ""] 6 | } 7 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "d3-format", 3 | "version": "3.1.0", 4 | "description": "Format numbers for human consumption.", 5 | "homepage": "https://d3js.org/d3-format/", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/d3/d3-format.git" 9 | }, 10 | "keywords": [ 11 | "d3", 12 | "d3-module", 13 | "format", 14 | "localization" 15 | ], 16 | "license": "ISC", 17 | "author": { 18 | "name": "Mike Bostock", 19 | "url": "http://bost.ocks.org/mike" 20 | }, 21 | "type": "module", 22 | "files": [ 23 | "dist/**/*.js", 24 | "src/**/*.js", 25 | "locale/*.json" 26 | ], 27 | "module": "src/index.js", 28 | "main": "src/index.js", 29 | "jsdelivr": "dist/d3-format.min.js", 30 | "unpkg": "dist/d3-format.min.js", 31 | "exports": { 32 | ".": { 33 | "umd": "./dist/d3-format.min.js", 34 | "default": "./src/index.js" 35 | }, 36 | "./locale/*": "./locale/*.json" 37 | }, 38 | "sideEffects": [ 39 | "./src/defaultLocale.js" 40 | ], 41 | "devDependencies": { 42 | "eslint": "8", 43 | "mocha": "9", 44 | "rollup": "2", 45 | "rollup-plugin-terser": "7" 46 | }, 47 | "scripts": { 48 | "test": "mocha 'test/**/*-test.js' && eslint src test", 49 | "prepublishOnly": "rm -rf dist && yarn test && rollup -c", 50 | "postpublish": "git push && git push --tags && cd ../d3.github.com && git pull && cp ../${npm_package_name}/dist/${npm_package_name}.js ${npm_package_name}.v${npm_package_version%%.*}.js && cp ../${npm_package_name}/dist/${npm_package_name}.min.js ${npm_package_name}.v${npm_package_version%%.*}.min.js && git add ${npm_package_name}.v${npm_package_version%%.*}.js ${npm_package_name}.v${npm_package_version%%.*}.min.js && git commit -m \"${npm_package_name} ${npm_package_version}\" && git push && cd -" 51 | }, 52 | "engines": { 53 | "node": ">=12" 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import {readFileSync} from "fs"; 2 | import {terser} from "rollup-plugin-terser"; 3 | import * as meta from "./package.json"; 4 | 5 | // Extract copyrights from the LICENSE. 6 | const copyright = readFileSync("./LICENSE", "utf-8") 7 | .split(/\n/g) 8 | .filter(line => /^Copyright\s+/.test(line)) 9 | .map(line => line.replace(/^Copyright\s+/, "")) 10 | .join(", "); 11 | 12 | const config = { 13 | input: "src/index.js", 14 | external: Object.keys(meta.dependencies || {}).filter(key => /^d3-/.test(key)), 15 | output: { 16 | file: `dist/${meta.name}.js`, 17 | name: "d3", 18 | format: "umd", 19 | indent: false, 20 | extend: true, 21 | banner: `// ${meta.homepage} v${meta.version} Copyright ${copyright}`, 22 | globals: Object.assign({}, ...Object.keys(meta.dependencies || {}).filter(key => /^d3-/.test(key)).map(key => ({[key]: "d3"}))) 23 | }, 24 | plugins: [] 25 | }; 26 | 27 | export default [ 28 | config, 29 | { 30 | ...config, 31 | output: { 32 | ...config.output, 33 | file: `dist/${meta.name}.min.js` 34 | }, 35 | plugins: [ 36 | ...config.plugins, 37 | terser({ 38 | output: { 39 | preamble: config.output.banner 40 | } 41 | }) 42 | ] 43 | } 44 | ]; 45 | -------------------------------------------------------------------------------- /src/defaultLocale.js: -------------------------------------------------------------------------------- 1 | import formatLocale from "./locale.js"; 2 | 3 | var locale; 4 | export var format; 5 | export var formatPrefix; 6 | 7 | defaultLocale({ 8 | thousands: ",", 9 | grouping: [3], 10 | currency: ["$", ""] 11 | }); 12 | 13 | export default function defaultLocale(definition) { 14 | locale = formatLocale(definition); 15 | format = locale.format; 16 | formatPrefix = locale.formatPrefix; 17 | return locale; 18 | } 19 | -------------------------------------------------------------------------------- /src/exponent.js: -------------------------------------------------------------------------------- 1 | import {formatDecimalParts} from "./formatDecimal.js"; 2 | 3 | export default function(x) { 4 | return x = formatDecimalParts(Math.abs(x)), x ? x[1] : NaN; 5 | } 6 | -------------------------------------------------------------------------------- /src/formatDecimal.js: -------------------------------------------------------------------------------- 1 | export default function(x) { 2 | return Math.abs(x = Math.round(x)) >= 1e21 3 | ? x.toLocaleString("en").replace(/,/g, "") 4 | : x.toString(10); 5 | } 6 | 7 | // Computes the decimal coefficient and exponent of the specified number x with 8 | // significant digits p, where x is positive and p is in [1, 21] or undefined. 9 | // For example, formatDecimalParts(1.23) returns ["123", 0]. 10 | export function formatDecimalParts(x, p) { 11 | if ((i = (x = p ? x.toExponential(p - 1) : x.toExponential()).indexOf("e")) < 0) return null; // NaN, ±Infinity 12 | var i, coefficient = x.slice(0, i); 13 | 14 | // The string returned by toExponential either has the form \d\.\d+e[-+]\d+ 15 | // (e.g., 1.2e+3) or the form \de[-+]\d+ (e.g., 1e+3). 16 | return [ 17 | coefficient.length > 1 ? coefficient[0] + coefficient.slice(2) : coefficient, 18 | +x.slice(i + 1) 19 | ]; 20 | } 21 | -------------------------------------------------------------------------------- /src/formatGroup.js: -------------------------------------------------------------------------------- 1 | export default function(grouping, thousands) { 2 | return function(value, width) { 3 | var i = value.length, 4 | t = [], 5 | j = 0, 6 | g = grouping[0], 7 | length = 0; 8 | 9 | while (i > 0 && g > 0) { 10 | if (length + g + 1 > width) g = Math.max(1, width - length); 11 | t.push(value.substring(i -= g, i + g)); 12 | if ((length += g + 1) > width) break; 13 | g = grouping[j = (j + 1) % grouping.length]; 14 | } 15 | 16 | return t.reverse().join(thousands); 17 | }; 18 | } 19 | -------------------------------------------------------------------------------- /src/formatNumerals.js: -------------------------------------------------------------------------------- 1 | export default function(numerals) { 2 | return function(value) { 3 | return value.replace(/[0-9]/g, function(i) { 4 | return numerals[+i]; 5 | }); 6 | }; 7 | } 8 | -------------------------------------------------------------------------------- /src/formatPrefixAuto.js: -------------------------------------------------------------------------------- 1 | import {formatDecimalParts} from "./formatDecimal.js"; 2 | 3 | export var prefixExponent; 4 | 5 | export default function(x, p) { 6 | var d = formatDecimalParts(x, p); 7 | if (!d) return x + ""; 8 | var coefficient = d[0], 9 | exponent = d[1], 10 | i = exponent - (prefixExponent = Math.max(-8, Math.min(8, Math.floor(exponent / 3))) * 3) + 1, 11 | n = coefficient.length; 12 | return i === n ? coefficient 13 | : i > n ? coefficient + new Array(i - n + 1).join("0") 14 | : i > 0 ? coefficient.slice(0, i) + "." + coefficient.slice(i) 15 | : "0." + new Array(1 - i).join("0") + formatDecimalParts(x, Math.max(0, p + i - 1))[0]; // less than 1y! 16 | } 17 | -------------------------------------------------------------------------------- /src/formatRounded.js: -------------------------------------------------------------------------------- 1 | import {formatDecimalParts} from "./formatDecimal.js"; 2 | 3 | export default function(x, p) { 4 | var d = formatDecimalParts(x, p); 5 | if (!d) return x + ""; 6 | var coefficient = d[0], 7 | exponent = d[1]; 8 | return exponent < 0 ? "0." + new Array(-exponent).join("0") + coefficient 9 | : coefficient.length > exponent + 1 ? coefficient.slice(0, exponent + 1) + "." + coefficient.slice(exponent + 1) 10 | : coefficient + new Array(exponent - coefficient.length + 2).join("0"); 11 | } 12 | -------------------------------------------------------------------------------- /src/formatSpecifier.js: -------------------------------------------------------------------------------- 1 | // [[fill]align][sign][symbol][0][width][,][.precision][~][type] 2 | var re = /^(?:(.)?([<>=^]))?([+\-( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?(~)?([a-z%])?$/i; 3 | 4 | export default function formatSpecifier(specifier) { 5 | if (!(match = re.exec(specifier))) throw new Error("invalid format: " + specifier); 6 | var match; 7 | return new FormatSpecifier({ 8 | fill: match[1], 9 | align: match[2], 10 | sign: match[3], 11 | symbol: match[4], 12 | zero: match[5], 13 | width: match[6], 14 | comma: match[7], 15 | precision: match[8] && match[8].slice(1), 16 | trim: match[9], 17 | type: match[10] 18 | }); 19 | } 20 | 21 | formatSpecifier.prototype = FormatSpecifier.prototype; // instanceof 22 | 23 | export function FormatSpecifier(specifier) { 24 | this.fill = specifier.fill === undefined ? " " : specifier.fill + ""; 25 | this.align = specifier.align === undefined ? ">" : specifier.align + ""; 26 | this.sign = specifier.sign === undefined ? "-" : specifier.sign + ""; 27 | this.symbol = specifier.symbol === undefined ? "" : specifier.symbol + ""; 28 | this.zero = !!specifier.zero; 29 | this.width = specifier.width === undefined ? undefined : +specifier.width; 30 | this.comma = !!specifier.comma; 31 | this.precision = specifier.precision === undefined ? undefined : +specifier.precision; 32 | this.trim = !!specifier.trim; 33 | this.type = specifier.type === undefined ? "" : specifier.type + ""; 34 | } 35 | 36 | FormatSpecifier.prototype.toString = function() { 37 | return this.fill 38 | + this.align 39 | + this.sign 40 | + this.symbol 41 | + (this.zero ? "0" : "") 42 | + (this.width === undefined ? "" : Math.max(1, this.width | 0)) 43 | + (this.comma ? "," : "") 44 | + (this.precision === undefined ? "" : "." + Math.max(0, this.precision | 0)) 45 | + (this.trim ? "~" : "") 46 | + this.type; 47 | }; 48 | -------------------------------------------------------------------------------- /src/formatTrim.js: -------------------------------------------------------------------------------- 1 | // Trims insignificant zeros, e.g., replaces 1.2000k with 1.2k. 2 | export default function(s) { 3 | out: for (var n = s.length, i = 1, i0 = -1, i1; i < n; ++i) { 4 | switch (s[i]) { 5 | case ".": i0 = i1 = i; break; 6 | case "0": if (i0 === 0) i0 = i; i1 = i; break; 7 | default: if (!+s[i]) break out; if (i0 > 0) i0 = 0; break; 8 | } 9 | } 10 | return i0 > 0 ? s.slice(0, i0) + s.slice(i1 + 1) : s; 11 | } 12 | -------------------------------------------------------------------------------- /src/formatTypes.js: -------------------------------------------------------------------------------- 1 | import formatDecimal from "./formatDecimal.js"; 2 | import formatPrefixAuto from "./formatPrefixAuto.js"; 3 | import formatRounded from "./formatRounded.js"; 4 | 5 | export default { 6 | "%": (x, p) => (x * 100).toFixed(p), 7 | "b": (x) => Math.round(x).toString(2), 8 | "c": (x) => x + "", 9 | "d": formatDecimal, 10 | "e": (x, p) => x.toExponential(p), 11 | "f": (x, p) => x.toFixed(p), 12 | "g": (x, p) => x.toPrecision(p), 13 | "o": (x) => Math.round(x).toString(8), 14 | "p": (x, p) => formatRounded(x * 100, p), 15 | "r": formatRounded, 16 | "s": formatPrefixAuto, 17 | "X": (x) => Math.round(x).toString(16).toUpperCase(), 18 | "x": (x) => Math.round(x).toString(16) 19 | }; 20 | -------------------------------------------------------------------------------- /src/identity.js: -------------------------------------------------------------------------------- 1 | export default function(x) { 2 | return x; 3 | } 4 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | export {default as formatDefaultLocale, format, formatPrefix} from "./defaultLocale.js"; 2 | export {default as formatLocale} from "./locale.js"; 3 | export {default as formatSpecifier, FormatSpecifier} from "./formatSpecifier.js"; 4 | export {default as precisionFixed} from "./precisionFixed.js"; 5 | export {default as precisionPrefix} from "./precisionPrefix.js"; 6 | export {default as precisionRound} from "./precisionRound.js"; 7 | -------------------------------------------------------------------------------- /src/locale.js: -------------------------------------------------------------------------------- 1 | import exponent from "./exponent.js"; 2 | import formatGroup from "./formatGroup.js"; 3 | import formatNumerals from "./formatNumerals.js"; 4 | import formatSpecifier from "./formatSpecifier.js"; 5 | import formatTrim from "./formatTrim.js"; 6 | import formatTypes from "./formatTypes.js"; 7 | import {prefixExponent} from "./formatPrefixAuto.js"; 8 | import identity from "./identity.js"; 9 | 10 | var map = Array.prototype.map, 11 | prefixes = ["y","z","a","f","p","n","µ","m","","k","M","G","T","P","E","Z","Y"]; 12 | 13 | export default function(locale) { 14 | var group = locale.grouping === undefined || locale.thousands === undefined ? identity : formatGroup(map.call(locale.grouping, Number), locale.thousands + ""), 15 | currencyPrefix = locale.currency === undefined ? "" : locale.currency[0] + "", 16 | currencySuffix = locale.currency === undefined ? "" : locale.currency[1] + "", 17 | decimal = locale.decimal === undefined ? "." : locale.decimal + "", 18 | numerals = locale.numerals === undefined ? identity : formatNumerals(map.call(locale.numerals, String)), 19 | percent = locale.percent === undefined ? "%" : locale.percent + "", 20 | minus = locale.minus === undefined ? "−" : locale.minus + "", 21 | nan = locale.nan === undefined ? "NaN" : locale.nan + ""; 22 | 23 | function newFormat(specifier) { 24 | specifier = formatSpecifier(specifier); 25 | 26 | var fill = specifier.fill, 27 | align = specifier.align, 28 | sign = specifier.sign, 29 | symbol = specifier.symbol, 30 | zero = specifier.zero, 31 | width = specifier.width, 32 | comma = specifier.comma, 33 | precision = specifier.precision, 34 | trim = specifier.trim, 35 | type = specifier.type; 36 | 37 | // The "n" type is an alias for ",g". 38 | if (type === "n") comma = true, type = "g"; 39 | 40 | // The "" type, and any invalid type, is an alias for ".12~g". 41 | else if (!formatTypes[type]) precision === undefined && (precision = 12), trim = true, type = "g"; 42 | 43 | // If zero fill is specified, padding goes after sign and before digits. 44 | if (zero || (fill === "0" && align === "=")) zero = true, fill = "0", align = "="; 45 | 46 | // Compute the prefix and suffix. 47 | // For SI-prefix, the suffix is lazily computed. 48 | var prefix = symbol === "$" ? currencyPrefix : symbol === "#" && /[boxX]/.test(type) ? "0" + type.toLowerCase() : "", 49 | suffix = symbol === "$" ? currencySuffix : /[%p]/.test(type) ? percent : ""; 50 | 51 | // What format function should we use? 52 | // Is this an integer type? 53 | // Can this type generate exponential notation? 54 | var formatType = formatTypes[type], 55 | maybeSuffix = /[defgprs%]/.test(type); 56 | 57 | // Set the default precision if not specified, 58 | // or clamp the specified precision to the supported range. 59 | // For significant precision, it must be in [1, 21]. 60 | // For fixed precision, it must be in [0, 20]. 61 | precision = precision === undefined ? 6 62 | : /[gprs]/.test(type) ? Math.max(1, Math.min(21, precision)) 63 | : Math.max(0, Math.min(20, precision)); 64 | 65 | function format(value) { 66 | var valuePrefix = prefix, 67 | valueSuffix = suffix, 68 | i, n, c; 69 | 70 | if (type === "c") { 71 | valueSuffix = formatType(value) + valueSuffix; 72 | value = ""; 73 | } else { 74 | value = +value; 75 | 76 | // Determine the sign. -0 is not less than 0, but 1 / -0 is! 77 | var valueNegative = value < 0 || 1 / value < 0; 78 | 79 | // Perform the initial formatting. 80 | value = isNaN(value) ? nan : formatType(Math.abs(value), precision); 81 | 82 | // Trim insignificant zeros. 83 | if (trim) value = formatTrim(value); 84 | 85 | // If a negative value rounds to zero after formatting, and no explicit positive sign is requested, hide the sign. 86 | if (valueNegative && +value === 0 && sign !== "+") valueNegative = false; 87 | 88 | // Compute the prefix and suffix. 89 | valuePrefix = (valueNegative ? (sign === "(" ? sign : minus) : sign === "-" || sign === "(" ? "" : sign) + valuePrefix; 90 | valueSuffix = (type === "s" ? prefixes[8 + prefixExponent / 3] : "") + valueSuffix + (valueNegative && sign === "(" ? ")" : ""); 91 | 92 | // Break the formatted value into the integer “value” part that can be 93 | // grouped, and fractional or exponential “suffix” part that is not. 94 | if (maybeSuffix) { 95 | i = -1, n = value.length; 96 | while (++i < n) { 97 | if (c = value.charCodeAt(i), 48 > c || c > 57) { 98 | valueSuffix = (c === 46 ? decimal + value.slice(i + 1) : value.slice(i)) + valueSuffix; 99 | value = value.slice(0, i); 100 | break; 101 | } 102 | } 103 | } 104 | } 105 | 106 | // If the fill character is not "0", grouping is applied before padding. 107 | if (comma && !zero) value = group(value, Infinity); 108 | 109 | // Compute the padding. 110 | var length = valuePrefix.length + value.length + valueSuffix.length, 111 | padding = length < width ? new Array(width - length + 1).join(fill) : ""; 112 | 113 | // If the fill character is "0", grouping is applied after padding. 114 | if (comma && zero) value = group(padding + value, padding.length ? width - valueSuffix.length : Infinity), padding = ""; 115 | 116 | // Reconstruct the final output based on the desired alignment. 117 | switch (align) { 118 | case "<": value = valuePrefix + value + valueSuffix + padding; break; 119 | case "=": value = valuePrefix + padding + value + valueSuffix; break; 120 | case "^": value = padding.slice(0, length = padding.length >> 1) + valuePrefix + value + valueSuffix + padding.slice(length); break; 121 | default: value = padding + valuePrefix + value + valueSuffix; break; 122 | } 123 | 124 | return numerals(value); 125 | } 126 | 127 | format.toString = function() { 128 | return specifier + ""; 129 | }; 130 | 131 | return format; 132 | } 133 | 134 | function formatPrefix(specifier, value) { 135 | var f = newFormat((specifier = formatSpecifier(specifier), specifier.type = "f", specifier)), 136 | e = Math.max(-8, Math.min(8, Math.floor(exponent(value) / 3))) * 3, 137 | k = Math.pow(10, -e), 138 | prefix = prefixes[8 + e / 3]; 139 | return function(value) { 140 | return f(k * value) + prefix; 141 | }; 142 | } 143 | 144 | return { 145 | format: newFormat, 146 | formatPrefix: formatPrefix 147 | }; 148 | } 149 | -------------------------------------------------------------------------------- /src/precisionFixed.js: -------------------------------------------------------------------------------- 1 | import exponent from "./exponent.js"; 2 | 3 | export default function(step) { 4 | return Math.max(0, -exponent(Math.abs(step))); 5 | } 6 | -------------------------------------------------------------------------------- /src/precisionPrefix.js: -------------------------------------------------------------------------------- 1 | import exponent from "./exponent.js"; 2 | 3 | export default function(step, value) { 4 | return Math.max(0, Math.max(-8, Math.min(8, Math.floor(exponent(value) / 3))) * 3 - exponent(Math.abs(step))); 5 | } 6 | -------------------------------------------------------------------------------- /src/precisionRound.js: -------------------------------------------------------------------------------- 1 | import exponent from "./exponent.js"; 2 | 3 | export default function(step, max) { 4 | step = Math.abs(step), max = Math.abs(max) - step; 5 | return Math.max(0, exponent(max) - exponent(step)) + 1; 6 | } 7 | -------------------------------------------------------------------------------- /test/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "eslint:recommended", 3 | "parserOptions": { 4 | "sourceType": "module", 5 | "ecmaVersion": 8 6 | }, 7 | "env": { 8 | "mocha": true 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /test/arabicLocale-test.js: -------------------------------------------------------------------------------- 1 | import assert from "assert"; 2 | import {readFileSync} from "fs"; 3 | import {formatLocale} from "../src/index.js"; 4 | 5 | function locale(locale) { 6 | return formatLocale(JSON.parse(readFileSync(`./locale/${locale}.json`, "utf8"))); 7 | } 8 | 9 | it("formatLocale() can format numbers using ar-001 locale", () => { 10 | assert.strictEqual(locale("ar-001").format("$,.2f")(-1234.56), "−١٬٢٣٤٫٥٦"); 11 | }); 12 | 13 | it("formatLocale() can format numbers using ar-AE locale", () => { 14 | assert.strictEqual(locale("ar-AE").format("$,.2f")(1234.56), "١٬٢٣٤٫٥٦ د.إ."); 15 | }); 16 | 17 | it("formatLocale() can format numbers using ar-BH locale", () => { 18 | assert.strictEqual(locale("ar-BH").format("$,.2f")(1234.56), "١٬٢٣٤٫٥٦ د.ب."); 19 | }); 20 | 21 | it("formatLocale() can format numbers using ar-DJ locale", () => { 22 | assert.strictEqual(locale("ar-DJ").format("$,.2f")(1234.56), "\u200fFdj ١٬٢٣٤٫٥٦"); 23 | }); 24 | 25 | it("formatLocale() can format numbers using ar-DZ locale", () => { 26 | assert.strictEqual(locale("ar-DZ").format("$,.2f")(1234.56), "د.ج. 1.234,56"); 27 | }); 28 | 29 | it("formatLocale() can format numbers using ar-EG locale", () => { 30 | assert.strictEqual(locale("ar-EG").format("$,.2f")(1234.56), "١٬٢٣٤٫٥٦ ج.م."); 31 | }); 32 | 33 | it("formatLocale() can format numbers using ar-EH locale", () => { 34 | assert.strictEqual(locale("ar-EH").format("$,.2f")(1234.56), "د.م. 1,234.56"); 35 | }); 36 | 37 | it("formatLocale() can format numbers using ar-ER locale", () => { 38 | assert.strictEqual(locale("ar-ER").format("$,.2f")(1234.56), "Nfk ١٬٢٣٤٫٥٦"); 39 | }); 40 | 41 | it("formatLocale() can format numbers using ar-IL locale", () => { 42 | assert.strictEqual(locale("ar-IL").format("$,.2f")(1234.56), "₪ ١٬٢٣٤٫٥٦"); 43 | }); 44 | 45 | it("formatLocale() can format numbers using ar-IQ locale", () => { 46 | assert.strictEqual(locale("ar-IQ").format("$,.2f")(1234.56), "١٬٢٣٤٫٥٦ د.ع."); 47 | }); 48 | 49 | it("formatLocale() can format numbers using ar-JO locale", () => { 50 | assert.strictEqual(locale("ar-JO").format("$,.2f")(1234.56), "١٬٢٣٤٫٥٦ د.أ."); 51 | }); 52 | 53 | it("formatLocale() can format numbers using ar-KM locale", () => { 54 | assert.strictEqual(locale("ar-KM").format("$,.2f")(1234.56), "١٬٢٣٤٫٥٦ ف.ج.ق."); 55 | }); 56 | 57 | it("formatLocale() can format numbers using ar-KW locale", () => { 58 | assert.strictEqual(locale("ar-KW").format("$,.2f")(1234.56), "١٬٢٣٤٫٥٦ د.ك."); 59 | }); 60 | 61 | it("formatLocale() can format numbers using ar-LB locale", () => { 62 | assert.strictEqual(locale("ar-LB").format("$,.2f")(1234.56), "١٬٢٣٤٫٥٦ ل.ل."); 63 | }); 64 | 65 | it("formatLocale() can format numbers using ar-MA locale", () => { 66 | assert.strictEqual(locale("ar-MA").format("$,.2f")(1234.56), "د.م. 1.234,56"); 67 | }); 68 | 69 | it("formatLocale() can format numbers using ar-MR locale", () => { 70 | assert.strictEqual(locale("ar-MR").format("$,.2f")(1234.56), "١٬٢٣٤٫٥٦ أ.م."); 71 | }); 72 | 73 | it("formatLocale() can format numbers using ar-OM locale", () => { 74 | assert.strictEqual(locale("ar-OM").format("$,.2f")(1234.56), "١٬٢٣٤٫٥٦ ر.ع."); 75 | }); 76 | 77 | it("formatLocale() can format numbers using ar-PS locale", () => { 78 | assert.strictEqual(locale("ar-PS").format("$,.2f")(1234.56), "₪ ١٬٢٣٤٫٥٦"); 79 | }); 80 | 81 | it("formatLocale() can format numbers using ar-QA locale", () => { 82 | assert.strictEqual(locale("ar-QA").format("$,.2f")(1234.56), "١٬٢٣٤٫٥٦ ر.ق."); 83 | }); 84 | 85 | it("formatLocale() can format numbers using ar-SA locale", () => { 86 | assert.strictEqual(locale("ar-SA").format("$,.2f")(1234.56), "١٬٢٣٤٫٥٦ ر.س."); 87 | }); 88 | 89 | it("formatLocale() can format numbers using ar-SD locale", () => { 90 | assert.strictEqual(locale("ar-SD").format("$,.2f")(1234.56), "١٬٢٣٤٫٥٦ ج.س."); 91 | }); 92 | 93 | it("formatLocale() can format numbers using ar-SO locale", () => { 94 | assert.strictEqual(locale("ar-SO").format("$,.2f")(1234.56), "‏S ١٬٢٣٤٫٥٦"); 95 | }); 96 | 97 | it("formatLocale() can format numbers using ar-SS locale", () => { 98 | assert.strictEqual(locale("ar-SS").format("$,.2f")(1234.56), "£ ١٬٢٣٤٫٥٦"); 99 | }); 100 | 101 | it("formatLocale() can format numbers using ar-SY locale", () => { 102 | assert.strictEqual(locale("ar-SY").format("$,.2f")(1234.56), "١٬٢٣٤٫٥٦ ل.س."); 103 | }); 104 | 105 | it("formatLocale() can format numbers using ar-TD locale", () => { 106 | assert.strictEqual(locale("ar-TD").format("$,.2f")(1234.56), "\u200fFCFA ١٬٢٣٤٫٥٦"); 107 | }); 108 | 109 | it("formatLocale() can format numbers using ar-TN locale", () => { 110 | assert.strictEqual(locale("ar-TN").format("$,.2f")(1234.56), "د.ت. 1.234,56"); 111 | }); 112 | 113 | it("formatLocale() can format numbers using ar-YE locale", () => { 114 | assert.strictEqual(locale("ar-YE").format("$,.2f")(1234.56), "١٬٢٣٤٫٥٦ ر.ى."); 115 | }); 116 | -------------------------------------------------------------------------------- /test/defaultLocale-test.js: -------------------------------------------------------------------------------- 1 | import assert from "assert"; 2 | import {format, formatPrefix, formatDefaultLocale} from "../src/index.js"; 3 | 4 | const enUs = { 5 | decimal: ".", 6 | thousands: ",", 7 | grouping: [3], 8 | currency: ["$", ""] 9 | }; 10 | 11 | const frFr = { 12 | decimal: ",", 13 | thousands: ".", 14 | grouping: [3], 15 | currency: ["", "\u00a0€"], 16 | percent: "\u202f%" 17 | }; 18 | 19 | it("formatDefaultLocale(definition) returns the new default locale", () => { 20 | const locale = formatDefaultLocale(frFr); 21 | try { 22 | assert.strictEqual(locale.format("$,.2f")(12345678.90), "12.345.678,90 €"); 23 | assert.strictEqual(locale.format(",.0%")(12345678.90), "1.234.567.890\u202f%"); 24 | } finally { 25 | formatDefaultLocale(enUs); 26 | } 27 | }); 28 | 29 | it("formatDefaultLocale(definition) affects format", () => { 30 | const locale = formatDefaultLocale(frFr); 31 | try { 32 | assert.strictEqual(format, locale.format); 33 | assert.strictEqual(format("$,.2f")(12345678.90), "12.345.678,90 €"); 34 | } finally { 35 | formatDefaultLocale(enUs); 36 | } 37 | }); 38 | 39 | it("formatDefaultLocale(definition) affects formatPrefix", () => { 40 | const locale = formatDefaultLocale(frFr); 41 | try { 42 | assert.strictEqual(formatPrefix, locale.formatPrefix); 43 | assert.strictEqual(formatPrefix(",.2", 1e3)(12345678.90), "12.345,68k"); 44 | } finally { 45 | formatDefaultLocale(enUs); 46 | } 47 | }); 48 | -------------------------------------------------------------------------------- /test/format-test.js: -------------------------------------------------------------------------------- 1 | import assert from "assert"; 2 | import {format} from "../src/index.js"; 3 | 4 | it("format(specifier)(number) returns a string", () => { 5 | assert.strictEqual(typeof format("d")(0), "string"); 6 | }); 7 | 8 | it("format(specifier).toString() returns the normalized specifier", () => { 9 | assert.strictEqual(format("d") + "", " >-d"); 10 | }); 11 | 12 | it("format(specifier) throws an error for invalid formats", () => { 13 | assert.throws(() => { format("foo"); }, /invalid format: foo/); 14 | assert.throws(() => { format(".-2s"); }, /invalid format: \.-2s/); 15 | assert.throws(() => { format(".f"); }, /invalid format: \.f/); 16 | }); 17 | 18 | it("format(\",.\") unreasonable precision values are clamped to reasonable values", () => { 19 | assert.strictEqual(format(".30f")(0), "0.00000000000000000000"); 20 | assert.strictEqual(format(".0g")(1), "1"); 21 | }); 22 | 23 | it("format(\"s\") handles very small and very large values", () => { 24 | assert.strictEqual(format("s")(Number.MIN_VALUE), "0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005y"); 25 | assert.strictEqual(format("s")(Number.MAX_VALUE), "179769000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000Y"); 26 | }); 27 | 28 | it("format(\"n\") is equivalent to format(\",g\")", () => { 29 | assert.strictEqual(format("n")(123456.78), "123,457"); 30 | assert.strictEqual(format(",g")(123456.78), "123,457"); 31 | }); 32 | 33 | it("format(\"012\") is equivalent to format(\"0=12\")", () => { 34 | assert.strictEqual(format("012")(123.456), "00000123.456"); 35 | assert.strictEqual(format("0=12")(123.456), "00000123.456"); 36 | }); 37 | -------------------------------------------------------------------------------- /test/format-trim-test.js: -------------------------------------------------------------------------------- 1 | import assert from "assert"; 2 | import {format} from "../src/index.js"; 3 | 4 | it("format(\"~r\") trims insignificant zeros", () => { 5 | const f = format("~r"); 6 | assert.strictEqual(f(1), "1"); 7 | assert.strictEqual(f(0.1), "0.1"); 8 | assert.strictEqual(f(0.01), "0.01"); 9 | assert.strictEqual(f(10.0001), "10.0001"); 10 | assert.strictEqual(f(123.45), "123.45"); 11 | assert.strictEqual(f(123.456), "123.456"); 12 | assert.strictEqual(f(123.4567), "123.457"); 13 | assert.strictEqual(f(0.000009), "0.000009"); 14 | assert.strictEqual(f(0.0000009), "0.0000009"); 15 | assert.strictEqual(f(0.00000009), "0.00000009"); 16 | assert.strictEqual(f(0.111119), "0.111119"); 17 | assert.strictEqual(f(0.1111119), "0.111112"); 18 | assert.strictEqual(f(0.11111119), "0.111111"); 19 | }); 20 | 21 | it("format(\"~e\") trims insignificant zeros", () => { 22 | const f = format("~e"); 23 | assert.strictEqual(f(0), "0e+0"); 24 | assert.strictEqual(f(42), "4.2e+1"); 25 | assert.strictEqual(f(42000000), "4.2e+7"); 26 | assert.strictEqual(f(0.042), "4.2e-2"); 27 | assert.strictEqual(f(-4), "−4e+0"); 28 | assert.strictEqual(f(-42), "−4.2e+1"); 29 | assert.strictEqual(f(42000000000), "4.2e+10"); 30 | assert.strictEqual(f(0.00000000042), "4.2e-10"); 31 | }); 32 | 33 | it("format(\".4~e\") trims insignificant zeros", () => { 34 | const f = format(".4~e"); 35 | assert.strictEqual(f(0.00000000012345), "1.2345e-10"); 36 | assert.strictEqual(f(0.00000000012340), "1.234e-10"); 37 | assert.strictEqual(f(0.00000000012300), "1.23e-10"); 38 | assert.strictEqual(f(-0.00000000012345), "−1.2345e-10"); 39 | assert.strictEqual(f(-0.00000000012340), "−1.234e-10"); 40 | assert.strictEqual(f(-0.00000000012300), "−1.23e-10"); 41 | assert.strictEqual(f(12345000000), "1.2345e+10"); 42 | assert.strictEqual(f(12340000000), "1.234e+10"); 43 | assert.strictEqual(f(12300000000), "1.23e+10"); 44 | assert.strictEqual(f(-12345000000), "−1.2345e+10"); 45 | assert.strictEqual(f(-12340000000), "−1.234e+10"); 46 | assert.strictEqual(f(-12300000000), "−1.23e+10"); 47 | }); 48 | 49 | it("format(\"~s\") trims insignificant zeros", () => { 50 | const f = format("~s"); 51 | assert.strictEqual(f(0), "0"); 52 | assert.strictEqual(f(1), "1"); 53 | assert.strictEqual(f(10), "10"); 54 | assert.strictEqual(f(100), "100"); 55 | assert.strictEqual(f(999.5), "999.5"); 56 | assert.strictEqual(f(999500), "999.5k"); 57 | assert.strictEqual(f(1000), "1k"); 58 | assert.strictEqual(f(1400), "1.4k"); 59 | assert.strictEqual(f(1500), "1.5k"); 60 | assert.strictEqual(f(1500.5), "1.5005k"); 61 | assert.strictEqual(f(1e-15), "1f"); 62 | assert.strictEqual(f(1e-12), "1p"); 63 | assert.strictEqual(f(1e-9), "1n"); 64 | assert.strictEqual(f(1e-6), "1µ"); 65 | assert.strictEqual(f(1e-3), "1m"); 66 | assert.strictEqual(f(1e0), "1"); 67 | assert.strictEqual(f(1e3), "1k"); 68 | assert.strictEqual(f(1e6), "1M"); 69 | assert.strictEqual(f(1e9), "1G"); 70 | assert.strictEqual(f(1e12), "1T"); 71 | assert.strictEqual(f(1e15), "1P"); 72 | }); 73 | 74 | it("format(\"~%\") trims insignificant zeros", () => { 75 | const f = format("~%"); 76 | assert.strictEqual(f(0), "0%"); 77 | assert.strictEqual(f(0.1), "10%"); 78 | assert.strictEqual(f(0.01), "1%"); 79 | assert.strictEqual(f(0.001), "0.1%"); 80 | assert.strictEqual(f(0.0001), "0.01%"); 81 | }); 82 | 83 | it("trimming respects commas", () => { 84 | const f = format(",~g"); 85 | assert.strictEqual(f(10000.0), "10,000"); 86 | assert.strictEqual(f(10000.1), "10,000.1"); 87 | }); 88 | -------------------------------------------------------------------------------- /test/format-type-%-test.js: -------------------------------------------------------------------------------- 1 | import assert from "assert"; 2 | import {format} from "../src/index.js"; 3 | 4 | it("format(\"%\") can output a whole percentage", () => { 5 | const f = format(".0%"); 6 | assert.strictEqual(f(0), "0%"); 7 | assert.strictEqual(f(0.042), "4%"); 8 | assert.strictEqual(f(0.42), "42%"); 9 | assert.strictEqual(f(4.2), "420%"); 10 | assert.strictEqual(f(-.042), "−4%"); 11 | assert.strictEqual(f(-.42), "−42%"); 12 | assert.strictEqual(f(-4.2), "−420%"); 13 | }); 14 | 15 | it("format(\".%\") can output a percentage with precision", () => { 16 | const f1 = format(".1%"); 17 | assert.strictEqual(f1(0.234), "23.4%"); 18 | const f2 = format(".2%"); 19 | assert.strictEqual(f2(0.234), "23.40%"); 20 | }); 21 | 22 | it("format(\"%\") fill respects suffix", () => { 23 | assert.strictEqual(format("020.0%")(42), "0000000000000004200%"); 24 | assert.strictEqual(format("20.0%")(42), " 4200%"); 25 | }); 26 | 27 | it("format(\"^%\") align center puts suffix adjacent to number", () => { 28 | assert.strictEqual(format("^21.0%")(0.42), " 42% "); 29 | assert.strictEqual(format("^21,.0%")(422), " 42,200% "); 30 | assert.strictEqual(format("^21,.0%")(-422), " −42,200% "); 31 | }); 32 | -------------------------------------------------------------------------------- /test/format-type-b-test.js: -------------------------------------------------------------------------------- 1 | import assert from "assert"; 2 | import {format} from "../src/index.js"; 3 | 4 | it("format(\"b\") binary", () => { 5 | assert.strictEqual(format("b")(10), "1010"); 6 | }); 7 | 8 | it("format(\"#b\") binary with prefix", () => { 9 | assert.strictEqual(format("#b")(10), "0b1010"); 10 | }); 11 | -------------------------------------------------------------------------------- /test/format-type-c-test.js: -------------------------------------------------------------------------------- 1 | import assert from "assert"; 2 | import {format, formatLocale} from "../src/index.js"; 3 | 4 | it("format(\"c\") unicode character", () => { 5 | assert.strictEqual(format("c")("☃"), "☃"); 6 | assert.strictEqual(format("020c")("☃"), "0000000000000000000☃"); 7 | assert.strictEqual(format(" ^20c")("☃"), " ☃ "); 8 | assert.strictEqual(format("$c")("☃"), "$☃"); 9 | }); 10 | 11 | it("format(\"c\") does not localize a decimal point", () => { 12 | assert.strictEqual(formatLocale({decimal: "/"}).format("c")("."), "."); 13 | }); 14 | -------------------------------------------------------------------------------- /test/format-type-d-test.js: -------------------------------------------------------------------------------- 1 | import assert from "assert"; 2 | import {format} from "../src/index.js"; 3 | 4 | it("format(\"d\") can zero fill", () => { 5 | const f = format("08d"); 6 | assert.strictEqual(f(0), "00000000"); 7 | assert.strictEqual(f(42), "00000042"); 8 | assert.strictEqual(f(42000000), "42000000"); 9 | assert.strictEqual(f(420000000), "420000000"); 10 | assert.strictEqual(f(-4), "−0000004"); 11 | assert.strictEqual(f(-42), "−0000042"); 12 | assert.strictEqual(f(-4200000), "−4200000"); 13 | assert.strictEqual(f(-42000000), "−42000000"); 14 | }); 15 | 16 | it("format(\"d\") can space fill", () => { 17 | const f = format("8d"); 18 | assert.strictEqual(f(0), " 0"); 19 | assert.strictEqual(f(42), " 42"); 20 | assert.strictEqual(f(42000000), "42000000"); 21 | assert.strictEqual(f(420000000), "420000000"); 22 | assert.strictEqual(f(-4), " −4"); 23 | assert.strictEqual(f(-42), " −42"); 24 | assert.strictEqual(f(-4200000), "−4200000"); 25 | assert.strictEqual(f(-42000000), "−42000000"); 26 | }); 27 | 28 | it("format(\"d\") can underscore fill", () => { 29 | const f = format("_>8d"); 30 | assert.strictEqual(f(0), "_______0"); 31 | assert.strictEqual(f(42), "______42"); 32 | assert.strictEqual(f(42000000), "42000000"); 33 | assert.strictEqual(f(420000000), "420000000"); 34 | assert.strictEqual(f(-4), "______−4"); 35 | assert.strictEqual(f(-42), "_____−42"); 36 | assert.strictEqual(f(-4200000), "−4200000"); 37 | assert.strictEqual(f(-42000000), "−42000000"); 38 | }); 39 | 40 | it("format(\"d\") can zero fill with sign and group", () => { 41 | const f = format("+08,d"); 42 | assert.strictEqual(f(0), "+0,000,000"); 43 | assert.strictEqual(f(42), "+0,000,042"); 44 | assert.strictEqual(f(42000000), "+42,000,000"); 45 | assert.strictEqual(f(420000000), "+420,000,000"); 46 | assert.strictEqual(f(-4), "−0,000,004"); 47 | assert.strictEqual(f(-42), "−0,000,042"); 48 | assert.strictEqual(f(-4200000), "−4,200,000"); 49 | assert.strictEqual(f(-42000000), "−42,000,000"); 50 | }); 51 | 52 | it("format(\"d\") always uses zero precision", () => { 53 | const f = format(".2d"); 54 | assert.strictEqual(f(0), "0"); 55 | assert.strictEqual(f(42), "42"); 56 | assert.strictEqual(f(-4.2), "−4"); 57 | }); 58 | 59 | it("format(\"d\") rounds non-integers", () => { 60 | const f = format("d"); 61 | assert.strictEqual(f(4.2), "4"); 62 | }); 63 | 64 | it("format(\",d\") can group thousands", () => { 65 | const f = format(",d"); 66 | assert.strictEqual(f(0), "0"); 67 | assert.strictEqual(f(42), "42"); 68 | assert.strictEqual(f(42000000), "42,000,000"); 69 | assert.strictEqual(f(420000000), "420,000,000"); 70 | assert.strictEqual(f(-4), "−4"); 71 | assert.strictEqual(f(-42), "−42"); 72 | assert.strictEqual(f(-4200000), "−4,200,000"); 73 | assert.strictEqual(f(-42000000), "−42,000,000"); 74 | assert.strictEqual(f(1e21), "1,000,000,000,000,000,000,000"); 75 | assert.strictEqual(f(1.3e27), "1,300,000,000,000,000,000,000,000,000"); 76 | assert.strictEqual(f(1.3e107), "130,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000"); 77 | }); 78 | 79 | it("format(\"0,d\") can group thousands and zero fill", () => { 80 | assert.strictEqual(format("01,d")(0), "0"); 81 | assert.strictEqual(format("01,d")(0), "0"); 82 | assert.strictEqual(format("02,d")(0), "00"); 83 | assert.strictEqual(format("03,d")(0), "000"); 84 | assert.strictEqual(format("04,d")(0), "0,000"); 85 | assert.strictEqual(format("05,d")(0), "0,000"); 86 | assert.strictEqual(format("06,d")(0), "00,000"); 87 | assert.strictEqual(format("08,d")(0), "0,000,000"); 88 | assert.strictEqual(format("013,d")(0), "0,000,000,000"); 89 | assert.strictEqual(format("021,d")(0), "0,000,000,000,000,000"); 90 | assert.strictEqual(format("013,d")(-42000000), "−0,042,000,000"); 91 | assert.strictEqual(format("012,d")(1e21), "1,000,000,000,000,000,000,000"); 92 | assert.strictEqual(format("013,d")(1e21), "1,000,000,000,000,000,000,000"); 93 | assert.strictEqual(format("014,d")(1e21), "1,000,000,000,000,000,000,000"); 94 | assert.strictEqual(format("015,d")(1e21), "1,000,000,000,000,000,000,000"); 95 | }); 96 | 97 | it("format(\"0,d\") can group thousands and zero fill with overflow", () => { 98 | assert.strictEqual(format("01,d")(1), "1"); 99 | assert.strictEqual(format("01,d")(1), "1"); 100 | assert.strictEqual(format("02,d")(12), "12"); 101 | assert.strictEqual(format("03,d")(123), "123"); 102 | assert.strictEqual(format("05,d")(12345), "12,345"); 103 | assert.strictEqual(format("08,d")(12345678), "12,345,678"); 104 | assert.strictEqual(format("013,d")(1234567890123), "1,234,567,890,123"); 105 | }); 106 | 107 | it("format(\",d\") can group thousands and space fill", () => { 108 | assert.strictEqual(format("1,d")(0), "0"); 109 | assert.strictEqual(format("1,d")(0), "0"); 110 | assert.strictEqual(format("2,d")(0), " 0"); 111 | assert.strictEqual(format("3,d")(0), " 0"); 112 | assert.strictEqual(format("5,d")(0), " 0"); 113 | assert.strictEqual(format("8,d")(0), " 0"); 114 | assert.strictEqual(format("13,d")(0), " 0"); 115 | assert.strictEqual(format("21,d")(0), " 0"); 116 | }); 117 | 118 | it("format(\",d\") can group thousands and space fill with overflow", () => { 119 | assert.strictEqual(format("1,d")(1), "1"); 120 | assert.strictEqual(format("1,d")(1), "1"); 121 | assert.strictEqual(format("2,d")(12), "12"); 122 | assert.strictEqual(format("3,d")(123), "123"); 123 | assert.strictEqual(format("5,d")(12345), "12,345"); 124 | assert.strictEqual(format("8,d")(12345678), "12,345,678"); 125 | assert.strictEqual(format("13,d")(1234567890123), "1,234,567,890,123"); 126 | }); 127 | 128 | it("format(\" { 129 | assert.strictEqual(format("<1,d")(0), "0"); 130 | assert.strictEqual(format("<1,d")(0), "0"); 131 | assert.strictEqual(format("<2,d")(0), "0 "); 132 | assert.strictEqual(format("<3,d")(0), "0 "); 133 | assert.strictEqual(format("<5,d")(0), "0 "); 134 | assert.strictEqual(format("<8,d")(0), "0 "); 135 | assert.strictEqual(format("<13,d")(0), "0 "); 136 | assert.strictEqual(format("<21,d")(0), "0 "); 137 | }); 138 | 139 | it("format(\">d\") align right", () => { 140 | assert.strictEqual(format(">1,d")(0), "0"); 141 | assert.strictEqual(format(">1,d")(0), "0"); 142 | assert.strictEqual(format(">2,d")(0), " 0"); 143 | assert.strictEqual(format(">3,d")(0), " 0"); 144 | assert.strictEqual(format(">5,d")(0), " 0"); 145 | assert.strictEqual(format(">8,d")(0), " 0"); 146 | assert.strictEqual(format(">13,d")(0), " 0"); 147 | assert.strictEqual(format(">21,d")(0), " 0"); 148 | assert.strictEqual(format(">21,d")(1000), " 1,000"); 149 | assert.strictEqual(format(">21,d")(1e21), "1,000,000,000,000,000,000,000"); 150 | }); 151 | 152 | it("format(\"^d\") align center", () => { 153 | assert.strictEqual(format("^1,d")(0), "0"); 154 | assert.strictEqual(format("^1,d")(0), "0"); 155 | assert.strictEqual(format("^2,d")(0), "0 "); 156 | assert.strictEqual(format("^3,d")(0), " 0 "); 157 | assert.strictEqual(format("^5,d")(0), " 0 "); 158 | assert.strictEqual(format("^8,d")(0), " 0 "); 159 | assert.strictEqual(format("^13,d")(0), " 0 "); 160 | assert.strictEqual(format("^21,d")(0), " 0 "); 161 | assert.strictEqual(format("^21,d")(1000), " 1,000 "); 162 | assert.strictEqual(format("^21,d")(1e21), "1,000,000,000,000,000,000,000"); 163 | }); 164 | 165 | it("format(\"=+,d\") pad after sign", () => { 166 | assert.strictEqual(format("=+1,d")(0), "+0"); 167 | assert.strictEqual(format("=+1,d")(0), "+0"); 168 | assert.strictEqual(format("=+2,d")(0), "+0"); 169 | assert.strictEqual(format("=+3,d")(0), "+ 0"); 170 | assert.strictEqual(format("=+5,d")(0), "+ 0"); 171 | assert.strictEqual(format("=+8,d")(0), "+ 0"); 172 | assert.strictEqual(format("=+13,d")(0), "+ 0"); 173 | assert.strictEqual(format("=+21,d")(0), "+ 0"); 174 | assert.strictEqual(format("=+21,d")(1e21), "+1,000,000,000,000,000,000,000"); 175 | }); 176 | 177 | it("format(\"=+$,d\") pad after sign with currency", () => { 178 | assert.strictEqual(format("=+$1,d")(0), "+$0"); 179 | assert.strictEqual(format("=+$1,d")(0), "+$0"); 180 | assert.strictEqual(format("=+$2,d")(0), "+$0"); 181 | assert.strictEqual(format("=+$3,d")(0), "+$0"); 182 | assert.strictEqual(format("=+$5,d")(0), "+$ 0"); 183 | assert.strictEqual(format("=+$8,d")(0), "+$ 0"); 184 | assert.strictEqual(format("=+$13,d")(0), "+$ 0"); 185 | assert.strictEqual(format("=+$21,d")(0), "+$ 0"); 186 | assert.strictEqual(format("=+$21,d")(1e21), "+$1,000,000,000,000,000,000,000"); 187 | }); 188 | 189 | it("format(\" ,d\") a space can denote positive numbers", () => { 190 | assert.strictEqual(format(" 1,d")(-1), "−1"); 191 | assert.strictEqual(format(" 1,d")(0), " 0"); 192 | assert.strictEqual(format(" 2,d")(0), " 0"); 193 | assert.strictEqual(format(" 3,d")(0), " 0"); 194 | assert.strictEqual(format(" 5,d")(0), " 0"); 195 | assert.strictEqual(format(" 8,d")(0), " 0"); 196 | assert.strictEqual(format(" 13,d")(0), " 0"); 197 | assert.strictEqual(format(" 21,d")(0), " 0"); 198 | assert.strictEqual(format(" 21,d")(1e21), " 1,000,000,000,000,000,000,000"); 199 | }); 200 | 201 | it("format(\"-,d\") explicitly only use a sign for negative numbers", () => { 202 | assert.strictEqual(format("-1,d")(-1), "−1"); 203 | assert.strictEqual(format("-1,d")(0), "0"); 204 | assert.strictEqual(format("-2,d")(0), " 0"); 205 | assert.strictEqual(format("-3,d")(0), " 0"); 206 | assert.strictEqual(format("-5,d")(0), " 0"); 207 | assert.strictEqual(format("-8,d")(0), " 0"); 208 | assert.strictEqual(format("-13,d")(0), " 0"); 209 | assert.strictEqual(format("-21,d")(0), " 0"); 210 | }); 211 | 212 | it("format(\"d\") can format negative zero as zero", () => { 213 | assert.strictEqual(format("1d")(-0), "0"); 214 | assert.strictEqual(format("1d")(-1e-12), "0"); 215 | }); 216 | -------------------------------------------------------------------------------- /test/format-type-e-test.js: -------------------------------------------------------------------------------- 1 | import assert from "assert"; 2 | import {format} from "../src/index.js"; 3 | 4 | it("format(\"e\") can output exponent notation", () => { 5 | const f = format("e"); 6 | assert.strictEqual(f(0), "0.000000e+0"); 7 | assert.strictEqual(f(42), "4.200000e+1"); 8 | assert.strictEqual(f(42000000), "4.200000e+7"); 9 | assert.strictEqual(f(420000000), "4.200000e+8"); 10 | assert.strictEqual(f(-4), "−4.000000e+0"); 11 | assert.strictEqual(f(-42), "−4.200000e+1"); 12 | assert.strictEqual(f(-4200000), "−4.200000e+6"); 13 | assert.strictEqual(f(-42000000), "−4.200000e+7"); 14 | assert.strictEqual(format(".0e")(42), "4e+1") 15 | assert.strictEqual(format(".3e")(42), "4.200e+1") 16 | }); 17 | 18 | it("format(\"e\") can format negative zero as zero", () => { 19 | assert.strictEqual(format("1e")(-0), "0.000000e+0"); 20 | assert.strictEqual(format("1e")(-1e-12), "−1.000000e-12"); 21 | }); 22 | 23 | it("format(\",e\") does not group Infinity", () => { 24 | assert.strictEqual(format(",e")(Infinity), "Infinity"); 25 | }); 26 | 27 | it("format(\".3e\") can format negative infinity", () => { 28 | assert.strictEqual(format(".3e")(-Infinity), "−Infinity"); 29 | }); 30 | -------------------------------------------------------------------------------- /test/format-type-f-test.js: -------------------------------------------------------------------------------- 1 | import assert from "assert"; 2 | import {format} from "../src/index.js"; 3 | 4 | it("format(\"f\") can output fixed-point notation", () => { 5 | assert.strictEqual(format(".1f")(0.49), "0.5"); 6 | assert.strictEqual(format(".2f")(0.449), "0.45"); 7 | assert.strictEqual(format(".3f")(0.4449), "0.445"); 8 | assert.strictEqual(format(".5f")(0.444449), "0.44445"); 9 | assert.strictEqual(format(".1f")(100), "100.0"); 10 | assert.strictEqual(format(".2f")(100), "100.00"); 11 | assert.strictEqual(format(".3f")(100), "100.000"); 12 | assert.strictEqual(format(".5f")(100), "100.00000"); 13 | }); 14 | 15 | it("format(\"+$,f\") can output a currency with comma-grouping and sign", () => { 16 | const f = format("+$,.2f"); 17 | assert.strictEqual(f(0), "+$0.00"); 18 | assert.strictEqual(f(0.429), "+$0.43"); 19 | assert.strictEqual(f(-0.429), "−$0.43"); 20 | assert.strictEqual(f(-1), "−$1.00"); 21 | assert.strictEqual(f(1e4), "+$10,000.00"); 22 | }); 23 | 24 | it("format(\",.f\") can group thousands, space fill, and round to significant digits", () => { 25 | assert.strictEqual(format("10,.1f")(123456.49), " 123,456.5"); 26 | assert.strictEqual(format("10,.2f")(1234567.449), "1,234,567.45"); 27 | assert.strictEqual(format("10,.3f")(12345678.4449), "12,345,678.445"); 28 | assert.strictEqual(format("10,.5f")(123456789.444449), "123,456,789.44445"); 29 | assert.strictEqual(format("10,.1f")(123456), " 123,456.0"); 30 | assert.strictEqual(format("10,.2f")(1234567), "1,234,567.00"); 31 | assert.strictEqual(format("10,.3f")(12345678), "12,345,678.000"); 32 | assert.strictEqual(format("10,.5f")(123456789), "123,456,789.00000"); 33 | }); 34 | 35 | it("format(\"f\") can display integers in fixed-point notation", () => { 36 | assert.strictEqual(format("f")(42), "42.000000"); 37 | }); 38 | 39 | it("format(\"f\") can format negative zero as zero", () => { 40 | assert.strictEqual(format("f")(-0), "0.000000"); 41 | assert.strictEqual(format("f")(-1e-12), "0.000000"); 42 | }); 43 | 44 | it("format(\"+f\") signs negative zero correctly", () => { 45 | assert.strictEqual(format("+f")(-0), "−0.000000"); 46 | assert.strictEqual(format("+f")(+0), "+0.000000"); 47 | assert.strictEqual(format("+f")(-1e-12), "−0.000000"); 48 | assert.strictEqual(format("+f")(+1e-12), "+0.000000"); 49 | }); 50 | 51 | it("format(\"f\") can format negative infinity", () => { 52 | assert.strictEqual(format("f")(-Infinity), "−Infinity"); 53 | }); 54 | 55 | it("format(\",f\") does not group Infinity", () => { 56 | assert.strictEqual(format(",f")(Infinity), "Infinity"); 57 | }); 58 | -------------------------------------------------------------------------------- /test/format-type-g-test.js: -------------------------------------------------------------------------------- 1 | import assert from "assert"; 2 | import {format} from "../src/index.js"; 3 | 4 | it("format(\"g\") can output general notation", () => { 5 | assert.strictEqual(format(".1g")(0.049), "0.05"); 6 | assert.strictEqual(format(".1g")(0.49), "0.5"); 7 | assert.strictEqual(format(".2g")(0.449), "0.45"); 8 | assert.strictEqual(format(".3g")(0.4449), "0.445"); 9 | assert.strictEqual(format(".5g")(0.444449), "0.44445"); 10 | assert.strictEqual(format(".1g")(100), "1e+2"); 11 | assert.strictEqual(format(".2g")(100), "1.0e+2"); 12 | assert.strictEqual(format(".3g")(100), "100"); 13 | assert.strictEqual(format(".5g")(100), "100.00"); 14 | assert.strictEqual(format(".5g")(100.2), "100.20"); 15 | assert.strictEqual(format(".2g")(0.002), "0.0020"); 16 | }); 17 | 18 | it("format(\",g\") can group thousands with general notation", () => { 19 | const f = format(",.12g"); 20 | assert.strictEqual(f(0), "0.00000000000"); 21 | assert.strictEqual(f(42), "42.0000000000"); 22 | assert.strictEqual(f(42000000), "42,000,000.0000"); 23 | assert.strictEqual(f(420000000), "420,000,000.000"); 24 | assert.strictEqual(f(-4), "−4.00000000000"); 25 | assert.strictEqual(f(-42), "−42.0000000000"); 26 | assert.strictEqual(f(-4200000), "−4,200,000.00000"); 27 | assert.strictEqual(f(-42000000), "−42,000,000.0000"); 28 | }); 29 | -------------------------------------------------------------------------------- /test/format-type-n-test.js: -------------------------------------------------------------------------------- 1 | import assert from "assert"; 2 | import {format} from "../src/index.js"; 3 | 4 | it("format(\"n\") is an alias for \",g\"", () => { 5 | const f = format(".12n"); 6 | assert.strictEqual(f(0), "0.00000000000"); 7 | assert.strictEqual(f(42), "42.0000000000"); 8 | assert.strictEqual(f(42000000), "42,000,000.0000"); 9 | assert.strictEqual(f(420000000), "420,000,000.000"); 10 | assert.strictEqual(f(-4), "−4.00000000000"); 11 | assert.strictEqual(f(-42), "−42.0000000000"); 12 | assert.strictEqual(f(-4200000), "−4,200,000.00000"); 13 | assert.strictEqual(f(-42000000), "−42,000,000.0000"); 14 | assert.strictEqual(f(.0042), "0.00420000000000"); 15 | assert.strictEqual(f(.42), "0.420000000000"); 16 | assert.strictEqual(f(1e21), "1.00000000000e+21"); 17 | }); 18 | 19 | it("format(\"n\") uses zero padding", () => { 20 | assert.strictEqual(format("01.0n")(0), "0"); 21 | assert.strictEqual(format("02.0n")(0), "00"); 22 | assert.strictEqual(format("03.0n")(0), "000"); 23 | assert.strictEqual(format("05.0n")(0), "0,000"); 24 | assert.strictEqual(format("08.0n")(0), "0,000,000"); 25 | assert.strictEqual(format("013.0n")(0), "0,000,000,000"); 26 | assert.strictEqual(format("021.0n")(0), "0,000,000,000,000,000"); 27 | assert.strictEqual(format("013.8n")(-42000000), "−0,042,000,000"); 28 | }); 29 | -------------------------------------------------------------------------------- /test/format-type-none-test.js: -------------------------------------------------------------------------------- 1 | import assert from "assert"; 2 | import {format} from "../src/index.js"; 3 | 4 | it("format(\".[precision]\") uses significant precision and trims insignificant zeros", () => { 5 | assert.strictEqual(format(".1")(4.9), "5"); 6 | assert.strictEqual(format(".1")(0.49), "0.5"); 7 | assert.strictEqual(format(".2")(4.9), "4.9"); 8 | assert.strictEqual(format(".2")(0.49), "0.49"); 9 | assert.strictEqual(format(".2")(0.449), "0.45"); 10 | assert.strictEqual(format(".3")(4.9), "4.9"); 11 | assert.strictEqual(format(".3")(0.49), "0.49"); 12 | assert.strictEqual(format(".3")(0.449), "0.449"); 13 | assert.strictEqual(format(".3")(0.4449), "0.445"); 14 | assert.strictEqual(format(".5")(0.444449), "0.44445"); 15 | }); 16 | 17 | it("format(\".[precision]\") does not trim significant zeros", () => { 18 | assert.strictEqual(format(".5")(10), "10"); 19 | assert.strictEqual(format(".5")(100), "100"); 20 | assert.strictEqual(format(".5")(1000), "1000"); 21 | assert.strictEqual(format(".5")(21010), "21010"); 22 | assert.strictEqual(format(".5")(1.10001), "1.1"); 23 | assert.strictEqual(format(".5")(1.10001e6), "1.1e+6"); 24 | assert.strictEqual(format(".6")(1.10001), "1.10001"); 25 | assert.strictEqual(format(".6")(1.10001e6), "1.10001e+6"); 26 | }); 27 | 28 | it("format(\".[precision]\") also trims the decimal point if there are only insignificant zeros", () => { 29 | assert.strictEqual(format(".5")(1.00001), "1"); 30 | assert.strictEqual(format(".5")(1.00001e6), "1e+6"); 31 | assert.strictEqual(format(".6")(1.00001), "1.00001"); 32 | assert.strictEqual(format(".6")(1.00001e6), "1.00001e+6"); 33 | }); 34 | 35 | it("format(\"$\") can output a currency", () => { 36 | const f = format("$"); 37 | assert.strictEqual(f(0), "$0"); 38 | assert.strictEqual(f(.042), "$0.042"); 39 | assert.strictEqual(f(.42), "$0.42"); 40 | assert.strictEqual(f(4.2), "$4.2"); 41 | assert.strictEqual(f(-.042), "−$0.042"); 42 | assert.strictEqual(f(-.42), "−$0.42"); 43 | assert.strictEqual(f(-4.2), "−$4.2"); 44 | }); 45 | 46 | it("format(\"($\") can output a currency with parentheses for negative values", () => { 47 | const f = format("($"); 48 | assert.strictEqual(f(0), "$0"); 49 | assert.strictEqual(f(.042), "$0.042"); 50 | assert.strictEqual(f(.42), "$0.42"); 51 | assert.strictEqual(f(4.2), "$4.2"); 52 | assert.strictEqual(f(-.042), "($0.042)"); 53 | assert.strictEqual(f(-.42), "($0.42)"); 54 | assert.strictEqual(f(-4.2), "($4.2)"); 55 | }); 56 | 57 | it("format(\"\") can format negative zero as zero", () => { 58 | assert.strictEqual(format("")(-0), "0"); 59 | }); 60 | 61 | it("format(\"\") can format negative infinity", () => { 62 | assert.strictEqual(format("")(-Infinity), "−Infinity"); 63 | }); 64 | -------------------------------------------------------------------------------- /test/format-type-o-test.js: -------------------------------------------------------------------------------- 1 | import assert from "assert"; 2 | import {format} from "../src/index.js"; 3 | 4 | it("format(\"o\") octal", () => { 5 | assert.strictEqual(format("o")(10), "12"); 6 | }); 7 | 8 | it("format(\"#o\") octal with prefix", () => { 9 | assert.strictEqual(format("#o")(10), "0o12"); 10 | }); 11 | -------------------------------------------------------------------------------- /test/format-type-p-test.js: -------------------------------------------------------------------------------- 1 | import assert from "assert"; 2 | import {format} from "../src/index.js"; 3 | 4 | it("format(\"p\") can output a percentage", () => { 5 | const f = format("p"); 6 | assert.strictEqual(f(.00123), "0.123000%"); 7 | assert.strictEqual(f(.0123), "1.23000%"); 8 | assert.strictEqual(f(.123), "12.3000%"); 9 | assert.strictEqual(f(.234), "23.4000%"); 10 | assert.strictEqual(f(1.23), "123.000%"); 11 | assert.strictEqual(f(-.00123), "−0.123000%"); 12 | assert.strictEqual(f(-.0123), "−1.23000%"); 13 | assert.strictEqual(f(-.123), "−12.3000%"); 14 | assert.strictEqual(f(-1.23), "−123.000%"); 15 | }); 16 | 17 | it("format(\"+p\") can output a percentage with rounding and sign", () => { 18 | const f = format("+.2p"); 19 | assert.strictEqual(f(.00123), "+0.12%"); 20 | assert.strictEqual(f(.0123), "+1.2%"); 21 | assert.strictEqual(f(.123), "+12%"); 22 | assert.strictEqual(f(1.23), "+120%"); 23 | assert.strictEqual(f(-.00123), "−0.12%"); 24 | assert.strictEqual(f(-.0123), "−1.2%"); 25 | assert.strictEqual(f(-.123), "−12%"); 26 | assert.strictEqual(f(-1.23), "−120%"); 27 | }); 28 | -------------------------------------------------------------------------------- /test/format-type-r-test.js: -------------------------------------------------------------------------------- 1 | import assert from "assert"; 2 | import {format} from "../src/index.js"; 3 | 4 | it("format(\"r\") can round to significant digits", () => { 5 | assert.strictEqual(format(".2r")(0), "0.0"); 6 | assert.strictEqual(format(".1r")(0.049), "0.05"); 7 | assert.strictEqual(format(".1r")(-0.049), "−0.05"); 8 | assert.strictEqual(format(".1r")(0.49), "0.5"); 9 | assert.strictEqual(format(".1r")(-0.49), "−0.5"); 10 | assert.strictEqual(format(".2r")(0.449), "0.45"); 11 | assert.strictEqual(format(".3r")(0.4449), "0.445"); 12 | assert.strictEqual(format(".3r")(1.00), "1.00"); 13 | assert.strictEqual(format(".3r")(0.9995), "1.00"); 14 | assert.strictEqual(format(".5r")(0.444449), "0.44445"); 15 | assert.strictEqual(format("r")(123.45), "123.450"); 16 | assert.strictEqual(format(".1r")(123.45), "100"); 17 | assert.strictEqual(format(".2r")(123.45), "120"); 18 | assert.strictEqual(format(".3r")(123.45), "123"); 19 | assert.strictEqual(format(".4r")(123.45), "123.5"); 20 | assert.strictEqual(format(".5r")(123.45), "123.45"); 21 | assert.strictEqual(format(".6r")(123.45), "123.450"); 22 | assert.strictEqual(format(".1r")(.9), "0.9"); 23 | assert.strictEqual(format(".1r")(.09), "0.09"); 24 | assert.strictEqual(format(".1r")(.949), "0.9"); 25 | assert.strictEqual(format(".1r")(.0949), "0.09"); 26 | assert.strictEqual(format(".1r")(.0000000129), "0.00000001"); 27 | assert.strictEqual(format(".2r")(.0000000129), "0.000000013"); 28 | assert.strictEqual(format(".2r")(.00000000129), "0.0000000013"); 29 | assert.strictEqual(format(".3r")(.00000000129), "0.00000000129"); 30 | assert.strictEqual(format(".4r")(.00000000129), "0.000000001290"); 31 | assert.strictEqual(format(".10r")(.9999999999), "0.9999999999"); 32 | assert.strictEqual(format(".15r")(.999999999999999), "0.999999999999999"); 33 | }); 34 | 35 | it("format(\"r\") can round very small numbers", () => { 36 | const f = format(".2r"); 37 | assert.strictEqual(f(1e-22), "0.00000000000000000000010"); 38 | }); 39 | -------------------------------------------------------------------------------- /test/format-type-s-test.js: -------------------------------------------------------------------------------- 1 | import assert from "assert"; 2 | import {format} from "../src/index.js"; 3 | 4 | it("format(\"s\") outputs SI-prefix notation with default precision 6", () => { 5 | const f = format("s"); 6 | assert.strictEqual(f(0), "0.00000"); 7 | assert.strictEqual(f(1), "1.00000"); 8 | assert.strictEqual(f(10), "10.0000"); 9 | assert.strictEqual(f(100), "100.000"); 10 | assert.strictEqual(f(999.5), "999.500"); 11 | assert.strictEqual(f(999500), "999.500k"); 12 | assert.strictEqual(f(1000), "1.00000k"); 13 | assert.strictEqual(f(100), "100.000"); 14 | assert.strictEqual(f(1400), "1.40000k"); 15 | assert.strictEqual(f(1500.5), "1.50050k"); 16 | assert.strictEqual(f(.00001), "10.0000µ"); 17 | assert.strictEqual(f(.000001), "1.00000µ"); 18 | }); 19 | 20 | it("format(\"[.precision]s\") outputs SI-prefix notation with precision significant digits", () => { 21 | const f1 = format(".3s"); 22 | assert.strictEqual(f1(0), "0.00"); 23 | assert.strictEqual(f1(1), "1.00"); 24 | assert.strictEqual(f1(10), "10.0"); 25 | assert.strictEqual(f1(100), "100"); 26 | assert.strictEqual(f1(999.5), "1.00k"); 27 | assert.strictEqual(f1(999500), "1.00M"); 28 | assert.strictEqual(f1(1000), "1.00k"); 29 | assert.strictEqual(f1(1500.5), "1.50k"); 30 | assert.strictEqual(f1(145500000), "146M"); 31 | assert.strictEqual(f1(145999999.99999347), "146M"); 32 | assert.strictEqual(f1(1e26), "100Y"); 33 | assert.strictEqual(f1(.000001), "1.00µ"); 34 | assert.strictEqual(f1(.009995), "10.0m"); 35 | const f2 = format(".4s"); 36 | assert.strictEqual(f2(999.5), "999.5"); 37 | assert.strictEqual(f2(999500), "999.5k"); 38 | assert.strictEqual(f2(.009995), "9.995m"); 39 | }); 40 | 41 | it("format(\"s\") formats numbers smaller than 1e-24 with yocto", () => { 42 | const f = format(".8s"); 43 | assert.strictEqual(f(1.29e-30), "0.0000013y"); // Note: rounded! 44 | assert.strictEqual(f(1.29e-29), "0.0000129y"); 45 | assert.strictEqual(f(1.29e-28), "0.0001290y"); 46 | assert.strictEqual(f(1.29e-27), "0.0012900y"); 47 | assert.strictEqual(f(1.29e-26), "0.0129000y"); 48 | assert.strictEqual(f(1.29e-25), "0.1290000y"); 49 | assert.strictEqual(f(1.29e-24), "1.2900000y"); 50 | assert.strictEqual(f(1.29e-23), "12.900000y"); 51 | assert.strictEqual(f(1.29e-22), "129.00000y"); 52 | assert.strictEqual(f(1.29e-21), "1.2900000z"); 53 | assert.strictEqual(f(-1.29e-30), "−0.0000013y"); // Note: rounded! 54 | assert.strictEqual(f(-1.29e-29), "−0.0000129y"); 55 | assert.strictEqual(f(-1.29e-28), "−0.0001290y"); 56 | assert.strictEqual(f(-1.29e-27), "−0.0012900y"); 57 | assert.strictEqual(f(-1.29e-26), "−0.0129000y"); 58 | assert.strictEqual(f(-1.29e-25), "−0.1290000y"); 59 | assert.strictEqual(f(-1.29e-24), "−1.2900000y"); 60 | assert.strictEqual(f(-1.29e-23), "−12.900000y"); 61 | assert.strictEqual(f(-1.29e-22), "−129.00000y"); 62 | assert.strictEqual(f(-1.29e-21), "−1.2900000z"); 63 | }); 64 | 65 | it("format(\"s\") formats numbers larger than 1e24 with yotta", () => { 66 | const f = format(".8s"); 67 | assert.strictEqual(f(1.23e+21), "1.2300000Z"); 68 | assert.strictEqual(f(1.23e+22), "12.300000Z"); 69 | assert.strictEqual(f(1.23e+23), "123.00000Z"); 70 | assert.strictEqual(f(1.23e+24), "1.2300000Y"); 71 | assert.strictEqual(f(1.23e+25), "12.300000Y"); 72 | assert.strictEqual(f(1.23e+26), "123.00000Y"); 73 | assert.strictEqual(f(1.23e+27), "1230.0000Y"); 74 | assert.strictEqual(f(1.23e+28), "12300.000Y"); 75 | assert.strictEqual(f(1.23e+29), "123000.00Y"); 76 | assert.strictEqual(f(1.23e+30), "1230000.0Y"); 77 | assert.strictEqual(f(-1.23e+21), "−1.2300000Z"); 78 | assert.strictEqual(f(-1.23e+22), "−12.300000Z"); 79 | assert.strictEqual(f(-1.23e+23), "−123.00000Z"); 80 | assert.strictEqual(f(-1.23e+24), "−1.2300000Y"); 81 | assert.strictEqual(f(-1.23e+25), "−12.300000Y"); 82 | assert.strictEqual(f(-1.23e+26), "−123.00000Y"); 83 | assert.strictEqual(f(-1.23e+27), "−1230.0000Y"); 84 | assert.strictEqual(f(-1.23e+28), "−12300.000Y"); 85 | assert.strictEqual(f(-1.23e+29), "−123000.00Y"); 86 | assert.strictEqual(f(-1.23e+30), "−1230000.0Y"); 87 | }); 88 | 89 | it("format(\"$s\") outputs SI-prefix notation with a currency symbol", () => { 90 | const f1 = format("$.2s"); 91 | assert.strictEqual(f1(0), "$0.0"); 92 | assert.strictEqual(f1(2.5e5), "$250k"); 93 | assert.strictEqual(f1(-2.5e8), "−$250M"); 94 | assert.strictEqual(f1(2.5e11), "$250G"); 95 | const f2 = format("$.3s"); 96 | assert.strictEqual(f2(0), "$0.00"); 97 | assert.strictEqual(f2(1), "$1.00"); 98 | assert.strictEqual(f2(10), "$10.0"); 99 | assert.strictEqual(f2(100), "$100"); 100 | assert.strictEqual(f2(999.5), "$1.00k"); 101 | assert.strictEqual(f2(999500), "$1.00M"); 102 | assert.strictEqual(f2(1000), "$1.00k"); 103 | assert.strictEqual(f2(1500.5), "$1.50k"); 104 | assert.strictEqual(f2(145500000), "$146M"); 105 | assert.strictEqual(f2(145999999.9999347), "$146M"); 106 | assert.strictEqual(f2(1e26), "$100Y"); 107 | assert.strictEqual(f2(.000001), "$1.00µ"); 108 | assert.strictEqual(f2(.009995), "$10.0m"); 109 | const f3 = format("$.4s"); 110 | assert.strictEqual(f3(999.5), "$999.5"); 111 | assert.strictEqual(f3(999500), "$999.5k"); 112 | assert.strictEqual(f3(.009995), "$9.995m"); 113 | }); 114 | 115 | it("format(\"s\") SI-prefix notation precision is consistent for small and large numbers", () => { 116 | const f1 = format(".0s"); 117 | assert.strictEqual(f1(1e-5), "10µ"); 118 | assert.strictEqual(f1(1e-4), "100µ"); 119 | assert.strictEqual(f1(1e-3), "1m"); 120 | assert.strictEqual(f1(1e-2), "10m"); 121 | assert.strictEqual(f1(1e-1), "100m"); 122 | assert.strictEqual(f1(1e+0), "1"); 123 | assert.strictEqual(f1(1e+1), "10"); 124 | assert.strictEqual(f1(1e+2), "100"); 125 | assert.strictEqual(f1(1e+3), "1k"); 126 | assert.strictEqual(f1(1e+4), "10k"); 127 | assert.strictEqual(f1(1e+5), "100k"); 128 | const f2 = format(".4s"); 129 | assert.strictEqual(f2(1e-5), "10.00µ"); 130 | assert.strictEqual(f2(1e-4), "100.0µ"); 131 | assert.strictEqual(f2(1e-3), "1.000m"); 132 | assert.strictEqual(f2(1e-2), "10.00m"); 133 | assert.strictEqual(f2(1e-1), "100.0m"); 134 | assert.strictEqual(f2(1e+0), "1.000"); 135 | assert.strictEqual(f2(1e+1), "10.00"); 136 | assert.strictEqual(f2(1e+2), "100.0"); 137 | assert.strictEqual(f2(1e+3), "1.000k"); 138 | assert.strictEqual(f2(1e+4), "10.00k"); 139 | assert.strictEqual(f2(1e+5), "100.0k"); 140 | }); 141 | 142 | it("format(\"0[width],s\") will group thousands due to zero fill", () => { 143 | const f = format("020,s"); 144 | assert.strictEqual(f(42), "000,000,000,042.0000"); 145 | assert.strictEqual(f(42e12), "00,000,000,042.0000T"); 146 | }); 147 | 148 | it("format(\",s\") will group thousands for very large numbers", () => { 149 | const f = format(",s"); 150 | assert.strictEqual(f(42e30), "42,000,000Y"); 151 | }); 152 | -------------------------------------------------------------------------------- /test/format-type-x-test.js: -------------------------------------------------------------------------------- 1 | import assert from "assert"; 2 | import {format} from "../src/index.js"; 3 | 4 | it("format(\"x\") returns the expected hexadecimal (lowercase) string", () => { 5 | assert.strictEqual(format("x")(0xdeadbeef), "deadbeef"); 6 | }); 7 | 8 | it("format(\"#x\") returns the expected hexadecimal (lowercase) string with prefix", () => { 9 | assert.strictEqual(format("#x")(0xdeadbeef), "0xdeadbeef"); 10 | }); 11 | 12 | it("format(\",x\") groups thousands", () => { 13 | assert.strictEqual(format(",x")(0xdeadbeef), "de,adb,eef"); 14 | }); 15 | 16 | it("format(\",x\") groups thousands", () => { 17 | assert.strictEqual(format(",x")(0xdeadbeef), "de,adb,eef"); 18 | }); 19 | 20 | it("format(\"#,x\") does not group the prefix", () => { 21 | assert.strictEqual(format("#,x")(0xadeadbeef), "0xade,adb,eef"); 22 | }); 23 | 24 | it("format(\"+#x\") puts the sign before the prefix", () => { 25 | assert.strictEqual(format("+#x")(0xdeadbeef), "+0xdeadbeef"); 26 | assert.strictEqual(format("+#x")(-0xdeadbeef), "−0xdeadbeef"); 27 | assert.strictEqual(format(" #x")(0xdeadbeef), " 0xdeadbeef"); 28 | assert.strictEqual(format(" #x")(-0xdeadbeef), "−0xdeadbeef"); 29 | }); 30 | 31 | it("format(\"$,x\") formats hexadecimal currency", () => { 32 | assert.strictEqual(format("$,x")(0xdeadbeef), "$de,adb,eef"); 33 | }); 34 | 35 | it("format(\"[.precision]x\") always has precision zero", () => { 36 | assert.strictEqual(format(".2x")(0xdeadbeef), "deadbeef"); 37 | assert.strictEqual(format(".2x")(-4.2), "−4"); 38 | }); 39 | 40 | it("format(\"x\") rounds non-integers", () => { 41 | assert.strictEqual(format("x")(2.4), "2"); 42 | }); 43 | 44 | it("format(\"x\") can format negative zero as zero", () => { 45 | assert.strictEqual(format("x")(-0), "0"); 46 | assert.strictEqual(format("x")(-1e-12), "0"); 47 | }); 48 | 49 | it("format(\"x\") does not consider -0xeee to be positive", () => { 50 | assert.strictEqual(format("x")(-0xeee), "−eee"); 51 | }); 52 | 53 | it("format(\"X\") returns the expected hexadecimal (uppercase) string", () => { 54 | assert.strictEqual(format("X")(0xdeadbeef), "DEADBEEF"); 55 | }); 56 | 57 | it("format(\"#X\") returns the expected hexadecimal (uppercase) string with prefix", () => { 58 | assert.strictEqual(format("#X")(0xdeadbeef), "0xDEADBEEF"); 59 | }); 60 | 61 | it("format(\"X\") can format negative zero as zero", () => { 62 | assert.strictEqual(format("X")(-0), "0"); 63 | assert.strictEqual(format("X")(-1e-12), "0"); 64 | }); 65 | 66 | it("format(\"X\") does not consider -0xeee to be positive", () => { 67 | assert.strictEqual(format("X")(-0xeee), "−EEE"); 68 | }); 69 | 70 | it("format(\"#[width]x\") considers the prefix", () => { 71 | assert.strictEqual(format("20x")(0xdeadbeef), " deadbeef"); 72 | assert.strictEqual(format("#20x")(0xdeadbeef), " 0xdeadbeef"); 73 | assert.strictEqual(format("020x")(0xdeadbeef), "000000000000deadbeef"); 74 | assert.strictEqual(format("#020x")(0xdeadbeef), "0x0000000000deadbeef"); 75 | }); 76 | -------------------------------------------------------------------------------- /test/formatPrefix-test.js: -------------------------------------------------------------------------------- 1 | import assert from "assert"; 2 | import {formatPrefix} from "../src/index.js"; 3 | 4 | it("formatPrefix(\"s\", value)(number) formats with the SI prefix appropriate to the specified value", () => { 5 | assert.strictEqual(formatPrefix(",.0s", 1e-6)(.00042), "420µ"); 6 | assert.strictEqual(formatPrefix(",.0s", 1e-6)(.0042), "4,200µ"); 7 | assert.strictEqual(formatPrefix(",.3s", 1e-3)(.00042), "0.420m"); 8 | }); 9 | 10 | it("formatPrefix(\"s\", value)(number) uses yocto for very small reference values", () => { 11 | assert.strictEqual(formatPrefix(",.0s", 1e-27)(1e-24), "1y"); 12 | }); 13 | 14 | it("formatPrefix(\"s\", value)(number) uses yotta for very small reference values", () => { 15 | assert.strictEqual(formatPrefix(",.0s", 1e27)(1e24), "1Y"); 16 | }); 17 | 18 | it("formatPrefix(\"$,s\", value)(number) formats with the specified SI prefix", () => { 19 | const f = formatPrefix(" $12,.1s", 1e6); 20 | assert.strictEqual(f(-42e6), " −$42.0M"); 21 | assert.strictEqual(f(+4.2e6), " $4.2M"); 22 | }); 23 | -------------------------------------------------------------------------------- /test/formatSpecifier-test.js: -------------------------------------------------------------------------------- 1 | import assert from "assert"; 2 | import {format, formatSpecifier, FormatSpecifier} from "../src/index.js"; 3 | 4 | it("formatSpecifier(specifier) throws an error for invalid formats", () => { 5 | assert.throws(() => { formatSpecifier("foo"); }, /invalid format: foo/); 6 | assert.throws(() => { formatSpecifier(".-2s"); }, /invalid format: \.-2s/); 7 | assert.throws(() => { formatSpecifier(".f"); }, /invalid format: \.f/); 8 | }); 9 | 10 | it("formatSpecifier(specifier) returns an instanceof formatSpecifier", () => { 11 | const s = formatSpecifier(""); 12 | assert.strictEqual(s instanceof formatSpecifier, true); 13 | }); 14 | 15 | it("formatSpecifier(\"\") has the expected defaults", () => { 16 | const s = formatSpecifier(""); 17 | assert.strictEqual(s.fill, " "); 18 | assert.strictEqual(s.align, ">"); 19 | assert.strictEqual(s.sign, "-"); 20 | assert.strictEqual(s.symbol, ""); 21 | assert.strictEqual(s.zero, false); 22 | assert.strictEqual(s.width, undefined); 23 | assert.strictEqual(s.comma, false); 24 | assert.strictEqual(s.precision, undefined); 25 | assert.strictEqual(s.trim, false); 26 | assert.strictEqual(s.type, ""); 27 | }); 28 | 29 | it("formatSpecifier(specifier) preserves unknown types", () => { 30 | const s = formatSpecifier("q"); 31 | assert.strictEqual(s.trim, false); 32 | assert.strictEqual(s.type, "q"); 33 | }); 34 | 35 | it("formatSpecifier(specifier) preserves shorthand", () => { 36 | const s = formatSpecifier(""); 37 | assert.strictEqual(s.trim, false); 38 | assert.strictEqual(s.type, ""); 39 | }); 40 | 41 | it("formatSpecifier(specifier).toString() reflects current field values", () => { 42 | const s = formatSpecifier(""); 43 | assert.strictEqual((s.fill = "_", s) + "", "_>-"); 44 | assert.strictEqual((s.align = "^", s) + "", "_^-"); 45 | assert.strictEqual((s.sign = "+", s) + "", "_^+"); 46 | assert.strictEqual((s.symbol = "$", s) + "", "_^+$"); 47 | assert.strictEqual((s.zero = true, s) + "", "_^+$0"); 48 | assert.strictEqual((s.width = 12, s) + "", "_^+$012"); 49 | assert.strictEqual((s.comma = true, s) + "", "_^+$012,"); 50 | assert.strictEqual((s.precision = 2, s) + "", "_^+$012,.2"); 51 | assert.strictEqual((s.type = "f", s) + "", "_^+$012,.2f"); 52 | assert.strictEqual((s.trim = true, s) + "", "_^+$012,.2~f"); 53 | assert.strictEqual(format(s)(42), "+$0,000,000,042"); 54 | }); 55 | 56 | it("formatSpecifier(specifier).toString() clamps precision to zero", () => { 57 | const s = formatSpecifier(""); 58 | assert.strictEqual((s.precision = -1, s) + "", " >-.0"); 59 | }); 60 | 61 | it("formatSpecifier(specifier).toString() clamps width to one", () => { 62 | const s = formatSpecifier(""); 63 | assert.strictEqual((s.width = -1, s) + "", " >-1"); 64 | }); 65 | 66 | it("new FormatSpecifier({}) has the expected defaults", () => { 67 | const s = new FormatSpecifier({}); 68 | assert.strictEqual(s.fill, " "); 69 | assert.strictEqual(s.align, ">"); 70 | assert.strictEqual(s.sign, "-"); 71 | assert.strictEqual(s.symbol, ""); 72 | assert.strictEqual(s.zero, false); 73 | assert.strictEqual(s.width, undefined); 74 | assert.strictEqual(s.comma, false); 75 | assert.strictEqual(s.precision, undefined); 76 | assert.strictEqual(s.trim, false); 77 | assert.strictEqual(s.type, ""); 78 | }); 79 | 80 | it("new FormatSpecifier({…}) coerces all inputs to the expected types", () => { 81 | const s = new FormatSpecifier({ 82 | fill: 1, 83 | align: 2, 84 | sign: 3, 85 | symbol: 4, 86 | zero: 5, 87 | width: 6, 88 | comma: 7, 89 | precision: 8, 90 | trim: 9, 91 | type: 10 92 | }); 93 | assert.strictEqual(s.fill, "1"); 94 | assert.strictEqual(s.align, "2"); 95 | assert.strictEqual(s.sign, "3"); 96 | assert.strictEqual(s.symbol, "4"); 97 | assert.strictEqual(s.zero, true); 98 | assert.strictEqual(s.width, 6); 99 | assert.strictEqual(s.comma, true); 100 | assert.strictEqual(s.precision, 8); 101 | assert.strictEqual(s.trim, true); 102 | assert.strictEqual(s.type, "10"); 103 | }); 104 | -------------------------------------------------------------------------------- /test/locale-test.js: -------------------------------------------------------------------------------- 1 | import assert from "assert"; 2 | import {readdirSync, readFileSync} from "fs"; 3 | import {join} from "path"; 4 | import {formatLocale} from "../src/index.js"; 5 | 6 | function locale(locale) { 7 | return formatLocale(JSON.parse(readFileSync(`./locale/${locale}.json`, "utf8"))); 8 | } 9 | 10 | it("formatLocale({decimal: decimal}) observes the specified decimal point", () => { 11 | assert.strictEqual(formatLocale({decimal: "|"}).format("06.2f")(2), "002|00"); 12 | assert.strictEqual(formatLocale({decimal: "/"}).format("06.2f")(2), "002/00"); 13 | }); 14 | 15 | it("formatLocale({currency: [prefix, suffix]}) observes the specified currency prefix and suffix", () => { 16 | assert.strictEqual(formatLocale({decimal: ".", currency: ["฿", ""]}).format("$06.2f")(2), "฿02.00"); 17 | assert.strictEqual(formatLocale({decimal: ".", currency: ["", "฿"]}).format("$06.2f")(2), "02.00฿"); 18 | }); 19 | 20 | it("formatLocale({currency: [prefix, suffix]}) places the currency suffix after the SI suffix", () => { 21 | assert.strictEqual(formatLocale({decimal: ",", currency: ["", " €"]}).format("$.3s")(1.2e9), "1,20G €"); 22 | }); 23 | 24 | it("formatLocale({grouping: undefined}) does not perform any grouping", () => { 25 | assert.strictEqual(formatLocale({decimal: "."}).format("012,.2f")(2), "000000002.00"); 26 | }); 27 | 28 | it("formatLocale({grouping: [sizes…]}) observes the specified group sizes", () => { 29 | assert.strictEqual(formatLocale({decimal: ".", grouping: [3], thousands: ","}).format("012,.2f")(2), "0,000,002.00"); 30 | assert.strictEqual(formatLocale({decimal: ".", grouping: [2], thousands: ","}).format("012,.2f")(2), "0,00,00,02.00"); 31 | assert.strictEqual(formatLocale({decimal: ".", grouping: [2, 3], thousands: ","}).format("012,.2f")(2), "00,000,02.00"); 32 | assert.strictEqual(formatLocale({decimal: ".", grouping: [3, 2, 2, 2, 2, 2, 2], thousands: ","}).format(",d")(1e12), "10,00,00,00,00,000"); 33 | }); 34 | 35 | it("formatLocale(…) can format numbers using the Indian numbering system.", () => { 36 | const format = locale("en-IN").format(","); 37 | assert.strictEqual(format(10), "10"); 38 | assert.strictEqual(format(100), "100"); 39 | assert.strictEqual(format(1000), "1,000"); 40 | assert.strictEqual(format(10000), "10,000"); 41 | assert.strictEqual(format(100000), "1,00,000"); 42 | assert.strictEqual(format(1000000), "10,00,000"); 43 | assert.strictEqual(format(10000000), "1,00,00,000"); 44 | assert.strictEqual(format(10000000.4543), "1,00,00,000.4543"); 45 | assert.strictEqual(format(1000.321), "1,000.321"); 46 | assert.strictEqual(format(10.5), "10.5"); 47 | assert.strictEqual(format(-10), "−10"); 48 | assert.strictEqual(format(-100), "−100"); 49 | assert.strictEqual(format(-1000), "−1,000"); 50 | assert.strictEqual(format(-10000), "−10,000"); 51 | assert.strictEqual(format(-100000), "−1,00,000"); 52 | assert.strictEqual(format(-1000000), "−10,00,000"); 53 | assert.strictEqual(format(-10000000), "−1,00,00,000"); 54 | assert.strictEqual(format(-10000000.4543), "−1,00,00,000.4543"); 55 | assert.strictEqual(format(-1000.321), "−1,000.321"); 56 | assert.strictEqual(format(-10.5), "−10.5"); 57 | }); 58 | 59 | it("formatLocale({thousands: separator}) observes the specified group separator", () => { 60 | assert.strictEqual(formatLocale({decimal: ".", grouping: [3], thousands: " "}).format("012,.2f")(2), "0 000 002.00"); 61 | assert.strictEqual(formatLocale({decimal: ".", grouping: [3], thousands: "/"}).format("012,.2f")(2), "0/000/002.00"); 62 | }); 63 | 64 | it("formatLocale({percent: percent}) observes the specified percent sign", () => { 65 | assert.strictEqual(formatLocale({decimal: ".", percent: "!"}).format("06.2%")(2), "200.00!"); 66 | assert.strictEqual(formatLocale({decimal: ".", percent: "﹪"}).format("06.2%")(2), "200.00﹪"); 67 | }); 68 | 69 | it("formatLocale({minus: minus}) observes the specified minus sign", () => { 70 | assert.strictEqual(formatLocale({decimal: ".", minus: "-"}).format("06.2f")(-2), "-02.00"); 71 | assert.strictEqual(formatLocale({decimal: ".", minus: "−"}).format("06.2f")(-2), "−02.00"); 72 | assert.strictEqual(formatLocale({decimal: ".", minus: "➖"}).format("06.2f")(-2), "➖02.00"); 73 | assert.strictEqual(formatLocale({decimal: "."}).format("06.2f")(-2), "−02.00"); 74 | }); 75 | 76 | it("formatLocale({nan: nan}) observes the specified not-a-number representation", () => { 77 | assert.strictEqual(formatLocale({nan: "N/A"}).format("6.2f")(undefined), " N/A"); 78 | assert.strictEqual(formatLocale({nan: "-"}).format("<6.2g")(undefined), "- "); 79 | assert.strictEqual(formatLocale({}).format(" 6.2f")(undefined), " NaN"); 80 | }); 81 | 82 | it("locale data is valid", async () => { 83 | for (const file of readdirSync("locale")) { 84 | if (!/\.json$/i.test(file)) continue; 85 | const locale = JSON.parse(readFileSync(join("locale", file), "utf8")); 86 | assert.strictEqual("currency" in locale, true); 87 | assert.strictEqual("decimal" in locale, true); 88 | assert.strictEqual("grouping" in locale, true); 89 | assert.strictEqual("thousands" in locale, true); 90 | formatLocale(locale); 91 | } 92 | }); 93 | -------------------------------------------------------------------------------- /test/precisionFixed-test.js: -------------------------------------------------------------------------------- 1 | import assert from "assert"; 2 | import {precisionFixed} from "../src/index.js"; 3 | 4 | it("precisionFixed(number) returns the expected value", () => { 5 | assert.strictEqual(precisionFixed(8.9), 0); 6 | assert.strictEqual(precisionFixed(1.1), 0); 7 | assert.strictEqual(precisionFixed(0.89), 1); 8 | assert.strictEqual(precisionFixed(0.11), 1); 9 | assert.strictEqual(precisionFixed(0.089), 2); 10 | assert.strictEqual(precisionFixed(0.011), 2); 11 | }); 12 | -------------------------------------------------------------------------------- /test/precisionPrefix-test.js: -------------------------------------------------------------------------------- 1 | import assert from "assert"; 2 | import {precisionPrefix} from "../src/index.js"; 3 | 4 | // A generalization from µ to all prefixes: 5 | // assert.strictEqual(precisionPrefix(1e-6, 1e-6), 0); // 1µ 6 | // assert.strictEqual(precisionPrefix(1e-6, 1e-7), 0); // 10µ 7 | // assert.strictEqual(precisionPrefix(1e-6, 1e-8), 0); // 100µ 8 | it("precisionPrefix(step, value) returns zero if step has the same units as value", () => { 9 | for (var i = -24; i <= 24; i += 3) { 10 | for (var j = i; j < i + 3; ++j) { 11 | assert.strictEqual(precisionPrefix(+("1e" + i), +("1e" + j)), 0); 12 | } 13 | } 14 | }); 15 | 16 | // A generalization from µ to all prefixes: 17 | // assert.strictEqual(precisionPrefix(1e-9, 1e-6), 3); // 0.001µ 18 | // assert.strictEqual(precisionPrefix(1e-8, 1e-6), 2); // 0.01µ 19 | // assert.strictEqual(precisionPrefix(1e-7, 1e-6), 1); // 0.1µ 20 | it("precisionPrefix(step, value) returns greater than zero if fractional digits are needed", () => { 21 | for (var i = -24; i <= 24; i += 3) { 22 | for (var j = i - 4; j < i; ++j) { 23 | assert.strictEqual(precisionPrefix(+("1e" + j), +("1e" + i)), i - j); 24 | } 25 | } 26 | }); 27 | 28 | it("precisionPrefix(step, value) returns the expected precision when value is less than one yocto", () => { 29 | assert.strictEqual(precisionPrefix(1e-24, 1e-24), 0); // 1y 30 | assert.strictEqual(precisionPrefix(1e-25, 1e-25), 1); // 0.1y 31 | assert.strictEqual(precisionPrefix(1e-26, 1e-26), 2); // 0.01y 32 | assert.strictEqual(precisionPrefix(1e-27, 1e-27), 3); // 0.001y 33 | assert.strictEqual(precisionPrefix(1e-28, 1e-28), 4); // 0.0001y 34 | }); 35 | 36 | it("precisionPrefix(step, value) returns the expected precision when value is greater than than one yotta", () => { 37 | assert.strictEqual(precisionPrefix(1e24, 1e24), 0); // 1Y 38 | assert.strictEqual(precisionPrefix(1e24, 1e25), 0); // 10Y 39 | assert.strictEqual(precisionPrefix(1e24, 1e26), 0); // 100Y 40 | assert.strictEqual(precisionPrefix(1e24, 1e27), 0); // 1000Y 41 | assert.strictEqual(precisionPrefix(1e23, 1e27), 1); // 1000.0Y 42 | }); 43 | -------------------------------------------------------------------------------- /test/precisionRound-test.js: -------------------------------------------------------------------------------- 1 | import assert from "assert"; 2 | import {precisionRound} from "../src/index.js"; 3 | 4 | it("precisionRound(step, max) returns the expected value", () => { 5 | assert.strictEqual(precisionRound(0.1, 1.1), 2); // "1.0", "1.1" 6 | assert.strictEqual(precisionRound(0.01, 0.99), 2); // "0.98", "0.99" 7 | assert.strictEqual(precisionRound(0.01, 1.00), 2); // "0.99", "1.0" 8 | assert.strictEqual(precisionRound(0.01, 1.01), 3); // "1.00", "1.01" 9 | }); 10 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@babel/code-frame@^7.10.4": 6 | version "7.16.0" 7 | resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.0.tgz#0dfc80309beec8411e65e706461c408b0bb9b431" 8 | integrity sha512-IF4EOMEV+bfYwOmNxGzSnjR2EmQod7f1UXOpZM3l4i4o4QNwzjtJAu/HxdjHq0aYBvdqMuQEY1eg0nqW9ZPORA== 9 | dependencies: 10 | "@babel/highlight" "^7.16.0" 11 | 12 | "@babel/helper-validator-identifier@^7.15.7": 13 | version "7.15.7" 14 | resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz#220df993bfe904a4a6b02ab4f3385a5ebf6e2389" 15 | integrity sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w== 16 | 17 | "@babel/highlight@^7.16.0": 18 | version "7.16.0" 19 | resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.16.0.tgz#6ceb32b2ca4b8f5f361fb7fd821e3fddf4a1725a" 20 | integrity sha512-t8MH41kUQylBtu2+4IQA3atqevA2lRgqA2wyVB/YiWmsDSuylZZuXOUy9ric30hfzauEFfdsuk/eXTRrGrfd0g== 21 | dependencies: 22 | "@babel/helper-validator-identifier" "^7.15.7" 23 | chalk "^2.0.0" 24 | js-tokens "^4.0.0" 25 | 26 | "@eslint/eslintrc@^1.0.5": 27 | version "1.0.5" 28 | resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.0.5.tgz#33f1b838dbf1f923bfa517e008362b78ddbbf318" 29 | integrity sha512-BLxsnmK3KyPunz5wmCCpqy0YelEoxxGmH73Is+Z74oOTMtExcjkr3dDR6quwrjh1YspA8DH9gnX1o069KiS9AQ== 30 | dependencies: 31 | ajv "^6.12.4" 32 | debug "^4.3.2" 33 | espree "^9.2.0" 34 | globals "^13.9.0" 35 | ignore "^4.0.6" 36 | import-fresh "^3.2.1" 37 | js-yaml "^4.1.0" 38 | minimatch "^3.0.4" 39 | strip-json-comments "^3.1.1" 40 | 41 | "@humanwhocodes/config-array@^0.9.2": 42 | version "0.9.2" 43 | resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.9.2.tgz#68be55c737023009dfc5fe245d51181bb6476914" 44 | integrity sha512-UXOuFCGcwciWckOpmfKDq/GyhlTf9pN/BzG//x8p8zTOFEcGuA68ANXheFS0AGvy3qgZqLBUkMs7hqzqCKOVwA== 45 | dependencies: 46 | "@humanwhocodes/object-schema" "^1.2.1" 47 | debug "^4.1.1" 48 | minimatch "^3.0.4" 49 | 50 | "@humanwhocodes/object-schema@^1.2.1": 51 | version "1.2.1" 52 | resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" 53 | integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== 54 | 55 | "@types/node@*": 56 | version "16.11.11" 57 | resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.11.tgz#6ea7342dfb379ea1210835bada87b3c512120234" 58 | integrity sha512-KB0sixD67CeecHC33MYn+eYARkqTheIRNuu97y2XMjR7Wu3XibO1vaY6VBV6O/a89SPI81cEUIYT87UqUWlZNw== 59 | 60 | "@ungap/promise-all-settled@1.1.2": 61 | version "1.1.2" 62 | resolved "https://registry.yarnpkg.com/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44" 63 | integrity sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q== 64 | 65 | acorn-jsx@^5.3.1: 66 | version "5.3.2" 67 | resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" 68 | integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== 69 | 70 | acorn@^8.6.0: 71 | version "8.6.0" 72 | resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.6.0.tgz#e3692ba0eb1a0c83eaa4f37f5fa7368dd7142895" 73 | integrity sha512-U1riIR+lBSNi3IbxtaHOIKdH8sLFv3NYfNv8sg7ZsNhcfl4HF2++BfqqrNAxoCLQW1iiylOj76ecnaUxz+z9yw== 74 | 75 | ajv@^6.10.0, ajv@^6.12.4: 76 | version "6.12.6" 77 | resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" 78 | integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== 79 | dependencies: 80 | fast-deep-equal "^3.1.1" 81 | fast-json-stable-stringify "^2.0.0" 82 | json-schema-traverse "^0.4.1" 83 | uri-js "^4.2.2" 84 | 85 | ansi-colors@4.1.1, ansi-colors@^4.1.1: 86 | version "4.1.1" 87 | resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" 88 | integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== 89 | 90 | ansi-regex@^5.0.1: 91 | version "5.0.1" 92 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" 93 | integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== 94 | 95 | ansi-styles@^3.2.1: 96 | version "3.2.1" 97 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" 98 | integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== 99 | dependencies: 100 | color-convert "^1.9.0" 101 | 102 | ansi-styles@^4.0.0, ansi-styles@^4.1.0: 103 | version "4.3.0" 104 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" 105 | integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== 106 | dependencies: 107 | color-convert "^2.0.1" 108 | 109 | anymatch@~3.1.2: 110 | version "3.1.2" 111 | resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" 112 | integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== 113 | dependencies: 114 | normalize-path "^3.0.0" 115 | picomatch "^2.0.4" 116 | 117 | argparse@^2.0.1: 118 | version "2.0.1" 119 | resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" 120 | integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== 121 | 122 | balanced-match@^1.0.0: 123 | version "1.0.2" 124 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" 125 | integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== 126 | 127 | binary-extensions@^2.0.0: 128 | version "2.2.0" 129 | resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" 130 | integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== 131 | 132 | brace-expansion@^1.1.7: 133 | version "1.1.11" 134 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" 135 | integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== 136 | dependencies: 137 | balanced-match "^1.0.0" 138 | concat-map "0.0.1" 139 | 140 | braces@~3.0.2: 141 | version "3.0.2" 142 | resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" 143 | integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== 144 | dependencies: 145 | fill-range "^7.0.1" 146 | 147 | browser-stdout@1.3.1: 148 | version "1.3.1" 149 | resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" 150 | integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== 151 | 152 | buffer-from@^1.0.0: 153 | version "1.1.2" 154 | resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" 155 | integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== 156 | 157 | callsites@^3.0.0: 158 | version "3.1.0" 159 | resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" 160 | integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== 161 | 162 | camelcase@^6.0.0: 163 | version "6.2.1" 164 | resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.2.1.tgz#250fd350cfd555d0d2160b1d51510eaf8326e86e" 165 | integrity sha512-tVI4q5jjFV5CavAU8DXfza/TJcZutVKo/5Foskmsqcm0MsL91moHvwiGNnqaa2o6PF/7yT5ikDRcVcl8Rj6LCA== 166 | 167 | chalk@^2.0.0: 168 | version "2.4.2" 169 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" 170 | integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== 171 | dependencies: 172 | ansi-styles "^3.2.1" 173 | escape-string-regexp "^1.0.5" 174 | supports-color "^5.3.0" 175 | 176 | chalk@^4.0.0, chalk@^4.1.0: 177 | version "4.1.2" 178 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" 179 | integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== 180 | dependencies: 181 | ansi-styles "^4.1.0" 182 | supports-color "^7.1.0" 183 | 184 | chokidar@3.5.2: 185 | version "3.5.2" 186 | resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.2.tgz#dba3976fcadb016f66fd365021d91600d01c1e75" 187 | integrity sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ== 188 | dependencies: 189 | anymatch "~3.1.2" 190 | braces "~3.0.2" 191 | glob-parent "~5.1.2" 192 | is-binary-path "~2.1.0" 193 | is-glob "~4.0.1" 194 | normalize-path "~3.0.0" 195 | readdirp "~3.6.0" 196 | optionalDependencies: 197 | fsevents "~2.3.2" 198 | 199 | cliui@^7.0.2: 200 | version "7.0.4" 201 | resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" 202 | integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== 203 | dependencies: 204 | string-width "^4.2.0" 205 | strip-ansi "^6.0.0" 206 | wrap-ansi "^7.0.0" 207 | 208 | color-convert@^1.9.0: 209 | version "1.9.3" 210 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" 211 | integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== 212 | dependencies: 213 | color-name "1.1.3" 214 | 215 | color-convert@^2.0.1: 216 | version "2.0.1" 217 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" 218 | integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== 219 | dependencies: 220 | color-name "~1.1.4" 221 | 222 | color-name@1.1.3: 223 | version "1.1.3" 224 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" 225 | integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= 226 | 227 | color-name@~1.1.4: 228 | version "1.1.4" 229 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" 230 | integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== 231 | 232 | commander@^2.20.0: 233 | version "2.20.3" 234 | resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" 235 | integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== 236 | 237 | concat-map@0.0.1: 238 | version "0.0.1" 239 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" 240 | integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= 241 | 242 | cross-spawn@^7.0.2: 243 | version "7.0.3" 244 | resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" 245 | integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== 246 | dependencies: 247 | path-key "^3.1.0" 248 | shebang-command "^2.0.0" 249 | which "^2.0.1" 250 | 251 | debug@4.3.2: 252 | version "4.3.2" 253 | resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b" 254 | integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw== 255 | dependencies: 256 | ms "2.1.2" 257 | 258 | debug@^4.1.1, debug@^4.3.2: 259 | version "4.3.3" 260 | resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" 261 | integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== 262 | dependencies: 263 | ms "2.1.2" 264 | 265 | decamelize@^4.0.0: 266 | version "4.0.0" 267 | resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" 268 | integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== 269 | 270 | deep-is@^0.1.3: 271 | version "0.1.4" 272 | resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" 273 | integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== 274 | 275 | diff@5.0.0: 276 | version "5.0.0" 277 | resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" 278 | integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== 279 | 280 | doctrine@^3.0.0: 281 | version "3.0.0" 282 | resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" 283 | integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== 284 | dependencies: 285 | esutils "^2.0.2" 286 | 287 | emoji-regex@^8.0.0: 288 | version "8.0.0" 289 | resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" 290 | integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== 291 | 292 | enquirer@^2.3.5: 293 | version "2.3.6" 294 | resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" 295 | integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== 296 | dependencies: 297 | ansi-colors "^4.1.1" 298 | 299 | escalade@^3.1.1: 300 | version "3.1.1" 301 | resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" 302 | integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== 303 | 304 | escape-string-regexp@4.0.0, escape-string-regexp@^4.0.0: 305 | version "4.0.0" 306 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" 307 | integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== 308 | 309 | escape-string-regexp@^1.0.5: 310 | version "1.0.5" 311 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" 312 | integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= 313 | 314 | eslint-scope@^7.1.0: 315 | version "7.1.0" 316 | resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.1.0.tgz#c1f6ea30ac583031f203d65c73e723b01298f153" 317 | integrity sha512-aWwkhnS0qAXqNOgKOK0dJ2nvzEbhEvpy8OlJ9kZ0FeZnA6zpjv1/Vei+puGFFX7zkPCkHHXb7IDX3A+7yPrRWg== 318 | dependencies: 319 | esrecurse "^4.3.0" 320 | estraverse "^5.2.0" 321 | 322 | eslint-utils@^3.0.0: 323 | version "3.0.0" 324 | resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672" 325 | integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA== 326 | dependencies: 327 | eslint-visitor-keys "^2.0.0" 328 | 329 | eslint-visitor-keys@^2.0.0: 330 | version "2.1.0" 331 | resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" 332 | integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== 333 | 334 | eslint-visitor-keys@^3.1.0: 335 | version "3.1.0" 336 | resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.1.0.tgz#eee4acea891814cda67a7d8812d9647dd0179af2" 337 | integrity sha512-yWJFpu4DtjsWKkt5GeNBBuZMlNcYVs6vRCLoCVEJrTjaSB6LC98gFipNK/erM2Heg/E8mIK+hXG/pJMLK+eRZA== 338 | 339 | eslint@8: 340 | version "8.4.0" 341 | resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.4.0.tgz#2fa01b271cafc28addc2719e551acff5e89f5230" 342 | integrity sha512-kv0XQcAQJL/VD9THQKhTQZVqkJKA+tIj/v2ZKNaIHRAADcJWFb+B/BAewUYuF6UVg1s2xC5qXVoDk0G8sKGeTA== 343 | dependencies: 344 | "@eslint/eslintrc" "^1.0.5" 345 | "@humanwhocodes/config-array" "^0.9.2" 346 | ajv "^6.10.0" 347 | chalk "^4.0.0" 348 | cross-spawn "^7.0.2" 349 | debug "^4.3.2" 350 | doctrine "^3.0.0" 351 | enquirer "^2.3.5" 352 | escape-string-regexp "^4.0.0" 353 | eslint-scope "^7.1.0" 354 | eslint-utils "^3.0.0" 355 | eslint-visitor-keys "^3.1.0" 356 | espree "^9.2.0" 357 | esquery "^1.4.0" 358 | esutils "^2.0.2" 359 | fast-deep-equal "^3.1.3" 360 | file-entry-cache "^6.0.1" 361 | functional-red-black-tree "^1.0.1" 362 | glob-parent "^6.0.1" 363 | globals "^13.6.0" 364 | ignore "^4.0.6" 365 | import-fresh "^3.0.0" 366 | imurmurhash "^0.1.4" 367 | is-glob "^4.0.0" 368 | js-yaml "^4.1.0" 369 | json-stable-stringify-without-jsonify "^1.0.1" 370 | levn "^0.4.1" 371 | lodash.merge "^4.6.2" 372 | minimatch "^3.0.4" 373 | natural-compare "^1.4.0" 374 | optionator "^0.9.1" 375 | progress "^2.0.0" 376 | regexpp "^3.2.0" 377 | semver "^7.2.1" 378 | strip-ansi "^6.0.1" 379 | strip-json-comments "^3.1.0" 380 | text-table "^0.2.0" 381 | v8-compile-cache "^2.0.3" 382 | 383 | espree@^9.2.0: 384 | version "9.2.0" 385 | resolved "https://registry.yarnpkg.com/espree/-/espree-9.2.0.tgz#c50814e01611c2d0f8bd4daa83c369eabba80dbc" 386 | integrity sha512-oP3utRkynpZWF/F2x/HZJ+AGtnIclaR7z1pYPxy7NYM2fSO6LgK/Rkny8anRSPK/VwEA1eqm2squui0T7ZMOBg== 387 | dependencies: 388 | acorn "^8.6.0" 389 | acorn-jsx "^5.3.1" 390 | eslint-visitor-keys "^3.1.0" 391 | 392 | esquery@^1.4.0: 393 | version "1.4.0" 394 | resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5" 395 | integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w== 396 | dependencies: 397 | estraverse "^5.1.0" 398 | 399 | esrecurse@^4.3.0: 400 | version "4.3.0" 401 | resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" 402 | integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== 403 | dependencies: 404 | estraverse "^5.2.0" 405 | 406 | estraverse@^5.1.0, estraverse@^5.2.0: 407 | version "5.3.0" 408 | resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" 409 | integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== 410 | 411 | esutils@^2.0.2: 412 | version "2.0.3" 413 | resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" 414 | integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== 415 | 416 | fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: 417 | version "3.1.3" 418 | resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" 419 | integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== 420 | 421 | fast-json-stable-stringify@^2.0.0: 422 | version "2.1.0" 423 | resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" 424 | integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== 425 | 426 | fast-levenshtein@^2.0.6: 427 | version "2.0.6" 428 | resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" 429 | integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= 430 | 431 | file-entry-cache@^6.0.1: 432 | version "6.0.1" 433 | resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" 434 | integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== 435 | dependencies: 436 | flat-cache "^3.0.4" 437 | 438 | fill-range@^7.0.1: 439 | version "7.0.1" 440 | resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" 441 | integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== 442 | dependencies: 443 | to-regex-range "^5.0.1" 444 | 445 | find-up@5.0.0: 446 | version "5.0.0" 447 | resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" 448 | integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== 449 | dependencies: 450 | locate-path "^6.0.0" 451 | path-exists "^4.0.0" 452 | 453 | flat-cache@^3.0.4: 454 | version "3.0.4" 455 | resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" 456 | integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== 457 | dependencies: 458 | flatted "^3.1.0" 459 | rimraf "^3.0.2" 460 | 461 | flat@^5.0.2: 462 | version "5.0.2" 463 | resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" 464 | integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== 465 | 466 | flatted@^3.1.0: 467 | version "3.2.4" 468 | resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.4.tgz#28d9969ea90661b5134259f312ab6aa7929ac5e2" 469 | integrity sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw== 470 | 471 | fs.realpath@^1.0.0: 472 | version "1.0.0" 473 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" 474 | integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= 475 | 476 | fsevents@~2.3.2: 477 | version "2.3.2" 478 | resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" 479 | integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== 480 | 481 | functional-red-black-tree@^1.0.1: 482 | version "1.0.1" 483 | resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" 484 | integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= 485 | 486 | get-caller-file@^2.0.5: 487 | version "2.0.5" 488 | resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" 489 | integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== 490 | 491 | glob-parent@^6.0.1: 492 | version "6.0.2" 493 | resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" 494 | integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== 495 | dependencies: 496 | is-glob "^4.0.3" 497 | 498 | glob-parent@~5.1.2: 499 | version "5.1.2" 500 | resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" 501 | integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== 502 | dependencies: 503 | is-glob "^4.0.1" 504 | 505 | glob@7.1.7: 506 | version "7.1.7" 507 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90" 508 | integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ== 509 | dependencies: 510 | fs.realpath "^1.0.0" 511 | inflight "^1.0.4" 512 | inherits "2" 513 | minimatch "^3.0.4" 514 | once "^1.3.0" 515 | path-is-absolute "^1.0.0" 516 | 517 | glob@^7.1.3: 518 | version "7.2.0" 519 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" 520 | integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== 521 | dependencies: 522 | fs.realpath "^1.0.0" 523 | inflight "^1.0.4" 524 | inherits "2" 525 | minimatch "^3.0.4" 526 | once "^1.3.0" 527 | path-is-absolute "^1.0.0" 528 | 529 | globals@^13.6.0, globals@^13.9.0: 530 | version "13.12.0" 531 | resolved "https://registry.yarnpkg.com/globals/-/globals-13.12.0.tgz#4d733760304230a0082ed96e21e5c565f898089e" 532 | integrity sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg== 533 | dependencies: 534 | type-fest "^0.20.2" 535 | 536 | growl@1.10.5: 537 | version "1.10.5" 538 | resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" 539 | integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== 540 | 541 | has-flag@^3.0.0: 542 | version "3.0.0" 543 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" 544 | integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= 545 | 546 | has-flag@^4.0.0: 547 | version "4.0.0" 548 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" 549 | integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== 550 | 551 | he@1.2.0: 552 | version "1.2.0" 553 | resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" 554 | integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== 555 | 556 | ignore@^4.0.6: 557 | version "4.0.6" 558 | resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" 559 | integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== 560 | 561 | import-fresh@^3.0.0, import-fresh@^3.2.1: 562 | version "3.3.0" 563 | resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" 564 | integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== 565 | dependencies: 566 | parent-module "^1.0.0" 567 | resolve-from "^4.0.0" 568 | 569 | imurmurhash@^0.1.4: 570 | version "0.1.4" 571 | resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" 572 | integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= 573 | 574 | inflight@^1.0.4: 575 | version "1.0.6" 576 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" 577 | integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= 578 | dependencies: 579 | once "^1.3.0" 580 | wrappy "1" 581 | 582 | inherits@2: 583 | version "2.0.4" 584 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" 585 | integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== 586 | 587 | is-binary-path@~2.1.0: 588 | version "2.1.0" 589 | resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" 590 | integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== 591 | dependencies: 592 | binary-extensions "^2.0.0" 593 | 594 | is-extglob@^2.1.1: 595 | version "2.1.1" 596 | resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" 597 | integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= 598 | 599 | is-fullwidth-code-point@^3.0.0: 600 | version "3.0.0" 601 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" 602 | integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== 603 | 604 | is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: 605 | version "4.0.3" 606 | resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" 607 | integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== 608 | dependencies: 609 | is-extglob "^2.1.1" 610 | 611 | is-number@^7.0.0: 612 | version "7.0.0" 613 | resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" 614 | integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== 615 | 616 | is-plain-obj@^2.1.0: 617 | version "2.1.0" 618 | resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" 619 | integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== 620 | 621 | is-unicode-supported@^0.1.0: 622 | version "0.1.0" 623 | resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" 624 | integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== 625 | 626 | isexe@^2.0.0: 627 | version "2.0.0" 628 | resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" 629 | integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= 630 | 631 | jest-worker@^26.2.1: 632 | version "26.6.2" 633 | resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.6.2.tgz#7f72cbc4d643c365e27b9fd775f9d0eaa9c7a8ed" 634 | integrity sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ== 635 | dependencies: 636 | "@types/node" "*" 637 | merge-stream "^2.0.0" 638 | supports-color "^7.0.0" 639 | 640 | js-tokens@^4.0.0: 641 | version "4.0.0" 642 | resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" 643 | integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== 644 | 645 | js-yaml@4.1.0, js-yaml@^4.1.0: 646 | version "4.1.0" 647 | resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" 648 | integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== 649 | dependencies: 650 | argparse "^2.0.1" 651 | 652 | json-schema-traverse@^0.4.1: 653 | version "0.4.1" 654 | resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" 655 | integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== 656 | 657 | json-stable-stringify-without-jsonify@^1.0.1: 658 | version "1.0.1" 659 | resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" 660 | integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= 661 | 662 | levn@^0.4.1: 663 | version "0.4.1" 664 | resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" 665 | integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== 666 | dependencies: 667 | prelude-ls "^1.2.1" 668 | type-check "~0.4.0" 669 | 670 | locate-path@^6.0.0: 671 | version "6.0.0" 672 | resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" 673 | integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== 674 | dependencies: 675 | p-locate "^5.0.0" 676 | 677 | lodash.merge@^4.6.2: 678 | version "4.6.2" 679 | resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" 680 | integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== 681 | 682 | log-symbols@4.1.0: 683 | version "4.1.0" 684 | resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" 685 | integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== 686 | dependencies: 687 | chalk "^4.1.0" 688 | is-unicode-supported "^0.1.0" 689 | 690 | lru-cache@^6.0.0: 691 | version "6.0.0" 692 | resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" 693 | integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== 694 | dependencies: 695 | yallist "^4.0.0" 696 | 697 | merge-stream@^2.0.0: 698 | version "2.0.0" 699 | resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" 700 | integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== 701 | 702 | minimatch@3.0.4, minimatch@^3.0.4: 703 | version "3.0.4" 704 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" 705 | integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== 706 | dependencies: 707 | brace-expansion "^1.1.7" 708 | 709 | mocha@9: 710 | version "9.1.3" 711 | resolved "https://registry.yarnpkg.com/mocha/-/mocha-9.1.3.tgz#8a623be6b323810493d8c8f6f7667440fa469fdb" 712 | integrity sha512-Xcpl9FqXOAYqI3j79pEtHBBnQgVXIhpULjGQa7DVb0Po+VzmSIK9kanAiWLHoRR/dbZ2qpdPshuXr8l1VaHCzw== 713 | dependencies: 714 | "@ungap/promise-all-settled" "1.1.2" 715 | ansi-colors "4.1.1" 716 | browser-stdout "1.3.1" 717 | chokidar "3.5.2" 718 | debug "4.3.2" 719 | diff "5.0.0" 720 | escape-string-regexp "4.0.0" 721 | find-up "5.0.0" 722 | glob "7.1.7" 723 | growl "1.10.5" 724 | he "1.2.0" 725 | js-yaml "4.1.0" 726 | log-symbols "4.1.0" 727 | minimatch "3.0.4" 728 | ms "2.1.3" 729 | nanoid "3.1.25" 730 | serialize-javascript "6.0.0" 731 | strip-json-comments "3.1.1" 732 | supports-color "8.1.1" 733 | which "2.0.2" 734 | workerpool "6.1.5" 735 | yargs "16.2.0" 736 | yargs-parser "20.2.4" 737 | yargs-unparser "2.0.0" 738 | 739 | ms@2.1.2: 740 | version "2.1.2" 741 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" 742 | integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== 743 | 744 | ms@2.1.3: 745 | version "2.1.3" 746 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" 747 | integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== 748 | 749 | nanoid@3.1.25: 750 | version "3.1.25" 751 | resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.25.tgz#09ca32747c0e543f0e1814b7d3793477f9c8e152" 752 | integrity sha512-rdwtIXaXCLFAQbnfqDRnI6jaRHp9fTcYBjtFKE8eezcZ7LuLjhUaQGNeMXf1HmRoCH32CLz6XwX0TtxEOS/A3Q== 753 | 754 | natural-compare@^1.4.0: 755 | version "1.4.0" 756 | resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" 757 | integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= 758 | 759 | normalize-path@^3.0.0, normalize-path@~3.0.0: 760 | version "3.0.0" 761 | resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" 762 | integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== 763 | 764 | once@^1.3.0: 765 | version "1.4.0" 766 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 767 | integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= 768 | dependencies: 769 | wrappy "1" 770 | 771 | optionator@^0.9.1: 772 | version "0.9.1" 773 | resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" 774 | integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== 775 | dependencies: 776 | deep-is "^0.1.3" 777 | fast-levenshtein "^2.0.6" 778 | levn "^0.4.1" 779 | prelude-ls "^1.2.1" 780 | type-check "^0.4.0" 781 | word-wrap "^1.2.3" 782 | 783 | p-limit@^3.0.2: 784 | version "3.1.0" 785 | resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" 786 | integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== 787 | dependencies: 788 | yocto-queue "^0.1.0" 789 | 790 | p-locate@^5.0.0: 791 | version "5.0.0" 792 | resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" 793 | integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== 794 | dependencies: 795 | p-limit "^3.0.2" 796 | 797 | parent-module@^1.0.0: 798 | version "1.0.1" 799 | resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" 800 | integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== 801 | dependencies: 802 | callsites "^3.0.0" 803 | 804 | path-exists@^4.0.0: 805 | version "4.0.0" 806 | resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" 807 | integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== 808 | 809 | path-is-absolute@^1.0.0: 810 | version "1.0.1" 811 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" 812 | integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= 813 | 814 | path-key@^3.1.0: 815 | version "3.1.1" 816 | resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" 817 | integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== 818 | 819 | picomatch@^2.0.4, picomatch@^2.2.1: 820 | version "2.3.0" 821 | resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972" 822 | integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw== 823 | 824 | prelude-ls@^1.2.1: 825 | version "1.2.1" 826 | resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" 827 | integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== 828 | 829 | progress@^2.0.0: 830 | version "2.0.3" 831 | resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" 832 | integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== 833 | 834 | punycode@^2.1.0: 835 | version "2.1.1" 836 | resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" 837 | integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== 838 | 839 | randombytes@^2.1.0: 840 | version "2.1.0" 841 | resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" 842 | integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== 843 | dependencies: 844 | safe-buffer "^5.1.0" 845 | 846 | readdirp@~3.6.0: 847 | version "3.6.0" 848 | resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" 849 | integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== 850 | dependencies: 851 | picomatch "^2.2.1" 852 | 853 | regexpp@^3.2.0: 854 | version "3.2.0" 855 | resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" 856 | integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== 857 | 858 | require-directory@^2.1.1: 859 | version "2.1.1" 860 | resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" 861 | integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= 862 | 863 | resolve-from@^4.0.0: 864 | version "4.0.0" 865 | resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" 866 | integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== 867 | 868 | rimraf@^3.0.2: 869 | version "3.0.2" 870 | resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" 871 | integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== 872 | dependencies: 873 | glob "^7.1.3" 874 | 875 | rollup-plugin-terser@7: 876 | version "7.0.2" 877 | resolved "https://registry.yarnpkg.com/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz#e8fbba4869981b2dc35ae7e8a502d5c6c04d324d" 878 | integrity sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ== 879 | dependencies: 880 | "@babel/code-frame" "^7.10.4" 881 | jest-worker "^26.2.1" 882 | serialize-javascript "^4.0.0" 883 | terser "^5.0.0" 884 | 885 | rollup@2: 886 | version "2.60.2" 887 | resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.60.2.tgz#3f45ace36a9b10b4297181831ea0719922513463" 888 | integrity sha512-1Bgjpq61sPjgoZzuiDSGvbI1tD91giZABgjCQBKM5aYLnzjq52GoDuWVwT/cm/MCxCMPU8gqQvkj8doQ5C8Oqw== 889 | optionalDependencies: 890 | fsevents "~2.3.2" 891 | 892 | safe-buffer@^5.1.0: 893 | version "5.2.1" 894 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" 895 | integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== 896 | 897 | semver@^7.2.1: 898 | version "7.3.5" 899 | resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" 900 | integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== 901 | dependencies: 902 | lru-cache "^6.0.0" 903 | 904 | serialize-javascript@6.0.0: 905 | version "6.0.0" 906 | resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" 907 | integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== 908 | dependencies: 909 | randombytes "^2.1.0" 910 | 911 | serialize-javascript@^4.0.0: 912 | version "4.0.0" 913 | resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-4.0.0.tgz#b525e1238489a5ecfc42afacc3fe99e666f4b1aa" 914 | integrity sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw== 915 | dependencies: 916 | randombytes "^2.1.0" 917 | 918 | shebang-command@^2.0.0: 919 | version "2.0.0" 920 | resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" 921 | integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== 922 | dependencies: 923 | shebang-regex "^3.0.0" 924 | 925 | shebang-regex@^3.0.0: 926 | version "3.0.0" 927 | resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" 928 | integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== 929 | 930 | source-map-support@~0.5.20: 931 | version "0.5.21" 932 | resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" 933 | integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== 934 | dependencies: 935 | buffer-from "^1.0.0" 936 | source-map "^0.6.0" 937 | 938 | source-map@^0.6.0: 939 | version "0.6.1" 940 | resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" 941 | integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== 942 | 943 | source-map@~0.7.2: 944 | version "0.7.3" 945 | resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" 946 | integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== 947 | 948 | string-width@^4.1.0, string-width@^4.2.0: 949 | version "4.2.3" 950 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" 951 | integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== 952 | dependencies: 953 | emoji-regex "^8.0.0" 954 | is-fullwidth-code-point "^3.0.0" 955 | strip-ansi "^6.0.1" 956 | 957 | strip-ansi@^6.0.0, strip-ansi@^6.0.1: 958 | version "6.0.1" 959 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" 960 | integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== 961 | dependencies: 962 | ansi-regex "^5.0.1" 963 | 964 | strip-json-comments@3.1.1, strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: 965 | version "3.1.1" 966 | resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" 967 | integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== 968 | 969 | supports-color@8.1.1: 970 | version "8.1.1" 971 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" 972 | integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== 973 | dependencies: 974 | has-flag "^4.0.0" 975 | 976 | supports-color@^5.3.0: 977 | version "5.5.0" 978 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" 979 | integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== 980 | dependencies: 981 | has-flag "^3.0.0" 982 | 983 | supports-color@^7.0.0, supports-color@^7.1.0: 984 | version "7.2.0" 985 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" 986 | integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== 987 | dependencies: 988 | has-flag "^4.0.0" 989 | 990 | terser@^5.0.0: 991 | version "5.10.0" 992 | resolved "https://registry.yarnpkg.com/terser/-/terser-5.10.0.tgz#b86390809c0389105eb0a0b62397563096ddafcc" 993 | integrity sha512-AMmF99DMfEDiRJfxfY5jj5wNH/bYO09cniSqhfoyxc8sFoYIgkJy86G04UoZU5VjlpnplVu0K6Tx6E9b5+DlHA== 994 | dependencies: 995 | commander "^2.20.0" 996 | source-map "~0.7.2" 997 | source-map-support "~0.5.20" 998 | 999 | text-table@^0.2.0: 1000 | version "0.2.0" 1001 | resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" 1002 | integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= 1003 | 1004 | to-regex-range@^5.0.1: 1005 | version "5.0.1" 1006 | resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" 1007 | integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== 1008 | dependencies: 1009 | is-number "^7.0.0" 1010 | 1011 | type-check@^0.4.0, type-check@~0.4.0: 1012 | version "0.4.0" 1013 | resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" 1014 | integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== 1015 | dependencies: 1016 | prelude-ls "^1.2.1" 1017 | 1018 | type-fest@^0.20.2: 1019 | version "0.20.2" 1020 | resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" 1021 | integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== 1022 | 1023 | uri-js@^4.2.2: 1024 | version "4.4.1" 1025 | resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" 1026 | integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== 1027 | dependencies: 1028 | punycode "^2.1.0" 1029 | 1030 | v8-compile-cache@^2.0.3: 1031 | version "2.3.0" 1032 | resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" 1033 | integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== 1034 | 1035 | which@2.0.2, which@^2.0.1: 1036 | version "2.0.2" 1037 | resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" 1038 | integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== 1039 | dependencies: 1040 | isexe "^2.0.0" 1041 | 1042 | word-wrap@^1.2.3: 1043 | version "1.2.3" 1044 | resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" 1045 | integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== 1046 | 1047 | workerpool@6.1.5: 1048 | version "6.1.5" 1049 | resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.1.5.tgz#0f7cf076b6215fd7e1da903ff6f22ddd1886b581" 1050 | integrity sha512-XdKkCK0Zqc6w3iTxLckiuJ81tiD/o5rBE/m+nXpRCB+/Sq4DqkfXZ/x0jW02DG1tGsfUGXbTJyZDP+eu67haSw== 1051 | 1052 | wrap-ansi@^7.0.0: 1053 | version "7.0.0" 1054 | resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" 1055 | integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== 1056 | dependencies: 1057 | ansi-styles "^4.0.0" 1058 | string-width "^4.1.0" 1059 | strip-ansi "^6.0.0" 1060 | 1061 | wrappy@1: 1062 | version "1.0.2" 1063 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 1064 | integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= 1065 | 1066 | y18n@^5.0.5: 1067 | version "5.0.8" 1068 | resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" 1069 | integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== 1070 | 1071 | yallist@^4.0.0: 1072 | version "4.0.0" 1073 | resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" 1074 | integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== 1075 | 1076 | yargs-parser@20.2.4: 1077 | version "20.2.4" 1078 | resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" 1079 | integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== 1080 | 1081 | yargs-parser@^20.2.2: 1082 | version "20.2.9" 1083 | resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" 1084 | integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== 1085 | 1086 | yargs-unparser@2.0.0: 1087 | version "2.0.0" 1088 | resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" 1089 | integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== 1090 | dependencies: 1091 | camelcase "^6.0.0" 1092 | decamelize "^4.0.0" 1093 | flat "^5.0.2" 1094 | is-plain-obj "^2.1.0" 1095 | 1096 | yargs@16.2.0: 1097 | version "16.2.0" 1098 | resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" 1099 | integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== 1100 | dependencies: 1101 | cliui "^7.0.2" 1102 | escalade "^3.1.1" 1103 | get-caller-file "^2.0.5" 1104 | require-directory "^2.1.1" 1105 | string-width "^4.2.0" 1106 | y18n "^5.0.5" 1107 | yargs-parser "^20.2.2" 1108 | 1109 | yocto-queue@^0.1.0: 1110 | version "0.1.0" 1111 | resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" 1112 | integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== 1113 | --------------------------------------------------------------------------------