Couper le role BnF meme quand le prenom finit par une initiale
NettoyageIsbd.Auteur("Cormen, Thomas H. Auteur du texte") renvoyait
« Thomas H. Auteur du texte Cormen » : le point de l initiale etait
protege, donc plus aucun point ne servait de separateur de role.
Ce qui tranche : dans « Nom, Prenom », la seule chose qui puisse suivre
une initiale et faire encore partie du nom est une autre initiale
(« Tolkien, J. R. R. »). Tout le reste est le role. Le point est conserve
quand il clot une initiale, pour ne pas amputer le prenom.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -128,7 +128,9 @@ public static partial class NettoyageIsbd
|
||||
var pointRole = IndexDuPointDeRole(s);
|
||||
if (pointRole >= 0)
|
||||
{
|
||||
s = s[..pointRole];
|
||||
// Quand le rôle suit une initiale (« Cormen, Thomas H. Auteur du texte »), le point
|
||||
// qui sert de séparateur appartient aussi au nom : on le conserve.
|
||||
s = EstPointDInitiale(s, pointRole) ? s[..(pointRole + 1)] : s[..pointRole];
|
||||
}
|
||||
|
||||
s = RetirerPonctuationFinale(s);
|
||||
@@ -174,12 +176,7 @@ public static partial class NettoyageIsbd
|
||||
|
||||
while (s.EndsWith('.'))
|
||||
{
|
||||
var i = s.Length - 1;
|
||||
var estInitiale = i >= 1
|
||||
&& char.IsUpper(s[i - 1])
|
||||
&& (i == 1 || s[i - 2] == ' ' || s[i - 2] == '-' || s[i - 2] == '\'');
|
||||
|
||||
if (estInitiale)
|
||||
if (EstPointDInitiale(s, s.Length - 1))
|
||||
{
|
||||
break;
|
||||
}
|
||||
@@ -194,9 +191,15 @@ public static partial class NettoyageIsbd
|
||||
/// Position du point qui introduit le rôle, ou -1.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Un point suivi d'une espace sépare le rôle du nom. On ignore les points d'initiales
|
||||
/// (« Cormen, Thomas H. Auteur ») : un point précédé d'une majuscule isolée n'est pas
|
||||
/// un séparateur de rôle.
|
||||
/// Un point suivi d'une espace sépare le rôle du nom. Le point d'une initiale
|
||||
/// (« Cormen, Thomas <b>H.</b> ») n'en est pas un — le couper amputerait le prénom.
|
||||
/// <para>
|
||||
/// Mais protéger l'initiale ne doit pas protéger le rôle qui la suit : « Cormen, Thomas H.
|
||||
/// Auteur du texte » renvoyait auparavant « Thomas H. Auteur du texte Cormen ». Ce qui
|
||||
/// tranche : dans « Nom, Prénom », la seule chose qui puisse suivre une initiale et faire
|
||||
/// encore partie du nom est <b>une autre initiale</b> (« Tolkien, J. R. R. »). Tout le
|
||||
/// reste est le rôle.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
private static int IndexDuPointDeRole(string s)
|
||||
{
|
||||
@@ -207,16 +210,31 @@ public static partial class NettoyageIsbd
|
||||
continue;
|
||||
}
|
||||
|
||||
var estInitiale = i >= 1
|
||||
&& char.IsUpper(s[i - 1])
|
||||
&& (i == 1 || s[i - 2] == ' ' || s[i - 2] == '-' || s[i - 2] == '\'');
|
||||
|
||||
if (!estInitiale)
|
||||
if (EstPointDInitiale(s, i) && CommenceParUneInitiale(s, i + 2))
|
||||
{
|
||||
return i;
|
||||
continue;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Le point en <paramref name="i"/> clôt-il une initiale (majuscule isolée) ?
|
||||
/// </summary>
|
||||
private static bool EstPointDInitiale(string s, int i)
|
||||
=> i >= 1
|
||||
&& char.IsUpper(s[i - 1])
|
||||
&& (i == 1 || s[i - 2] == ' ' || s[i - 2] == '-' || s[i - 2] == '\'');
|
||||
|
||||
/// <summary>
|
||||
/// Le texte à partir de <paramref name="debut"/> commence-t-il par une initiale
|
||||
/// (une majuscule suivie d'un point ou de la fin de chaîne) ?
|
||||
/// </summary>
|
||||
private static bool CommenceParUneInitiale(string s, int debut)
|
||||
=> debut < s.Length
|
||||
&& char.IsUpper(s[debut])
|
||||
&& (debut + 1 == s.Length || s[debut + 1] == '.');
|
||||
}
|
||||
|
||||
@@ -85,12 +85,17 @@ public class NettoyageIsbdTests
|
||||
public void Auteur_laisse_passer_ce_qui_est_deja_propre(string brut, string attendu)
|
||||
=> Assert.Equal(attendu, NettoyageIsbd.Auteur(brut));
|
||||
|
||||
[Fact]
|
||||
public void Auteur_ne_coupe_pas_sur_une_initiale()
|
||||
{
|
||||
// « H. » est une initiale, pas un séparateur de rôle : la couper amputerait le prénom.
|
||||
Assert.Equal("Thomas H. Cormen", NettoyageIsbd.Auteur("Cormen, Thomas H."));
|
||||
}
|
||||
[Theory]
|
||||
// Contre-exemples : le nom se termine légitimement par une initiale, il n'y a pas de rôle
|
||||
// à retirer — couper au point amputerait le prénom.
|
||||
[InlineData("Cormen, Thomas H.", "Thomas H. Cormen")]
|
||||
[InlineData("Tolkien, J. R. R.", "J. R. R. Tolkien")]
|
||||
// Cas réel : le rôle suit une initiale. Protéger le point de l'initiale ne doit pas
|
||||
// protéger le rôle — sinon on obtient « Thomas H. Auteur du texte Cormen ».
|
||||
[InlineData("Cormen, Thomas H. Auteur du texte", "Thomas H. Cormen")]
|
||||
[InlineData("Tolkien, J. R. R. (1892-1973). Auteur du texte", "J. R. R. Tolkien")]
|
||||
public void Auteur_distingue_une_initiale_d_un_role(string brut, string attendu)
|
||||
=> Assert.Equal(attendu, NettoyageIsbd.Auteur(brut));
|
||||
|
||||
[Theory]
|
||||
[InlineData("le Livre de poche (Paris)", "le Livre de poche")]
|
||||
|
||||
Reference in New Issue
Block a user