Add configurable place display and shortening (#294)

* Add configurable place display and shortening

* Fix prettier formatting stuff

* Move place shortening logic to Chart
This commit is contained in:
Rokas
2026-06-04 21:33:08 +03:00
committed by GitHub
parent 1fc83bc77e
commit 059c9d9413
12 changed files with 269 additions and 6 deletions

View File

@@ -0,0 +1,50 @@
import {describe, expect, it} from '@jest/globals';
import {PlaceDisplay, shortenPlace} from './place_util';
const LONG = 'Cyclone, Keating Township, McKean, Pennsylvania, United States';
describe('shortenPlace', () => {
it('returns full place unchanged in FULL mode', () => {
expect(shortenPlace(LONG, PlaceDisplay.FULL)).toBe(LONG);
});
it('returns undefined in HIDE mode', () => {
expect(shortenPlace(LONG, PlaceDisplay.HIDE)).toBeUndefined();
});
it('defaults to 2 components in SHORT mode', () => {
expect(shortenPlace(LONG, PlaceDisplay.SHORT)).toBe(
'Cyclone, Keating Township',
);
});
it('keeps first N components when count is specified', () => {
expect(shortenPlace(LONG, PlaceDisplay.SHORT, 1)).toBe('Cyclone');
expect(shortenPlace(LONG, PlaceDisplay.SHORT, 3)).toBe(
'Cyclone, Keating Township, McKean',
);
});
it('leaves place unchanged when it has fewer parts than count', () => {
expect(shortenPlace('Berlin, Germany', PlaceDisplay.SHORT, 3)).toBe(
'Berlin, Germany',
);
});
it('leaves single-component place unchanged in SHORT mode', () => {
expect(shortenPlace('Germany', PlaceDisplay.SHORT)).toBe('Germany');
});
it('handles undefined place', () => {
expect(shortenPlace(undefined, PlaceDisplay.SHORT)).toBeUndefined();
});
it('handles empty string', () => {
expect(shortenPlace('', PlaceDisplay.SHORT)).toBe('');
});
it('is idempotent — applying SHORT twice with same count gives same result', () => {
const once = shortenPlace(LONG, PlaceDisplay.SHORT, 2);
expect(shortenPlace(once, PlaceDisplay.SHORT, 2)).toBe(once);
});
});

36
src/util/place_util.ts Normal file
View File

@@ -0,0 +1,36 @@
export enum PlaceDisplay {
FULL,
SHORT,
HIDE,
}
export const DEFAULT_PLACE_DISPLAY_COUNT = 2;
/**
* Shortens a GEDCOM place string for display in chart nodes.
*
* GEDCOM places are comma-separated from most-specific to least-specific,
* e.g. "Cyclone, McKean, Pennsylvania, United States".
* SHORT keeps the first `count` components (most-specific).
* HIDE removes the place entirely.
*/
export function shortenPlace(
place: string | undefined,
mode: PlaceDisplay,
count: number = DEFAULT_PLACE_DISPLAY_COUNT,
): string | undefined {
if (!place || mode === PlaceDisplay.FULL) {
return place;
}
if (mode === PlaceDisplay.HIDE) {
return undefined;
}
const parts = place
.split(',')
.map((p) => p.trim())
.filter(Boolean);
if (parts.length <= count) {
return place;
}
return parts.slice(0, count).join(', ');
}