Conversor de maiúsculas

Converta texto entre camelCase, snake_case, kebab-case, Title Case e mais, com maiúsculas conforme o idioma e ferramentas de linhas.

Texto

Formas de escrita

  • UPPERCASE
    XMLHTTPREQUEST HANDLER FOR ISTANBUL CITY GUIDE
  • lowercase
    xmlhttprequest handler for istanbul city guide
  • Title Case
    Xmlhttprequest Handler For Istanbul City Guide
  • Sentence case
    Xmlhttprequest handler for istanbul city guide
  • camelCase
    xmlHttpRequestHandlerForIstanbulCityGuide
  • PascalCase
    XmlHttpRequestHandlerForIstanbulCityGuide
  • snake_case
    xml_http_request_handler_for_istanbul_city_guide
  • kebab-case
    xml-http-request-handler-for-istanbul-city-guide
  • CONSTANT_CASE
    XML_HTTP_REQUEST_HANDLER_FOR_ISTANBUL_CITY_GUIDE
  • dot.case
    xml.http.request.handler.for.istanbul.city.guide

Operações com linhas

Resultado
XMLHttpRequest handler for istanbul city guide

Linhas: 1

Uma única divisão em palavras, dez formas de escrita

Mudar as maiúsculas de um texto parece a coisa mais simples que um programa pode fazer, e é a origem de um número surpreendente de erros reais. Parte da razão é que «maiúsculas e minúsculas» são na verdade dois problemas distintos sob um mesmo nome. Passar um texto para UPPERCASE ou lowercase é uma correspondência caractere a caractere definida pelo Unicode. Passá-lo para camelCase ou snake_case é outra coisa: primeiro é preciso decidir onde estão as palavras e só depois recompor e juntar. Esta ferramenta faz as duas coisas, mostra todos os resultados de uma vez e, sobretudo, diz quais dessas respostas dependem de uma definição de idioma.

As seis formas de programação saem todas da mesma divisão, por isso nunca podem contradizer-se. Estes são os seus limites:

  • Uma minúscula seguida de uma maiúscula inicia uma nova palavra, e é isso que transforma fooBar em foo e Bar.
  • Uma sequência de maiúsculas termina onde começa a palavra seguinte, ou seja, na última maiúscula antes de uma minúscula. XMLHttpRequest dá XML, Http e Request; IOError dá IO e Error.
  • Um dígito seguido de uma maiúscula inicia uma nova palavra, por isso html5Parser dá html5 e Parser.
  • Tudo o que não for letra, dígito ou marca combinante separa palavras: espaços, sublinhados, hífens, pontos e sinais de pontuação.

De resto, os dígitos ficam colados à palavra que os precede, e por isso utf8 e address2 passam inteiros. É uma divergência deliberada em relação ao lodash, cujo divisor trata cada sequência de dígitos como palavra própria e transforma utf8 em utf_8 — tecnicamente coerente, mas não o que alguém quis dizer ao nomear uma variável.

A divisão está escrita com propriedades do Unicode e não com uma classe de caracteres ASCII, por isso não se limita ao inglês. Um identificador em cirílico divide-se nos seus limites de maiúsculas exatamente como um latino. Uma escrita sem distinção de maiúsculas — hebraico, árabe, chinês, japonês, coreano — não tem esses limites para encontrar, portanto as suas palavras dividem-se apenas por separadores, e essa é a resposta correta, não uma limitação.

Siglas: duas respostas corretas

Depois de XMLHttpRequest ser dividido em XML, Http e Request, recompô-lo como PascalCase levanta uma pergunta sem uma única resposta correta. Recompondo cada palavra obtém-se XmlHttpRequest, que é o que o lodash produz e o que o guia de estilo Java da Google pede: tratar a sigla como uma palavra comum para que os limites continuem visíveis em nomes como ParseXmlDocument. Mantendo a sequência de maiúsculas obtém-se XMLHttpRequest, que é o nome real da API do navegador e a convenção seguida por grande parte do DOM e por muito do ‎.NET.

Ambas aparecem em bases de código reais, por isso a ferramenta oferece as duas e recompõe por predefinição. A opção afeta apenas camelCase e PascalCase: as restantes formas recompõem a palavra inteira de qualquer modo, portanto XMLHttpRequest dá xml_http_request e XML_HTTP_REQUEST em qualquer dos casos.

Um pormenor está fixo e não se escolhe: a primeira palavra de um nome em camelCase passa sempre inteiramente a minúsculas, mesmo quando é uma sigla. Mantê-la daria PascalCase, e mantê-la a meio daria xMLHttpRequest, uma forma que nenhum guia de estilo recomenda e em que qualquer leitor tropeça. Por isso XMLHttpRequest dá xmlHttpRequest nos dois casos, enquanto parseXMLDocument mantém a sigla do meio quando assim se pede.

O i turco e por que o idioma é uma escolha

O JavaScript tem dois métodos para passar a maiúsculas, e a diferença entre eles já derrubou sistemas em produção. O método toUpperCase aplica a correspondência do Unicode independente do idioma: a letra i passa a I. O método toLocaleUpperCase aplica as regras de um idioma específico, e em turco e azeri a maiúscula de i é İ, a maiúscula com ponto, porque esses alfabetos têm também um ı sem ponto cuja maiúscula é I. Passe a maiúsculas a entrada de um utilizador turco com o idioma dele, compare-a com uma palavra-chave de protocolo e a comparação falha num caractere quase idêntico.

É o erro de internacionalização mais comum no tratamento de cadeias e é invisível até acontecer consigo. Por isso esta ferramenta nunca adivinha. A sua predefinição é a correspondência independente do idioma, que é a de que precisam identificadores, tokens de protocolo, cabeçalhos HTTP e chaves de base de dados. Escolher um idioma passa para as regras dele, e sempre que essa escolha altera um resultado a ferramenta mostra ao lado a resposta independente do idioma, para que se veja exatamente o que o idioma fez.

'i'.toUpperCase()             // 'I'
'i'.toLocaleUpperCase('tr')   // 'İ'  dotted capital
'I'.toLocaleLowerCase('tr')   // 'ı'  dotless lowercase
'ISTANBUL'.toLocaleLowerCase('tr')  // 'ıstanbul'

Outros três idiomas mudam a resposta, e a ferramenta oferece-os todos. O lituano mantém o ponto sobre o i ao passar a minúscula uma maiúscula que traz outro acento, por isso Ì dá um i seguido de um ponto combinante e de um acento grave combinante, e não o único ì pré-composto. O grego elimina o tonos ao passar a maiúsculas, por isso άνθρωπος dá ΑΝΘΡΩΠΟΣ e não ΆΝΘΡΩΠΟΣ, porque o grego não escreve o acento sobre as maiúsculas. O azeri partilha com o turco o i com ponto e sem ponto.

Dois casos famosos não são regras de idioma, e vale a pena saber qual é qual. O ß alemão passa a SS em todos os idiomas, porque é uma regra SpecialCasing do Unicode e não uma regra alemã — razão pela qual a correspondência também não é reversível, e SS volta a ss. E um sigma grego no fim de palavra passa à forma final ς e não a σ, em todo o lado: isso é uma condição contextual sobre a posição do caractere, não uma definição de idioma. Ambos se veem nesta ferramenta sem escolher idioma nenhum.

Aqui Title case e Sentence case são mecânicos

O Title Case desta ferramenta põe em maiúscula a primeira letra de cada palavra e em minúscula o resto. O Sentence case põe em maiúscula a primeira letra do texto e a de cada frase seguinte, entendendo-se que uma frase termina em ponto, ponto de exclamação, ponto de interrogação ou reticências seguidos de um espaço. Ambos passam primeiro a entrada a minúsculas, e é isso que os torna úteis num texto que chegou AOS GRITOS.

São regras deliberadamente mecânicas, e a alternativa merece explicação. Os guias de estilo ingleses definem o maiúsculo de títulos pelas palavras curtas que ficam em minúscula — e discordam entre si quanto à lista, quanto a pôr em maiúscula a palavra depois de dois pontos e quanto às preposições de quatro letras ou mais. Aplicar um deles aqui seria entregar convenções jornalísticas americanas a leitores que escrevem em hebraico, japonês ou turco, onde o conceito não se transfere de todo. Pôr cada palavra em maiúscula é previsível, explicável em qualquer idioma e fácil de ajustar à mão depois.

A condição do espaço no Sentence case é o que impede que 3.5 metres se torne 3.5 Metres, já que ali o ponto é seguido de um dígito. Não resolve as abreviaturas: e.g. this continua a iniciar uma frase falsa, porque saber que «e.g.» não é um fim de frase exige uma lista das abreviaturas desse idioma. Um apóstrofo dentro de uma palavra também não inicia outra, por isso it's é posto em maiúscula uma só vez e dá It's e não It'S.

Ordenar: ordem alfabética ou ordem de bytes

As ferramentas de linhas cortam, removem duplicadas, ordenam, invertem e numeram, e a ordenação levanta a questão do idioma uma segunda vez. A ordem alfabética é uma propriedade de um idioma, não do Unicode. O alemão coloca ä junto de a: a, ä, z. O sueco trata-a como letra distinta no fim do alfabeto: a, z, ä. Ambos estão certos no seu país, e a ferramenta usa o idioma escolhido no topo da página.

A outra opção é a ordem por ponto de código, que é a que se quer quando a resposta tem de coincidir com outra coisa. Comparar por ponto de código é a ordem de bytes em UTF-8, por isso reproduz exatamente o que LC_ALL=C sort, git e a comparação de cadeias predefinida da maioria das linguagens produzem: todas as maiúsculas antes de todas as minúsculas, de modo que B vem antes de a. Escolha-a quando comparar com a saída de uma ferramenta; escolha a ordenação por idioma quando a lista for lida por uma pessoa.

A ordem numérica natural — item2 antes de item10 e não depois — é uma função da ordenação por idioma, por isso só está disponível com a regra alfabética. A ordem de bytes não tem o conceito de número dentro de uma cadeia, nem o tem a ordenação que imita, de modo que oferecer as duas juntas prometeria algo que a saída não poderia cumprir.

As operações são executadas numa ordem fixa, e essa ordem importa. O corte acontece antes da remoção de duplicadas, por isso duas linhas que só diferiam num espaço final são reconhecidas como a mesma. A ordenação acontece antes da inversão, por isso inverter significa sempre «inverte o que estou a ver». São indicados tanto o número de linhas vazias como o de duplicadas removidas, porque uma contagem silenciosa é a maneira de não se reparar que a lista não era o que se pensava.

Onde isto é executado

Tudo acontece no seu navegador. As correspondências de maiúsculas vêm da própria implementação de Unicode do motor de JavaScript e a ordenação de Intl.Collator, por isso as respostas concordam com o ambiente de execução que vai realmente processar as suas cadeias e não com uma tabela que alguém copiou há anos. Nada do que colar é carregado, guardado ou registado, o que torna a ferramenta segura para nomes, linhas de registo e tudo o mais que preferiria não enviar para um servidor apenas para lhe mudar as maiúsculas.

Perguntas frequentes

O meu texto é enviado para um servidor?
Não. Cada conversão é executada no seu navegador usando as correspondências de maiúsculas do Unicode do próprio motor de JavaScript, e nada do que colar é carregado ou registado.
Porque é que escolher turco me mostra dois resultados diferentes?
Porque o turco muda a resposta. O seu alfabeto tem um i com ponto e um ı sem ponto, por isso a maiúscula de i é İ e não I. Sempre que um idioma altera um resultado, a ferramenta mostra ao lado a resposta independente do idioma, que é a de que precisam identificadores e tokens de protocolo.
Devo usar a correspondência independente do idioma ou a de um idioma?
Use a independente do idioma para tudo o que uma máquina vá ler: identificadores, cabeçalhos HTTP, chaves de base de dados, tokens de protocolo, nomes de ficheiros. Use a de um idioma para texto que uma pessoa vá ler nesse idioma. Confundi-las é o clássico erro do i turco.
Porque é que XMLHttpRequest é convertido em XmlHttpRequest?
Porque as siglas são recompostas por predefinição, tal como fazem o lodash e vários guias de estilo importantes. Ative a opção de siglas para manter a sequência de maiúsculas e recuperar XMLHttpRequest. Só afeta camelCase e PascalCase, já que as restantes formas recompõem cada palavra de qualquer modo.
Porque é que utf8 continua a ser uma palavra quando o lodash a divide?
Porque aqui os dígitos colam-se à palavra que os precede, por isso utf8 e address2 passam inteiros. Um dígito seguido de uma maiúscula inicia de facto uma nova palavra, e é isso que divide html5Parser em html5 e Parser.
Porque é que Title Case põe em maiúscula palavras curtas como «of» e «the»?
Porque a regra é mecânica de propósito. Os guias de estilo ingleses discordam entre si sobre que palavras curtas ficam em minúscula, e as suas convenções não se transferem para os restantes idiomas deste site. Pôr cada palavra em maiúscula é previsível e fácil de ajustar à mão.
Porque é que não posso usar a ordem numérica natural com a ordenação por ponto de código?
A ordem natural é uma função da ordenação por idioma. A ordem por ponto de código é ordem de bytes, que não tem noção de número dentro de uma cadeia — nem a tem o LC_ALL=C sort que reproduz. Oferecer as duas daria uma saída que já não coincidiria com a ferramenta imitada.
Porque é que ß passa a SS mesmo sem idioma selecionado?
Porque essa correspondência é uma regra SpecialCasing do Unicode e não uma regra do alemão, por isso aplica-se em todo o lado. Também não é reversível: SS passa a ss e não de volta a ß. O sigma final grego funciona da mesma maneira — depende da posição da letra, não de um idioma.