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. |