br_validators 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2a8eb5df36f0aae424cad2f9f7be8d3ca4b319d144b58023af72d61a94a597bc
4
- data.tar.gz: 6cbba05d5a095be1b04d0d9b0e5aa63116fca27cd0b2eb2902fc7a66a844a7b7
3
+ metadata.gz: 6f48e272ba459e1e9962ac199162b257eea94025b41c02c64501a663c71058b3
4
+ data.tar.gz: 3c194886a75d84f28c23b4a62414383735ba70509ef25f2d960fc23996efdcc7
5
5
  SHA512:
6
- metadata.gz: aa4a7ece5360498679b28eeef9b8dea03c73e24c2742bc7f6a669a2e97f8a5453bf0ee313dec7f5804f8ca3c34d4e7c57a24b56710ab1e23f583c5c0c90b11d0
7
- data.tar.gz: f97f6579ff6a8333b86bff8da5eb6d279defa9aca7641b1eedc51e794b9884092d245ecacaaa45f68719d925246e7242e827daa8957e28886af5b262745a0642
6
+ metadata.gz: 1fa44a6062e29f87a87fdca434a07b7cada13d7b091b06cfc21c1cb98de331ef0c44add691368d2d651703f209349d41478cdae03736e6bd566358caf26298f9
7
+ data.tar.gz: cd6d9864713501561878ceff7c9a505de1f6791dcd6fb61001a224dbe762bf8c863b40d1f9414f891634c540ba19c149524547ee612372616cfbbf8cff59854a
data/CHANGELOG.md CHANGED
@@ -3,9 +3,21 @@
3
3
  As mudanças de cada versão ficam aqui. O projeto segue o
4
4
  [versionamento semântico](https://semver.org/lang/pt-BR/).
5
5
 
6
- ## [Não lançado]
6
+ ## [0.1.1] - 2026-10-25
7
7
 
8
- - Página para testar os validadores no navegador (https://br-validators-gem.vercel.app).
8
+ ### Corrigido
9
+
10
+ - CNPJ: letras fora do ASCII, como `ı` (i sem ponto) e `ß`, não viram mais letras
11
+ válidas ao passar para maiúsculas. Antes, `"12abcı3450de60"` passava como válido.
12
+ - Texto com bytes inválidos (UTF-8 quebrado) devolve `false` em vez de levantar
13
+ `ArgumentError`.
14
+ - Espaços Unicode, como o espaço não separável que vem ao copiar de PDFs e sites,
15
+ contam como máscara em CPF, CNPJ, CNS e boleto, e são ignorados nas pontas da chave Pix.
16
+
17
+ ### Outros
18
+
19
+ - Página para testar os validadores no navegador (https://br-validators.vercel.app).
20
+ - Publicação também pelo botão "Run workflow", recusando versão já publicada.
9
21
 
10
22
  ## [0.1.0] - 2026-10-25
11
23
 
data/README.md CHANGED
@@ -10,8 +10,8 @@ No `Gemfile`:
10
10
  gem "br_validators"
11
11
  ```
12
12
 
13
- > A versão 0.1.0 está pronta e vai ser publicada no RubyGems em breve. Até lá, use direto
14
- > do GitHub: `gem "br_validators", github: "PedroPedrassolli/br_validators"`.
13
+ Ou direto: `gem install br_validators`. A gem está publicada no
14
+ [RubyGems](https://rubygems.org/gems/br_validators).
15
15
 
16
16
  ## O que tem
17
17
 
@@ -36,6 +36,11 @@ BrValidators::CNPJ.format("12abc34501de35") # => "12.ABC.345/01DE-35"
36
36
  BrValidators::CNS.format("898000000000436") # => "898 0000 0000 0436"
37
37
  ```
38
38
 
39
+ Pontos, hífens e espaços são ignorados em qualquer posição, inclusive o espaço não
40
+ separável que vem junto ao copiar de um PDF ou de um site. Texto corrompido (bytes que
41
+ não são UTF-8 válido) só dá `false`, sem erro. Passe sempre o documento como texto: um
42
+ número inteiro perde os zeros à esquerda (`01234567890` vira `1234567890`).
43
+
39
44
  A chave Pix é um caso à parte: em vez de `format` e `strip`, ela tem `type`, que diz
40
45
  o tipo da chave. Ela precisa estar como o Banco Central guarda (sem máscara, e-mail e
41
46
  chave aleatória em minúsculas):
@@ -81,7 +86,7 @@ mensagens de erro em português e inglês.
81
86
 
82
87
  ## Página de teste
83
88
 
84
- Dá para testar cada validador no navegador em https://br-validators-gem.vercel.app. A página
89
+ Dá para testar cada validador no navegador em https://br-validators.vercel.app. A página
85
90
  (`public/`) é HTML e JavaScript puro e chama uma função Ruby da Vercel
86
91
  (`api/validar.rb`) que usa a própria gem, então as regras ficam num lugar só:
87
92
 
@@ -25,7 +25,7 @@ module BrValidators
25
25
  end
26
26
  end
27
27
 
28
- # Um arquivo por validador (o Rails espera uma classe por arquivo).
28
+ # Um arquivo por validador: uma classe por arquivo, como no resto da gem.
29
29
  require_relative "validators/cpf_validator"
30
30
  require_relative "validators/cnpj_validator"
31
31
  require_relative "validators/cns_validator"
@@ -19,11 +19,14 @@ module BrValidators
19
19
  # diz que o dígito de cada bloco usa o mesmo módulo do verificador geral.
20
20
  # https://cmsarquivos.febraban.org.br/Arquivos/documentos/PDF/Layout%20-%20C%C3%B3digo%20de%20Barras%20-%20Vers%C3%A3o%207%20-%2001_03_2023_mn.pdf
21
21
  module Boleto
22
- # Pontos, espaços e hífens que aparecem na linha impressa.
23
- MASK = /[.\-\s]/
22
+ # Pontos, espaços e hífens que aparecem na linha impressa. A linha copiada do
23
+ # PDF do boleto ou do site do banco costuma vir com espaço não separável, que
24
+ # [:space:] também pega.
25
+ MASK = /[.\-[:space:]]/
24
26
 
27
+ # O scrub está explicado no CPF: texto corrompido vira inválido, sem erro.
25
28
  def self.strip(value)
26
- value.to_s.gsub(MASK, "")
29
+ value.to_s.scrub.gsub(MASK, "")
27
30
  end
28
31
 
29
32
  # :cobranca, :arrecadacao ou nil se a linha for inválida.
@@ -14,8 +14,9 @@ module BrValidators
14
14
  # Fonte: manual do dígito verificador do CNPJ, da Receita Federal.
15
15
  # https://www.gov.br/receitafederal/pt-br/centrais-de-conteudo/publicacoes/documentos-tecnicos/cnpj/manual-dv-cnpj.pdf
16
16
  module CNPJ
17
- # Caracteres de máscara aceitos na entrada: ponto, barra, hífen e espaços.
18
- MASK = %r{[./\-\s]}
17
+ # Caracteres de máscara aceitos na entrada: ponto, barra, hífen e espaços
18
+ # (inclusive os espaços Unicode, como o não separável).
19
+ MASK = %r{[./\-[:space:]]}
19
20
 
20
21
  # 12 caracteres alfanuméricos e 2 dígitos no final.
21
22
  PATTERN = /\A[0-9A-Z]{12}\d{2}\z/
@@ -23,8 +24,12 @@ module BrValidators
23
24
  # Tira a máscara e passa as letras para maiúsculas:
24
25
  # "12.abc.345/01de-35" vira "12ABC34501DE35".
25
26
  # A Receita só usa maiúsculas, mas é comum alguém digitar em minúsculas.
27
+ #
28
+ # upcase(:ascii) mexe só nas letras de a a z. O upcase normal segue o Unicode e
29
+ # transforma "ı" (i sem ponto) em "I" e "ß" em "SS", o que faria um texto
30
+ # errado passar como CNPJ válido. O scrub está explicado no CPF.
26
31
  def self.strip(value)
27
- value.to_s.gsub(MASK, "").upcase
32
+ value.to_s.scrub.gsub(MASK, "").upcase(:ascii)
28
33
  end
29
34
 
30
35
  def self.valid?(value)
@@ -19,11 +19,13 @@ module BrValidators
19
19
  # https://rni-docs.anvisa.gov.br/docs/regras_gerais/validacoes/validacaoCNS/
20
20
  module CNS
21
21
  # O cartão mostra o número em grupos separados por espaço; aceitamos também
22
- # pontos e hífens, que às vezes aparecem em sistemas antigos.
23
- MASK = /[.\-\s]/
22
+ # pontos e hífens, que às vezes aparecem em sistemas antigos. Espaços Unicode
23
+ # (como o não separável) também contam como espaço.
24
+ MASK = /[.\-[:space:]]/
24
25
 
26
+ # O scrub está explicado no CPF: texto corrompido vira inválido, sem erro.
25
27
  def self.strip(value)
26
- value.to_s.gsub(MASK, "")
28
+ value.to_s.scrub.gsub(MASK, "")
27
29
  end
28
30
 
29
31
  def self.valid?(value)
@@ -9,12 +9,16 @@ module BrValidators
9
9
  # por 11 for 0 ou 1, o dígito é 0; senão, é 11 menos o resto.
10
10
  module CPF
11
11
  # Caracteres de máscara que aceitamos na entrada: ponto, hífen e espaços.
12
- MASK = /[.\-\s]/
12
+ # [:space:] pega também os espaços Unicode, como o espaço não separável que
13
+ # vem junto ao copiar um número de um PDF ou de um site.
14
+ MASK = /[.\-[:space:]]/
13
15
 
14
16
  # Tira a máscara: "123.456.789-09" vira "12345678909".
15
17
  # Não remove letras nem outros símbolos, para que valid? possa recusá-los.
18
+ # O scrub troca bytes inválidos (texto corrompido) por "�", que nunca passa na
19
+ # validação; sem ele, o gsub levantaria um erro em vez de devolver false.
16
20
  def self.strip(value)
17
- value.to_s.gsub(MASK, "")
21
+ value.to_s.scrub.gsub(MASK, "")
18
22
  end
19
23
 
20
24
  def self.valid?(value)
@@ -18,6 +18,9 @@ module BrValidators
18
18
  module Pix
19
19
  MAX_LENGTH = 77
20
20
 
21
+ # Espaços nas pontas, inclusive os Unicode (o strip do Ruby só tira os ASCII).
22
+ EDGE_SPACES = /\A[[:space:]]+|[[:space:]]+\z/
23
+
21
24
  PHONE = /\A\+[1-9][0-9]\d{1,14}\z/
22
25
  EVP = /\A[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\z/
23
26
 
@@ -42,8 +45,9 @@ module BrValidators
42
45
  # Devolve :cpf, :cnpj, :phone, :email ou :evp, ou nil se a chave for inválida.
43
46
  # Só os espaços nas pontas são ignorados: o resto precisa estar exatamente
44
47
  # como o DICT guarda (sem máscara, e-mail e chave aleatória em minúsculas).
48
+ # O scrub está explicado no CPF: texto corrompido vira inválido, sem erro.
45
49
  def self.type(value)
46
- key = value.to_s.strip
50
+ key = value.to_s.scrub.gsub(EDGE_SPACES, "")
47
51
  return nil if key.size > MAX_LENGTH
48
52
 
49
53
  found = CHECKS.find { |_type, check| check.call(key) }
@@ -2,5 +2,5 @@
2
2
 
3
3
  # Versão da gem, lida também pelo gemspec.
4
4
  module BrValidators
5
- VERSION = "0.1.0"
5
+ VERSION = "0.1.1"
6
6
  end
data/lib/br_validators.rb CHANGED
@@ -14,6 +14,8 @@ require_relative "br_validators/boleto"
14
14
  # valid?(valor) -> true ou false
15
15
  # format(valor) -> o documento com a máscara, ou nil se for inválido
16
16
  # strip(valor) -> o documento sem a máscara
17
+ # A chave Pix é a exceção: tem valid? e type, mas não format nem strip, porque
18
+ # precisa estar exatamente como o Banco Central guarda. Pix e Boleto têm type.
17
19
  module BrValidators
18
20
  end
19
21
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: br_validators
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pedro Pedrassolli