TransWikia.com

Capitalizar texto em JavaScript, ignorando abreviações

Stack Overflow em Português Asked by Marlucio Pires on November 30, 2021

Tenho um código em JavaScript para capitalizar texto que trata algumas exceções.

Contudo, gostaria de tratar mais algumas, tais como ignorar abreviações, que seriam ter um ponto antes ou depois da primeira letra e ignorar alguns algarismos romanos.

Alguma sugestão?
Segue meu código até o momento:

function testaCapitalize() {
  var texto1 = "alto dO cruzeiro";
  var texto2 = "joão paulo II";
  var texto3 = "N.S. aparecida";
  var texto4 = "N.S. DAS GRAÇAS";
  document.getElementById('resultado').innerHTML =
    capitalize(texto1) +
    "<br/>" +
    capitalize(texto2) +
    "<br/>" +
    capitalize(texto3) +
    "<br/>" +
    capitalize(texto4);
}

function capitalize(texto) {

  texto = texto.toLowerCase().replace(/(?:^|s)S/g, function(capitalize) {
    return capitalize.toUpperCase();
  });
  //preposição digitada
  var PreposM = ["Da", "Do", "Das", "Dos", "A", "E", "De", "DE"];
  //preposição substituta
  var prepos = ["da", "do", "das", "dos", "a", "e", "de", "de"];

  for (var i = PreposM.length - 1; i >= 0; i--) {
    texto = texto.replace(RegExp("\b" + PreposM[i].replace(/[-/\^$*+?.()|[]{}]/g, '\$&') + "\b", "g"), prepos[i]);
  }

  return texto;
}
<input type="button" onclick="testaCapitalize()" value='Testa'>
<div id='resultado'>

</div>
function capitalize(texto) {

    texto = texto.toLowerCase().replace(/(?:^|s)S/g, function(capitalize) {
      return capitalize.toUpperCase();
    });
    //preposição digitada
    var PreposM = ["Da", "Do", "Das", "Dos", "A", "E", "De", "DE"];
    //preposição substituta
    var prepos = ["da", "do", "das", "dos", "a", "e", "de", "de"];

    for (var i = PreposM.length - 1; i >= 0; i--) {
      texto = texto.replace(RegExp("\b" + PreposM[i].replace(/[-/\^$*+?.()|[]{}]/g, '\$&') + "\b", "g"), prepos[i]);
    }

  return texto;
}

2 Answers

Talvez seja mais simples fazer um split para quebrar o texto em palavras, aí você verifica cada palavra separadamente. Depois é só juntar tudo de novo no final.

Isso é mais fácil do que tentar uma regex gigante que trata todos os casos de uma vez (embora até seja possível, não acho que vale a pena a complicação).

Assumindo que sempre há um espaço separando as palavras, uma maneira de resolver seria:

function abreviacao(s) {
    return /^([A-Z].)+$/.test(s);
}

function numeralRomano(s) {
    return /^M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$/.test(s);
}

function capitalize(texto) {
    let prepos = ["da", "do", "das", "dos", "a", "e", "de" ];
    return texto.split(' ') // quebra o texto em palavras
       .map((palavra) => { // para cada palavra
           if (abreviacao(palavra) || numeralRomano(palavra)) {
                return palavra;
           }

           palavra = palavra.toLowerCase();
           if (prepos.includes(palavra)) {
                return palavra;
           }
           return palavra.charAt(0).toUpperCase() + palavra.slice(1);
       })
       .join(' '); // junta as palavras novamente
}

let textos = ["alto dO cruzeiro", "joão paulo II", "N.S. aparecida", "N.S. DAS GRAÇAS"];
textos.forEach(t => console.log(capitalize(t)));

O split retorna um array contendo as palavras. Em seguida eu uso map para trocar cada palavra pelo seu equivalente "capitalizado".

Caso a palavra seja abreviação ou numeral romano, ela é retornada sem modificação. Se ela é uma das preposições, é transformada em minúscula.

Caso não seja nenhuma das exceções, apenas a primeira letra é convertida para maiúscula. Por fim, eu uso join para juntar todas as palavras em uma única string, tendo as palavras separadas por espaço.

O resultado do código acima é:

Alto do Cruzeiro
João Paulo II
N.S. Aparecida
N.S. das Graças

Para a abreviação eu usei a regex /^([A-Z].)+$/: uma letra maiúscula seguida de ponto, podendo se repetir várias vezes (ex: "A.", "A.B.", "A.B.C.", etc, todas são consideradas abreviações). Os marcadores ^ e $ (respectivamente o início e fim da string) garantem que a palavra só pode ter isso.

Mas se quiser verificar apenas que a primeira letra está seguida de um ponto e tanto faz o resto, pode trocar para /^[A-Z]./ (ou /^[A-Z]./i para considerar letras maiúsculas e minúsculas).

Para numerais romanos, peguei a regex desta resposta. A princípio você poderia verificar se a string só possui os caracteres I, V, X, L, D, C e M, mas a regex também verifica as quantidades e ordem em que aparecem, evitando casos inválidos como XM, por exemplo (veja aqui mais alguns exemplos).

Answered by hkotsubo on November 30, 2021

Para facilitar o trabalho você pode utilizar a biblioteca https://www.npmjs.com/package/capitalize-pt-br

Instalando da seguinte forma, caso utilizado o NPM:

npm install --save capitalize-pt-br

Em caso de não utilização do NPM, pode-se baixar a biblioteca e implementar no projeto fazendo o import manual do script

A implementação com a biblioteca seria a seguinte:

const capitalize = require('capitalize-pt-br')

capitalize('HELLO WORLD')

Esta função retornaria o seguinte:

Hello World

Caso haja necessidade de manter uma palavra minúscula, pode-se usar o segundo parâmetro da função, da seguinte forma:

const capitalize = require('capitalize-pt-br')

capitalize('HELLO WORLD', ['world'])

Esta função retornaria o seguinte:

Hello world

Caso haja necessidade de manter uma palavra minúscula e outra maiúscula, pode-se usar o segundo parâmetro da função, da seguinte forma:

const capitalize = require('capitalize-pt-br')

capitalize('HELLO WORLD', ['world'], ['hello'])

Esta função retornaria o seguinte:

HELLO world

Answered by Vinicius Farias on November 30, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP