From 13bb73439714e6aabdc8611f4ca23c51bac0d703 Mon Sep 17 00:00:00 2001 From: Javier Casas Velasco Date: Thu, 12 Jun 2025 13:26:42 -0500 Subject: [PATCH 1/3] Implement per-field stringifier --- README.md | 6 ++++++ fixed-width.d.ts | 6 ++++++ package.json | 2 +- src/options.mjs | 1 + src/options.spec.mjs | 2 ++ src/stringify.mjs | 7 ++++++- src/stringify.spec.mjs | 25 +++++++++++++++++++++++++ 7 files changed, 47 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f31a52a..67753ee 100644 --- a/README.md +++ b/README.md @@ -468,6 +468,12 @@ Type: `` Field's width. Required. +#### `field.stringify` + +Type: `` + +A function that converts the field into a custom string. Useful for custom formatting, for example, formatting a Date into DD/MM/YYYY format. Only used while stringifying. + ## Errors All errors that can occur during the parsing or serializing phase contain an error code. Error objects also contain enough info (properties) to debug the problem. diff --git a/fixed-width.d.ts b/fixed-width.d.ts index fca16ad..2147eb4 100644 --- a/fixed-width.d.ts +++ b/fixed-width.d.ts @@ -93,6 +93,12 @@ export interface Field { value: string, context: { column: number; line: number; width: number } ) => any; + /** + * Custom way of writing the value to the file + */ + stringify?: ( + value: any + ) => string; /** * Field's column number. This is 1-based. First column is 1. */ diff --git a/package.json b/package.json index d2e51e6..8326713 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@evologi/fixed-width", - "version": "1.0.1", + "version": "1.0.2", "description": "A fixed-width file format toolset with streaming support and flexible options.", "type": "module", "main": "./fixed-width.cjs", diff --git a/src/options.mjs b/src/options.mjs index dbb907c..ed73985 100644 --- a/src/options.mjs +++ b/src/options.mjs @@ -111,6 +111,7 @@ function parseField (field, index, defaultColumn, defaultPad, encoding) { column, pad, property: isPropertyKey(field.property) ? field.property : index, + stringify: typeof field.stringify === 'function' ? field.stringify : null, width: field.width } } diff --git a/src/options.spec.mjs b/src/options.spec.mjs index c67aa5b..f0b7c78 100644 --- a/src/options.spec.mjs +++ b/src/options.spec.mjs @@ -21,6 +21,7 @@ test('defaults', t => { column: 1, pad: ' ', property: 0, + stringify: null, width: 2 }, { @@ -29,6 +30,7 @@ test('defaults', t => { column: 3, pad: ' ', property: 1, + stringify: null, width: 2 } ], diff --git a/src/stringify.mjs b/src/stringify.mjs index 433b08c..c1a942e 100644 --- a/src/stringify.mjs +++ b/src/stringify.mjs @@ -116,7 +116,12 @@ export function replaceWith (text, value, index = 0) { } export function stringifyField (obj, field, options, line) { - let value = stringifyValue(obj[field.property], options.encoding) + let value = obj[field.property]; + if(field.stringify) { + value = field.stringify(value); + } + value = stringifyValue(value, options.encoding) + if (typeof value !== 'string') { throw new FixedWidthError( 'EXPECTED_STRING_VALUE', diff --git a/src/stringify.spec.mjs b/src/stringify.spec.mjs index 54b280d..35f2c46 100644 --- a/src/stringify.spec.mjs +++ b/src/stringify.spec.mjs @@ -38,6 +38,31 @@ test('stringify fields', t => { t.is(text, ' 1.3 42 ') }) +test('stringify with custom stringifier', t => { + const options = parseOptions([ + { + align: 'left', + property: 'b', + width: 10, + stringify: (date) => { + // Sample formatting that writes the date in American format (MM/DD/YYYY) + const year = (date.getYear() + 1900).toString(); + const month = date.getMonth().toString().padStart(2, "0"); + const day = date.getDate().toString().padStart(2, "0"); + const result = `${month}/${day}/${year}` + return result + } + } + ]) + + const values = { + b: new Date(2020, 3, 15) + } + + const text = stringifyFields(values, options) + t.is(text, '03/15/2020') +}) + test('expected string value', t => { t.throws( () => stringify( From c8c32c638b896944a32d7cb7dfc99e39717e5d73 Mon Sep 17 00:00:00 2001 From: Javier Casas Velasco Date: Tue, 24 Jun 2025 14:43:21 -0500 Subject: [PATCH 2/3] Undo version in package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8326713..d2e51e6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@evologi/fixed-width", - "version": "1.0.2", + "version": "1.0.1", "description": "A fixed-width file format toolset with streaming support and flexible options.", "type": "module", "main": "./fixed-width.cjs", From 059375c811d9fb295e851522df719171f462961c Mon Sep 17 00:00:00 2001 From: Javier Casas Velasco Date: Tue, 24 Jun 2025 14:45:48 -0500 Subject: [PATCH 3/3] Linter --- src/stringify.mjs | 8 ++++---- src/stringify.spec.mjs | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/stringify.mjs b/src/stringify.mjs index c1a942e..56f5a28 100644 --- a/src/stringify.mjs +++ b/src/stringify.mjs @@ -116,11 +116,11 @@ export function replaceWith (text, value, index = 0) { } export function stringifyField (obj, field, options, line) { - let value = obj[field.property]; - if(field.stringify) { - value = field.stringify(value); + let value = obj[field.property] + if (field.stringify) { + value = field.stringify(value) } - value = stringifyValue(value, options.encoding) + value = stringifyValue(value, options.encoding) if (typeof value !== 'string') { throw new FixedWidthError( diff --git a/src/stringify.spec.mjs b/src/stringify.spec.mjs index 35f2c46..2b25ef7 100644 --- a/src/stringify.spec.mjs +++ b/src/stringify.spec.mjs @@ -46,9 +46,9 @@ test('stringify with custom stringifier', t => { width: 10, stringify: (date) => { // Sample formatting that writes the date in American format (MM/DD/YYYY) - const year = (date.getYear() + 1900).toString(); - const month = date.getMonth().toString().padStart(2, "0"); - const day = date.getDate().toString().padStart(2, "0"); + const year = (date.getYear() + 1900).toString() + const month = date.getMonth().toString().padStart(2, '0') + const day = date.getDate().toString().padStart(2, '0') const result = `${month}/${day}/${year}` return result }