-
-
Notifications
You must be signed in to change notification settings - Fork 0
Add validate tags #7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
WalkthroughThis 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
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Areas requiring attention:
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
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. Comment |
Code Metrics Report
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%)
Reported by octocov |
There was a problem hiding this 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 uset.Parallelwith captured range variablett(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
ttand subtests run in parallel, this is subject to the standard Go range‑variable capture bug: subtests can see the wrongtt(often the last one), making tests flaky or misleading.Two straightforward fixes:
- Shadow
ttat 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‑levelt.Parallel()on the parent test.This should be applied consistently to all
for _, tt := range testsblocks 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
textorplaintextfor 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
📒 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
partshas length 0 (empty string input after SplitN), both return values will be empty strings. This is handled correctly since the callers checkif 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, andmacare 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 ofparseRequiredIfParamsforrequired_ifandrequired_unlesshandles the "FieldName value" format, whilerequired_withandrequired_withoutcorrectly 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‑factoredThe 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
Validateusing the precompiled regex ortime.Parse/net.ParseMAC, and aNamereturning 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 behaviorThe 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 consistentThe new cross‑field validators (
requiredIf,requiredUnless,requiredWith,requiredWithout) correctly:
- Embed
baseCrossFieldValidatorforTargetField().- Implement the expected conditions in
Validate(required whentarget == value, required unlesstarget == 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.
| // 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 | ||
| ``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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
urlpara que el vacío sea aceptado (y usarrequiredpara obligar presencia), ajustando los tests, - O bien mantener
urlestricto y actualizar el ejemplo (datos y/o salida) para reflejar 3 filas válidas y un error adicional enwebsite.
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.
| // 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 | ||
| ``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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
urltreat empty strings as valid (and keep the example as‑is, but update tests likeTestURLValidator), or - Keep
urlstrict and update the example (data and/or output: either give Bob a URL or showLignes valides : 3and one extra validation error forwebsite).
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.
| Вывод: | ||
| ``` | ||
| === Результат обработки === | ||
| Всего строк: 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 | ||
| ``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
| Вывод: | ||
| ``` | ||
| === Отчёт о валидации === | ||
| Всего строк: 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 | ||
| ``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
| // 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 | ||
| ``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
高级 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)
| // 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 | ||
| ``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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
urltreat empty strings as ok (leaving “required” to enforce presence), and updating tests accordingly, or - Keeping
urlstrict 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.
| // 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*\)$` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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:
rgbRegexPatternreuses the 0–255 range for the percentage form (the%branches), so values likergb(200%, 0%, 0%)pass even though CSS‑style RGB percentages are normally 0–100%.- The alpha portion in
rgbaRegexPattern/hslaRegexPatternuses(?:(?:0.[1-9]*)|[01]), which:- Accepts
0.and0.5,0.75, etc. - Rejects common forms like
0.0,0.25with trailing zeros (0.50), and1.0.
- Accepts
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.
Summary by CodeRabbit
Release Notes v0.2.0
New Features
Performance
Documentation
✏️ Tip: You can customize this high-level summary in your review settings.