11540 sujets

JavaScript, DOM et API Web HTML5

Bonjour Messieurs/Dames,

Je souhaiterais pouvoir régénérer une bonne casse (pour une meilleure lisibilité) sur un texte côté client (en javascript).

Mes données d'entrée peuvent être un texte (brut) tout en majuscule, comme un mixte des deux.

Pour cela, j'ai déjà créer une fonction :

function restore_case(string)
{     
string =     string.toLowerCase();
string =     string.charAt(0).toUpperCase()+string.slice(1);
string =     string.replace(/((\.)|(\?)|(\!)|((((\n)|(\r))?[\w+]) ?((\))|(\-))+)|(\n)|(\r))+ ?([A-Z+])/gmi, function(a) { return a.toUpperCase(); });
return string;
}


Le résultat est pratiquement bon, sauf pour un cas, celui des listes non numériques comme celle-ci :

a)test
a) test
a ) test

A)TEST
A) TEST
A ) TEST


Les lignes telles que "a)test" deviendront "A)Test", la partie après la parenthèse est comme prévu, mais la lettre avant la parenthèse ne devrait pas changer de casse.

Je bataille dur sur cette Regex, mais je n'y arrive pas d'un seul coup, en effet, je suis obligé de faire 2 replace avec 2 Regex, mais je perds la casse d'origine.


//Regex pour mettre les majuscules au bon endroit
/((\.)|(\?)|(\!)|((((\n)|(\r))?[\w+]) ?((\))|(\-))+)|(\n)|(\r))+ ?([A-Z+])/gmi

//Regex pour corriger
/([A-Z]) ?(\)|\-)+/gmi


Si vous ne trouvez pas non plus, mais avez une optimisation à amener, je suis tout autant preneur !

Par avance merci !

P.S: Le code est visible sur jsFiddle où l'on peut voir le résultat sur une chaîne de test.
Modifié par Super_baloo8 (15 Nov 2012 - 11:52)
Salut,

À ta place je mettrais en place une solution sans expressions régulières, qui parcourt une seule fois la chaîne, comme par exemple :
function restoreCase(string) {
  var res = "", upperCase = true;
  for (var i = 0; i < string.length; ++i) {
    var c = string.charAt(i);

    upperCase = upperCase && !/^ ?[-)]/.test(string.charAt(i + 1) + string.charAt(i + 2));
    res += upperCase ? c.toUpperCase() : c.toLowerCase();

    var upperCaseChar = /[-!)\r\n.?]/.test(c);
    if (upperCaseChar || !/\s/.test(c)) {
      upperCase = upperCaseChar;
    }
  }

  return res;
}

Bonus : cela fonctionne aussi pour les caractères accentués.
Salut Julien,

Merci beaucoup, ça réponds presque complètement à mon besoin en rajoutant une fonction supplémentaire que je n'avais pas vu ! Vraiment merci !

J'aurais penser qu'une regex aurait été plus performante, mais non ! (http://jsperf.com/s2j)

Pour le "presque", je m'exploque, le cas des parenthèses et des tirets ne fonctionne pas

TEST-TEST TEST(test)TEST


Donne ceci :

Test-Test Test(test)Test


A la place de ceci:

Test-test Test(test)test



Je pense que la modification doit se faire ici:

upperCase = upperCase && !/^[-) ?]/.test(string.charAt(i + 1) + string.charAt(i + 2));


Mais même en rajoutant le test arrière ne fait rien.

En même temps, on corrige déjà ce type de donnée.

Alors c'est à moi de faire un choix, soit ce sont les listes qui primes, soit je vais devoir gérer à la regex ces cas spéciaux en sus.

Ce qui donnerait ceci :

function restore_case(string)
		{
		var res = '', upperCase = true;
		for(var i = 0; i < string.length; ++i)
			{
			var c = string.charAt(i);
			upperCase = upperCase && !/^[-) ?]/.test(string.charAt(i + 1) + string.charAt(i + 2));
			res += upperCase ? c.toUpperCase() : c.toLowerCase();
			var upperCaseChar = /[-!)\r\n.?]/.test(c);
			if(upperCaseChar || !/\s/.test(c))
				{
				upperCase = upperCaseChar;
				}
			}
		res = res.replace(/ ?\((.*)\) ?[A-Z]{1}/gi, function(a) {return a.toLowerCase();});
		return res;
		}
Salut,

Je n'avais pas compris parfaitement ton besoin. Le code suivant convient-il ?
function restoreCase(string) {
  var res = "", upperCase = true;
  for (var i = 0; i < string.length; ++i) {
    var c = string.charAt(i);
    var listItem = (upperCase && /^ ?[-)]/.test(string.charAt(i + 1) + string.charAt(i + 2)));
    var upperCaseChar = /[\r\n.?!]/.test(c);

    res += (upperCase && !listItem) ? c.toUpperCase() : c.toLowerCase();

    if (!listItem && (upperCaseChar || !/[-) ]/.test(c))) {
      upperCase = upperCaseChar;
    }
  }

  return res;
}

Modifié par Julien Royer (21 Nov 2012 - 16:10)