Português (Brasil)

Ferramentas de texto e do dia a dia · Kit de ferramentas de texto

Caracteres invisíveis: espaços ininterruptos, juntas de largura zero e recortes

· Fundo

limpeza de texto Unicode publicação

Linhas de texto visíveis revelando espaços ocultos e caracteres Unicode de largura zero
Ilustração vetorial original ToolAcre

Examina os caracteres que não se parecem com nada — espaços ininterruptos, espaços e junções de largura zero, marcas de ordem de bytes — de onde eles vêm, o que conta como espaço em branco e como localizá-los e removê-los.

Duas linhas idênticas que não são duplicadas – como um caractere invisível derrota a desduplicação e a pesquisa

Duas linhas podem parecer idênticas em um editor, mas falhar nas verificações de igualdade, pesquisa ou desduplicação. Um pode conter um espaço U+0020 comum enquanto o outro contém U+00A0, um espaço ininterrupto. Um caractere de largura zero pode criar o mesmo problema sem ocupar qualquer largura visível, deixando um editor com dois rótulos aparentemente correspondentes que permanecem cadeias distintas.

Isto não é meramente cosmético. Os pontos de código ocultos podem dividir dimensões analíticas, anular uma operação de localização exata, preservar uma linha duplicada ou fazer com que um identificador copiado falhe na validação. Antes de reescrever o conteúdo a olho nu, mantenha uma cópia da fonte e compare sistematicamente as strings suspeitas. A renderização visível é uma evidência sobre a aparência, não uma prova de que suas sequências Unicode subjacentes correspondem.

De onde eles vêm – páginas da web, processadores de texto, sequências de emojis e copiar e colar de PDFs

Personagens invisíveis geralmente chegam através do trabalho comum. As páginas da Web usam espaços inseparáveis ​​para manter os termos juntos, os processadores de texto preservam o espaçamento orientado ao layout e a extração PDF reconstrói o texto a partir de glifos posicionados. A cópia entre esses sistemas pode transportar caracteres de formatação para um campo CMS mesmo quando o destino exibe apenas palavras e espaços familiares.

Outras marcas invisíveis são partes intencionais de sistemas de escrita ou emojis. Um marceneiro de largura zero pode combinar componentes de emoji em um símbolo exibido, enquanto marceneiros e não-marceneiros afetam a modelagem em vários scripts. Essa origem é importante: “não consigo ver” não significa “é seguro excluir”. A limpeza deve ter como alvo um artefato diagnosticado, não todos os personagens cuja largura de avanço seja zero.

A família de espaços em branco - espaços comuns, ininterruptos, estreitos e ideográficos, e o que o corte de JavaScript considera espaços em branco

Unicode contém mais do que o espaço cotidiano. U+00A0 é o espaço inquebrável, U+202F é o espaço estreito e ininterrupto e U+3000 é o espaço ideográfico. O tratamento de espaços em branco JavaScript inclui esses caracteres, portanto, `trim()`, `trimStart()` e `trimEnd()` podem removê-los quando ocorrerem na borda relevante de uma string.

O corte de linha do Text Toolkit chama esses métodos JavaScript em cada linha. Ele não normaliza o espaçamento interno, portanto permanece ali um espaço ininterrupto entre duas palavras. Sua estatística de “caracteres sem espaços” remove caracteres correspondentes a JavaScript `s`, que é mais amplo que o espaço ASCII. Use esse número como uma medida definida, não como uma promessa de que todos os pontos de código invisíveis foram excluídos.

A família de largura zero - espaço de largura zero, joiner e não-joiner, word joiner e a marca de ordem de byte, que não são espaços em branco de forma alguma

A família de largura zero segue regras diferentes. Espaço de largura zero U+200B, não-joiner de largura zero U+200C, joiner de largura zero U+200D e joiner de palavra U+2060 são caracteres de formato em vez de espaço em branco JavaScript. Portanto, `trim()` comum não os remove. Uma linha contendo uma dessas marcas não fica em branco simplesmente porque a tela não mostra tinta.

U+FEFF tem duas histórias relacionadas: no início dos dados codificados pode sinalizar uma marca de ordem de bytes, enquanto no texto serviu como um espaço sem quebra de largura zero. ECMAScript inclui U+FEFF em seu conjunto de espaços em branco, ao contrário de U+200B a U+200D. Tratar toda a família de largura zero como um tipo de espaço em branco contradiria, portanto, o comportamento real do JavaScript.

Detectando-os – usando o contador de caracteres para detectar contagens que não correspondem ao que você vê, lembrando que alguns marceneiros se ligam a um vizinho e ficam escondidos

Uma contagem surpreendente pode alertá-lo sobre conteúdo oculto, mas não consegue identificar todos os casos. ToolAcre conta clusters de grafemas com `Intl.Segmenter` quando disponível. Um marceneiro que participa de uma sequência de emoji pode ajudar vários pontos de código a formar um grafema, portanto, adicioná-lo ou removê-lo pode alterar a renderização sem produzir o simples aumento de um caractere que um contador de pontos de código mostraria.

Use várias pistas juntas: correspondências exatas com falha, um resultado inesperado “sem espaços”, texto copiado inspecionado em um editor compatível com Unicode ou uma pesquisa regex para pontos de código específicos. O contador de fallback usa pontos de código quando o Segmentador não está disponível, portanto, os resultados também podem diferir de acordo com a capacidade do navegador. A contagem restringe a investigação; não é um scanner de caracteres ocultos ou um visualizador de nomes Unicode.

Detectando personagens ocultos: as contagens fornecem pistas, não um inventário completo

Para um artefato de copiar e colar confirmado, trabalhe em uma duplicata e abra Localizar e substituir no modo regex. Procurar por `[​]` e substituí-lo por nada remove espaços de largura zero e caracteres U+FEFF incorporados em todo o texto. A ferramenta compila o padrão com o sinalizador global de JavaScript, relata a contagem de substituições e deixa o texto inalterado se o padrão for inválido.

Não amplie automaticamente esse padrão para `[​-‍]`. A faixa também remove U+200C e U+200D, que podem alterar o formato do script e dividir um emoji unido em símbolos separados. Adicione esses pontos de código somente quando a inspeção provar que eles são indesejados. Após a substituição, execute a desduplicação e compare a saída com o original preservado antes de publicar.

Exemplo resolvido: remova apenas caracteres indesejados de largura zero confirmados antes de desduplicar

Esta limpeza não aborda caracteres de controle bidirecionais, homóglifos ou todos os problemas de segurança associados a texto confuso. As marcas direcionais podem alterar a ordem visual, enquanto os ataques homóglifos usam diferentes caracteres visíveis que se assemelham. Nenhum dos problemas é resolvido com a exclusão de espaços, e um regex indiscriminado de caracteres invisíveis pode danificar o conteúdo multilíngue legítimo, ignorando o risco real.

O kit de ferramentas também não expõe sinalizadores regex, como Unicode ou modo multilinha, destaca cada correspondência futura ou percorre substituições individualmente. Substitua todas as operações no texto completo, portanto a contagem relatada e a ação Desfazer são salvaguardas importantes. Para código-fonte, cópia legal ou scripts desconhecidos, inspecione cada caractere com uma ferramenta Unicode dedicada antes de fazer edições em massa.

Conclusão - invisível não significa inofensivo; o contador do Text Toolkit e a localização e substituição de regex expõem e removem-nos sem sair do navegador

Invisível não significa vazio, intercambiável ou prejudicial. Espaços inseparáveis ​​são espaços em branco com semântica de layout; joiners de largura zero podem transportar semântica de modelagem; U+FEFF se comporta de maneira diferente novamente sob corte JavaScript. A limpeza precisa começa nomeando o ponto de código, entendendo por que ele pode estar presente e decidindo se o destino ainda precisa de sua função.

Use o Text Toolkit como um ambiente de trabalho controlado do lado do navegador: as contagens podem expor uma discrepância, localizar e substituir regex pode remover um conjunto definido com precisão e a desduplicação pode confirmar que as diferenças ocultas desapareceram. Preserve um original, evite excluir marceneiros por padrão e verifique o resultado renderizado. Uma correção restrita e revisável é mais segura do que tratar todos os Unicode invisíveis como detritos.