Import GEDCOM : lieu lisible, sans colonnes vides ni codes

Heredis remplit toutes les colonnes de son format de lieu, même vides, avec
le code INSEE (« La Roche-sur-Yon,85191,Vendée,Pays de la Loire,France, »).
Le lieu de naissance importé garde les noms seulement, séparés par « , »,
sans case vide, code INSEE ou postal, ni répétition. Un lieu déjà propre
ne change pas.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
IliesAllaliandClaude Opus 5.5 committed 2026-10-16 20:20:17 +02:00
1 parent 0e96ffc020
commit bca0543803
2 files changed
+43 -1

No files matched your search

+17 -1
View File
@@ -37,6 +37,22 @@ function clip(value: string | null, max: number): string | null {
return trimmed ? trimmed.slice(0, max) : null
}
// Lieu d'un GEDCOM : les logiciels remplissent toutes les colonnes de leur format de lieu, même vides, et y
// glissent des codes. Heredis écrit « La Roche-sur-Yon,85191,Vendée,Pays de la Loire,France, » (ville, code
// INSEE, département, région, pays, subdivision). On garde les noms, sans case vide, sans code INSEE ni
// postal, sans répétition : « La Roche-sur-Yon, Vendée, Pays de la Loire, France ».
export function cleanGedcomPlace(value: string | null | undefined): string | null {
if (!value) return null
const parts: string[] = []
for (const raw of value.split(',')) {
const part = raw.trim()
if (!part || /^(\d{4,5}|2[AB]\d{3})$/i.test(part)) continue
if (parts.length && parts[parts.length - 1].toLowerCase() === part.toLowerCase()) continue
parts.push(part)
}
return parts.length ? parts.join(', ') : null
}
// Export : un champ sur une ligne ne doit jamais en créer une autre (enregistrement injecté)
function oneLine(value: string | null | undefined): string {
return String(value ?? '').replace(/[\r\n]+/g, ' ')
@@ -527,7 +543,7 @@ export const gedcomRoutes: FastifyPluginAsync = async (app) => {
const birtNode = findChild(indi, 'BIRT')
const birthDateIso = gedcomDateToIso(findChild(birtNode, 'DATE')?.value ?? '')
const birthPlace = clip(findChild(birtNode, 'PLAC')?.value ?? null, 200)
const birthPlace = clip(cleanGedcomPlace(findChild(birtNode, 'PLAC')?.value), 200)
const deatNode = findChild(indi, 'DEAT')
const deathDateIso = gedcomDateToIso(findChild(deatNode, 'DATE')?.value ?? '')
+26
View File
@@ -0,0 +1,26 @@
import { describe, expect, it } from 'vitest'
import { cleanGedcomPlace } from '../src/routes/gedcom'
describe('lieu importé d’un GEDCOM', () => {
it('Heredis : colonnes vides et code INSEE retirés', () => {
expect(cleanGedcomPlace('La Roche-sur-Yon,85191,Vendée,Pays de la Loire,France,')).toBe('La Roche-sur-Yon, Vendée, Pays de la Loire, France')
expect(cleanGedcomPlace('Ménéac,56129,,,,')).toBe('Ménéac')
expect(cleanGedcomPlace('Ajaccio,2A004,Corse-du-Sud,Corse,France,')).toBe('Ajaccio, Corse-du-Sud, Corse, France')
})
it('Gramps, Geneanet : un lieu déjà propre ne change pas', () => {
expect(cleanGedcomPlace('Lille, Nord, Hauts-de-France, France')).toBe('Lille, Nord, Hauts-de-France, France')
expect(cleanGedcomPlace('Paris')).toBe('Paris')
})
it('code postal et répétitions écartés', () => {
expect(cleanGedcomPlace('Caen, 14000, Calvados, Calvados, France')).toBe('Caen, Calvados, France')
})
it('rien de lisible : pas de lieu', () => {
expect(cleanGedcomPlace(',,,,')).toBeNull()
expect(cleanGedcomPlace('')).toBeNull()
expect(cleanGedcomPlace(undefined)).toBeNull()
})
})