From 6fda0a22a2ab3e0e91f716b855b9b79ba4984e82 Mon Sep 17 00:00:00 2001
From: yelper <2660559+yelper@users.noreply.github.com>
Date: Fri, 4 Sep 2026 15:23:35 -0700
Subject: [PATCH 1/2] reimplement changes on TS rewrite
---
API.md | 2 ++
lib/createPartition.ts | 1 +
lib/formatInfo.ts | 1 +
lib/parseFormatSection.ts | 1 +
lib/types.ts | 3 +++
test/info.spec.ts | 38 ++++++++++++++++++++++++++++++++++++++
6 files changed, 46 insertions(+)
diff --git a/API.md b/API.md
index cc1fdb7..d7e794f 100644
--- a/API.md
+++ b/API.md
@@ -808,6 +808,7 @@ type FormatInfo = {
isText: boolean;
level: number;
maxDecimals: number;
+ minDecimals: number;
parentheses: 0 | 1;
scale: number;
type: | "currency"
@@ -840,6 +841,7 @@ See the [getFormatInfo](#functionsgetformatinfomd) method.
| `isText` | `boolean` | Corresponds to the output from isTextFormat. |
| `level` | `number` | An arbirarty number that represents the format's specificity if you want to compare one to another. Integer comparisons roughly match Excel's resolutions when it determines which format wins out. |
| `maxDecimals` | `number` | The maximum number of decimals this format will emit. |
+| `minDecimals` | `number` | The minimum number of decimal places this format will reserve. |
| `parentheses` | `0` \| `1` | 1 if the positive portion of the number format contains an open parenthesis, else a 0. This is replicates Excel's `CELL("parentheses")` functionality. |
| `scale` | `number` | The multiplier used when formatting the number (100 for percentages). |
| `type` | \| `"currency"` \| `"date"` \| `"datetime"` \| `"error"` \| `"fraction"` \| `"general"` \| `"grouped"` \| `"number"` \| `"percent"` \| `"scientific"` \| `"text"` \| `"time"` | A string identifier for the type of the number formatter. |
diff --git a/lib/createPartition.ts b/lib/createPartition.ts
index 35ca39d..3e0f75f 100644
--- a/lib/createPartition.ts
+++ b/lib/createPartition.ts
@@ -15,6 +15,7 @@ export function createPartition (tokens?: RenderToken[]): Partition {
pattern: '',
int_max: 0,
frac_max: 0,
+ frac_min: 0,
man_p: '',
num_p: '',
num_min: 0,
diff --git a/lib/formatInfo.ts b/lib/formatInfo.ts
index bad0d37..a581d6b 100644
--- a/lib/formatInfo.ts
+++ b/lib/formatInfo.ts
@@ -65,6 +65,7 @@ export function info (partitions: Partition[], currencyId?: string): FormatInfo
isText: isText(partitions),
isPercent: isPercent(partitions),
maxDecimals: partPos.general ? 9 : frac_max,
+ minDecimals: partPos.general ? 0 : partPos.frac_min,
scale: partPos.scale ?? 1,
color: 0,
parentheses: 0,
diff --git a/lib/parseFormatSection.ts b/lib/parseFormatSection.ts
index 407f506..0ac4d80 100644
--- a/lib/parseFormatSection.ts
+++ b/lib/parseFormatSection.ts
@@ -470,6 +470,7 @@ export function parseFormatSection (inputTokens: Token[]) {
}
part.int_min = min;
part.frac_max = fracPattern.length;
+ part.frac_min = countNonHash(fracPattern);
let num_pat = part.num_pattern.join('');
// let den_pat = part.den_pattern.join('');
diff --git a/lib/types.ts b/lib/types.ts
index 5b0bd26..4a629e7 100644
--- a/lib/types.ts
+++ b/lib/types.ts
@@ -134,6 +134,7 @@ export type Partition = {
int_max: number,
den_max: number,
frac_max: number,
+ frac_min: number,
date_eval: boolean,
date_system: typeof EPOCH_1900 | typeof EPOCH_1317,
dec_fractions?: boolean;
@@ -188,6 +189,8 @@ export type FormatInfo = {
isPercent: boolean;
/** The maximum number of decimals this format will emit. */
maxDecimals: number;
+ /** The minimum number of decimal places this format will reserve. */
+ minDecimals: number;
/**
* 1 if the format uses color on the negative portion of the string, else
* a 0. This replicates Excel's `CELL("color")` functionality.
diff --git a/test/info.spec.ts b/test/info.spec.ts
index 09709e7..7424ac4 100644
--- a/test/info.spec.ts
+++ b/test/info.spec.ts
@@ -6,6 +6,7 @@ const commonProps = {
isText: false,
isPercent: false,
maxDecimals: 0,
+ minDecimals: 0,
grouped: 0,
parentheses: 0,
color: 0,
@@ -42,6 +43,7 @@ test('getFormatInfo', () => {
isText: false,
isPercent: false,
maxDecimals: 0,
+ minDecimals: 0,
color: 0,
scale: 1,
parentheses: 0,
@@ -58,6 +60,7 @@ test('getFormatInfo', () => {
isText: false,
isPercent: false,
maxDecimals: 0,
+ minDecimals: 0,
scale: 1,
color: 0,
parentheses: 0,
@@ -73,6 +76,7 @@ test('getFormatInfo', () => {
isText: false,
isPercent: false,
maxDecimals: 0,
+ minDecimals: 0,
scale: 1,
color: 0,
parentheses: 0,
@@ -111,24 +115,49 @@ test('Numbers', () => {
});
assertInfo('0.0', {
type: 'number',
+ minDecimals: 1,
maxDecimals: 1,
code: 'F1',
level: 4
});
+ assertInfo('0.#', {
+ type: 'number',
+ minDecimals: 0,
+ maxDecimals: 1,
+ code: 'F1',
+ level: 4
+ });
+ assertInfo('0.00##', {
+ type: 'number',
+ minDecimals: 2,
+ maxDecimals: 4,
+ code: 'F4',
+ level: 4
+ });
+ assertInfo('0.0?', {
+ type: 'number',
+ minDecimals: 2,
+ maxDecimals: 2,
+ code: 'F2',
+ level: 4
+ });
assertInfo('0.000', {
type: 'number',
+ minDecimals: 3,
maxDecimals: 3,
code: 'F3',
level: 4
});
assertInfo('0.000000000000000', {
type: 'number',
+ minDecimals: 15,
maxDecimals: 15,
code: 'F15',
level: 4
});
assertInfo('0.0000000000000000', {
type: 'number',
+ minDecimals: 16,
maxDecimals: 16,
code: 'F15',
level: 4
@@ -143,6 +172,7 @@ test('Numbers', () => {
});
assertInfo('#,##0.00', {
type: 'grouped',
+ minDecimals: 2,
maxDecimals: 2,
code: ',2',
grouped: 1,
@@ -150,6 +180,7 @@ test('Numbers', () => {
});
assertInfo('(#,##0.00)', {
type: 'grouped',
+ minDecimals: 2,
maxDecimals: 2,
code: ',2()',
parentheses: 1,
@@ -159,6 +190,7 @@ test('Numbers', () => {
assertInfo('0.00,"K"', {
type: 'number',
+ minDecimals: 2,
maxDecimals: 2,
code: 'F2',
scale: 0.001,
@@ -166,6 +198,7 @@ test('Numbers', () => {
});
assertInfo('0.00,,"K"', {
type: 'number',
+ minDecimals: 2,
maxDecimals: 2,
code: 'F2',
scale: 0.000001,
@@ -264,6 +297,7 @@ test('Currency', () => {
assertInfo('#,##0.00 €', {
type: 'currency',
code: 'C2',
+ minDecimals: 2,
maxDecimals: 2,
grouped: 1,
level: 10.4
@@ -271,6 +305,7 @@ test('Currency', () => {
assertInfo('₿ 0.0000', {
type: 'currency',
code: 'C4',
+ minDecimals: 4,
maxDecimals: 4,
level: 10.4
});
@@ -307,6 +342,7 @@ test('Percentages', () => {
scale: 100,
code: 'P2-',
color: 1,
+ minDecimals: 2,
maxDecimals: 2,
level: 10.6
});
@@ -321,6 +357,7 @@ test('Scientific', () => {
assertInfo('0.00E+00', {
type: 'scientific',
code: 'S2',
+ minDecimals: 2,
maxDecimals: 2,
level: 6
});
@@ -328,6 +365,7 @@ test('Scientific', () => {
type: 'scientific',
code: 'S1-',
color: 1,
+ minDecimals: 1,
maxDecimals: 1,
level: 6
});
From 843a810405a0f941884c9f75f0c4b3cf49844a0b Mon Sep 17 00:00:00 2001
From: yelper <2660559+yelper@users.noreply.github.com>
Date: Fri, 4 Sep 2026 15:27:10 -0700
Subject: [PATCH 2/2] revert changes to API.md as requested
---
API.md | 2 --
1 file changed, 2 deletions(-)
diff --git a/API.md b/API.md
index d7e794f..cc1fdb7 100644
--- a/API.md
+++ b/API.md
@@ -808,7 +808,6 @@ type FormatInfo = {
isText: boolean;
level: number;
maxDecimals: number;
- minDecimals: number;
parentheses: 0 | 1;
scale: number;
type: | "currency"
@@ -841,7 +840,6 @@ See the [getFormatInfo](#functionsgetformatinfomd) method.
| `isText` | `boolean` | Corresponds to the output from isTextFormat. |
| `level` | `number` | An arbirarty number that represents the format's specificity if you want to compare one to another. Integer comparisons roughly match Excel's resolutions when it determines which format wins out. |
| `maxDecimals` | `number` | The maximum number of decimals this format will emit. |
-| `minDecimals` | `number` | The minimum number of decimal places this format will reserve. |
| `parentheses` | `0` \| `1` | 1 if the positive portion of the number format contains an open parenthesis, else a 0. This is replicates Excel's `CELL("parentheses")` functionality. |
| `scale` | `number` | The multiplier used when formatting the number (100 for percentages). |
| `type` | \| `"currency"` \| `"date"` \| `"datetime"` \| `"error"` \| `"fraction"` \| `"general"` \| `"grouped"` \| `"number"` \| `"percent"` \| `"scientific"` \| `"text"` \| `"time"` | A string identifier for the type of the number formatter. |