diff --git a/TiaCodegen-ts/src/Extensions/NaturalComparer.ts b/TiaCodegen-ts/src/Extensions/NaturalComparer.ts index a11560d..cf49d0a 100644 --- a/TiaCodegen-ts/src/Extensions/NaturalComparer.ts +++ b/TiaCodegen-ts/src/Extensions/NaturalComparer.ts @@ -21,8 +21,10 @@ export class NaturalComparer { } if (vx !== vy) return vx < vy ? -1 : 1; } else { - const cmp = cx.toUpperCase().localeCompare(cy.toUpperCase()); - if (cmp !== 0) return cmp; + // Ordinal comparison like char.ToUpperInvariant(cx).CompareTo(...) in the C# version + const ux = cx.toUpperCase(); + const uy = cy.toUpperCase(); + if (ux !== uy) return ux < uy ? -1 : 1; i++; j++; } diff --git a/TiaCodegen-ts/tests/NaturalComparer.test.ts b/TiaCodegen-ts/tests/NaturalComparer.test.ts new file mode 100644 index 0000000..63dd2b8 --- /dev/null +++ b/TiaCodegen-ts/tests/NaturalComparer.test.ts @@ -0,0 +1,15 @@ +import { NaturalComparer } from '../src/Extensions/NaturalComparer'; + +describe('NaturalComparer', () => { + test('orders punctuation ordinally like the C# version', () => { + const names = ['GroupSignals.1_1.X', 'GroupSignals.1.X', 'GroupSignals.1_2.X', 'A_b', 'A.b', 'Ab', 'A-b', 'A b']; + names.sort((a, b) => new NaturalComparer().compare(a, b)); + expect(names).toEqual(['A b', 'A-b', 'A.b', 'Ab', 'A_b', 'GroupSignals.1.X', 'GroupSignals.1_1.X', 'GroupSignals.1_2.X']); + }); + + test('compares numbers naturally and letters case-insensitively', () => { + const comparer = new NaturalComparer(); + expect(comparer.compare('a2', 'a10')).toBeLessThan(0); + expect(comparer.compare('a', 'A')).toBe(0); + }); +});