format-quantity 1.1.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -63,6 +63,8 @@ formatQuantity(3.875, { vulgarFractions: true }); // "3⅞"
63
63
  formatQuantity(3.875, true); // "3⅞"
64
64
  ```
65
65
 
66
+ Note: `formatQuantity` supports sixteenths, but no vulgar fraction characters exist for that denomination. Therefore the `vulgarFractions` option has no effect if the fraction portion of the final string is an odd numerator over a denominator of `16`.
67
+
66
68
  ### `tolerance`
67
69
 
68
70
  | Type | Default |
@@ -99,7 +101,7 @@ formatQuantity(3.875, { fractionSlash: true, vulgarFractions: true }); // "3⅞"
99
101
 
100
102
  | Name | Type | Description |
101
103
  | ------------------------ | ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
102
- | `defaultTolerance` | `number` | `0.009` |
104
+ | `defaultTolerance` | `number` | `0.0075` |
103
105
  | `fractionDecimalMatches` | `[number, VulgarFraction][]` | List of fractions and the decimal values that are close enough to match them (inputs are evaluated against the decimal values in the order of this array) |
104
106
  | `vulgarToPlainMap` | `object` | Map of vulgar fraction characters to their equivalent ASCII strings (`"⅓"` to `"1/3"`, `"⅞"` to `"7/8"`, etc.) |
105
107
  | `FormatQuantityOptions` | `interface` | Shape of `formatQuantity`'s second parameter, if not a `boolean` value |
@@ -1,9 +1,12 @@
1
- import type { VulgarFraction } from './types';
2
- export declare const defaultTolerance = 0.009;
1
+ import type { SimpleFraction, VulgarFraction } from './types';
2
+ export declare const defaultTolerance = 0.0075;
3
+ export declare const vulgarFractions: string[];
3
4
  /**
4
- * A map of vulgar fractions to their traditional ASCII equivalents.
5
+ * A map of vulgar or simple fractions to their traditional ASCII equivalents.
6
+ * Simple fractions map to themselves.
5
7
  */
6
- export declare const vulgarToPlainMap: {
7
- [vf in VulgarFraction]: `${number}/${number}`;
8
- };
9
- export declare const fractionDecimalMatches: [number, VulgarFraction][];
8
+ export declare const vulgarToPlainMap: Record<string, SimpleFraction>;
9
+ export declare const fractionDecimalMatches: [
10
+ number,
11
+ VulgarFraction | SimpleFraction
12
+ ][];
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const i=.009,n={"\xBC":"1/4","\xBD":"1/2","\xBE":"3/4","\u2150":"1/7","\u2151":"1/9","\u2152":"1/10","\u2153":"1/3","\u2154":"2/3","\u2155":"1/5","\u2156":"2/5","\u2157":"3/5","\u2158":"4/5","\u2159":"1/6","\u215A":"5/6","\u215B":"1/8","\u215C":"3/8","\u215D":"5/8","\u215E":"7/8"},d=[[.33,"\u2153"],[.66,"\u2154"],[.2,"\u2155"],[.4,"\u2156"],[.6,"\u2157"],[.8,"\u2158"],[.166,"\u2159"],[.833,"\u215A"],[.143,"\u2150"],[.111,"\u2151"],[.1,"\u2152"],[.125,"\u215B"],[.25,"\xBC"],[.375,"\u215C"],[.5,"\xBD"],[.625,"\u215D"],[.75,"\xBE"],[.875,"\u215E"]],h=(a,t,u)=>Math.abs(a-t)<u,M=(a,t)=>{var f;const u=typeof a=="string"?parseFloat(a):a;if(isNaN(u)||u===null)return null;if(u===0)return"";const l=Math.abs(u),r=Math.floor(l),c=`${u<0?"-":""}${r===0?"":`${r} `}`,s=l-r;if(s===0)return`${u}`;const o=typeof t=="boolean"?{vulgarFractions:t}:t!=null?t:{},g=o.vulgarFractions?c.trim():c,m=e=>o.vulgarFractions?e:o.fractionSlash?n[e].replace("/","\u2044"):n[e];for(const[e,B]of d)if(h(s,e,(f=o.tolerance)!=null?f:i))return`${g}${m(B)}`;return`${u}`};exports.default=M;exports.defaultTolerance=i;exports.formatQuantity=M;exports.fractionDecimalMatches=d;exports.vulgarToPlainMap=n;
1
+ "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const f=.0075,B=["\xBC","\xBD","\xBE","\u2150","\u2151","\u2152","\u2153","\u2154","\u2155","\u2156","\u2157","\u2158","\u2159","\u215A","\u215B","\u215C","\u215D","\u215E"],r={"\xBC":"1/4","\xBD":"1/2","\xBE":"3/4","\u2150":"1/7","\u2151":"1/9","\u2152":"1/10","\u2153":"1/3","\u2154":"2/3","\u2155":"1/5","\u2156":"2/5","\u2157":"3/5","\u2158":"4/5","\u2159":"1/6","\u215A":"5/6","\u215B":"1/8","\u215C":"3/8","\u215D":"5/8","\u215E":"7/8","1/16":"1/16","3/16":"3/16","5/16":"5/16","7/16":"7/16","9/16":"9/16","11/16":"11/16","13/16":"13/16","15/16":"15/16"},g=[[.33,"\u2153"],[.66,"\u2154"],[.2,"\u2155"],[.4,"\u2156"],[.6,"\u2157"],[.8,"\u2158"],[.166,"\u2159"],[.833,"\u215A"],[.143,"\u2150"],[.111,"\u2151"],[.1,"\u2152"],[.125,"\u215B"],[.25,"\xBC"],[.375,"\u215C"],[.5,"\xBD"],[.625,"\u215D"],[.75,"\xBE"],[.875,"\u215E"],[.0625,"1/16"],[.1875,"3/16"],[.3125,"5/16"],[.4375,"7/16"],[.5625,"9/16"],[.6875,"11/16"],[.8125,"13/16"],[.9375,"15/16"]],D=(t,u,a)=>Math.abs(t-u)<a,M=(t,u)=>u.vulgarFractions?t:u.fractionSlash?r[t].replace("/","\u2044"):r[t],d=(t,u)=>{var s;const a=typeof t=="string"?parseFloat(t):t;if(isNaN(a)||a===null)return null;if(a===0)return"";const n=Math.abs(a),e=Math.floor(n),o=`${a<0?"-":""}${e===0?"":`${e} `}`,c=n-e;if(c===0)return`${a}`;const l=typeof u=="boolean"?{vulgarFractions:u}:u!=null?u:{};for(const[v,x]of g)if(D(c,v,(s=l.tolerance)!=null?s:f)){const i=M(x,l);return`${B.includes(i)?o.trim():o}${i}`}return`${a}`};exports.default=d;exports.defaultTolerance=f;exports.formatQuantity=d;exports.fractionDecimalMatches=g;exports.vulgarFractions=B;exports.vulgarToPlainMap=r;
2
2
  //# sourceMappingURL=format-quantity.cjs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"format-quantity.cjs.js","sources":["../src/constants.ts","../src/formatQuantity.ts"],"sourcesContent":["import type { VulgarFraction } from './types';\n\nexport const defaultTolerance = 0.009;\n\n/**\n * A map of vulgar fractions to their traditional ASCII equivalents.\n */\nexport const vulgarToPlainMap: {\n [vf in VulgarFraction]: `${number}/${number}`;\n} = {\n '¼': '1/4',\n '½': '1/2',\n '¾': '3/4',\n '⅐': '1/7',\n '⅑': '1/9',\n '⅒': '1/10',\n '⅓': '1/3',\n '⅔': '2/3',\n '⅕': '1/5',\n '⅖': '2/5',\n '⅗': '3/5',\n '⅘': '4/5',\n '⅙': '1/6',\n '⅚': '5/6',\n '⅛': '1/8',\n '⅜': '3/8',\n '⅝': '5/8',\n '⅞': '7/8',\n};\n\nexport const fractionDecimalMatches: [number, VulgarFraction][] = [\n [0.33, '⅓'],\n [0.66, '⅔'],\n [0.2, '⅕'],\n [0.4, '⅖'],\n [0.6, '⅗'],\n [0.8, '⅘'],\n [0.166, '⅙'],\n [0.833, '⅚'],\n [0.143, '⅐'],\n [0.111, '⅑'],\n [0.1, '⅒'],\n [0.125, '⅛'],\n [0.25, '¼'],\n [0.375, '⅜'],\n [0.5, '½'],\n [0.625, '⅝'],\n [0.75, '¾'],\n [0.875, '⅞'],\n];\n","import {\n defaultTolerance,\n fractionDecimalMatches,\n vulgarToPlainMap,\n} from './constants';\nimport type {\n FormatQuantity,\n FormatQuantityOptions,\n VulgarFraction,\n} from './types';\n\n/**\n * Determines if two numbers are close enough to consider\n * them equal for the purposes of this package.\n */\nconst closeEnough = (n1: number, n2: number, tolerance: number) =>\n Math.abs(n1 - n2) < tolerance;\n\n/**\n * Formats a number (or string that appears to be a number)\n * as one would see it written in imperial measurements, e.g.\n * \"1 1/2\" instead of \"1.5\". To use vulgar fraction characters\n * like \"½\", pass `true` as the second argument. For other options\n * see the [documentation](https://jakeboone02.github.io/format-quantity/).\n */\nexport const formatQuantity: FormatQuantity = (qty, options) => {\n const dQty = typeof qty === 'string' ? parseFloat(qty) : qty;\n\n // Return `null` if input is not number-like\n if (isNaN(dQty) || dQty === null) {\n return null;\n }\n\n // Return an empty string if the value is zero\n if (dQty === 0) {\n return '';\n }\n\n const dQtyAbs = Math.abs(dQty);\n const iFloor = Math.floor(dQtyAbs);\n const sFloor = `${dQty < 0 ? '-' : ''}${iFloor === 0 ? '' : `${iFloor} `}`;\n const dDecimal = dQtyAbs - iFloor;\n\n // For integers just return the given value as a string\n if (dDecimal === 0) {\n return `${dQty}`;\n }\n\n const opts: FormatQuantityOptions =\n typeof options === 'boolean' ? { vulgarFractions: options } : options ?? {};\n\n const sFloorFinal = opts.vulgarFractions ? sFloor.trim() : sFloor;\n\n const getFraction = (vulgarFraction: VulgarFraction) =>\n opts.vulgarFractions\n ? vulgarFraction\n : opts.fractionSlash\n ? vulgarToPlainMap[vulgarFraction].replace('/', '⁄')\n : vulgarToPlainMap[vulgarFraction];\n\n for (const [num, vf] of fractionDecimalMatches) {\n if (closeEnough(dDecimal, num, opts.tolerance ?? defaultTolerance)) {\n return `${sFloorFinal}${getFraction(vf)}`;\n }\n }\n\n return `${dQty}`;\n};\n"],"names":[],"mappings":"4GAEO,KAAM,GAAmB,KAKnB,EAET,CACF,OAAK,MACL,OAAK,MACL,OAAK,MACL,SAAK,MACL,SAAK,MACL,SAAK,OACL,SAAK,MACL,SAAK,MACL,SAAK,MACL,SAAK,MACL,SAAK,MACL,SAAK,MACL,SAAK,MACL,SAAK,MACL,SAAK,MACL,SAAK,MACL,SAAK,MACL,SAAK,KACP,EAEa,EAAqD,CAChE,CAAC,IAAM,QAAG,EACV,CAAC,IAAM,QAAG,EACV,CAAC,GAAK,QAAG,EACT,CAAC,GAAK,QAAG,EACT,CAAC,GAAK,QAAG,EACT,CAAC,GAAK,QAAG,EACT,CAAC,KAAO,QAAG,EACX,CAAC,KAAO,QAAG,EACX,CAAC,KAAO,QAAG,EACX,CAAC,KAAO,QAAG,EACX,CAAC,GAAK,QAAG,EACT,CAAC,KAAO,QAAG,EACX,CAAC,IAAM,MAAG,EACV,CAAC,KAAO,QAAG,EACX,CAAC,GAAK,MAAG,EACT,CAAC,KAAO,QAAG,EACX,CAAC,IAAM,MAAG,EACV,CAAC,KAAO,QAAG,CACb,EClCM,EAAc,CAAC,EAAY,EAAY,IAC3C,KAAK,IAAI,EAAK,CAAE,EAAI,EAST,EAAiC,CAAC,EAAK,IAAY,OAC9D,KAAM,GAAO,MAAO,IAAQ,SAAW,WAAW,CAAG,EAAI,EAGzD,GAAI,MAAM,CAAI,GAAK,IAAS,KACnB,MAAA,MAIT,GAAI,IAAS,EACJ,MAAA,GAGH,KAAA,GAAU,KAAK,IAAI,CAAI,EACvB,EAAS,KAAK,MAAM,CAAO,EAC3B,EAAS,GAAG,EAAO,EAAI,IAAM,KAAK,IAAW,EAAI,GAAK,GAAG,OACzD,EAAW,EAAU,EAG3B,GAAI,IAAa,EACf,MAAO,GAAG,IAGN,KAAA,GACJ,MAAO,IAAY,UAAY,CAAE,gBAAiB,CAAA,EAAY,UAAW,GAErE,EAAc,EAAK,gBAAkB,EAAO,KAAS,EAAA,EAErD,EAAc,AAAC,GACnB,EAAK,gBACD,EACA,EAAK,cACL,EAAiB,GAAgB,QAAQ,IAAK,QAAG,EACjD,EAAiB,GAEZ,SAAA,CAAC,EAAK,IAAO,GACtB,GAAI,EAAY,EAAU,EAAK,KAAK,YAAL,OAAkB,CAAgB,EACxD,MAAA,GAAG,IAAc,EAAY,CAAE,IAI1C,MAAO,GAAG,GACZ"}
1
+ {"version":3,"file":"format-quantity.cjs.js","sources":["../src/constants.ts","../src/formatQuantity.ts"],"sourcesContent":["import type { SimpleFraction, VulgarFraction } from './types';\n\nexport const defaultTolerance = 0.0075;\n\nexport const vulgarFractions = [\n '¼',\n '½',\n '¾',\n '⅐',\n '⅑',\n '⅒',\n '⅓',\n '⅔',\n '⅕',\n '⅖',\n '⅗',\n '⅘',\n '⅙',\n '⅚',\n '⅛',\n '⅜',\n '⅝',\n '⅞',\n];\n\n/**\n * A map of vulgar or simple fractions to their traditional ASCII equivalents.\n * Simple fractions map to themselves.\n */\nexport const vulgarToPlainMap: Record<string, SimpleFraction> = {\n '¼': '1/4',\n '½': '1/2',\n '¾': '3/4',\n '⅐': '1/7',\n '⅑': '1/9',\n '⅒': '1/10',\n '⅓': '1/3',\n '⅔': '2/3',\n '⅕': '1/5',\n '⅖': '2/5',\n '⅗': '3/5',\n '⅘': '4/5',\n '⅙': '1/6',\n '⅚': '5/6',\n '⅛': '1/8',\n '⅜': '3/8',\n '⅝': '5/8',\n '⅞': '7/8',\n '1/16': '1/16',\n '3/16': '3/16',\n '5/16': '5/16',\n '7/16': '7/16',\n '9/16': '9/16',\n '11/16': '11/16',\n '13/16': '13/16',\n '15/16': '15/16',\n};\n\nexport const fractionDecimalMatches: [\n number,\n VulgarFraction | SimpleFraction\n][] = [\n [0.33, '⅓'],\n [0.66, '⅔'],\n [0.2, '⅕'],\n [0.4, '⅖'],\n [0.6, '⅗'],\n [0.8, '⅘'],\n [0.166, '⅙'],\n [0.833, '⅚'],\n [0.143, '⅐'],\n [0.111, '⅑'],\n [0.1, '⅒'],\n [0.125, '⅛'],\n [0.25, '¼'],\n [0.375, '⅜'],\n [0.5, '½'],\n [0.625, '⅝'],\n [0.75, '¾'],\n [0.875, '⅞'],\n [0.0625, '1/16'],\n [0.1875, '3/16'],\n [0.3125, '5/16'],\n [0.4375, '7/16'],\n [0.5625, '9/16'],\n [0.6875, '11/16'],\n [0.8125, '13/16'],\n [0.9375, '15/16'],\n];\n","import {\n defaultTolerance,\n fractionDecimalMatches,\n vulgarFractions,\n vulgarToPlainMap,\n} from './constants';\nimport type {\n FormatQuantity,\n FormatQuantityOptions,\n SimpleFraction,\n VulgarFraction,\n} from './types';\n\n/**\n * Determines if two numbers are close enough to consider\n * them equal for the purposes of this package.\n */\nconst closeEnough = (n1: number, n2: number, tolerance: number) =>\n Math.abs(n1 - n2) < tolerance;\n\nconst getFraction = (\n fraction: VulgarFraction | SimpleFraction,\n opts: FormatQuantityOptions\n) =>\n opts.vulgarFractions\n ? fraction\n : opts.fractionSlash\n ? vulgarToPlainMap[fraction].replace('/', '⁄')\n : vulgarToPlainMap[fraction];\n\n/**\n * Formats a number (or string that appears to be a number)\n * as one would see it written in imperial measurements, e.g.\n * \"1 1/2\" instead of \"1.5\". To use vulgar fraction characters\n * like \"½\", pass `true` as the second argument. For other options\n * see the [documentation](https://jakeboone02.github.io/format-quantity/).\n */\nexport const formatQuantity: FormatQuantity = (qty, options) => {\n const dQty = typeof qty === 'string' ? parseFloat(qty) : qty;\n\n // Return `null` if input is not number-like\n if (isNaN(dQty) || dQty === null) {\n return null;\n }\n\n // Return an empty string if the value is zero\n if (dQty === 0) {\n return '';\n }\n\n const dQtyAbs = Math.abs(dQty);\n const iFloor = Math.floor(dQtyAbs);\n const sFloor = `${dQty < 0 ? '-' : ''}${iFloor === 0 ? '' : `${iFloor} `}`;\n const dDecimal = dQtyAbs - iFloor;\n\n // For integers just return the given value as a string\n if (dDecimal === 0) {\n return `${dQty}`;\n }\n\n const opts: FormatQuantityOptions =\n typeof options === 'boolean' ? { vulgarFractions: options } : options ?? {};\n\n for (const [num, vf] of fractionDecimalMatches) {\n if (closeEnough(dDecimal, num, opts.tolerance ?? defaultTolerance)) {\n const fraction = getFraction(vf, opts);\n const int = vulgarFractions.includes(fraction) ? sFloor.trim() : sFloor;\n return `${int}${fraction}`;\n }\n }\n\n return `${dQty}`;\n};\n"],"names":["defaultTolerance","vulgarFractions","vulgarToPlainMap","fractionDecimalMatches","closeEnough","n1","n2","tolerance","getFraction","fraction","opts","formatQuantity","qty","options","dQty","dQtyAbs","iFloor","sFloor","dDecimal","num","vf","_a"],"mappings":"4GAEO,MAAMA,EAAmB,MAEnBC,EAAkB,CAC7B,OACA,OACA,OACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,QACF,EAMaC,EAAmD,CAC9D,OAAK,MACL,OAAK,MACL,OAAK,MACL,SAAK,MACL,SAAK,MACL,SAAK,OACL,SAAK,MACL,SAAK,MACL,SAAK,MACL,SAAK,MACL,SAAK,MACL,SAAK,MACL,SAAK,MACL,SAAK,MACL,SAAK,MACL,SAAK,MACL,SAAK,MACL,SAAK,MACL,OAAQ,OACR,OAAQ,OACR,OAAQ,OACR,OAAQ,OACR,OAAQ,OACR,QAAS,QACT,QAAS,QACT,QAAS,OACX,EAEaC,EAGP,CACJ,CAAC,IAAM,QAAG,EACV,CAAC,IAAM,QAAG,EACV,CAAC,GAAK,QAAG,EACT,CAAC,GAAK,QAAG,EACT,CAAC,GAAK,QAAG,EACT,CAAC,GAAK,QAAG,EACT,CAAC,KAAO,QAAG,EACX,CAAC,KAAO,QAAG,EACX,CAAC,KAAO,QAAG,EACX,CAAC,KAAO,QAAG,EACX,CAAC,GAAK,QAAG,EACT,CAAC,KAAO,QAAG,EACX,CAAC,IAAM,MAAG,EACV,CAAC,KAAO,QAAG,EACX,CAAC,GAAK,MAAG,EACT,CAAC,KAAO,QAAG,EACX,CAAC,IAAM,MAAG,EACV,CAAC,KAAO,QAAG,EACX,CAAC,MAAQ,MAAM,EACf,CAAC,MAAQ,MAAM,EACf,CAAC,MAAQ,MAAM,EACf,CAAC,MAAQ,MAAM,EACf,CAAC,MAAQ,MAAM,EACf,CAAC,MAAQ,OAAO,EAChB,CAAC,MAAQ,OAAO,EAChB,CAAC,MAAQ,OAAO,CAClB,ECvEMC,EAAc,CAACC,EAAYC,EAAYC,IAC3C,KAAK,IAAIF,EAAKC,CAAE,EAAIC,EAEhBC,EAAc,CAClBC,EACAC,IAEAA,EAAK,gBACDD,EACAC,EAAK,cACLR,EAAiBO,GAAU,QAAQ,IAAK,QAAG,EAC3CP,EAAiBO,GASVE,EAAiC,CAACC,EAAKC,IAAY,OAC9D,MAAMC,EAAO,OAAOF,GAAQ,SAAW,WAAWA,CAAG,EAAIA,EAGzD,GAAI,MAAME,CAAI,GAAKA,IAAS,KACnB,OAAA,KAIT,GAAIA,IAAS,EACJ,MAAA,GAGH,MAAAC,EAAU,KAAK,IAAID,CAAI,EACvBE,EAAS,KAAK,MAAMD,CAAO,EAC3BE,EAAS,GAAGH,EAAO,EAAI,IAAM,KAAKE,IAAW,EAAI,GAAK,GAAGA,OACzDE,EAAWH,EAAUC,EAG3B,GAAIE,IAAa,EACf,MAAO,GAAGJ,IAGN,MAAAJ,EACJ,OAAOG,GAAY,UAAY,CAAE,gBAAiBA,CAAA,EAAYA,GAAA,KAAAA,EAAW,GAE3E,SAAW,CAACM,EAAKC,CAAE,IAAKjB,EACtB,GAAIC,EAAYc,EAAUC,GAAKE,EAAAX,EAAK,YAAL,KAAAW,EAAkBrB,CAAgB,EAAG,CAC5D,MAAAS,EAAWD,EAAYY,EAAIV,CAAI,EAErC,MAAO,GADKT,EAAgB,SAASQ,CAAQ,EAAIQ,EAAO,KAAS,EAAAA,IACjDR,GAClB,CAGF,MAAO,GAAGK,GACZ"}
@@ -1,5 +1,23 @@
1
- const defaultTolerance = 9e-3;
2
- const vulgarToPlainMap = {
1
+ const F = 75e-4, x = [
2
+ "\xBC",
3
+ "\xBD",
4
+ "\xBE",
5
+ "\u2150",
6
+ "\u2151",
7
+ "\u2152",
8
+ "\u2153",
9
+ "\u2154",
10
+ "\u2155",
11
+ "\u2156",
12
+ "\u2157",
13
+ "\u2158",
14
+ "\u2159",
15
+ "\u215A",
16
+ "\u215B",
17
+ "\u215C",
18
+ "\u215D",
19
+ "\u215E"
20
+ ], f = {
3
21
  "\xBC": "1/4",
4
22
  "\xBD": "1/2",
5
23
  "\xBE": "3/4",
@@ -17,9 +35,16 @@ const vulgarToPlainMap = {
17
35
  "\u215B": "1/8",
18
36
  "\u215C": "3/8",
19
37
  "\u215D": "5/8",
20
- "\u215E": "7/8"
21
- };
22
- const fractionDecimalMatches = [
38
+ "\u215E": "7/8",
39
+ "1/16": "1/16",
40
+ "3/16": "3/16",
41
+ "5/16": "5/16",
42
+ "7/16": "7/16",
43
+ "9/16": "9/16",
44
+ "11/16": "11/16",
45
+ "13/16": "13/16",
46
+ "15/16": "15/16"
47
+ }, D = [
23
48
  [0.33, "\u2153"],
24
49
  [0.66, "\u2154"],
25
50
  [0.2, "\u2155"],
@@ -37,34 +62,39 @@ const fractionDecimalMatches = [
37
62
  [0.5, "\xBD"],
38
63
  [0.625, "\u215D"],
39
64
  [0.75, "\xBE"],
40
- [0.875, "\u215E"]
41
- ];
42
- const closeEnough = (n1, n2, tolerance) => Math.abs(n1 - n2) < tolerance;
43
- const formatQuantity = (qty, options) => {
44
- var _a;
45
- const dQty = typeof qty === "string" ? parseFloat(qty) : qty;
46
- if (isNaN(dQty) || dQty === null) {
65
+ [0.875, "\u215E"],
66
+ [0.0625, "1/16"],
67
+ [0.1875, "3/16"],
68
+ [0.3125, "5/16"],
69
+ [0.4375, "7/16"],
70
+ [0.5625, "9/16"],
71
+ [0.6875, "11/16"],
72
+ [0.8125, "13/16"],
73
+ [0.9375, "15/16"]
74
+ ], d = (t, u, a) => Math.abs(t - u) < a, g = (t, u) => u.vulgarFractions ? t : u.fractionSlash ? f[t].replace("/", "\u2044") : f[t], $ = (t, u) => {
75
+ var l;
76
+ const a = typeof t == "string" ? parseFloat(t) : t;
77
+ if (isNaN(a) || a === null)
47
78
  return null;
48
- }
49
- if (dQty === 0) {
79
+ if (a === 0)
50
80
  return "";
51
- }
52
- const dQtyAbs = Math.abs(dQty);
53
- const iFloor = Math.floor(dQtyAbs);
54
- const sFloor = `${dQty < 0 ? "-" : ""}${iFloor === 0 ? "" : `${iFloor} `}`;
55
- const dDecimal = dQtyAbs - iFloor;
56
- if (dDecimal === 0) {
57
- return `${dQty}`;
58
- }
59
- const opts = typeof options === "boolean" ? { vulgarFractions: options } : options != null ? options : {};
60
- const sFloorFinal = opts.vulgarFractions ? sFloor.trim() : sFloor;
61
- const getFraction = (vulgarFraction) => opts.vulgarFractions ? vulgarFraction : opts.fractionSlash ? vulgarToPlainMap[vulgarFraction].replace("/", "\u2044") : vulgarToPlainMap[vulgarFraction];
62
- for (const [num, vf] of fractionDecimalMatches) {
63
- if (closeEnough(dDecimal, num, (_a = opts.tolerance) != null ? _a : defaultTolerance)) {
64
- return `${sFloorFinal}${getFraction(vf)}`;
81
+ const r = Math.abs(a), n = Math.floor(r), c = `${a < 0 ? "-" : ""}${n === 0 ? "" : `${n} `}`, o = r - n;
82
+ if (o === 0)
83
+ return `${a}`;
84
+ const e = typeof u == "boolean" ? { vulgarFractions: u } : u != null ? u : {};
85
+ for (const [i, B] of D)
86
+ if (d(o, i, (l = e.tolerance) != null ? l : 75e-4)) {
87
+ const s = g(B, e);
88
+ return `${x.includes(s) ? c.trim() : c}${s}`;
65
89
  }
66
- }
67
- return `${dQty}`;
90
+ return `${a}`;
91
+ };
92
+ export {
93
+ $ as default,
94
+ F as defaultTolerance,
95
+ $ as formatQuantity,
96
+ D as fractionDecimalMatches,
97
+ x as vulgarFractions,
98
+ f as vulgarToPlainMap
68
99
  };
69
- export { formatQuantity as default, defaultTolerance, formatQuantity, fractionDecimalMatches, vulgarToPlainMap };
70
100
  //# sourceMappingURL=format-quantity.es.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"format-quantity.es.js","sources":["../src/constants.ts","../src/formatQuantity.ts"],"sourcesContent":["import type { VulgarFraction } from './types';\n\nexport const defaultTolerance = 0.009;\n\n/**\n * A map of vulgar fractions to their traditional ASCII equivalents.\n */\nexport const vulgarToPlainMap: {\n [vf in VulgarFraction]: `${number}/${number}`;\n} = {\n '¼': '1/4',\n '½': '1/2',\n '¾': '3/4',\n '⅐': '1/7',\n '⅑': '1/9',\n '⅒': '1/10',\n '⅓': '1/3',\n '⅔': '2/3',\n '⅕': '1/5',\n '⅖': '2/5',\n '⅗': '3/5',\n '⅘': '4/5',\n '⅙': '1/6',\n '⅚': '5/6',\n '⅛': '1/8',\n '⅜': '3/8',\n '⅝': '5/8',\n '⅞': '7/8',\n};\n\nexport const fractionDecimalMatches: [number, VulgarFraction][] = [\n [0.33, '⅓'],\n [0.66, '⅔'],\n [0.2, '⅕'],\n [0.4, '⅖'],\n [0.6, '⅗'],\n [0.8, '⅘'],\n [0.166, '⅙'],\n [0.833, '⅚'],\n [0.143, '⅐'],\n [0.111, '⅑'],\n [0.1, '⅒'],\n [0.125, '⅛'],\n [0.25, '¼'],\n [0.375, '⅜'],\n [0.5, '½'],\n [0.625, '⅝'],\n [0.75, '¾'],\n [0.875, '⅞'],\n];\n","import {\n defaultTolerance,\n fractionDecimalMatches,\n vulgarToPlainMap,\n} from './constants';\nimport type {\n FormatQuantity,\n FormatQuantityOptions,\n VulgarFraction,\n} from './types';\n\n/**\n * Determines if two numbers are close enough to consider\n * them equal for the purposes of this package.\n */\nconst closeEnough = (n1: number, n2: number, tolerance: number) =>\n Math.abs(n1 - n2) < tolerance;\n\n/**\n * Formats a number (or string that appears to be a number)\n * as one would see it written in imperial measurements, e.g.\n * \"1 1/2\" instead of \"1.5\". To use vulgar fraction characters\n * like \"½\", pass `true` as the second argument. For other options\n * see the [documentation](https://jakeboone02.github.io/format-quantity/).\n */\nexport const formatQuantity: FormatQuantity = (qty, options) => {\n const dQty = typeof qty === 'string' ? parseFloat(qty) : qty;\n\n // Return `null` if input is not number-like\n if (isNaN(dQty) || dQty === null) {\n return null;\n }\n\n // Return an empty string if the value is zero\n if (dQty === 0) {\n return '';\n }\n\n const dQtyAbs = Math.abs(dQty);\n const iFloor = Math.floor(dQtyAbs);\n const sFloor = `${dQty < 0 ? '-' : ''}${iFloor === 0 ? '' : `${iFloor} `}`;\n const dDecimal = dQtyAbs - iFloor;\n\n // For integers just return the given value as a string\n if (dDecimal === 0) {\n return `${dQty}`;\n }\n\n const opts: FormatQuantityOptions =\n typeof options === 'boolean' ? { vulgarFractions: options } : options ?? {};\n\n const sFloorFinal = opts.vulgarFractions ? sFloor.trim() : sFloor;\n\n const getFraction = (vulgarFraction: VulgarFraction) =>\n opts.vulgarFractions\n ? vulgarFraction\n : opts.fractionSlash\n ? vulgarToPlainMap[vulgarFraction].replace('/', '⁄')\n : vulgarToPlainMap[vulgarFraction];\n\n for (const [num, vf] of fractionDecimalMatches) {\n if (closeEnough(dDecimal, num, opts.tolerance ?? defaultTolerance)) {\n return `${sFloorFinal}${getFraction(vf)}`;\n }\n }\n\n return `${dQty}`;\n};\n"],"names":[],"mappings":"AAEO,MAAM,mBAAmB;AAKzB,MAAM,mBAET;AAAA,EACF,QAAK;AAAA,EACL,QAAK;AAAA,EACL,QAAK;AAAA,EACL,UAAK;AAAA,EACL,UAAK;AAAA,EACL,UAAK;AAAA,EACL,UAAK;AAAA,EACL,UAAK;AAAA,EACL,UAAK;AAAA,EACL,UAAK;AAAA,EACL,UAAK;AAAA,EACL,UAAK;AAAA,EACL,UAAK;AAAA,EACL,UAAK;AAAA,EACL,UAAK;AAAA,EACL,UAAK;AAAA,EACL,UAAK;AAAA,EACL,UAAK;AACP;AAEO,MAAM,yBAAqD;AAAA,EAChE,CAAC,MAAM,QAAG;AAAA,EACV,CAAC,MAAM,QAAG;AAAA,EACV,CAAC,KAAK,QAAG;AAAA,EACT,CAAC,KAAK,QAAG;AAAA,EACT,CAAC,KAAK,QAAG;AAAA,EACT,CAAC,KAAK,QAAG;AAAA,EACT,CAAC,OAAO,QAAG;AAAA,EACX,CAAC,OAAO,QAAG;AAAA,EACX,CAAC,OAAO,QAAG;AAAA,EACX,CAAC,OAAO,QAAG;AAAA,EACX,CAAC,KAAK,QAAG;AAAA,EACT,CAAC,OAAO,QAAG;AAAA,EACX,CAAC,MAAM,MAAG;AAAA,EACV,CAAC,OAAO,QAAG;AAAA,EACX,CAAC,KAAK,MAAG;AAAA,EACT,CAAC,OAAO,QAAG;AAAA,EACX,CAAC,MAAM,MAAG;AAAA,EACV,CAAC,OAAO,QAAG;AACb;AClCA,MAAM,cAAc,CAAC,IAAY,IAAY,cAC3C,KAAK,IAAI,KAAK,EAAE,IAAI;AAST,MAAA,iBAAiC,CAAC,KAAK,YAAY;ADvBzD;ACwBL,QAAM,OAAO,OAAO,QAAQ,WAAW,WAAW,GAAG,IAAI;AAGzD,MAAI,MAAM,IAAI,KAAK,SAAS,MAAM;AACzB,WAAA;AAAA,EACT;AAGA,MAAI,SAAS,GAAG;AACP,WAAA;AAAA,EACT;AAEM,QAAA,UAAU,KAAK,IAAI,IAAI;AACvB,QAAA,SAAS,KAAK,MAAM,OAAO;AAC3B,QAAA,SAAS,GAAG,OAAO,IAAI,MAAM,KAAK,WAAW,IAAI,KAAK,GAAG;AAC/D,QAAM,WAAW,UAAU;AAG3B,MAAI,aAAa,GAAG;AAClB,WAAO,GAAG;AAAA,EACZ;AAEM,QAAA,OACJ,OAAO,YAAY,YAAY,EAAE,iBAAiB,QAAA,IAAY,4BAAW;AAE3E,QAAM,cAAc,KAAK,kBAAkB,OAAO,KAAS,IAAA;AAE3D,QAAM,cAAc,CAAC,mBACnB,KAAK,kBACD,iBACA,KAAK,gBACL,iBAAiB,gBAAgB,QAAQ,KAAK,QAAG,IACjD,iBAAiB;AAEZ,aAAA,CAAC,KAAK,OAAO,wBAAwB;AAC9C,QAAI,YAAY,UAAU,KAAK,WAAK,cAAL,YAAkB,gBAAgB,GAAG;AAC3D,aAAA,GAAG,cAAc,YAAY,EAAE;AAAA,IACxC;AAAA,EACF;AAEA,SAAO,GAAG;AACZ;;"}
1
+ {"version":3,"file":"format-quantity.es.js","sources":["../src/constants.ts","../src/formatQuantity.ts"],"sourcesContent":["import type { SimpleFraction, VulgarFraction } from './types';\n\nexport const defaultTolerance = 0.0075;\n\nexport const vulgarFractions = [\n '¼',\n '½',\n '¾',\n '⅐',\n '⅑',\n '⅒',\n '⅓',\n '⅔',\n '⅕',\n '⅖',\n '⅗',\n '⅘',\n '⅙',\n '⅚',\n '⅛',\n '⅜',\n '⅝',\n '⅞',\n];\n\n/**\n * A map of vulgar or simple fractions to their traditional ASCII equivalents.\n * Simple fractions map to themselves.\n */\nexport const vulgarToPlainMap: Record<string, SimpleFraction> = {\n '¼': '1/4',\n '½': '1/2',\n '¾': '3/4',\n '⅐': '1/7',\n '⅑': '1/9',\n '⅒': '1/10',\n '⅓': '1/3',\n '⅔': '2/3',\n '⅕': '1/5',\n '⅖': '2/5',\n '⅗': '3/5',\n '⅘': '4/5',\n '⅙': '1/6',\n '⅚': '5/6',\n '⅛': '1/8',\n '⅜': '3/8',\n '⅝': '5/8',\n '⅞': '7/8',\n '1/16': '1/16',\n '3/16': '3/16',\n '5/16': '5/16',\n '7/16': '7/16',\n '9/16': '9/16',\n '11/16': '11/16',\n '13/16': '13/16',\n '15/16': '15/16',\n};\n\nexport const fractionDecimalMatches: [\n number,\n VulgarFraction | SimpleFraction\n][] = [\n [0.33, '⅓'],\n [0.66, '⅔'],\n [0.2, '⅕'],\n [0.4, '⅖'],\n [0.6, '⅗'],\n [0.8, '⅘'],\n [0.166, '⅙'],\n [0.833, '⅚'],\n [0.143, '⅐'],\n [0.111, '⅑'],\n [0.1, '⅒'],\n [0.125, '⅛'],\n [0.25, '¼'],\n [0.375, '⅜'],\n [0.5, '½'],\n [0.625, '⅝'],\n [0.75, '¾'],\n [0.875, '⅞'],\n [0.0625, '1/16'],\n [0.1875, '3/16'],\n [0.3125, '5/16'],\n [0.4375, '7/16'],\n [0.5625, '9/16'],\n [0.6875, '11/16'],\n [0.8125, '13/16'],\n [0.9375, '15/16'],\n];\n","import {\n defaultTolerance,\n fractionDecimalMatches,\n vulgarFractions,\n vulgarToPlainMap,\n} from './constants';\nimport type {\n FormatQuantity,\n FormatQuantityOptions,\n SimpleFraction,\n VulgarFraction,\n} from './types';\n\n/**\n * Determines if two numbers are close enough to consider\n * them equal for the purposes of this package.\n */\nconst closeEnough = (n1: number, n2: number, tolerance: number) =>\n Math.abs(n1 - n2) < tolerance;\n\nconst getFraction = (\n fraction: VulgarFraction | SimpleFraction,\n opts: FormatQuantityOptions\n) =>\n opts.vulgarFractions\n ? fraction\n : opts.fractionSlash\n ? vulgarToPlainMap[fraction].replace('/', '⁄')\n : vulgarToPlainMap[fraction];\n\n/**\n * Formats a number (or string that appears to be a number)\n * as one would see it written in imperial measurements, e.g.\n * \"1 1/2\" instead of \"1.5\". To use vulgar fraction characters\n * like \"½\", pass `true` as the second argument. For other options\n * see the [documentation](https://jakeboone02.github.io/format-quantity/).\n */\nexport const formatQuantity: FormatQuantity = (qty, options) => {\n const dQty = typeof qty === 'string' ? parseFloat(qty) : qty;\n\n // Return `null` if input is not number-like\n if (isNaN(dQty) || dQty === null) {\n return null;\n }\n\n // Return an empty string if the value is zero\n if (dQty === 0) {\n return '';\n }\n\n const dQtyAbs = Math.abs(dQty);\n const iFloor = Math.floor(dQtyAbs);\n const sFloor = `${dQty < 0 ? '-' : ''}${iFloor === 0 ? '' : `${iFloor} `}`;\n const dDecimal = dQtyAbs - iFloor;\n\n // For integers just return the given value as a string\n if (dDecimal === 0) {\n return `${dQty}`;\n }\n\n const opts: FormatQuantityOptions =\n typeof options === 'boolean' ? { vulgarFractions: options } : options ?? {};\n\n for (const [num, vf] of fractionDecimalMatches) {\n if (closeEnough(dDecimal, num, opts.tolerance ?? defaultTolerance)) {\n const fraction = getFraction(vf, opts);\n const int = vulgarFractions.includes(fraction) ? sFloor.trim() : sFloor;\n return `${int}${fraction}`;\n }\n }\n\n return `${dQty}`;\n};\n"],"names":["defaultTolerance","vulgarFractions","vulgarToPlainMap","fractionDecimalMatches","closeEnough","n1","n2","tolerance","getFraction","fraction","opts","formatQuantity","qty","options","_a","dQty","dQtyAbs","iFloor","sFloor","dDecimal","num","vf"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- (function(u,o){typeof exports=="object"&&typeof module!="undefined"?o(exports):typeof define=="function"&&define.amd?define(["exports"],o):(u=typeof globalThis!="undefined"?globalThis:u||self,o(u.FormatQuantity={}))})(this,function(u){"use strict";const r={"\xBC":"1/4","\xBD":"1/2","\xBE":"3/4","\u2150":"1/7","\u2151":"1/9","\u2152":"1/10","\u2153":"1/3","\u2154":"2/3","\u2155":"1/5","\u2156":"2/5","\u2157":"3/5","\u2158":"4/5","\u2159":"1/6","\u215A":"5/6","\u215B":"1/8","\u215C":"3/8","\u215D":"5/8","\u215E":"7/8"},f=[[.33,"\u2153"],[.66,"\u2154"],[.2,"\u2155"],[.4,"\u2156"],[.6,"\u2157"],[.8,"\u2158"],[.166,"\u2159"],[.833,"\u215A"],[.143,"\u2150"],[.111,"\u2151"],[.1,"\u2152"],[.125,"\u215B"],[.25,"\xBC"],[.375,"\u215C"],[.5,"\xBD"],[.625,"\u215D"],[.75,"\xBE"],[.875,"\u215E"]],M=(n,t,e)=>Math.abs(n-t)<e,i=(n,t)=>{var h;const e=typeof n=="string"?parseFloat(n):n;if(isNaN(e)||e===null)return null;if(e===0)return"";const s=Math.abs(e),c=Math.floor(s),d=`${e<0?"-":""}${c===0?"":`${c} `}`,m=s-c;if(m===0)return`${e}`;const l=typeof t=="boolean"?{vulgarFractions:t}:t!=null?t:{},T=l.vulgarFractions?d.trim():d,g=a=>l.vulgarFractions?a:l.fractionSlash?r[a].replace("/","\u2044"):r[a];for(const[a,y]of f)if(M(m,a,(h=l.tolerance)!=null?h:.009))return`${T}${g(y)}`;return`${e}`};u.default=i,u.defaultTolerance=.009,u.formatQuantity=i,u.fractionDecimalMatches=f,u.vulgarToPlainMap=r,Object.defineProperties(u,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})});
1
+ (function(u,a){typeof exports=="object"&&typeof module<"u"?a(exports):typeof define=="function"&&define.amd?define(["exports"],a):(u=typeof globalThis<"u"?globalThis:u||self,a(u.FormatQuantity={}))})(this,function(u){"use strict";const c=["\xBC","\xBD","\xBE","\u2150","\u2151","\u2152","\u2153","\u2154","\u2155","\u2156","\u2157","\u2158","\u2159","\u215A","\u215B","\u215C","\u215D","\u215E"],o={"\xBC":"1/4","\xBD":"1/2","\xBE":"3/4","\u2150":"1/7","\u2151":"1/9","\u2152":"1/10","\u2153":"1/3","\u2154":"2/3","\u2155":"1/5","\u2156":"2/5","\u2157":"3/5","\u2158":"4/5","\u2159":"1/6","\u215A":"5/6","\u215B":"1/8","\u215C":"3/8","\u215D":"5/8","\u215E":"7/8","1/16":"1/16","3/16":"3/16","5/16":"5/16","7/16":"7/16","9/16":"9/16","11/16":"11/16","13/16":"13/16","15/16":"15/16"},r=[[.33,"\u2153"],[.66,"\u2154"],[.2,"\u2155"],[.4,"\u2156"],[.6,"\u2157"],[.8,"\u2158"],[.166,"\u2159"],[.833,"\u215A"],[.143,"\u2150"],[.111,"\u2151"],[.1,"\u2152"],[.125,"\u215B"],[.25,"\xBC"],[.375,"\u215C"],[.5,"\xBD"],[.625,"\u215D"],[.75,"\xBE"],[.875,"\u215E"],[.0625,"1/16"],[.1875,"3/16"],[.3125,"5/16"],[.4375,"7/16"],[.5625,"9/16"],[.6875,"11/16"],[.8125,"13/16"],[.9375,"15/16"]],h=(t,e,n)=>Math.abs(t-e)<n,v=(t,e)=>e.vulgarFractions?t:e.fractionSlash?o[t].replace("/","\u2044"):o[t],i=(t,e)=>{var g;const n=typeof t=="string"?parseFloat(t):t;if(isNaN(n)||n===null)return null;if(n===0)return"";const f=Math.abs(n),l=Math.floor(f),s=`${n<0?"-":""}${l===0?"":`${l} `}`,d=f-l;if(d===0)return`${n}`;const B=typeof e=="boolean"?{vulgarFractions:e}:e!=null?e:{};for(const[D,F]of r)if(h(d,D,(g=B.tolerance)!=null?g:.0075)){const m=v(F,B);return`${c.includes(m)?s.trim():s}${m}`}return`${n}`};u.default=i,u.defaultTolerance=.0075,u.formatQuantity=i,u.fractionDecimalMatches=r,u.vulgarFractions=c,u.vulgarToPlainMap=o,Object.defineProperties(u,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})});
2
2
  //# sourceMappingURL=format-quantity.umd.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"format-quantity.umd.js","sources":["../src/constants.ts","../src/formatQuantity.ts"],"sourcesContent":["import type { VulgarFraction } from './types';\n\nexport const defaultTolerance = 0.009;\n\n/**\n * A map of vulgar fractions to their traditional ASCII equivalents.\n */\nexport const vulgarToPlainMap: {\n [vf in VulgarFraction]: `${number}/${number}`;\n} = {\n '¼': '1/4',\n '½': '1/2',\n '¾': '3/4',\n '⅐': '1/7',\n '⅑': '1/9',\n '⅒': '1/10',\n '⅓': '1/3',\n '⅔': '2/3',\n '⅕': '1/5',\n '⅖': '2/5',\n '⅗': '3/5',\n '⅘': '4/5',\n '⅙': '1/6',\n '⅚': '5/6',\n '⅛': '1/8',\n '⅜': '3/8',\n '⅝': '5/8',\n '⅞': '7/8',\n};\n\nexport const fractionDecimalMatches: [number, VulgarFraction][] = [\n [0.33, '⅓'],\n [0.66, '⅔'],\n [0.2, '⅕'],\n [0.4, '⅖'],\n [0.6, '⅗'],\n [0.8, '⅘'],\n [0.166, '⅙'],\n [0.833, '⅚'],\n [0.143, '⅐'],\n [0.111, '⅑'],\n [0.1, '⅒'],\n [0.125, '⅛'],\n [0.25, '¼'],\n [0.375, '⅜'],\n [0.5, '½'],\n [0.625, '⅝'],\n [0.75, '¾'],\n [0.875, '⅞'],\n];\n","import {\n defaultTolerance,\n fractionDecimalMatches,\n vulgarToPlainMap,\n} from './constants';\nimport type {\n FormatQuantity,\n FormatQuantityOptions,\n VulgarFraction,\n} from './types';\n\n/**\n * Determines if two numbers are close enough to consider\n * them equal for the purposes of this package.\n */\nconst closeEnough = (n1: number, n2: number, tolerance: number) =>\n Math.abs(n1 - n2) < tolerance;\n\n/**\n * Formats a number (or string that appears to be a number)\n * as one would see it written in imperial measurements, e.g.\n * \"1 1/2\" instead of \"1.5\". To use vulgar fraction characters\n * like \"½\", pass `true` as the second argument. For other options\n * see the [documentation](https://jakeboone02.github.io/format-quantity/).\n */\nexport const formatQuantity: FormatQuantity = (qty, options) => {\n const dQty = typeof qty === 'string' ? parseFloat(qty) : qty;\n\n // Return `null` if input is not number-like\n if (isNaN(dQty) || dQty === null) {\n return null;\n }\n\n // Return an empty string if the value is zero\n if (dQty === 0) {\n return '';\n }\n\n const dQtyAbs = Math.abs(dQty);\n const iFloor = Math.floor(dQtyAbs);\n const sFloor = `${dQty < 0 ? '-' : ''}${iFloor === 0 ? '' : `${iFloor} `}`;\n const dDecimal = dQtyAbs - iFloor;\n\n // For integers just return the given value as a string\n if (dDecimal === 0) {\n return `${dQty}`;\n }\n\n const opts: FormatQuantityOptions =\n typeof options === 'boolean' ? { vulgarFractions: options } : options ?? {};\n\n const sFloorFinal = opts.vulgarFractions ? sFloor.trim() : sFloor;\n\n const getFraction = (vulgarFraction: VulgarFraction) =>\n opts.vulgarFractions\n ? vulgarFraction\n : opts.fractionSlash\n ? vulgarToPlainMap[vulgarFraction].replace('/', '⁄')\n : vulgarToPlainMap[vulgarFraction];\n\n for (const [num, vf] of fractionDecimalMatches) {\n if (closeEnough(dDecimal, num, opts.tolerance ?? defaultTolerance)) {\n return `${sFloorFinal}${getFraction(vf)}`;\n }\n }\n\n return `${dQty}`;\n};\n"],"names":[],"mappings":"wPAOO,KAAM,GAET,CACF,OAAK,MACL,OAAK,MACL,OAAK,MACL,SAAK,MACL,SAAK,MACL,SAAK,OACL,SAAK,MACL,SAAK,MACL,SAAK,MACL,SAAK,MACL,SAAK,MACL,SAAK,MACL,SAAK,MACL,SAAK,MACL,SAAK,MACL,SAAK,MACL,SAAK,MACL,SAAK,KACP,EAEa,EAAqD,CAChE,CAAC,IAAM,QAAG,EACV,CAAC,IAAM,QAAG,EACV,CAAC,GAAK,QAAG,EACT,CAAC,GAAK,QAAG,EACT,CAAC,GAAK,QAAG,EACT,CAAC,GAAK,QAAG,EACT,CAAC,KAAO,QAAG,EACX,CAAC,KAAO,QAAG,EACX,CAAC,KAAO,QAAG,EACX,CAAC,KAAO,QAAG,EACX,CAAC,GAAK,QAAG,EACT,CAAC,KAAO,QAAG,EACX,CAAC,IAAM,MAAG,EACV,CAAC,KAAO,QAAG,EACX,CAAC,GAAK,MAAG,EACT,CAAC,KAAO,QAAG,EACX,CAAC,IAAM,MAAG,EACV,CAAC,KAAO,QAAG,CACb,EClCM,EAAc,CAAC,EAAY,EAAY,IAC3C,KAAK,IAAI,EAAK,CAAE,EAAI,EAST,EAAiC,CAAC,EAAK,IAAY,OAC9D,KAAM,GAAO,MAAO,IAAQ,SAAW,WAAW,CAAG,EAAI,EAGzD,GAAI,MAAM,CAAI,GAAK,IAAS,KACnB,MAAA,MAIT,GAAI,IAAS,EACJ,MAAA,GAGH,KAAA,GAAU,KAAK,IAAI,CAAI,EACvB,EAAS,KAAK,MAAM,CAAO,EAC3B,EAAS,GAAG,EAAO,EAAI,IAAM,KAAK,IAAW,EAAI,GAAK,GAAG,OACzD,EAAW,EAAU,EAG3B,GAAI,IAAa,EACf,MAAO,GAAG,IAGN,KAAA,GACJ,MAAO,IAAY,UAAY,CAAE,gBAAiB,CAAA,EAAY,UAAW,GAErE,EAAc,EAAK,gBAAkB,EAAO,KAAS,EAAA,EAErD,EAAc,AAAC,GACnB,EAAK,gBACD,EACA,EAAK,cACL,EAAiB,GAAgB,QAAQ,IAAK,QAAG,EACjD,EAAiB,GAEZ,SAAA,CAAC,EAAK,IAAO,GACtB,GAAI,EAAY,EAAU,EAAK,KAAK,YAAL,OAAkB,IAAgB,EACxD,MAAA,GAAG,IAAc,EAAY,CAAE,IAI1C,MAAO,GAAG,GACZ"}
1
+ {"version":3,"file":"format-quantity.umd.js","sources":["../src/constants.ts","../src/formatQuantity.ts"],"sourcesContent":["import type { SimpleFraction, VulgarFraction } from './types';\n\nexport const defaultTolerance = 0.0075;\n\nexport const vulgarFractions = [\n '¼',\n '½',\n '¾',\n '⅐',\n '⅑',\n '⅒',\n '⅓',\n '⅔',\n '⅕',\n '⅖',\n '⅗',\n '⅘',\n '⅙',\n '⅚',\n '⅛',\n '⅜',\n '⅝',\n '⅞',\n];\n\n/**\n * A map of vulgar or simple fractions to their traditional ASCII equivalents.\n * Simple fractions map to themselves.\n */\nexport const vulgarToPlainMap: Record<string, SimpleFraction> = {\n '¼': '1/4',\n '½': '1/2',\n '¾': '3/4',\n '⅐': '1/7',\n '⅑': '1/9',\n '⅒': '1/10',\n '⅓': '1/3',\n '⅔': '2/3',\n '⅕': '1/5',\n '⅖': '2/5',\n '⅗': '3/5',\n '⅘': '4/5',\n '⅙': '1/6',\n '⅚': '5/6',\n '⅛': '1/8',\n '⅜': '3/8',\n '⅝': '5/8',\n '⅞': '7/8',\n '1/16': '1/16',\n '3/16': '3/16',\n '5/16': '5/16',\n '7/16': '7/16',\n '9/16': '9/16',\n '11/16': '11/16',\n '13/16': '13/16',\n '15/16': '15/16',\n};\n\nexport const fractionDecimalMatches: [\n number,\n VulgarFraction | SimpleFraction\n][] = [\n [0.33, '⅓'],\n [0.66, '⅔'],\n [0.2, '⅕'],\n [0.4, '⅖'],\n [0.6, '⅗'],\n [0.8, '⅘'],\n [0.166, '⅙'],\n [0.833, '⅚'],\n [0.143, '⅐'],\n [0.111, '⅑'],\n [0.1, '⅒'],\n [0.125, '⅛'],\n [0.25, '¼'],\n [0.375, '⅜'],\n [0.5, '½'],\n [0.625, '⅝'],\n [0.75, '¾'],\n [0.875, '⅞'],\n [0.0625, '1/16'],\n [0.1875, '3/16'],\n [0.3125, '5/16'],\n [0.4375, '7/16'],\n [0.5625, '9/16'],\n [0.6875, '11/16'],\n [0.8125, '13/16'],\n [0.9375, '15/16'],\n];\n","import {\n defaultTolerance,\n fractionDecimalMatches,\n vulgarFractions,\n vulgarToPlainMap,\n} from './constants';\nimport type {\n FormatQuantity,\n FormatQuantityOptions,\n SimpleFraction,\n VulgarFraction,\n} from './types';\n\n/**\n * Determines if two numbers are close enough to consider\n * them equal for the purposes of this package.\n */\nconst closeEnough = (n1: number, n2: number, tolerance: number) =>\n Math.abs(n1 - n2) < tolerance;\n\nconst getFraction = (\n fraction: VulgarFraction | SimpleFraction,\n opts: FormatQuantityOptions\n) =>\n opts.vulgarFractions\n ? fraction\n : opts.fractionSlash\n ? vulgarToPlainMap[fraction].replace('/', '⁄')\n : vulgarToPlainMap[fraction];\n\n/**\n * Formats a number (or string that appears to be a number)\n * as one would see it written in imperial measurements, e.g.\n * \"1 1/2\" instead of \"1.5\". To use vulgar fraction characters\n * like \"½\", pass `true` as the second argument. For other options\n * see the [documentation](https://jakeboone02.github.io/format-quantity/).\n */\nexport const formatQuantity: FormatQuantity = (qty, options) => {\n const dQty = typeof qty === 'string' ? parseFloat(qty) : qty;\n\n // Return `null` if input is not number-like\n if (isNaN(dQty) || dQty === null) {\n return null;\n }\n\n // Return an empty string if the value is zero\n if (dQty === 0) {\n return '';\n }\n\n const dQtyAbs = Math.abs(dQty);\n const iFloor = Math.floor(dQtyAbs);\n const sFloor = `${dQty < 0 ? '-' : ''}${iFloor === 0 ? '' : `${iFloor} `}`;\n const dDecimal = dQtyAbs - iFloor;\n\n // For integers just return the given value as a string\n if (dDecimal === 0) {\n return `${dQty}`;\n }\n\n const opts: FormatQuantityOptions =\n typeof options === 'boolean' ? { vulgarFractions: options } : options ?? {};\n\n for (const [num, vf] of fractionDecimalMatches) {\n if (closeEnough(dDecimal, num, opts.tolerance ?? defaultTolerance)) {\n const fraction = getFraction(vf, opts);\n const int = vulgarFractions.includes(fraction) ? sFloor.trim() : sFloor;\n return `${int}${fraction}`;\n }\n }\n\n return `${dQty}`;\n};\n"],"names":["vulgarFractions","vulgarToPlainMap","fractionDecimalMatches","closeEnough","n1","n2","tolerance","getFraction","fraction","opts","formatQuantity","qty","options","dQty","dQtyAbs","iFloor","sFloor","dDecimal","num","vf","_a"],"mappings":"sOAIO,MAAMA,EAAkB,CAC7B,OACA,OACA,OACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,QACF,EAMaC,EAAmD,CAC9D,OAAK,MACL,OAAK,MACL,OAAK,MACL,SAAK,MACL,SAAK,MACL,SAAK,OACL,SAAK,MACL,SAAK,MACL,SAAK,MACL,SAAK,MACL,SAAK,MACL,SAAK,MACL,SAAK,MACL,SAAK,MACL,SAAK,MACL,SAAK,MACL,SAAK,MACL,SAAK,MACL,OAAQ,OACR,OAAQ,OACR,OAAQ,OACR,OAAQ,OACR,OAAQ,OACR,QAAS,QACT,QAAS,QACT,QAAS,OACX,EAEaC,EAGP,CACJ,CAAC,IAAM,QAAG,EACV,CAAC,IAAM,QAAG,EACV,CAAC,GAAK,QAAG,EACT,CAAC,GAAK,QAAG,EACT,CAAC,GAAK,QAAG,EACT,CAAC,GAAK,QAAG,EACT,CAAC,KAAO,QAAG,EACX,CAAC,KAAO,QAAG,EACX,CAAC,KAAO,QAAG,EACX,CAAC,KAAO,QAAG,EACX,CAAC,GAAK,QAAG,EACT,CAAC,KAAO,QAAG,EACX,CAAC,IAAM,MAAG,EACV,CAAC,KAAO,QAAG,EACX,CAAC,GAAK,MAAG,EACT,CAAC,KAAO,QAAG,EACX,CAAC,IAAM,MAAG,EACV,CAAC,KAAO,QAAG,EACX,CAAC,MAAQ,MAAM,EACf,CAAC,MAAQ,MAAM,EACf,CAAC,MAAQ,MAAM,EACf,CAAC,MAAQ,MAAM,EACf,CAAC,MAAQ,MAAM,EACf,CAAC,MAAQ,OAAO,EAChB,CAAC,MAAQ,OAAO,EAChB,CAAC,MAAQ,OAAO,CAClB,ECvEMC,EAAc,CAACC,EAAYC,EAAYC,IAC3C,KAAK,IAAIF,EAAKC,CAAE,EAAIC,EAEhBC,EAAc,CAClBC,EACAC,IAEAA,EAAK,gBACDD,EACAC,EAAK,cACLR,EAAiBO,GAAU,QAAQ,IAAK,QAAG,EAC3CP,EAAiBO,GASVE,EAAiC,CAACC,EAAKC,IAAY,OAC9D,MAAMC,EAAO,OAAOF,GAAQ,SAAW,WAAWA,CAAG,EAAIA,EAGzD,GAAI,MAAME,CAAI,GAAKA,IAAS,KACnB,OAAA,KAIT,GAAIA,IAAS,EACJ,MAAA,GAGH,MAAAC,EAAU,KAAK,IAAID,CAAI,EACvBE,EAAS,KAAK,MAAMD,CAAO,EAC3BE,EAAS,GAAGH,EAAO,EAAI,IAAM,KAAKE,IAAW,EAAI,GAAK,GAAGA,OACzDE,EAAWH,EAAUC,EAG3B,GAAIE,IAAa,EACf,MAAO,GAAGJ,IAGN,MAAAJ,EACJ,OAAOG,GAAY,UAAY,CAAE,gBAAiBA,CAAA,EAAYA,GAAA,KAAAA,EAAW,GAE3E,SAAW,CAACM,EAAKC,CAAE,IAAKjB,EACtB,GAAIC,EAAYc,EAAUC,GAAKE,EAAAX,EAAK,YAAL,KAAAW,EAAkB,KAAgB,EAAG,CAC5D,MAAAZ,EAAWD,EAAYY,EAAIV,CAAI,EAErC,MAAO,GADKT,EAAgB,SAASQ,CAAQ,EAAIQ,EAAO,KAAS,EAAAA,IACjDR,GAClB,CAGF,MAAO,GAAGK,GACZ"}
package/dist/types.d.ts CHANGED
@@ -22,6 +22,8 @@ export interface FormatQuantityOptions {
22
22
  fractionSlash?: boolean;
23
23
  }
24
24
  export declare type FormatQuantity = (qty: string | number, options?: boolean | FormatQuantityOptions) => string | null;
25
+ declare type NumChar = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9';
26
+ export declare type SimpleFraction = `${NumChar}/${NumChar}` | `${NumChar}/${NumChar}${NumChar}` | `${NumChar}${NumChar}/${NumChar}${NumChar}`;
25
27
  export declare type VulgarFraction = '¼' | '½' | '¾' | '⅐' | '⅑' | '⅒' | '⅓' | '⅔' | '⅕' | '⅖' | '⅗' | '⅘' | '⅙' | '⅚' | '⅛' | '⅜' | '⅝' | '⅞';
26
28
  export declare type FormatQuantityTests = [
27
29
  string,
@@ -31,3 +33,4 @@ export declare type FormatQuantityTests = [
31
33
  Parameters<FormatQuantity>[1]
32
34
  ])[]
33
35
  ][];
36
+ export {};
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.1.0",
2
+ "version": "2.0.0",
3
3
  "name": "format-quantity",
4
4
  "author": "Jake Boone <jakeboone02@gmail.com>",
5
5
  "description": "Number formatter for imperial measurements with support for vulgar fractions",
@@ -39,15 +39,19 @@
39
39
  "publish:npm": "np"
40
40
  },
41
41
  "devDependencies": {
42
- "@babel/core": "^7.17.8",
43
- "@babel/preset-env": "^7.16.11",
44
- "@babel/preset-typescript": "^7.16.7",
45
- "@types/jest": "^27.4.1",
46
- "gh-pages": "^3.1.0",
47
- "jest": "^27.5.1",
48
- "np": "^7.3.0",
49
- "prettier": "^2.6.0",
50
- "typescript": "^4.1.5",
51
- "vite": "^2.8.6"
42
+ "@babel/core": "^7.19.1",
43
+ "@babel/preset-env": "^7.19.1",
44
+ "@babel/preset-typescript": "^7.18.6",
45
+ "@types/jest": "^29.0.2",
46
+ "gh-pages": "^4.0.0",
47
+ "jest": "^29.0.3",
48
+ "np": "^7.6.2",
49
+ "prettier": "^2.7.1",
50
+ "typescript": "^4.8.3",
51
+ "vite": "^3.1.0"
52
+ },
53
+ "packageManager": "yarn@3.2.3",
54
+ "publishConfig": {
55
+ "registry": "https://registry.npmjs.org"
52
56
  }
53
57
  }
package/CHANGELOG.md DELETED
@@ -1,38 +0,0 @@
1
- ## 1.0.2 (2022-04-16)
2
-
3
- - Update dependencies
4
- - Migrate from tsdx to Vite
5
-
6
- ## 1.0.1 (2021-02-15)
7
-
8
- - Added description to package.json
9
-
10
- ## 1.0.0 (2021-02-11)
11
-
12
- - New build system ([tsdx](https://tsdx.io/))
13
-
14
- ## 0.6.0 (2019-08-31)
15
-
16
- - Added ability to produce unicode vulgar fractions (pass `true` as the second argument)
17
-
18
- ## 0.5.0 (2019-08-24)
19
-
20
- ### Breaking change
21
-
22
- - Invalid inputs now return `null` instead of `"-1"`
23
-
24
- ### Bug fixes
25
-
26
- - Handles negative numbers properly
27
-
28
- ## 0.4.2 (2019-08-23)
29
-
30
- - Rewritten with TypeScript
31
-
32
- ## 0.3.2 (2018-09-21)
33
-
34
- ## 0.3.1 (2015-07-16)
35
-
36
- ## 0.3.0 (2015-07-16)
37
-
38
- ## 0.1.0 (2015-03-18)