Skip to content

Conversation

@nao1215
Copy link
Owner

@nao1215 nao1215 commented Dec 8, 2025

Summary by CodeRabbit

Release Notes v0.2.0

  • New Features

    • Added 20+ new validators including conditional required (required_if, required_unless, required_with, required_without), datetime, phone (e164), geolocation, UUID variants, ULID, and color format validation.
    • Added advanced preprocessing and validation examples with comprehensive benchmarks.
  • Performance

    • Improved processing speed by ~10% through optimized validation pipeline.
  • Documentation

    • Updated all README translations with expanded validation documentation and usage guides.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Dec 8, 2025

Walkthrough

This pull request introduces version 0.2.0 featuring a comprehensive expansion of the validation framework. New validators are added for conditional requirements, date/time formatting, phone numbers (E.164), geographic coordinates, UUID variants, ULID, hexadecimal, and color formats. Documentation is updated across six languages with advanced examples, integration scenarios, and complete validator reference tables. Performance improvements of ~10% are achieved through optimized preprocessing pipelines.

Changes

Cohort / File(s) Summary
Validator Implementations
cross_field.go, validate.go
Introduces 20+ new validators: conditional required validators (requiredIf, requiredUnless, requiredWith, requiredWithout), datetime with layout support, E.164 phone validation, latitude/longitude geolocation, UUID v3/v4/v5, ULID, hexadecimal/color formats (hex, RGB, RGBA, HSL, HSLA), MAC address. Includes regex patterns, constructor functions, and Validate interface implementations.
Validator Registry & Parsing
tag.go, parser.go
Adds new tag constants for all validators and extends parseValidateTag to recognize and instantiate the full validator suite. Includes parseRequiredIfParams helper for conditional required parsing.
Testing & Examples
example_test.go, validate_test.go
Adds Example_employeePreprocessing() and Example_detailedErrorReporting() demonstrations. Introduces test suite covering datetime, E.164, latitude, longitude, UUID variants, ULID, hexadecimal, colors, and MAC validators with success/failure cases.
Core Documentation
CHANGELOG.md, README.md
Announces v0.2.0 with feature list and performance notes. Expands README with conditional required validators subsection, new validator tags, advanced preprocessing/validation examples, and detailed error reporting scenarios.
Internationalized Documentation
doc/es/README.md, doc/fr/README.md, doc/ja/README.md, doc/ko/README.md, doc/ru/README.md, doc/zh-cn/README.md
Comprehensive localization of English README updates: advanced usage examples (Employee, Order structs), filesql integration patterns, expanded validator reference tables, design considerations, memory/performance guidance, and error reporting details.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Areas requiring attention:

  • Regex patterns in validate.go — Verify correctness of E.164 phone format, UUID variant patterns, color format regexes (RGB, HSL, hexadecimal), and geolocation coordinate boundary checks (latitude: -90 to 90, longitude: -180 to 180)
  • Parser logic in parser.go — Ensure parseRequiredIfParams correctly splits and extracts field names and expected values; validate cross-field validator wiring to new conditional validators
  • Datetime parsing — Review parseDateTimeImpl for edge cases with Go time layout formats and timezone handling
  • Documentation consistency — Spot-check translated READMEs for accuracy and completeness of validator descriptions and examples across languages

Poem

🐰 New validators hop into view,
From E.164 phones to latitude true,
Conditional requires with conditional cheer,
Colors, UUIDs, and MAC address near!
A rainbow of features, all tested and sound,
In docs of six tongues, the best proof is found! 🌈

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ❓ Inconclusive The title is vague and generic. While 'Add validate tags' technically relates to the changeset, it fails to convey the scope and significance of the extensive changes, including new validators, documentation updates, and performance improvements across multiple languages. Consider a more descriptive title such as 'Add 18+ validation tags and comprehensive documentation updates' or 'Introduce conditional, datetime, and format validators with multilingual docs' to better reflect the magnitude and nature of changes.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch nchika/add-validate-tags

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link

github-actions bot commented Dec 8, 2025

Code Metrics Report

main (f6bb84e) #7 (054faa6) +/-
Coverage 89.2% 88.8% -0.4%
Test Execution Time 1s 2s +1s
Details
  |                     | main (f6bb84e) | #7 (054faa6) |  +/-  |
  |---------------------|----------------|--------------|-------|
- | Coverage            |          89.2% |        88.8% | -0.4% |
  |   Files             |             10 |           10 |     0 |
  |   Lines             |           1383 |         1538 |  +155 |
+ |   Covered           |           1234 |         1367 |  +133 |
- | Test Execution Time |             1s |           2s |   +1s |

Code coverage of files in pull request scope (85.5% → 85.5%)

Files Coverage +/- Status
cross_field.go 74.1% -17.2% modified
parser.go 67.7% +2.8% modified
validate.go 97.5% +0.6% modified

Reported by octocov

@nao1215 nao1215 merged commit f670fd4 into main Dec 8, 2025
10 of 11 checks passed
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
validate_test.go (1)

20-2288: Subtests use t.Parallel with captured range variable tt (flaky tests)

Across this file, almost every pattern is:

for _, tt := range tests {
    t.Run(tt.input or tt.name, func(t *testing.T) {
        t.Parallel()
        msg := v.Validate(tt.input)
        // ...
    })
}

Because the closure captures the loop variable tt and subtests run in parallel, this is subject to the standard Go range‑variable capture bug: subtests can see the wrong tt (often the last one), making tests flaky or misleading.

Two straightforward fixes:

  • Shadow tt at the start of each loop:
for _, tt := range tests {
    tt := tt
    t.Run(tt.input, func(t *testing.T) {
        t.Parallel()
        // use tt safely here
    })
}
  • Or, if you don't need subtests themselves to be parallel, drop the inner t.Parallel() and keep only the top‑level t.Parallel() on the parent test.

This should be applied consistently to all for _, tt := range tests blocks in this file.

🧹 Nitpick comments (4)
doc/ja/README.md (2)

181-181: Add language specifier to fenced code block.

The output code block should have a language specifier for consistency and to satisfy linting rules. Consider using text or plaintext for console output.

-```
+```text
 === 処理結果 ===

296-296: Add language specifier to fenced code block.

Similar to the previous output block, add a language specifier for the validation report output.

-```
+```text
 === バリデーションレポート ===
doc/ko/README.md (2)

181-181: Add language specifier to fenced code block.

Same as the Japanese documentation, the output code block should have a language specifier.

-```
+```text
 === 처리 결과 ===

296-296: Add language specifier to fenced code block.

Add a language specifier for the validation report output block.

-```
+```text
 === 검증 보고서 ===
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f6bb84e and 51c7284.

📒 Files selected for processing (14)
  • CHANGELOG.md (1 hunks)
  • README.md (4 hunks)
  • cross_field.go (1 hunks)
  • doc/es/README.md (6 hunks)
  • doc/fr/README.md (7 hunks)
  • doc/ja/README.md (7 hunks)
  • doc/ko/README.md (7 hunks)
  • doc/ru/README.md (6 hunks)
  • doc/zh-cn/README.md (7 hunks)
  • example_test.go (1 hunks)
  • parser.go (3 hunks)
  • tag.go (1 hunks)
  • validate.go (4 hunks)
  • validate_test.go (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
example_test.go (2)
processor.go (1)
  • NewProcessor (25-29)
filetype.go (1)
  • FileTypeCSV (13-13)
🪛 LanguageTool
doc/es/README.md

[grammar] ~98-~98: Corrige la mayúscula.
Context: ...il: "jane@example.com" ``` ## Ejemplos Avanzados ### Preprocesamiento y Validación de Datos C...

(QB_NEW_ES_OTHER_ERROR_IDS_REPLACEMENT_ORTHOGRAPHY_UPPERCASE)


[grammar] ~100-~100: Corrige la mayúscula.
Context: ...mplos Avanzados ### Preprocesamiento y Validación de Datos Complejos Este ejemplo demues...

(QB_NEW_ES_OTHER_ERROR_IDS_REPLACEMENT_ORTHOGRAPHY_UPPERCASE)


[grammar] ~100-~100: Corrige la mayúscula.
Context: ...s ### Preprocesamiento y Validación de Datos Complejos Este ejemplo demuestra toda ...

(QB_NEW_ES_OTHER_ERROR_IDS_REPLACEMENT_ORTHOGRAPHY_UPPERCASE)


[grammar] ~100-~100: Aquí puede haber un error.
Context: ... Preprocesamiento y Validación de Datos Complejos Este ejemplo demuestra toda la potencia ...

(QB_NEW_ES)


[grammar] ~231-~231: Corrige la mayúscula.
Context: ... https://alice.dev ``` ### Informe Detallado de Errores Cuando la validación falla,...

(QB_NEW_ES_OTHER_ERROR_IDS_REPLACEMENT_ORTHOGRAPHY_UPPERCASE)


[grammar] ~231-~231: Corrige la mayúscula.
Context: ...lice.dev ``` ### Informe Detallado de Errores Cuando la validación falla, fileprep pro...

(QB_NEW_ES_OTHER_ERROR_IDS_REPLACEMENT_ORTHOGRAPHY_UPPERCASE)


[grammar] ~394-~394: Corrige la mayúscula.
Context: ...lidate:"boolean"` | ### Validadores de Tipo de Carácter | Etiqueta | Descripción |...

(QB_NEW_ES_OTHER_ERROR_IDS_REPLACEMENT_ORTHOGRAPHY_UPPERCASE)


[grammar] ~394-~394: Corrige la mayúscula.
Context: ...boolean"` | ### Validadores de Tipo de Carácter | Etiqueta | Descripción | Ejemplo | |--...

(QB_NEW_ES_OTHER_ERROR_IDS_REPLACEMENT_ORTHOGRAPHY_UPPERCASE)


[grammar] ~409-~409: Corrige la mayúscula.
Context: ...date:"multibyte"` | ### Validadores de Comparación Numérica | Etiqueta | Descripción | Ej...

(QB_NEW_ES_OTHER_ERROR_IDS_REPLACEMENT_ORTHOGRAPHY_UPPERCASE)


[grammar] ~409-~409: Aquí puede haber un error.
Context: ...yte"` | ### Validadores de Comparación Numérica | Etiqueta | Descripción | Ejemplo | |--...

(QB_NEW_ES)


[grammar] ~423-~423: Corrige la mayúscula.
Context: ...alidate:"len=10"` | ### Validadores de Cadenas | Etiqueta | Descripción | Ejemplo | |--...

(QB_NEW_ES_OTHER_ERROR_IDS_REPLACEMENT_ORTHOGRAPHY_UPPERCASE)


[grammar] ~448-~448: Corrige la mayúscula.
Context: ..."excludesrune=$"` | ### Validadores de Formato | Etiqueta | Descripción | Ejemplo | |--...

(QB_NEW_ES_OTHER_ERROR_IDS_REPLACEMENT_ORTHOGRAPHY_UPPERCASE)


[grammar] ~491-~491: Corrige la mayúscula.
Context: ...:"hostname_port"` | ### Validadores de Campo Cruzado | Etiqueta | Descripción | Eje...

(QB_NEW_ES_OTHER_ERROR_IDS_REPLACEMENT_ORTHOGRAPHY_UPPERCASE)


[grammar] ~491-~491: Aquí puede haber un error.
Context: ...name_port"` | ### Validadores de Campo Cruzado | Etiqueta | Descripción | Ejemplo | |--...

(QB_NEW_ES)


[grammar] ~504-~504: Corrige la mayúscula.
Context: ...ludes=Forbidden"` | ### Validadores de Requerimiento Condicional | Etiqueta | Descripción |...

(QB_NEW_ES_OTHER_ERROR_IDS_REPLACEMENT_ORTHOGRAPHY_UPPERCASE)


[grammar] ~504-~504: Aquí puede haber un error.
Context: ...n"` | ### Validadores de Requerimiento Condicional | Etiqueta | Descripción | Ejemplo | |--...

(QB_NEW_ES)


[grammar] ~568-~568: Corrige la mayúscula.
Context: ...eraciones de Diseño ### Vinculación de Columnas por Nombre Los campos struct se mapean...

(QB_NEW_ES_OTHER_ERROR_IDS_REPLACEMENT_ORTHOGRAPHY_UPPERCASE)


[grammar] ~568-~568: Corrige la mayúscula.
Context: ...Diseño ### Vinculación de Columnas por Nombre Los campos struct se mapean a las column...

(QB_NEW_ES_OTHER_ERROR_IDS_REPLACEMENT_ORTHOGRAPHY_UPPERCASE)


[grammar] ~581-~581: Oración con errores
Context: ...` El orden de las columnas no importa - los campos se emparejan por nombre, por...

(QB_NEW_ES_OTHER_ERROR_IDS_REPLACEMENT_MULTITOKEN)


[grammar] ~606-~606: Corrige la mayúscula.
Context: ...na "country" } ``` #### Sensibilidad a Mayúsculas/Minúsculas y Encabezados Duplicados **...

(QB_NEW_ES_OTHER_ERROR_IDS_REPLACEMENT_ORTHOGRAPHY_UPPERCASE)


[grammar] ~606-~606: Corrige la mayúscula.
Context: ..." } ``` #### Sensibilidad a Mayúsculas/Minúsculas y Encabezados Duplicados **La coincide...

(QB_NEW_ES_OTHER_ERROR_IDS_REPLACEMENT_ORTHOGRAPHY_UPPERCASE)


[grammar] ~606-~606: Corrige la mayúscula.
Context: ... Sensibilidad a Mayúsculas/Minúsculas y Encabezados Duplicados **La coincidencia de encabe...

(QB_NEW_ES_OTHER_ERROR_IDS_REPLACEMENT_ORTHOGRAPHY_UPPERCASE)


[grammar] ~606-~606: Aquí puede haber un error.
Context: ...d a Mayúsculas/Minúsculas y Encabezados Duplicados **La coincidencia de encabezados es sensib...

(QB_NEW_ES)


[grammar] ~626-~626: Corrige la mayúscula.
Context: ...a primera columna "id") ``` #### Notas Específicas de Formato LTSV, Parquet y XLSX si...

(QB_NEW_ES_OTHER_ERROR_IDS_REPLACEMENT_ORTHOGRAPHY_UPPERCASE)


[grammar] ~626-~626: Corrige la mayúscula.
Context: ...na "id") ``` #### Notas Específicas de Formato LTSV, Parquet y XLSX siguen las mismas...

(QB_NEW_ES_OTHER_ERROR_IDS_REPLACEMENT_ORTHOGRAPHY_UPPERCASE)


[grammar] ~639-~639: Corrige la mayúscula.
Context: ...ombre exacto de la columna. ### Uso de Memoria fileprep carga el **archivo completo en ...

(QB_NEW_ES_OTHER_ERROR_IDS_REPLACEMENT_ORTHOGRAPHY_UPPERCASE)


[grammar] ~643-~643: Corrige la mayúscula.
Context: ...nes para archivos grandes: | Tamaño de Archivo | Memoria Aprox. | Recomendación | |---...

(QB_NEW_ES_OTHER_ERROR_IDS_REPLACEMENT_ORTHOGRAPHY_UPPERCASE)


[grammar] ~643-~643: Corrige el error ortográfico.
Context: ...grandes: | Tamaño de Archivo | Memoria Aprox. | Recomendación | |-------------------...

(QB_NEW_ES_OTHER_ERROR_IDS_REPLACEMENT_ORTHOGRAPHY_MULTIPLE)


[grammar] ~678-~678: Agrega un signo de puntuación.
Context: ...ectos Relacionados o de Inspiración - [nao1215/filesql](https://github.com/nao1215/fil...

(QB_NEW_ES_OTHER_ERROR_IDS_MISSING_PUNCTUATION)


[grammar] ~679-~679: Cambia la palabra o signo.
Context: ...SV con validación y DataFrame simple en golang. - [go-playground/validator](https://gi...

(QB_NEW_ES_OTHER_ERROR_IDS_REPLACEMENT_OTHER)


[grammar] ~681-~681: Corrige el error ortográfico.
Context: ...-csv es un codificador/decodificador de csv con encabezado. ## Contribuciones ¡La...

(QB_NEW_ES_OTHER_ERROR_IDS_REPLACEMENT_ORTHOGRAPHY_OTHERCASE)


[grammar] ~692-~692: Cambia la palabra o signo.
Context: ... proyecto - Convertirse en patrocinador - su apoyo mantiene vivo el proyecto y mo...

(QB_NEW_ES_OTHER_ERROR_IDS_REPLACEMENT_PUNCTUATION)


[grammar] ~692-~692: Aquí puede haber un error.
Context: ...proyecto y motiva el desarrollo continuo Su apoyo, ya sea a través de estrellas, ...

(QB_NEW_ES)

doc/zh-cn/README.md

[uncategorized] ~442-~442: 数词与名词之间一般应存在量词,可能缺少量词。
Context: ...tains=@"| |containsany=chars| 值包含任一字符 |validate:"containsany=abc"| |con...

(wa5)


[uncategorized] ~628-~628: 动词的修饰一般为‘形容词(副词)+地+动词’。您的意思是否是:相同"地"区分
Context: ...### 格式特定说明 LTSV、Parquet 和 XLSX 遵循相同的区分大小写匹配规则。键/列名必须精确匹配: ```go type Record...

(wb4)


[uncategorized] ~637-~637: 动词的修饰一般为‘形容词(副词)+地+动词’。您的意思是否是:确切"地"列
Context: ...XLSX 列使用驼峰命名(userId),请使用 name 标签指定确切的列名。 ### 内存使用 fileprep 将整个文件加载到内存中进...

(wb4)

doc/fr/README.md

[grammar] ~100-~100: «  validation  » semble plus probable dans ce contexte
Context: ... Exemples Avancés ### Prétraitement et Validation de Données Complexes Cet exemple démon...

(QB_NEW_FR_OTHER_ERROR_IDS_REPLACEMENT_ORTHOGRAPHY_UPPERCASE)


[grammar] ~100-~100: «  données complexes  » semble plus probable dans ce contexte
Context: ...cés ### Prétraitement et Validation de Données Complexes Cet exemple démontre toute l...

(QB_NEW_FR_OTHER_ERROR_IDS_REPLACEMENT_ORTHOGRAPHY_UPPERCASE)


[grammar] ~100-~100: Il y a peut-être une erreur ici
Context: ... Prétraitement et Validation de Données Complexes Cet exemple démontre toute la puissance ...

(QB_NEW_FR)


[grammar] ~179-~179: Élément manquant
Context: ...: %s\n\n", emp.Website) } } Sortie : === Résultat du Traitement === Lignes totales : 4, Lignes valides : 4 Employé 1 : ID : 000042 Nom : John Doe Email : john.doe@company.com Département : ENGINEERING Salaire : 75000 Téléphone : +15551234567 Date Début : 2023-01-15 ID Manager : 000001 Site Web : https://company.com/john Employé 2 : ID : 000007 Nom : Jane Smith Email : jane@company.com Département : SALES Salaire : 120000 Téléphone : +15559876543 Date Début : 2022-06-01 ID Manager : 000002 Site Web : https://www.linkedin.com/in/jane Employé 3 : ID : 000123 Nom : Bob Wilson Email : bob.wilson@company.com Département : HR Salaire : 45000 Téléphone : +15551112222 Date Début : 2024-03-20 ID Manager : 000000 Site Web : Employé 4 : ID : 000099 Nom : Alice Brown Email : alice@company.com Département : MARKETING Salaire : 88500 Téléphone : +15554443333 Date Début : 2023-09-10 ID Manager : 000003 Site Web : https://alice.dev ``` ### Rapport d'Erreurs Détaillé Lorsque la v...

(QB_NEW_FR_OTHER_ERROR_IDS_MISSING_SPACE__
31)


[grammar] ~231-~231: Il y a peut-être une erreur ici
Context: ... https://alice.dev ``` ### Rapport d'Erreurs Détaillé Lorsque la validation échoue,...

(QB_NEW_FR)


[grammar] ~231-~231: Il y a peut-être une erreur ici
Context: ...//alice.dev ``` ### Rapport d'Erreurs Détaillé Lorsque la validation échoue, fileprep f...

(QB_NEW_FR)


[style] ~233-~233: Une autre structure peut sembler plus percutante.
Context: ...rnit des informations d'erreur précises incluant le numéro de ligne, le nom de colonne e...

(INCLUANT_EXCLUANT)


[grammar] ~294-~294: Il y a peut-être une erreur ici
Context: ...lumn, e.Message) } } } Sortie : === Rapport de Validation === Lignes totales : 4 Lignes valides : 1 Lignes invalides : 3 Erreurs totales : 23 === Détails des Erreurs === Ligne 2, Colonne 'order_id' : value must be a valid UUID version 4 Ligne 2, Colonne 'customer_id' : value must be numeric Ligne 2, Colonne 'email' : value must be a valid email address Ligne 2, Colonne 'amount' : value must be greater than 0 Ligne 2, Colonne 'currency' : value must have exactly 3 characters Ligne 2, Colonne 'country' : value must have exactly 2 characters Ligne 2, Colonne 'order_date' : value must be a valid datetime in format: 2006-01-02 Ligne 2, Colonne 'ip_address' : value must be a valid IP address Ligne 2, Colonne 'promo_code' : value must contain only alphanumeric characters Ligne 2, Colonne 'quantity' : value must be greater than or equal to 1 Ligne 2, Colonne 'unit_price' : value must be greater than 0 Ligne 2, Colonne 'ship_date' : value must be greater than field OrderDate Ligne 2, Colonne 'total_check' : value must equal field Amount Ligne 3, Colonne 'customer_id' : value is required Ligne 3, Colonne 'email' : value must be a valid email address Ligne 3, Colonne 'amount' : value must be less than or equal to 10000 Ligne 3, Colonne 'currency' : value must have exactly 3 characters Ligne 3, Colonne 'country' : value must contain only alphabetic characters Ligne 3, Colonne 'order_date' : value must be a valid datetime in format: 2006-01-02 Ligne 3, Colonne 'quantity' : value must be less than or equal to 100 Ligne 3, Colonne 'unit_price' : value must be greater than 0 Ligne 3, Colonne 'ship_date' : value must be greater than field OrderDate Ligne 4, Colonne 'ship_date' : value must be greater than field OrderDate ``` ## Balises de Prétraitement (prep) Plusi...

(QB_NEW_FR)


[grammar] ~356-~356: «  caractères  » semble plus probable dans ce contexte
Context: ...ep:"collapse_space"` | ### Filtrage de Caractères | Balise | Description | Exemple | |----...

(QB_NEW_FR_OTHER_ERROR_IDS_REPLACEMENT_ORTHOGRAPHY_UPPERCASE)


[typographical] ~370-~370: Une espace est requise.
Context: ... | |--------|-------------|---------| | pad_left=N:char | Remplir à gauche jusqu'à N carac...

(DEUX_POINTS_ESPACE)


[typographical] ~371-~371: Une espace est requise.
Context: ... caractères | prep:"pad_left=5:0" | | pad_right=N:char | Remplir à droite jusqu'à N carac...

(DEUX_POINTS_ESPACE)


[grammar] ~373-~373: «  avancés  » semble plus probable dans ce contexte
Context: ..."pad_right=10: "` | ### Préprocesseurs Avancés | Balise | Description | Exemple | |----...

(QB_NEW_FR_OTHER_ERROR_IDS_REPLACEMENT_ORTHOGRAPHY_UPPERCASE)


[typographical] ~381-~381: Une espace est requise.
Context: ...a d'URL | prep:"fix_scheme=https" | | regex_replace=pattern:replacement | Remplacement basé sur reg...

(DEUX_POINTS_ESPACE)


[style] ~381-~381: Utilisé hors du contexte militaire, on préfèrera d’autres tournures à « baser sur ».
Context: ...ace=pattern:replacement| Remplacement basé sur regex |prep:"regex_replace=\d+:X"` |...

(BASER_SUR)


[typographical] ~381-~381: Une espace est requise.
Context: ...cement| Remplacement basé sur regex |prep:"regex_replace=\d+:X" | ## Balises de Validation (valida...

(DEUX_POINTS_ESPACE)


[grammar] ~394-~394: «  type  » semble plus probable dans ce contexte
Context: ...lidate:"boolean"` | ### Validateurs de Type de Caractère | Balise | Description | ...

(QB_NEW_FR_OTHER_ERROR_IDS_REPLACEMENT_ORTHOGRAPHY_UPPERCASE)


[grammar] ~394-~394: «  caractère  » semble plus probable dans ce contexte
Context: ...boolean"` | ### Validateurs de Type de Caractère | Balise | Description | Exemple | |----...

(QB_NEW_FR_OTHER_ERROR_IDS_REPLACEMENT_ORTHOGRAPHY_UPPERCASE)


[typographical] ~407-~407: Le préfixe « multi » est généralement associé au terme qu’il précède.
Context: ...| multibyte | Contient des caractères multi-octets | validate:"multibyte" | ### Validat...

(PAS_DE_TRAIT_UNION)


[grammar] ~423-~423: «  chaînes  » semble plus probable dans ce contexte
Context: ...alidate:"len=10"` | ### Validateurs de Chaînes | Balise | Description | Exemple | |----...

(QB_NEW_FR_OTHER_ERROR_IDS_REPLACEMENT_ORTHOGRAPHY_UPPERCASE)


[grammar] ~448-~448: «  format  » semble plus probable dans ce contexte
Context: ..."excludesrune=$"` | ### Validateurs de Format | Balise | Description | Exemple | |----...

(QB_NEW_FR_OTHER_ERROR_IDS_REPLACEMENT_ORTHOGRAPHY_UPPERCASE)


[typographical] ~489-~489: Une espace est requise.
Context: ...rfc1123"| |hostname_port| hostname:port valide |validate:"hostname_port"`...

(DEUX_POINTS_ESPACE)


[typographical] ~500-~500: Souhaitez-vous écrire une flèche ou le symbole « ≤ » ?
Context: ..."| |ltefield=Field| La valeur est <= un autre champ |validate:"ltefield=En...

(FLECHES)


[grammar] ~523-~523: Il y a peut-être une erreur ici
Context: ...st | **Note sur la compression Parquet** : La compression externe (.parquet.gz`...

(QB_NEW_FR)


[grammar] ~523-~523: «  la  » semble plus probable dans ce contexte
Context: ... | Note sur la compression Parquet : La compression externe (.parquet.gz, etc...

(QB_NEW_FR_OTHER_ERROR_IDS_REPLACEMENT_ORTHOGRAPHY_UPPERCASE)


[typographical] ~523-~523: Caractère d’apostrophe incorrect.
Context: ...sion Parquet** : La compression externe (.parquet.gz, etc.) est pour le fichier ...

(APOS_INCORRECT)


[style] ~523-~523: Ce verbe peut être considéré comme familier dans un contexte formel.
Context: ...terne (Snappy, GZIP, LZ4, ZSTD) qui est gérée de manière transparente par la biblioth...

(VERBES_FAMILIERS_PREMIUM)


[typographical] ~525-~525: Le préfixe « multi » est généralement associé au terme qu’il précède.
Context: ...s feuilles suivantes dans les classeurs multi-feuilles seront ignorées. ## Intégration avec f...

(PAS_DE_TRAIT_UNION)


[grammar] ~566-~566: «  conception  » semble plus probable dans ce contexte
Context: ...RE age > 20") ``` ## Considérations de Conception ### Liaison de Colonnes par Nom Les champs ...

(QB_NEW_FR_OTHER_ERROR_IDS_REPLACEMENT_ORTHOGRAPHY_UPPERCASE)


[grammar] ~568-~568: «  colonnes  » semble plus probable dans ce contexte
Context: ...dérations de Conception ### Liaison de Colonnes par Nom Les champs struct sont mappés ...

(QB_NEW_FR_OTHER_ERROR_IDS_REPLACEMENT_ORTHOGRAPHY_UPPERCASE)


[grammar] ~568-~568: «  nom  » semble plus probable dans ce contexte
Context: ...Conception ### Liaison de Colonnes par Nom Les champs struct sont mappés aux colonn...

(QB_NEW_FR_OTHER_ERROR_IDS_REPLACEMENT_ORTHOGRAPHY_UPPERCASE)


[grammar] ~570-~570: Il y a peut-être une erreur ici
Context: ...ur correspondre aux en-têtes de colonne CSV : go // Colonnes du fichier : user_name, email_address, phone_number (n'importe quel ordre) type User struct { UserName string // → correspond à la colonne "user_name" EmailAddress string // → correspond à la colonne "email_address" PhoneNumber string // → correspond à la colonne "phone_number" } **L'ordre des colonnes n'a pas d'importanc...

(QB_NEW_FR)


[style] ~581-~581: Une modification de la structure de la négation apportera de la légèreté et de la précision à cette phrase.
Context: ...e_number" } ``` L'ordre des colonnes n'a pas d'importance - les champs sont associés ...

(NEGATION_AVOIR)


[grammar] ~583-~583: «  colonnes personnalisés  » semble plus probable dans ce contexte
Context: ...ans changer votre struct. #### Noms de Colonnes Personnalisés avec la Balise name Ut...

(QB_NEW_FR_OTHER_ERROR_IDS_REPLACEMENT_ORTHOGRAPHY_UPPERCASE)


[grammar] ~583-~583: «  colonnes personnalisés  » semble plus probable dans ce contexte
Context: ...er votre struct. #### Noms de Colonnes Personnalisés avec la Balise name Utilisez la bali...

(QB_NEW_FR_OTHER_ERROR_IDS_REPLACEMENT_ORTHOGRAPHY_UPPERCASE)


[grammar] ~583-~583: «  balise  » semble plus probable dans ce contexte
Context: ... Noms de Colonnes Personnalisés avec la Balise name Utilisez la balise name pour remplacer...

(QB_NEW_FR_OTHER_ERROR_IDS_REPLACEMENT_ORTHOGRAPHY_UPPERCASE)


[grammar] ~585-~585: Il y a peut-être une erreur ici
Context: ...pour remplacer le nom de colonne généré automatiquement : go type User struct { UserName string `name:"user"` // → correspond à la colonne "user" (pas "user_name") Email string `name:"mail_addr"` // → correspond à la colonne "mail_addr" (pas "email") Age string // → correspond à la colonne "age" (snake_case automatique) } #### Comportement des Colonnes Manquantes Si...

(QB_NEW_FR)


[grammar] ~595-~595: «  colonnes manquantes  » semble plus probable dans ce contexte
Context: ...tomatique) } ``` #### Comportement des Colonnes Manquantes Si une colonne CSV n'existe...

(QB_NEW_FR_OTHER_ERROR_IDS_REPLACEMENT_ORTHOGRAPHY_UPPERCASE)


[grammar] ~595-~595: Il y a peut-être une erreur ici
Context: ...) } ``` #### Comportement des Colonnes Manquantes Si une colonne CSV n'existe pas pour un ...

(QB_NEW_FR)


[grammar] ~597-~597: Il y a peut-être une erreur ici
Context: ... donc required détectera les colonnes manquantes : go type User struct { Name string `validate:"required"` // Erreur si la colonne "name" est manquante Country string // Chaîne vide si la colonne "country" est manquante } #### Sensibilité à la Casse et En-têtes en Do...

(QB_NEW_FR)


[grammar] ~606-~606: «  casse  » semble plus probable dans ce contexte
Context: ... manquante } ``` #### Sensibilité à la Casse et En-têtes en Double **La corresponda...

(QB_NEW_FR_OTHER_ERROR_IDS_REPLACEMENT_ORTHOGRAPHY_UPPERCASE)


[grammar] ~606-~606: «  en  » semble plus probable dans ce contexte
Context: ...e } ``` #### Sensibilité à la Casse et En-têtes en Double **La correspondance de...

(QB_NEW_FR_OTHER_ERROR_IDS_REPLACEMENT_ORTHOGRAPHY_UPPERCASE)


[grammar] ~606-~606: «  double  » semble plus probable dans ce contexte
Context: ...# Sensibilité à la Casse et En-têtes en Double **La correspondance des en-têtes est sensi...

(QB_NEW_FR_OTHER_ERROR_IDS_REPLACEMENT_ORTHOGRAPHY_UPPERCASE)


[typographical] ~608-~608: Caractère d’apostrophe incorrect.
Context: ...* Un champ struct UserName se mappe à user_name, mais des en-têtes comme User_Name, `...

(APOS_INCORRECT)


[typographical] ~608-~608: Caractère d’apostrophe incorrect.
Context: ... à user_name, mais des en-têtes comme User_Name, USER_NAME ou userName ne corre...

(APOS_INCORRECT)


[style] ~617-~617: L’adverbe précède le verbe à l’infinitif.
Context: ...t noms de colonnes Parquet/XLSX doivent correspondre exactement. Noms de colonnes en double : Si u...

(PLACE_DE_L_ADVERBE)


[grammar] ~619-~619: Il y a peut-être une erreur ici
Context: ...ndre exactement. Noms de colonnes en double : Si un fichier contient des noms d'en...

(QB_NEW_FR)


[grammar] ~619-~619: Typographie
Context: ...ement. Noms de colonnes en double : Si un fichier contient des noms d'en-têt...

(QB_NEW_FR_OTHER_ERROR_IDS_MISSING_ORTHOGRAPHY_SPACE)


[typographical] ~619-~619: Caractère d’apostrophe incorrect.
Context: ... des noms d'en-tête en double (par ex., id,id,name), la première occurrence est utilis...

(APOS_INCORRECT)


[grammar] ~619-~619: Il y a peut-être une erreur ici
Context: ...mière occurrence** est utilisée pour la liaison : csv id,id,name first,second,John → struct.ID = "first" (la première colonne "id" gagne) #### Notes Spécifiques aux Formats **LTSV, P...

(QB_NEW_FR)


[grammar] ~626-~626: «  spécifiques  » semble plus probable dans ce contexte
Context: ...ère colonne "id" gagne) ``` #### Notes Spécifiques aux Formats LTSV, Parquet et XLSX ...

(QB_NEW_FR_OTHER_ERROR_IDS_REPLACEMENT_ORTHOGRAPHY_UPPERCASE)


[grammar] ~626-~626: «  formats  » semble plus probable dans ce contexte
Context: ... gagne) ``` #### Notes Spécifiques aux Formats LTSV, Parquet et XLSX suivent les même...

(QB_NEW_FR_OTHER_ERROR_IDS_REPLACEMENT_ORTHOGRAPHY_UPPERCASE)


[grammar] ~628-~628: Il y a peut-être une erreur ici
Context: ...s/noms de colonnes doivent correspondre exactement : go type Record struct { UserID string // attend la clé/colonne "user_id" Email string `name:"EMAIL"` // utilisez la balise name pour les colonnes non snake_case } Si vos clés LTSV utilisent des tirets (`...

(QB_NEW_FR)


[typographical] ~637-~637: Caractère d’apostrophe incorrect.
Context: ... Si vos clés LTSV utilisent des tirets (user-id) ou si les colonnes Parquet/XLS...

(APOS_INCORRECT)


[typographical] ~637-~637: Caractère d’apostrophe incorrect.
Context: ...lonnes Parquet/XLSX utilisent camelCase (userId), utilisez la balise name pour...

(APOS_INCORRECT)


[style] ~649-~649: Utilisé hors du contexte militaire, on préfèrera d’autres tournures à « baser sur ».
Context: ...2, xz, zstd), l'utilisation mémoire est basée sur la taille décompressée. ## Perform...

(BASER_SUR)


[grammar] ~653-~653: Essayez «  une structure  »
Context: ...enchmark traitant des fichiers CSV avec un struct complexe contenant 21 colonnes. ...

(QB_NEW_FR_OTHER_ERROR_IDS_REPLACEMENT_MULTITOKEN)


[grammar] ~653-~653: Essayez «  une structure  »
Context: ...hmark traitant des fichiers CSV avec un struct complexe contenant 21 colonnes. Chaque ...

(QB_NEW_FR_OTHER_ERROR_IDS_REPLACEMENT_MULTITOKEN)


[grammar] ~655-~655: Il y a peut-être une erreur ici
Context: ...alidation : Balises de prétraitement utilisées : trim, lowercase, uppercase, keep_dig...

(QB_NEW_FR)


[grammar] ~655-~655: Typographie
Context: ...Balises de prétraitement utilisées : trim, lowercase, uppercase, keep_digits,...

(QB_NEW_FR_OTHER_ERROR_IDS_MISSING_ORTHOGRAPHY_SPACE)


[grammar] ~655-~655: Il y a peut-être une erreur ici
Context: ...pse_space, truncate, fix_scheme, default Balises de validation utilisées : requ...

(QB_NEW_FR)


[grammar] ~676-~676: «  liés  » semble plus probable dans ce contexte
Context: ...varient selon le matériel.* ## Projets Liés ou d'Inspiration - [nao1215/filesql](h...

(QB_NEW_FR_OTHER_ERROR_IDS_REPLACEMENT_ORTHOGRAPHY_UPPERCASE)


[grammar] ~676-~676: «  inspiration  » semble plus probable dans ce contexte
Context: ...selon le matériel.* ## Projets Liés ou d'Inspiration - [nao1215/filesql](https://github.com/nao1...

(QB_NEW_FR_OTHER_ERROR_IDS_REPLACEMENT_ORTHOGRAPHY_UPPERCASE)


[typographical] ~678-~678: Ce signe est un trait d’union, il ne sert qu’à former des mots composés. Employez un tiret ou un autre signe de ponctuation plus approprié.
Context: ...iés ou d'Inspiration - nao1215/filesql - Driver SQL pour CSV, TSV, LTSV, Parquet, Excel...

(TIRET)


[typographical] ~679-~679: Ce signe est un trait d’union, il ne sert qu’à former des mots composés. Employez un tiret ou un autre signe de ponctuation plus approprié.
Context: ...rt gzip, bzip2, xz, zstd. - nao1215/csv - Lecture CSV avec validation et DataFrame simple...

(TIRET)


[grammar] ~679-~679: Essayez de remplacer cet élément par «  go  »
Context: ... avec validation et DataFrame simple en golang. - [go-playground/validator](https://gi...

(QB_NEW_FR_OTHER_ERROR_IDS_REPLACEMENT_OTHER)


[typographical] ~680-~680: Ce signe est un trait d’union, il ne sert qu’à former des mots composés. Employez un tiret ou un autre signe de ponctuation plus approprié.
Context: ...le en golang. - go-playground/validator - Validation de Go Struct et Field, incluant Cross F...

(TIRET)


[style] ~680-~680: Une autre structure peut sembler plus percutante.
Context: ...or) - Validation de Go Struct et Field, incluant Cross Field, Cross Struct, Map, Slice e...

(INCLUANT_EXCLUANT)


[typographical] ~681-~681: Ce signe est un trait d’union, il ne sert qu’à former des mots composés. Employez un tiret ou un autre signe de ponctuation plus approprié.
Context: ...rray diving. - shogo82148/go-header-csv - go-header-csv est un encodeur/décodeur csv...

(TIRET)


[grammar] ~681-~681: «  csv  » semble plus probable dans ce contexte
Context: ... go-header-csv est un encodeur/décodeur csv avec en-tête. ## Contributions Les co...

(QB_NEW_FR_OTHER_ERROR_IDS_REPLACEMENT_ORTHOGRAPHY_OTHERCASE)


[typographical] ~692-~692: Ce signe est un trait d’union, il ne sert qu’à former des mots composés. Employez un tiret ou un autre signe de ponctuation plus approprié.
Context: ...à découvrir le projet - Devenir sponsor - votre soutien maintient le projet en vie et m...

(TIRET)


[grammar] ~692-~692: Il y a peut-être une erreur ici
Context: ...n vie et motive le développement continu Votre soutien, que ce soit par des étoil...

(QB_NEW_FR)


[grammar] ~694-~694: Il y a peut-être une erreur ici
Context: ...ons, est ce qui fait avancer ce projet. Merci ! ## Licence Ce projet est sous licence MIT ...

(QB_NEW_FR)

🪛 markdownlint-cli2 (0.18.1)
doc/es/README.md

181-181: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


296-296: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

doc/zh-cn/README.md

181-181: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


296-296: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

doc/fr/README.md

181-181: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


296-296: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

doc/ru/README.md

181-181: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


296-296: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

README.md

181-181: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


296-296: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

doc/ja/README.md

181-181: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


296-296: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Unit test (linux) (windows-latest, 1.24)
🔇 Additional comments (12)
tag.go (1)

124-174: Well-structured validation tag constants.

The new constants are logically grouped with clear comments and follow the existing naming convention. The organization into categories (conditional, datetime, phone, geolocation, UUID variants, hex/color, network) makes the code maintainable and easy to navigate.

CHANGELOG.md (1)

10-31: Comprehensive changelog entry.

The changelog entry thoroughly documents all new validators, performance improvements, and documentation updates. The commit and PR links provide excellent traceability for future reference.

doc/ja/README.md (1)

98-228: Excellent advanced examples section.

The complex data preprocessing and validation example effectively demonstrates real-world usage with messy data, including conditional validators (required_unless), preprocessing chains, and E.164 phone validation. The input/output examples provide clear understanding of the transformations.

parser.go (3)

227-240: Implementation looks correct with a minor edge case consideration.

The function correctly parses "FieldName value" format. One edge case: when parts has length 0 (empty string input after SplitN), both return values will be empty strings. This is handled correctly since the callers check if field != "" before using the result.


442-484: Well-implemented validator instantiation.

The new validator cases follow the established pattern consistently. The datetime validator correctly requires a non-empty value (layout parameter), while parameterless validators like e164, latitude, longitude, UUID variants, color validators, and mac are instantiated without conditions.


520-546: Conditional required validators correctly integrated.

The cross-field conditional validators (required_if, required_unless, required_with, required_without) are properly parsed and instantiated. The use of parseRequiredIfParams for required_if and required_unless handles the "FieldName value" format, while required_with and required_without correctly use the value directly as the field name.

doc/ko/README.md (1)

98-228: Well-translated documentation with comprehensive examples.

The Korean documentation maintains consistency with the Japanese version while providing clear, localized content. The advanced examples effectively demonstrate the new validators and preprocessing capabilities.

validate.go (1)

1513-1892: New datetime/phone/geo/ID/color/MAC validators look consistent and well‑factored

The added validators (datetimeValidator, e164Validator, latitudeValidator, longitudeValidator, uuid3/4/5, ulidValidator, hexadecimalValidator, hexColorValidator, rgbValidator, rgbaValidator, hslValidator, hslaValidator, macValidator) are cohesive:

  • Each has a simple constructor, a Validate using the precompiled regex or time.Parse/net.ParseMAC, and a Name returning the tag constant.
  • Most allow empty strings and delegate presence to required, which matches the pattern used elsewhere in the file.

Aside from the color‑regex points noted separately, the implementations themselves look solid.

example_test.go (1)

97-446: Examples align well with new validators and cross‑field behavior

The new examples (Example_complexPrepAndValidation, Example_employeePreprocessing, Example_crossFieldValidation, Example_detailedErrorReporting) exercise:

  • Preprocessing tags (trim, pad_left, keep_digits, collapse_space, fix_scheme, etc.).
  • New validators (datetime, e164, eqfield/gtfield, numeric range checks).
  • Cross‑field error reporting via ValidationErrors().

They read cleanly and are consistent with the current validator implementations and error messages in validate.go. No changes needed here.

cross_field.go (1)

292-412: Conditional required cross‑field validators look correct and consistent

The new cross‑field validators (requiredIf, requiredUnless, requiredWith, requiredWithout) correctly:

  • Embed baseCrossFieldValidator for TargetField().
  • Implement the expected conditions in Validate (required when target == value, required unless target == value, required when target is non‑empty, required when target is empty).
  • Return the appropriate tag names via Name().

They integrate cleanly with the existing cross‑field infrastructure.

doc/ru/README.md (2)

98-327: Comprehensive and practical advanced examples — excellent documentation.

The expanded sections with the Employee and Order examples effectively showcase the new validation framework. The examples demonstrate real-world scenarios (complex preprocessing, conditional validation, error reporting) with clear outputs that help readers understand the capabilities.

The validator tables are well-organized and cover the full breadth of new functionality (conditional validators, format validators, network validators, color validators, geographic validators, UUID/ULID variants).


527-564: filesql integration section is clear and actionable.

The integration example demonstrates proper error handling and Builder pattern usage. Code examples are practical and show the expected flow from fileprep processing to filesql query execution.

Comment on lines +114 to +228
// Employee representa datos de empleados con preprocesamiento y validación completos
type Employee struct {
// ID: rellenar a 6 dígitos, debe ser numérico
EmployeeID string `name:"id" prep:"trim,pad_left=6:0" validate:"required,numeric,len=6"`

// Nombre: limpiar espacios, requerido alfabético con espacios
FullName string `name:"name" prep:"trim,collapse_space" validate:"required,alphaspace"`

// Email: normalizar a minúsculas, validar formato
Email string `prep:"trim,lowercase" validate:"required,email"`

// Departamento: normalizar mayúsculas, debe ser uno de los valores permitidos
Department string `prep:"trim,uppercase" validate:"required,oneof=ENGINEERING SALES MARKETING HR"`

// Salario: mantener solo dígitos, validar rango
Salary string `prep:"trim,keep_digits" validate:"required,numeric,gte=30000,lte=500000"`

// Teléfono: extraer dígitos, validar formato E.164 después de agregar código de país
Phone string `prep:"trim,keep_digits,prefix=+1" validate:"e164"`

// Fecha de inicio: validar formato datetime
StartDate string `name:"start_date" prep:"trim" validate:"required,datetime=2006-01-02"`

// ID de gerente: requerido solo si el departamento no es HR
ManagerID string `name:"manager_id" prep:"trim,pad_left=6:0" validate:"required_unless=Department HR"`

// Sitio web: corregir esquema faltante, validar URL
Website string `prep:"trim,lowercase,fix_scheme=https" validate:"url"`
}

func main() {
// Datos CSV desordenados del mundo real
csvData := `id,name,email,department,salary,phone,start_date,manager_id,website
42, John Doe ,JOHN.DOE@COMPANY.COM,engineering,$75,000,555-123-4567,2023-01-15,000001,company.com/john
7,Jane Smith,jane@COMPANY.com, Sales ,"$120,000",(555) 987-6543,2022-06-01,000002,WWW.LINKEDIN.COM/in/jane
123,Bob Wilson,bob.wilson@company.com,HR,45000,555.111.2222,2024-03-20,,
99,Alice Brown,alice@company.com,Marketing,$88500,555-444-3333,2023-09-10,000003,https://alice.dev
`

processor := fileprep.NewProcessor(fileprep.FileTypeCSV)
var employees []Employee

_, result, err := processor.Process(strings.NewReader(csvData), &employees)
if err != nil {
fmt.Printf("Error fatal: %v\n", err)
return
}

fmt.Printf("=== Resultado del Procesamiento ===\n")
fmt.Printf("Filas totales: %d, Filas válidas: %d\n\n", result.RowCount, result.ValidRowCount)

for i, emp := range employees {
fmt.Printf("Empleado %d:\n", i+1)
fmt.Printf(" ID: %s\n", emp.EmployeeID)
fmt.Printf(" Nombre: %s\n", emp.FullName)
fmt.Printf(" Email: %s\n", emp.Email)
fmt.Printf(" Departamento: %s\n", emp.Department)
fmt.Printf(" Salario: %s\n", emp.Salary)
fmt.Printf(" Teléfono: %s\n", emp.Phone)
fmt.Printf(" Fecha Inicio: %s\n", emp.StartDate)
fmt.Printf(" ID Gerente: %s\n", emp.ManagerID)
fmt.Printf(" Sitio Web: %s\n\n", emp.Website)
}
}
```

Salida:
```
=== Resultado del Procesamiento ===
Filas totales: 4, Filas válidas: 4
Empleado 1:
ID: 000042
Nombre: John Doe
Email: john.doe@company.com
Departamento: ENGINEERING
Salario: 75000
Teléfono: +15551234567
Fecha Inicio: 2023-01-15
ID Gerente: 000001
Sitio Web: https://company.com/john
Empleado 2:
ID: 000007
Nombre: Jane Smith
Email: jane@company.com
Departamento: SALES
Salario: 120000
Teléfono: +15559876543
Fecha Inicio: 2022-06-01
ID Gerente: 000002
Sitio Web: https://www.linkedin.com/in/jane
Empleado 3:
ID: 000123
Nombre: Bob Wilson
Email: bob.wilson@company.com
Departamento: HR
Salario: 45000
Teléfono: +15551112222
Fecha Inicio: 2024-03-20
ID Gerente: 000000
Sitio Web:
Empleado 4:
ID: 000099
Nombre: Alice Brown
Email: alice@company.com
Departamento: MARKETING
Salario: 88500
Teléfono: +15554443333
Fecha Inicio: 2023-09-10
ID Gerente: 000003
Sitio Web: https://alice.dev
```
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Ejemplo de Employee: url no permite vacío pero la salida muestra 4 filas válidas

En el ejemplo avanzado, el campo:

Website string `prep:"trim,lowercase,fix_scheme=https" validate:"url"`

tiene la tercera fila con website vacío, mientras que la salida indica:

Filas totales: 4, Filas válidas: 4
...
Empleado 3:
  ...
  Sitio Web:

Con la implementación actual de urlValidator, la cadena vacía se considera inválida, por lo que esa fila sería inválida y ValidRowCount sería 3, con un error de validación para website.

Sería bueno:

  • O bien relajar url para que el vacío sea aceptado (y usar required para obligar presencia), ajustando los tests,
  • O bien mantener url estricto y actualizar el ejemplo (datos y/o salida) para reflejar 3 filas válidas y un error adicional en website.

Además, los bloques de “Salida:” podrían anotarse con un lenguaje (por ejemplo ```text) para resolver el aviso MD040.

🧰 Tools
🪛 markdownlint-cli2 (0.18.1)

181-181: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
In doc/es/README.md around lines 114 to 228, the example uses Website with
validate:"url" but the CSV includes an empty website for row 3 while the output
claims 4 valid rows; fix by either: 1) relaxing the url validator to treat empty
string as valid (i.e. accept empty unless validate:"required,url" is used) and
update tests accordingly, or 2) keep the url validator strict and update the
example CSV/output to show ValidRowCount: 3 and include the validation error for
website on row 3; also mark the "Salida:" code block with a language tag (e.g.
```text) to satisfy MD040.

Comment on lines +114 to +228
// Employee représente les données d'employé avec prétraitement et validation complets
type Employee struct {
// ID : compléter à 6 chiffres, doit être numérique
EmployeeID string `name:"id" prep:"trim,pad_left=6:0" validate:"required,numeric,len=6"`

// Nom : nettoyer les espaces, requis alphabétique avec espaces
FullName string `name:"name" prep:"trim,collapse_space" validate:"required,alphaspace"`

// Email : normaliser en minuscules, valider le format
Email string `prep:"trim,lowercase" validate:"required,email"`

// Département : normaliser en majuscules, doit être une des valeurs autorisées
Department string `prep:"trim,uppercase" validate:"required,oneof=ENGINEERING SALES MARKETING HR"`

// Salaire : garder uniquement les chiffres, valider la plage
Salary string `prep:"trim,keep_digits" validate:"required,numeric,gte=30000,lte=500000"`

// Téléphone : extraire les chiffres, valider le format E.164 après ajout du code pays
Phone string `prep:"trim,keep_digits,prefix=+1" validate:"e164"`

// Date de début : valider le format datetime
StartDate string `name:"start_date" prep:"trim" validate:"required,datetime=2006-01-02"`

// ID Manager : requis seulement si le département n'est pas HR
ManagerID string `name:"manager_id" prep:"trim,pad_left=6:0" validate:"required_unless=Department HR"`

// Site web : corriger le schéma manquant, valider l'URL
Website string `prep:"trim,lowercase,fix_scheme=https" validate:"url"`
}

func main() {
// Données CSV désordonnées du monde réel
csvData := `id,name,email,department,salary,phone,start_date,manager_id,website
42, John Doe ,JOHN.DOE@COMPANY.COM,engineering,$75,000,555-123-4567,2023-01-15,000001,company.com/john
7,Jane Smith,jane@COMPANY.com, Sales ,"$120,000",(555) 987-6543,2022-06-01,000002,WWW.LINKEDIN.COM/in/jane
123,Bob Wilson,bob.wilson@company.com,HR,45000,555.111.2222,2024-03-20,,
99,Alice Brown,alice@company.com,Marketing,$88500,555-444-3333,2023-09-10,000003,https://alice.dev
`

processor := fileprep.NewProcessor(fileprep.FileTypeCSV)
var employees []Employee

_, result, err := processor.Process(strings.NewReader(csvData), &employees)
if err != nil {
fmt.Printf("Erreur fatale : %v\n", err)
return
}

fmt.Printf("=== Résultat du Traitement ===\n")
fmt.Printf("Lignes totales : %d, Lignes valides : %d\n\n", result.RowCount, result.ValidRowCount)

for i, emp := range employees {
fmt.Printf("Employé %d :\n", i+1)
fmt.Printf(" ID : %s\n", emp.EmployeeID)
fmt.Printf(" Nom : %s\n", emp.FullName)
fmt.Printf(" Email : %s\n", emp.Email)
fmt.Printf(" Département : %s\n", emp.Department)
fmt.Printf(" Salaire : %s\n", emp.Salary)
fmt.Printf(" Téléphone : %s\n", emp.Phone)
fmt.Printf(" Date Début : %s\n", emp.StartDate)
fmt.Printf(" ID Manager : %s\n", emp.ManagerID)
fmt.Printf(" Site Web : %s\n\n", emp.Website)
}
}
```

Sortie :
```
=== Résultat du Traitement ===
Lignes totales : 4, Lignes valides : 4
Employé 1 :
ID : 000042
Nom : John Doe
Email : john.doe@company.com
Département : ENGINEERING
Salaire : 75000
Téléphone : +15551234567
Date Début : 2023-01-15
ID Manager : 000001
Site Web : https://company.com/john
Employé 2 :
ID : 000007
Nom : Jane Smith
Email : jane@company.com
Département : SALES
Salaire : 120000
Téléphone : +15559876543
Date Début : 2022-06-01
ID Manager : 000002
Site Web : https://www.linkedin.com/in/jane
Employé 3 :
ID : 000123
Nom : Bob Wilson
Email : bob.wilson@company.com
Département : HR
Salaire : 45000
Téléphone : +15551112222
Date Début : 2024-03-20
ID Manager : 000000
Site Web :
Employé 4 :
ID : 000099
Nom : Alice Brown
Email : alice@company.com
Département : MARKETING
Salaire : 88500
Téléphone : +15554443333
Date Début : 2023-09-10
ID Manager : 000003
Site Web : https://alice.dev
```
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Advanced Employee example conflicts with current url validator behavior

Website is tagged validate:"url" but Employé 3 has an empty website column while the output claims Lignes valides : 4. With the current urlValidator.Validate, an empty string returns "value must be a valid URL", so that row will be invalid and ValidRowCount will be 3, not 4.

You likely want one of:

  • Make url treat empty strings as valid (and keep the example as‑is, but update tests like TestURLValidator), or
  • Keep url strict and update the example (data and/or output: either give Bob a URL or show Lignes valides : 3 and one extra validation error for website).

Also, to quiet markdownlint MD040, consider adding an explicit language (e.g. ```text) to the “Sortie :” fenced blocks.

🧰 Tools
🪛 LanguageTool

[grammar] ~179-~179: Élément manquant
Context: ...: %s\n\n", emp.Website) } } Sortie : === Résultat du Traitement === Lignes totales : 4, Lignes valides : 4 Employé 1 : ID : 000042 Nom : John Doe Email : john.doe@company.com Département : ENGINEERING Salaire : 75000 Téléphone : +15551234567 Date Début : 2023-01-15 ID Manager : 000001 Site Web : https://company.com/john Employé 2 : ID : 000007 Nom : Jane Smith Email : jane@company.com Département : SALES Salaire : 120000 Téléphone : +15559876543 Date Début : 2022-06-01 ID Manager : 000002 Site Web : https://www.linkedin.com/in/jane Employé 3 : ID : 000123 Nom : Bob Wilson Email : bob.wilson@company.com Département : HR Salaire : 45000 Téléphone : +15551112222 Date Début : 2024-03-20 ID Manager : 000000 Site Web : Employé 4 : ID : 000099 Nom : Alice Brown Email : alice@company.com Département : MARKETING Salaire : 88500 Téléphone : +15554443333 Date Début : 2023-09-10 ID Manager : 000003 Site Web : https://alice.dev ``` ### Rapport d'Erreurs Détaillé Lorsque la v...

(QB_NEW_FR_OTHER_ERROR_IDS_MISSING_SPACE__
31)

🪛 markdownlint-cli2 (0.18.1)

181-181: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
In doc/fr/README.md lines 114-228, the example assumes empty Website values are
accepted but the current url validator rejects empty strings; either update the
validator or the README. Fix by making the url validator treat empty string as
valid (adjust urlValidator.Validate to return nil for empty input and update
TestURLValidator accordingly), or alternatively update the CSV example and
expected output to give Bob a URL or change "Lignes valides" to 3 and show the
validation error for website; also add an explicit language tag (e.g. ```text)
to the "Sortie :" fenced code blocks to silence markdownlint MD040.

Comment on lines +180 to +228
Вывод:
```
=== Результат обработки ===
Всего строк: 4, Валидных: 4
Сотрудник 1:
ID: 000042
Имя: John Doe
Email: john.doe@company.com
Отдел: ENGINEERING
Зарплата: 75000
Телефон: +15551234567
Дата начала: 2023-01-15
ID руков.: 000001
Сайт: https://company.com/john
Сотрудник 2:
ID: 000007
Имя: Jane Smith
Email: jane@company.com
Отдел: SALES
Зарплата: 120000
Телефон: +15559876543
Дата начала: 2022-06-01
ID руков.: 000002
Сайт: https://www.linkedin.com/in/jane
Сотрудник 3:
ID: 000123
Имя: Bob Wilson
Email: bob.wilson@company.com
Отдел: HR
Зарплата: 45000
Телефон: +15551112222
Дата начала: 2024-03-20
ID руков.: 000000
Сайт:
Сотрудник 4:
ID: 000099
Имя: Alice Brown
Email: alice@company.com
Отдел: MARKETING
Зарплата: 88500
Телефон: +15554443333
Дата начала: 2023-09-10
ID руков.: 000003
Сайт: https://alice.dev
```
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add language specifier to code block output.

The fenced code block at line 181 (showing "Вывод:" output) is missing a language specifier for markdown linting compliance.

Apply this diff to add the language specifier:

 Вывод:
-```
+```text
 === Результат обработки ===
🧰 Tools
🪛 markdownlint-cli2 (0.18.1)

181-181: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
In doc/ru/README.md around lines 180 to 228 the fenced code block showing the
"Вывод:" output is missing a language specifier; update the opening fence from
``` to ```text (i.e., replace the opening triple backticks immediately after
"Вывод:" with ```text) so the code block is marked as plain text for markdown
linting.

Comment on lines +295 to +327
Вывод:
```
=== Отчёт о валидации ===
Всего строк: 4
Валидных: 1
Невалидных: 3
Всего ошибок: 23
=== Детали ошибок ===
Строка 2, Колонка 'order_id': value must be a valid UUID version 4
Строка 2, Колонка 'customer_id': value must be numeric
Строка 2, Колонка 'email': value must be a valid email address
Строка 2, Колонка 'amount': value must be greater than 0
Строка 2, Колонка 'currency': value must have exactly 3 characters
Строка 2, Колонка 'country': value must have exactly 2 characters
Строка 2, Колонка 'order_date': value must be a valid datetime in format: 2006-01-02
Строка 2, Колонка 'ip_address': value must be a valid IP address
Строка 2, Колонка 'promo_code': value must contain only alphanumeric characters
Строка 2, Колонка 'quantity': value must be greater than or equal to 1
Строка 2, Колонка 'unit_price': value must be greater than 0
Строка 2, Колонка 'ship_date': value must be greater than field OrderDate
Строка 2, Колонка 'total_check': value must equal field Amount
Строка 3, Колонка 'customer_id': value is required
Строка 3, Колонка 'email': value must be a valid email address
Строка 3, Колонка 'amount': value must be less than or equal to 10000
Строка 3, Колонка 'currency': value must have exactly 3 characters
Строка 3, Колонка 'country': value must contain only alphabetic characters
Строка 3, Колонка 'order_date': value must be a valid datetime in format: 2006-01-02
Строка 3, Колонка 'quantity': value must be less than or equal to 100
Строка 3, Колонка 'unit_price': value must be greater than 0
Строка 3, Колонка 'ship_date': value must be greater than field OrderDate
Строка 4, Колонка 'ship_date': value must be greater than field OrderDate
```
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add language specifier to code block output.

The fenced code block at line 296 (showing "Вывод:" output) is missing a language specifier for markdown linting compliance.

Apply this diff to add the language specifier:

 Вывод:
-```
+```text
 === Отчёт о валидации ===
🧰 Tools
🪛 markdownlint-cli2 (0.18.1)

296-296: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
In doc/ru/README.md around lines 295 to 327 the fenced code block showing the
"Вывод:" output is missing a language specifier; update the opening fence from
``` to ```text so the block starts with ```text (i.e., add the "text" language
tag to the code fence) to satisfy markdown linting.

Comment on lines +114 to +228
// Employee 表示带有综合预处理和验证的员工数据
type Employee struct {
// ID:填充到6位数字,必须是数字
EmployeeID string `name:"id" prep:"trim,pad_left=6:0" validate:"required,numeric,len=6"`

// 姓名:清理空白,必须是字母和空格
FullName string `name:"name" prep:"trim,collapse_space" validate:"required,alphaspace"`

// 邮箱:规范化为小写,验证格式
Email string `prep:"trim,lowercase" validate:"required,email"`

// 部门:规范化大小写,必须是允许的值之一
Department string `prep:"trim,uppercase" validate:"required,oneof=ENGINEERING SALES MARKETING HR"`

// 薪资:只保留数字,验证范围
Salary string `prep:"trim,keep_digits" validate:"required,numeric,gte=30000,lte=500000"`

// 电话:提取数字,添加国家代码后验证 E.164 格式
Phone string `prep:"trim,keep_digits,prefix=+1" validate:"e164"`

// 入职日期:验证日期格式
StartDate string `name:"start_date" prep:"trim" validate:"required,datetime=2006-01-02"`

// 经理 ID:如果部门不是 HR 则必填
ManagerID string `name:"manager_id" prep:"trim,pad_left=6:0" validate:"required_unless=Department HR"`

// 网站:修复缺失的协议,验证 URL
Website string `prep:"trim,lowercase,fix_scheme=https" validate:"url"`
}

func main() {
// 真实的"脏" CSV 数据
csvData := `id,name,email,department,salary,phone,start_date,manager_id,website
42, John Doe ,JOHN.DOE@COMPANY.COM,engineering,$75,000,555-123-4567,2023-01-15,000001,company.com/john
7,Jane Smith,jane@COMPANY.com, Sales ,"$120,000",(555) 987-6543,2022-06-01,000002,WWW.LINKEDIN.COM/in/jane
123,Bob Wilson,bob.wilson@company.com,HR,45000,555.111.2222,2024-03-20,,
99,Alice Brown,alice@company.com,Marketing,$88500,555-444-3333,2023-09-10,000003,https://alice.dev
`

processor := fileprep.NewProcessor(fileprep.FileTypeCSV)
var employees []Employee

_, result, err := processor.Process(strings.NewReader(csvData), &employees)
if err != nil {
fmt.Printf("致命错误:%v\n", err)
return
}

fmt.Printf("=== 处理结果 ===\n")
fmt.Printf("总行数:%d,有效行数:%d\n\n", result.RowCount, result.ValidRowCount)

for i, emp := range employees {
fmt.Printf("员工 %d\n", i+1)
fmt.Printf(" ID: %s\n", emp.EmployeeID)
fmt.Printf(" 姓名: %s\n", emp.FullName)
fmt.Printf(" 邮箱: %s\n", emp.Email)
fmt.Printf(" 部门: %s\n", emp.Department)
fmt.Printf(" 薪资: %s\n", emp.Salary)
fmt.Printf(" 电话: %s\n", emp.Phone)
fmt.Printf(" 入职日期: %s\n", emp.StartDate)
fmt.Printf(" 经理 ID: %s\n", emp.ManagerID)
fmt.Printf(" 网站: %s\n\n", emp.Website)
}
}
```

输出:
```
=== 处理结果 ===
总行数:4,有效行数:4
员工 1:
ID: 000042
姓名: John Doe
邮箱: john.doe@company.com
部门: ENGINEERING
薪资: 75000
电话: +15551234567
入职日期: 2023-01-15
经理 ID: 000001
网站: https://company.com/john
员工 2:
ID: 000007
姓名: Jane Smith
邮箱: jane@company.com
部门: SALES
薪资: 120000
电话: +15559876543
入职日期: 2022-06-01
经理 ID: 000002
网站: https://www.linkedin.com/in/jane
员工 3:
ID: 000123
姓名: Bob Wilson
邮箱: bob.wilson@company.com
部门: HR
薪资: 45000
电话: +15551112222
入职日期: 2024-03-20
经理 ID: 000000
网站:
员工 4:
ID: 000099
姓名: Alice Brown
邮箱: alice@company.com
部门: MARKETING
薪资: 88500
电话: +15554443333
入职日期: 2023-09-10
经理 ID: 000003
网站: https://alice.dev
```
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

高级 Employee 示例中 url 验证器与示例输出不一致

在“复杂数据预处理和验证”示例中:

Website string `prep:"trim,lowercase,fix_scheme=https" validate:"url"`

第三行的 website 为空,但输出中显示:

总行数:4,有效行数:4
...
员工 3:
  ...
  网站:

当前 urlValidator 对空字符串会返回错误(视为“不是有效 URL”),因此这一行实际上会被标记为无效,ValidRowCount 应为 3,而不是 4。

建议在以下两者中择一:

  • url 在值为空时视为通过(是否必填交给 required),并相应更新单元测试;或
  • 保持 url 严格,并调整该示例的数据/输出(例如给员工 3 一个 URL,或显示 3 条有效行并多一个 website 错误)。

同时,可将“输出:”代码块标注为 ```text 等语言,以满足 markdownlint 的 MD040 要求。

🧰 Tools
🪛 markdownlint-cli2 (0.18.1)

181-181: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

Comment on lines +114 to +228
// Employee represents employee data with comprehensive preprocessing and validation
type Employee struct {
// ID: pad to 6 digits, must be numeric
EmployeeID string `name:"id" prep:"trim,pad_left=6:0" validate:"required,numeric,len=6"`

// Name: clean whitespace, required alphabetic with spaces
FullName string `name:"name" prep:"trim,collapse_space" validate:"required,alphaspace"`

// Email: normalize to lowercase, validate format
Email string `prep:"trim,lowercase" validate:"required,email"`

// Department: normalize case, must be one of allowed values
Department string `prep:"trim,uppercase" validate:"required,oneof=ENGINEERING SALES MARKETING HR"`

// Salary: keep only digits, validate range
Salary string `prep:"trim,keep_digits" validate:"required,numeric,gte=30000,lte=500000"`

// Phone: extract digits, validate E.164 format after adding country code
Phone string `prep:"trim,keep_digits,prefix=+1" validate:"e164"`

// Start date: validate datetime format
StartDate string `name:"start_date" prep:"trim" validate:"required,datetime=2006-01-02"`

// Manager ID: required only if department is not HR
ManagerID string `name:"manager_id" prep:"trim,pad_left=6:0" validate:"required_unless=Department HR"`

// Website: fix missing scheme, validate URL
Website string `prep:"trim,lowercase,fix_scheme=https" validate:"url"`
}

func main() {
// Messy real-world CSV data
csvData := `id,name,email,department,salary,phone,start_date,manager_id,website
42, John Doe ,JOHN.DOE@COMPANY.COM,engineering,$75,000,555-123-4567,2023-01-15,000001,company.com/john
7,Jane Smith,jane@COMPANY.com, Sales ,"$120,000",(555) 987-6543,2022-06-01,000002,WWW.LINKEDIN.COM/in/jane
123,Bob Wilson,bob.wilson@company.com,HR,45000,555.111.2222,2024-03-20,,
99,Alice Brown,alice@company.com,Marketing,$88500,555-444-3333,2023-09-10,000003,https://alice.dev
`

processor := fileprep.NewProcessor(fileprep.FileTypeCSV)
var employees []Employee

_, result, err := processor.Process(strings.NewReader(csvData), &employees)
if err != nil {
fmt.Printf("Fatal error: %v\n", err)
return
}

fmt.Printf("=== Processing Result ===\n")
fmt.Printf("Total rows: %d, Valid rows: %d\n\n", result.RowCount, result.ValidRowCount)

for i, emp := range employees {
fmt.Printf("Employee %d:\n", i+1)
fmt.Printf(" ID: %s\n", emp.EmployeeID)
fmt.Printf(" Name: %s\n", emp.FullName)
fmt.Printf(" Email: %s\n", emp.Email)
fmt.Printf(" Department: %s\n", emp.Department)
fmt.Printf(" Salary: %s\n", emp.Salary)
fmt.Printf(" Phone: %s\n", emp.Phone)
fmt.Printf(" Start Date: %s\n", emp.StartDate)
fmt.Printf(" Manager ID: %s\n", emp.ManagerID)
fmt.Printf(" Website: %s\n\n", emp.Website)
}
}
```

Output:
```
=== Processing Result ===
Total rows: 4, Valid rows: 4
Employee 1:
ID: 000042
Name: John Doe
Email: john.doe@company.com
Department: ENGINEERING
Salary: 75000
Phone: +15551234567
Start Date: 2023-01-15
Manager ID: 000001
Website: https://company.com/john
Employee 2:
ID: 000007
Name: Jane Smith
Email: jane@company.com
Department: SALES
Salary: 120000
Phone: +15559876543
Start Date: 2022-06-01
Manager ID: 000002
Website: https://www.linkedin.com/in/jane
Employee 3:
ID: 000123
Name: Bob Wilson
Email: bob.wilson@company.com
Department: HR
Salary: 45000
Phone: +15551112222
Start Date: 2024-03-20
Manager ID: 000000
Website:
Employee 4:
ID: 000099
Name: Alice Brown
Email: alice@company.com
Department: MARKETING
Salary: 88500
Phone: +15554443333
Start Date: 2023-09-10
Manager ID: 000003
Website: https://alice.dev
```
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Advanced Employee example: url validator vs empty Website row

In the “Complex Data Preprocessing and Validation” example, Website is tagged validate:"url", but the third row’s website column is empty while the output claims:

Total rows: 4, Valid rows: 4
...
Employee 3:
  ...
  Website:

With the current urlValidator, "" is considered invalid (and TestURLValidator asserts that), so this row would be invalid and ValidRowCount would be 3, with a validation error for website.

Consider either:

  • Making url treat empty strings as ok (leaving “required” to enforce presence), and updating tests accordingly, or
  • Keeping url strict and adjusting this example’s data and/or output (e.g., give Employee 3 a URL or show 3 valid rows and include the URL error).

Also, to satisfy markdownlint MD040, you can annotate the “Output:” fences here and below with a language like ```text.

🧰 Tools
🪛 markdownlint-cli2 (0.18.1)

181-181: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
In README.md around lines 114-228, the example claims 4 valid rows while the
Website field on row 3 is empty but the `url` validator treats empty strings as
invalid; either make the `url` validator accept empty values (so only `required`
enforces presence) and update the `TestURLValidator` accordingly, or keep `url`
strict and change the example/data/output to provide a URL for Employee 3 (or
show Valid rows: 3 and include the website validation error). Also annotate the
output fenced code blocks with a language (e.g., ```text) to satisfy
markdownlint MD040.

Comment on lines +23 to +48
// E.164 phone number pattern
e164RegexPattern = `^\+[1-9]?[0-9]{7,14}$`
// Latitude pattern: -90 to 90
latitudeRegexPattern = `^[-+]?([1-8]?\d(\.\d+)?|90(\.0+)?)$`
// Longitude pattern: -180 to 180
longitudeRegexPattern = `^[-+]?(180(\.0+)?|((1[0-7]\d)|([1-9]?\d))(\.\d+)?)$`
// UUID version 3 pattern
uuid3RegexPattern = `^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-3[0-9a-fA-F]{3}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$`
// UUID version 4 pattern
uuid4RegexPattern = `^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$`
// UUID version 5 pattern
uuid5RegexPattern = `^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-5[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$`
// ULID pattern (26 characters, Crockford's base32)
ulidRegexPattern = `^(?i)[A-HJKMNP-TV-Z0-9]{26}$`
// Hexadecimal pattern
hexadecimalRegexPattern = `^(0[xX])?[0-9a-fA-F]+$`
// Hex color pattern (#RGB, #RGBA, #RRGGBB, #RRGGBBAA)
hexColorRegexPattern = `^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$`
// RGB color pattern
rgbRegexPattern = `^rgb\(\s*(?:(?:0|[1-9]\d?|1\d\d?|2[0-4]\d|25[0-5])\s*,\s*(?:0|[1-9]\d?|1\d\d?|2[0-4]\d|25[0-5])\s*,\s*(?:0|[1-9]\d?|1\d\d?|2[0-4]\d|25[0-5])|(?:0|[1-9]\d?|1\d\d?|2[0-4]\d|25[0-5])%\s*,\s*(?:0|[1-9]\d?|1\d\d?|2[0-4]\d|25[0-5])%\s*,\s*(?:0|[1-9]\d?|1\d\d?|2[0-4]\d|25[0-5])%)\s*\)$`
// RGBA color pattern
rgbaRegexPattern = `^rgba\(\s*(?:(?:0|[1-9]\d?|1\d\d?|2[0-4]\d|25[0-5])\s*,\s*(?:0|[1-9]\d?|1\d\d?|2[0-4]\d|25[0-5])\s*,\s*(?:0|[1-9]\d?|1\d\d?|2[0-4]\d|25[0-5])|(?:0|[1-9]\d?|1\d\d?|2[0-4]\d|25[0-5])%\s*,\s*(?:0|[1-9]\d?|1\d\d?|2[0-4]\d|25[0-5])%\s*,\s*(?:0|[1-9]\d?|1\d\d?|2[0-4]\d|25[0-5])%)\s*,\s*(?:(?:0.[1-9]*)|[01])\s*\)$`
// HSL color pattern
hslRegexPattern = `^hsl\(\s*(?:0|[1-9]\d?|[12]\d\d|3[0-5]\d|360)\s*,\s*(?:(?:0|[1-9]\d?|100)%)\s*,\s*(?:(?:0|[1-9]\d?|100)%)\s*\)$`
// HSLA color pattern
hslaRegexPattern = `^hsla\(\s*(?:0|[1-9]\d?|[12]\d\d|3[0-5]\d|360)\s*,\s*(?:(?:0|[1-9]\d?|100)%)\s*,\s*(?:(?:0|[1-9]\d?|100)%)\s*,\s*(?:(?:0.[1-9]*)|[01])\s*\)$`
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

RGB(A)/HSL(A) regexes accept out‑of‑range values and reject some valid ones

The new color regexes are mostly good, but there are a couple of semantic issues:

  • rgbRegexPattern reuses the 0–255 range for the percentage form (the % branches), so values like rgb(200%, 0%, 0%) pass even though CSS‑style RGB percentages are normally 0–100%.
  • The alpha portion in rgbaRegexPattern/hslaRegexPattern uses (?:(?:0.[1-9]*)|[01]), which:
    • Accepts 0. and 0.5, 0.75, etc.
    • Rejects common forms like 0.0, 0.25 with trailing zeros (0.50), and 1.0.

Consider tightening these regexes to something closer to:

  • Percent components: (?:0|[1-9]\d?|100)% (0–100%).
  • Alpha: (?:0(?:\.\d+)?|1(?:\.0+)?) (0, 1, or decimal between 0 and 1 inclusive).

That will better match the “valid RGB/RGBA/HSL/HSLA color” wording in the docs while keeping behavior predictable.

Also applies to: 71-84, 1770-1859

🤖 Prompt for AI Agents
In validate.go around lines 23-48 (and also update the analogous patterns at
71-84 and 1770-1859), the RGB/A and HSL/A regexes incorrectly allow percent
components >100 and accept/reject invalid alpha formats; replace the percent
component branches with a 0–100% pattern (e.g. use (?:0|[1-9]\d?|100)% for
percent values) and replace the alpha branches with a strict 0..1 decimal
pattern (e.g. use (?:0(?:\.\d+)?|1(?:\.0+)?) for alpha), ensuring both numeric
and percent forms for rgb/rgba and hsl/hsla are updated consistently.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants