Skip to content
35 changes: 31 additions & 4 deletions docs/pt-br/utilities.md
Original file line number Diff line number Diff line change
Expand Up @@ -721,11 +721,14 @@ Fonte: [Resolução Anatel nº 749/2022](https://informacoes.anatel.gov.br/legis

Formata um número de telefone de acordo com os padrões brasileiros. Se `value` incluir o DDD, informe `{ mask: 'auto' }` ou `'nanp'`: a máscara padrão `"sn"` assume que não há DDD e o trunca.

- **Opções** (`FormatPhoneOptions`): `mask` (`PhoneMask`, padrão `"sn"`) escolhe um dos padrões abaixo. Uma `mask` desconhecida recai para `"sn"`.
- **Opções** (`FormatPhoneOptions`): `mask` (`PhoneMask`, padrão `"sn"`) escolhe um dos padrões abaixo. Uma `mask` desconhecida recai para `"sn"`. `obfuscate` (padrão `false`) esconde o número do assinante em todas as máscaras.
- `"sn"`: apenas o número assinante, 9 dígitos. `"nanp"`: DDD mais número assinante, 11 dígitos para celular e 10 para fixo; outros tamanhos mantêm o agrupamento de 11 dígitos.
- `"e164"` e `"international"` removem antes o código de país, como `parsePhone`, e recaem para `"service"` para um número de serviço.
- `"service"`: os Códigos Não Geográficos (`0800 123 4567`) e os números abreviados `300X`/`400X` (`4004-1234`).
- `"auto"`: `"service"` para um número de serviço, `"international"` quando `value` traz código de país, senão `"nanp"` para mais de 9 dígitos, ou `"sn"`.
- O `obfuscate` mantém 2 dígitos, a contagem que a conta gov.br usa para o celular cadastrado, e mantém o prefixo que indica uma região ou um serviço, e não um assinante: o DDD, o código do tipo `0800` e a raiz `300X`/`400X`.
- Os 2 dígitos são os últimos que cabem na própria máscara, então na máscara padrão `"sn"` um valor com DDD é truncado antes, igual ao que acontece sem `obfuscate`, e o par visível é o 8º e o 9º dígito, e não os 2 últimos de `value`.
- Um código de utilidade pública de 3 dígitos (`190`) não identifica ninguém e é devolvido como está; num valor que a máscara `"service"` não reconhece cada dígito vira um `*`, o que esconde os dígitos, mas não quantos eram. Os padrões ofuscados têm um número fixo de posições, então em `"e164"` o que passa do 11º dígito nacional é descartado.

```javascript
import { formatPhone } from '@brazilian-utils/brazilian-utils';
Expand All @@ -741,10 +744,19 @@ formatPhone('08001234567', { mask: 'service' }); // 0800 123 4567
formatPhone('40041234', { mask: 'service' }); // 4004-1234
formatPhone('+5511987654321', { mask: 'auto' }); // +55 11 98765-4321 ("auto" detecta o prefixo +55 e escolhe "international")
formatPhone('5508001234567', { mask: 'auto' }); // 0800 123 4567 ("auto" lê o número 0800, não um +55 08)
formatPhone('987654321', { obfuscate: true }); // *****-**21
formatPhone('11987654321', { mask: 'auto', obfuscate: true }); // (11) *****-**21
formatPhone('1130000000', { mask: 'auto', obfuscate: true }); // (11) ****-**00
formatPhone('+5511987654321', { mask: 'auto', obfuscate: true }); // +55 11 *****-**21
formatPhone('11987654321', { mask: 'e164', obfuscate: true }); // +5511*******21
formatPhone('08001234567', { mask: 'service', obfuscate: true }); // 0800 *** **67
formatPhone('40041234', { mask: 'service', obfuscate: true }); // 4004-**34
formatPhone('11988887766', { mask: 'service', obfuscate: true }); // *********** (não é número de serviço)
formatPhone('11987654321', { obfuscate: true }); // *****-**43 (CUIDADO: a "sn" trunca antes, então "43", e não "21")
formatPhone('11900000000'); // 11900-0000 (CUIDADO: a máscara padrão "sn" trunca um número com DDD)
```

Fonte: [ITU-T E.164](https://www.itu.int/rec/T-REC-E.164), [Resolução Anatel nº 749/2022](https://informacoes.anatel.gov.br/legislacao/resolucoes/2022/1641-resolucao-749).
Fonte: [ITU-T E.164](https://www.itu.int/rec/T-REC-E.164), [Resolução Anatel nº 749/2022](https://informacoes.anatel.gov.br/legislacao/resolucoes/2022/1641-resolucao-749), [conta gov.br](https://acesso.gov.br/faq/_perguntasdafaq/formarrecuperarconta.html) para quantos dígitos de um celular ficam visíveis.

### parsePhone

Expand Down Expand Up @@ -1009,13 +1021,16 @@ isValidPis('12056412547'); // false

Formata um PIS.

- **Opções** (`FormatPisOptions`): `pad` completa o valor com zeros à esquerda até 11 dígitos antes de aplicar a máscara (padrão `false`).
- **Opções** (`FormatPisOptions`): `pad` completa o valor com zeros à esquerda até 11 dígitos antes de aplicar a máscara (padrão `false`); `obfuscate` esconde os 3 primeiros dígitos e o dígito verificador.
- O `obfuscate` é aplicado depois do `pad`.
- Nenhuma autoridade publica uma regra de mascaramento para o PIS, então o `obfuscate` usa a que a Lei nº 12.309/2010, art. 87, § 5º define para o CPF ("ocultar os três primeiros dígitos e os dois dígitos verificadores"), um número com a mesma estrutura.

```javascript
import { formatPis } from '@brazilian-utils/brazilian-utils';

formatPis('12345678901'); // 123.45678.90-1
formatPis('123456789', { pad: true }); // 001.23456.78-9
formatPis('12345678901', { obfuscate: true }); // ***.45678.90-*
```

### parsePis
Expand All @@ -1038,6 +1053,8 @@ import { generatePis } from '@brazilian-utils/brazilian-utils';
generatePis(); // '91077906857'
```

Fonte: [Lei nº 12.309/2010, art. 87, § 5º](https://www.planalto.gov.br/ccivil_03/_ato2007-2010/2010/lei/l12309.htm), a regra de mascaramento do CPF que o `obfuscate` toma emprestada.

## Processo jurídico

### isValidProcessoJuridico
Expand Down Expand Up @@ -1992,13 +2009,16 @@ Fonte: [Resolução CONTRAN nº 886/2021, art. 4º](https://www.gov.br/transport

Formata uma CNH.

- **Opções** (`FormatCnhOptions`): `pad` completa o valor com zeros à esquerda até os 11 dígitos antes de aplicar a máscara (padrão `false`).
- **Opções** (`FormatCnhOptions`): `pad` completa o valor com zeros à esquerda até os 11 dígitos antes de aplicar a máscara (padrão `false`); `obfuscate` esconde os 3 primeiros dígitos e os 2 dígitos verificadores.
- O `obfuscate` é aplicado depois do `pad`.
- Nenhuma autoridade publica uma regra de mascaramento para a CNH, então o `obfuscate` usa a que a Lei nº 12.309/2010, art. 87, § 5º define para o CPF ("ocultar os três primeiros dígitos e os dois dígitos verificadores"), um número com a mesma estrutura.

```javascript
import { formatCnh } from '@brazilian-utils/brazilian-utils';

formatCnh('02650306461'); // 026503064-61
formatCnh('2650306461', { pad: true }); // 026503064-61
formatCnh('02650306461', { obfuscate: true }); // ***503064-**
```

### parseCnh
Expand All @@ -2021,6 +2041,8 @@ import { generateCnh } from '@brazilian-utils/brazilian-utils';
generateCnh(); // '02650306461'
```

Fonte: [Lei nº 12.309/2010, art. 87, § 5º](https://www.planalto.gov.br/ccivil_03/_ato2007-2010/2010/lei/l12309.htm), a regra de mascaramento do CPF que o `obfuscate` toma emprestada.

## Natureza jurídica

### isValidLegalNature
Expand Down Expand Up @@ -2185,13 +2207,16 @@ Fonte: [Resolução TSE nº 23.659/2021, art. 36](https://www.tse.jus.br/legisla

Formata um título de eleitor com o agrupamento de 12 dígitos `0000 0000 00 00`.

- **Opções** (`FormatVoterIdOptions`): `obfuscate` esconde os 3 primeiros dígitos e os 2 dígitos verificadores, deixando visível o código da unidade federativa.
- O agrupamento de 13 dígitos `0000 0000 0 00 00` só é usado quando o valor tem mais de 12 dígitos e o código da UF (o 10º e o 11º dígitos) é `01` ou `02`.
- Os dígitos além da última posição do padrão são descartados.
- Nenhuma autoridade publica uma regra de mascaramento para o título de eleitor, então o `obfuscate` usa a que a Lei nº 12.309/2010, art. 87, § 5º define para o CPF ("ocultar os três primeiros dígitos e os dois dígitos verificadores"), um número com a mesma estrutura.

```javascript
import { formatVoterId } from '@brazilian-utils/brazilian-utils';

formatVoterId('123456780175'); // '1234 5678 01 75'
formatVoterId('123456780175', { obfuscate: true }); // '***4 5678 01 **'
formatVoterId('1234567880191'); // '1234 5678 8 01 91' (título de 13 dígitos SP/MG)
```

Expand Down Expand Up @@ -2221,6 +2246,8 @@ generateVoterId('SP'); // título de eleitor aleatório válido de São Paulo
generateVoterId('XX'); // usa "ZZ" em vez de lançar erro
```

Fonte: [Lei nº 12.309/2010, art. 87, § 5º](https://www.planalto.gov.br/ccivil_03/_ato2007-2010/2010/lei/l12309.htm), a regra de mascaramento do CPF que o `obfuscate` toma emprestada.

## CNS

### isValidCns
Expand Down
35 changes: 31 additions & 4 deletions docs/utilities.md
Original file line number Diff line number Diff line change
Expand Up @@ -721,11 +721,14 @@ Source: [Resolução Anatel nº 749/2022](https://informacoes.anatel.gov.br/legi

Format a phone number according to Brazilian patterns. If `value` includes a DDD, pass `{ mask: 'auto' }` or `'nanp'`: the default `"sn"` mask assumes no DDD and truncates one.

- **Options** (`FormatPhoneOptions`): `mask` (`PhoneMask`, default `"sn"`) picks one of the patterns below. An unknown `mask` falls back to `"sn"`.
- **Options** (`FormatPhoneOptions`): `mask` (`PhoneMask`, default `"sn"`) picks one of the patterns below. An unknown `mask` falls back to `"sn"`. `obfuscate` (default `false`) hides the subscriber number under every mask.
- `"sn"`: subscriber number only, 9 digits. `"nanp"`: DDD plus subscriber number, 11 digits for a mobile and 10 for a landline; any other length keeps the 11 digit grouping.
- `"e164"` and `"international"` drop the country code first, as `parsePhone` does, and fall back to `"service"` for a service number.
- `"service"`: the Códigos Não Geográficos (`0800 123 4567`) and the abbreviated `300X`/`400X` numbers (`4004-1234`).
- `"auto"`: `"service"` for a service number, `"international"` when `value` carries a country code, otherwise `"nanp"` for more than 9 digits, else `"sn"`.
- `obfuscate` keeps 2 digits, the count the gov.br account shows for a registered mobile, and keeps the prefix that names a region or a service instead of a subscriber: the DDD, the `0800`-like code and the `300X`/`400X` root.
- The 2 digits are the last ones the mask itself has room for, so under the default `"sn"` a DDD-prefixed value is truncated first, exactly as it is without `obfuscate`, and the visible pair is the 8th and 9th digit rather than the last 2 of `value`.
- A 3 digit public utility code (`190`) identifies no one and is returned as it is; a value the `"service"` mask does not recognize has every digit replaced by a `*`, which hides the digits but not how many there were. The obfuscated patterns have a fixed number of slots, so under `"e164"` anything past the 11th national digit is dropped.

```javascript
import { formatPhone } from '@brazilian-utils/brazilian-utils';
Expand All @@ -741,10 +744,19 @@ formatPhone('08001234567', { mask: 'service' }); // 0800 123 4567
formatPhone('40041234', { mask: 'service' }); // 4004-1234
formatPhone('+5511987654321', { mask: 'auto' }); // +55 11 98765-4321 ("auto" detects the +55 prefix and picks "international")
formatPhone('5508001234567', { mask: 'auto' }); // 0800 123 4567 ("auto" reads the 0800 number, not a +55 08 one)
formatPhone('987654321', { obfuscate: true }); // *****-**21
formatPhone('11987654321', { mask: 'auto', obfuscate: true }); // (11) *****-**21
formatPhone('1130000000', { mask: 'auto', obfuscate: true }); // (11) ****-**00
formatPhone('+5511987654321', { mask: 'auto', obfuscate: true }); // +55 11 *****-**21
formatPhone('11987654321', { mask: 'e164', obfuscate: true }); // +5511*******21
formatPhone('08001234567', { mask: 'service', obfuscate: true }); // 0800 *** **67
formatPhone('40041234', { mask: 'service', obfuscate: true }); // 4004-**34
formatPhone('11988887766', { mask: 'service', obfuscate: true }); // *********** (not a service number)
formatPhone('11987654321', { obfuscate: true }); // *****-**43 (BEWARE: "sn" truncates first, so "43", not "21")
formatPhone('11900000000'); // 11900-0000 (BEWARE: default "sn" truncates a DDD-prefixed number)
```

Source: [ITU-T E.164](https://www.itu.int/rec/T-REC-E.164), [Resolução Anatel nº 749/2022](https://informacoes.anatel.gov.br/legislacao/resolucoes/2022/1641-resolucao-749).
Source: [ITU-T E.164](https://www.itu.int/rec/T-REC-E.164), [Resolução Anatel nº 749/2022](https://informacoes.anatel.gov.br/legislacao/resolucoes/2022/1641-resolucao-749), [conta gov.br](https://acesso.gov.br/faq/_perguntasdafaq/formarrecuperarconta.html) for how many digits of a mobile stay visible.

### parsePhone

Expand Down Expand Up @@ -1009,13 +1021,16 @@ isValidPis('12056412547'); // false

Format a PIS.

- **Options** (`FormatPisOptions`): `pad` left-pads the value with zeros to 11 digits before masking (default `false`).
- **Options** (`FormatPisOptions`): `pad` left-pads the value with zeros to 11 digits before masking (default `false`); `obfuscate` hides the first 3 digits and the check digit.
- `obfuscate` is applied after `pad`.
- No authority publishes a masking rule for the PIS, so `obfuscate` applies the one Lei nº 12.309/2010, art. 87, § 5º sets for the CPF ("ocultar os três primeiros dígitos e os dois dígitos verificadores"), a number with the same structure.

```javascript
import { formatPis } from '@brazilian-utils/brazilian-utils';

formatPis('12345678901'); // 123.45678.90-1
formatPis('123456789', { pad: true }); // 001.23456.78-9
formatPis('12345678901', { obfuscate: true }); // ***.45678.90-*
```

### parsePis
Expand All @@ -1038,6 +1053,8 @@ import { generatePis } from '@brazilian-utils/brazilian-utils';
generatePis(); // '91077906857'
```

Source: [Lei nº 12.309/2010, art. 87, § 5º](https://www.planalto.gov.br/ccivil_03/_ato2007-2010/2010/lei/l12309.htm), the CPF masking rule `obfuscate` borrows.

## Processo jurídico

### isValidProcessoJuridico
Expand Down Expand Up @@ -1992,13 +2009,16 @@ Source: [Resolução CONTRAN nº 886/2021, art. 4º](https://www.gov.br/transpor

Format a CNH.

- **Options** (`FormatCnhOptions`): `pad` left-pads the value with zeros to the full 11 digits before masking (default `false`).
- **Options** (`FormatCnhOptions`): `pad` left-pads the value with zeros to the full 11 digits before masking (default `false`); `obfuscate` hides the first 3 digits and the 2 check digits.
- `obfuscate` is applied after `pad`.
- No authority publishes a masking rule for the CNH, so `obfuscate` applies the one Lei nº 12.309/2010, art. 87, § 5º sets for the CPF ("ocultar os três primeiros dígitos e os dois dígitos verificadores"), a number with the same structure.

```javascript
import { formatCnh } from '@brazilian-utils/brazilian-utils';

formatCnh('02650306461'); // 026503064-61
formatCnh('2650306461', { pad: true }); // 026503064-61
formatCnh('02650306461', { obfuscate: true }); // ***503064-**
```

### parseCnh
Expand All @@ -2021,6 +2041,8 @@ import { generateCnh } from '@brazilian-utils/brazilian-utils';
generateCnh(); // '02650306461'
```

Source: [Lei nº 12.309/2010, art. 87, § 5º](https://www.planalto.gov.br/ccivil_03/_ato2007-2010/2010/lei/l12309.htm), the CPF masking rule `obfuscate` borrows.

## Legal nature

### isValidLegalNature
Expand Down Expand Up @@ -2185,13 +2207,16 @@ Source: [Resolução TSE nº 23.659/2021, art. 36](https://www.tse.jus.br/legisl

Format a voter ID number with the 12-digit grouping `0000 0000 00 00`.

- **Options** (`FormatVoterIdOptions`): `obfuscate` hides the first 3 digits and the 2 check digits, leaving the federative union code visible.
- The 13-digit grouping `0000 0000 0 00 00` is used only when the value has more than 12 digits and its UF code (the 10th and 11th digits) is `01` or `02`.
- Digits past the last slot of the pattern are dropped.
- No authority publishes a masking rule for the voter ID, so `obfuscate` applies the one Lei nº 12.309/2010, art. 87, § 5º sets for the CPF ("ocultar os três primeiros dígitos e os dois dígitos verificadores"), a number with the same structure.

```javascript
import { formatVoterId } from '@brazilian-utils/brazilian-utils';

formatVoterId('123456780175'); // '1234 5678 01 75'
formatVoterId('123456780175', { obfuscate: true }); // '***4 5678 01 **'
formatVoterId('1234567880191'); // '1234 5678 8 01 91' (13-digit SP/MG voter id)
```

Expand Down Expand Up @@ -2221,6 +2246,8 @@ generateVoterId('SP'); // valid random voter ID for Sao Paulo
generateVoterId('XX'); // falls back to "ZZ" instead of throwing
```

Source: [Lei nº 12.309/2010, art. 87, § 5º](https://www.planalto.gov.br/ccivil_03/_ato2007-2010/2010/lei/l12309.htm), the CPF masking rule `obfuscate` borrows.

## CNS

### isValidCns
Expand Down
10 changes: 9 additions & 1 deletion reports/api/brazilian-utils.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ export const formatCnh: (value: string | number, options?: FormatCnhOptions) =>
// @public
export type FormatCnhOptions = {
pad?: boolean;
obfuscate?: boolean;
};

// @public
Expand Down Expand Up @@ -305,6 +306,7 @@ export const formatPhone: (value: string | number, options?: FormatPhoneOptions)
// @public
export type FormatPhoneOptions = {
mask?: PhoneMask;
obfuscate?: boolean;
};

// @public
Expand All @@ -313,6 +315,7 @@ export const formatPis: (value: string | number, options?: FormatPisOptions) =>
// @public
export type FormatPisOptions = {
pad?: boolean;
obfuscate?: boolean;
};

// @public
Expand All @@ -332,7 +335,12 @@ export type FormatSuframaOptions = {
};

// @public
export const formatVoterId: (value: string | number) => string;
export const formatVoterId: (value: string | number, options?: FormatVoterIdOptions) => string;

// @public
export type FormatVoterIdOptions = {
obfuscate?: boolean;
};

// @public
export const generateBoleto: (params?: GenerateBoletoParams) => string;
Expand Down
7 changes: 4 additions & 3 deletions scripts/llms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,15 +57,16 @@ function slugify(heading: string): string {
const ABBREVIATION_PLACEHOLDER = String.fromCharCode(1);

/**
* Extracts the first sentence of a paragraph, treating `e.g.`/`i.e.` as
* abbreviations rather than sentence boundaries.
* Extracts the first sentence of a paragraph, treating `e.g.`, `i.e.` and `art.` (the way a
* Brazilian law article is cited, as in "LGPD, art. 6º III") as abbreviations rather than
* sentence boundaries.
* @param {string} paragraph - The paragraph to extract the first sentence from.
* @returns {string} The first sentence of `paragraph`.
*/
function firstSentence(paragraph: string): string {
const withoutLinks = paragraph.replaceAll(/\[([^\]]+)\]\([^)]+\)/g, "$1");
const protectedText = withoutLinks.replaceAll(
/\b(e\.g|i\.e)\./gi,
/\b(e\.g|i\.e|art)\./gi,
(_match, abbr: string) => `${abbr}${ABBREVIATION_PLACEHOLDER}`,
);
const match = /[\s\S]*?[.!?](?=\s|$)/.exec(protectedText);
Expand Down
9 changes: 9 additions & 0 deletions src/format-cnh/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export const PATTERN = "000000000-00";

/**
* No authority publishes a masking rule for the CNH registry number, so this applies the rule
* Lei nº 12.309/2010, art. 87, § 5º, sets for the CPF ("ocultar os três primeiros dígitos e os
* dois dígitos verificadores") to a number with the same structure: the first 3 digits and the
* 2 check digits are hidden, e.g. "***456789-**".
*/
export const OBFUSCATED_PATTERN = "***000000-**";
Loading
Loading