L'usage principal de configlet est la vérification : s'assurer que les fichiers de configuration d'un parcours sont correctement structurés, tant sur le plan syntaxique que sémantique. Un parcours mal configuré risque de ne pas se synchroniser correctement, de s'afficher de façon erronée sur le site ou d'offrir une expérience utilisateur perfectible ; les garde-fous de configlet jouent donc un rôle important dans le maintien de l'intégrité d'Exercism.
La commande lint permet de vérifier un parcours.
configlet [global-options] lint [command-options]
Global options:
-h, --help Show this help message and exit
--version Show this tool's version information and exit
-t, --track-dir <dir> Specify a track directory to use instead of the current directory
-v, --verbosity <verbosity> The verbosity of output. Allowed values: q[uiet], n[ormal], d[etailed]
Voici les règles de vérification appliquées.
Le linter doit vérifier que tous les fichiers requis sont présents. Les fichiers non spécifiques aux exercices qui doivent être présents sont :
config.jsondocs/ABOUT.mddocs/INSTALLATION.mddocs/LEARNING.mddocs/RESOURCES.mddocs/SNIPPET.txtdocs/TESTS.mdexercises/shared/.docs/help.mdexercises/shared/.docs/tests.mdLes fichiers spécifiques aux exercices d'apprentissage qui doivent être présents sont :
exercises/concept/<slug>/.docs/hints.mdexercises/concept/<slug>/.docs/instructions.mdexercises/concept/<slug>/.docs/introduction.mdexercises/concept/<slug>/.meta/config.jsonIl y aura une liste similaire pour les exercices d'entraînement, mais les spécifications correspondantes n'ont pas encore été définies.
Chaque concept listé dans config.json doit posséder les fichiers suivants :
concepts/<slug>/about.mdconcepts/<slug>/introduction.mdconcepts/<slug>/links.jsonLe fichier config.json doit satisfaire aux vérifications suivantes :
"language" est requise"language" doit être une chaîne non vide¹ d'une longueur <= 255"slug" est requise"slug" doit être une chaîne en kebab-case² d'une longueur <= 255"active" est requise"active" doit être un booléen"blurb" est requise"blurb" doit être une chaîne non vide¹ d'une longueur <= 400"version" est requise"version" doit être l'entier 3
"status.concept_exercises" est requise"status.concept_exercises" doit être un booléen"status.test_runner" est requise"status.test_runner" doit être un booléen"status.representer" est requise"status.representer" doit être un booléen"status.analyzer" est requise"status.analyzer" doit être un booléen"online_editor.indent_style" est requise"online_editor.indent_style" doit être la chaîne space ou tab
"online_editor.indent_size" est requise"online_editor.indent_size" doit être un entier >= 0 et <= 8"online_editor.highlightjs_language" est facultative"online_editor.highlightjs_language" doit être une chaîne non vide¹"files" est facultative"files" doit être un objet"files.solution" est facultative"files.solution" doit être un tableau"files.solution" doivent être des motifs valides⁵"files.solution" ne doivent pas contenir de doublons"files.test" est facultative"files.test" doit être un tableau"files.test" doivent être des motifs valides⁵"files.test" ne doivent pas contenir de doublons"files.example" est facultative"files.example" doit être un tableau"files.example" doivent être des motifs valides⁵"files.example" ne doivent pas contenir de doublons"files.exemplar" est facultative"files.exemplar" doit être un tableau"files.exemplar" doivent être des motifs valides⁵"files.exemplar" ne doivent pas contenir de doublons"files.editor" est facultative"files.editor" doit être un tableau"files.editor" doivent être des motifs valides⁵"files.editor" ne doivent pas contenir de doublons"files.invalidator" est facultative"files.invalidator" doit être un tableau"files.invalidator" doivent être des motifs valides⁵"files.invalidator" ne doivent pas contenir de doublons"files.solution", "files.test", "files.example", "files.exemplar", "files.editor" ou "files.invalidator" (pas de chevauchement)
d ou plsql, les fichiers de "files.solution" et "files.test" peuvent se chevaucher"files.example et "files.exemplar" peuvent se chevaucher"test_runner.average_run_time" est requise si "status.test_runner" est égal à true
"test_runner.average_run_time" doit être un entier > 0"approaches.snippet_extension" est requise si le parcours possède une ou plusieurs approches"approaches.snippet_extension" doit être une chaîne non vide¹"exercises" est requise"exercises.concept" est requise"exercises.concept" doit être un tableau"exercises.concept[].slug" est requise"exercises.concept[].slug" doit être une chaîne en kebab-case² d'une longueur <= 255"exercises.concept[].slug" doit être unique dans "exercises.concept[].slug" et ne peut pas exister dans "exercises.practice[].slug"
"exercises.concept[].name" est requise"exercises.concept[].name" doit être une chaîne en Title Case³ d'une longueur <= 255"exercises.concept[].uuid" est requise"exercises.concept[].uuid" doit être une chaîne UUID de version 4 unique⁶"exercises.concept[].uuid" de chaque exercice ne doit jamais changer"exercises.concept[].concepts" est requise"exercises.concept[].concepts" doit être un tableau de chaînes non vide si "exercises.concept[].status" n'est pas égal à deprecated
"exercises.concept[].concepts" doit être un tableau vide si "exercises.concept[].status" est égal à deprecated
"exercises.concept[].concepts" doivent être des chaînes en kebab-case²"exercises.concept[].concepts" ne doivent pas contenir de doublons"exercises.concept[].concepts" ne doivent pas figurer dans la propriété "concepts" d'un autre exercice d'apprentissage"exercises.concept[].concepts" doivent correspondre à la propriété "concepts.slug" de l'un des concepts"exercises.concept[].prerequisites" est requise"exercises.concept[].prerequisites" doit être un tableau de chaînes non vide si "exercises.concept[].status" n'est pas égal à deprecated, à l'exception d'exactement un exercice, qui est autorisé à avoir un tableau vide comme valeur"exercises.concept[].prerequisites" doit être un tableau vide si "exercises.concept[].status" est égal à deprecated
"exercises.concept[].prerequisites" doivent être des chaînes en kebab-case²"exercises.concept[].prerequisites" ne doivent pas contenir de doublons"exercises.concept[].prerequisites" doivent correspondre aux valeurs de la propriété "concepts" d'un autre exercice d'apprentissage"exercises.concept[].prerequisites" ne doivent correspondre à aucune des valeurs de la propriété "exercises.concept[].concepts" de l'exercice"exercises.concept[].prerequisites" doivent correspondre à la propriété "concepts.slug" de l'un des concepts"exercises.concept[].concepts" et "exercises.concept[].prerequisites"
"exercises.concept[].status" est facultative"exercises.concept[].status" doit être la chaîne wip, beta, active ou deprecated
"exercises.practice" est requise"exercises.practice" doit être un tableau"exercises.practice[].slug" est requise"exercises.practice[].slug" doit être une chaîne en kebab-case² d'une longueur <= 255"exercises.practice[].slug" doit être unique dans "exercises.practice[].slug" et ne peut pas exister dans "exercises.concept[].slug"
"exercises.practice[].slug" égale à la chaîne hello-world
"exercises.practice[].name" est requise"exercises.practice[].name" doit être une chaîne en Title Case³ d'une longueur <= 255"exercises.practice[].uuid" est requise"exercises.practice[].uuid" doit être une chaîne UUID de version 4 unique⁶"exercises.practice[].uuid" de chaque exercice ne doit jamais changer"exercises.practice[].difficulty" est requise"exercises.practice[].difficulty" doit être un entier >= 1 et <= 10"exercises.practice[].practices" est requise"exercises.practice[].practices" doit être un tableau de chaînes non vide si "exercises.practice[].status" n'est pas égal à deprecated
"exercises.practice[].practices" doit être un tableau vide si "exercises.practice[].status" est égal à deprecated
"exercises.practice[].practices" doivent être des chaînes en kebab-case²"exercises.practice[].practices" ne doivent pas contenir de doublons"exercises.practice[].practices" doivent correspondre à la propriété "concepts[].slug" de l'un des concepts"exercises.practice[].practices" ne doivent pas référencer le slug d'un même concept plus de 10 fois (tous exercices confondus)"exercises.practice[].prerequisites" est requise"exercises.practice[].prerequisites" doit être un tableau de chaînes non vide si "exercises.practice[].status" n'est pas égal à deprecated
"exercises.practice[].prerequisites" doit être un tableau vide si "exercises.practice[].status" est égal à deprecated
"exercises.practice[].prerequisites" doit être un tableau vide si "exercises.practice[].slug" est égal à hello-world
"exercises.practice[].prerequisites" doivent être des chaînes en kebab-case²"exercises.practice[].prerequisites" ne doivent pas contenir de doublons"exercises.practice[].prerequisites" doivent correspondre aux valeurs de "exercises.concept[].concepts" d'un exercice d'apprentissage"exercises.practice[].prerequisites" doivent correspondre à la propriété "concepts[].slug" de l'un des concepts"exercises.practice[].status" est facultative"exercises.practice[].status" doit être la chaîne wip, beta, active ou deprecated
"exercises.practice[].status" doit, si "exercises.practice[].slug" est égal à hello-world, être soit omise, soit la chaîne active
"exercises.foregone" est facultative"exercises.foregone" doit être un tableau"exercises.foregone" doivent être des chaînes en kebab-case²"exercises.foregone" ne doivent pas contenir de doublons"exercises.foregone" ne doivent correspondre à aucun des slugs d'exercice d'apprentissage ou d'entraînement"concepts" est requise"concepts" doit être un tableau"concepts[].uuid" est requise"concepts[].uuid" doit être une chaîne UUID de version 4 unique⁶"concepts[].uuid" de chaque concept ne doit jamais changer"concepts[].slug" est requise"concepts[].slug" doit être une chaîne en kebab-case² d'une longueur <= 255"concepts[].name" est requise"concepts[].name" doit être une chaîne en Title Case³ d'une longueur <= 255"concepts[].tags" est facultative"concepts[].tags.all" est facultative, sauf si "concepts[].tags.any" est vide"concepts[].tags.all" doit être un tableau"concepts[].tags.all" doivent être des chaînes non vides de type tag⁷ d'une longueur <= 255"concepts[].tags.all" ne doivent pas contenir de doublons"concepts[].tags.any" est facultative, sauf si "concepts[].tags.all" est vide"concepts[].tags.any" doit être un tableau"concepts[].tags.any" doivent être des chaînes non vides de type tag⁷ d'une longueur <= 255"concepts[].tags.any" ne doivent pas contenir de doublons"concepts[].tags.not" est facultative"concepts[].tags.not" doit être un tableau"concepts[].tags.not" doivent être des chaînes non vides de type tag⁷ d'une longueur <= 255"concepts[].tags.not" ne doivent pas contenir de doublons"concepts" doit avoir un fichier concept/<concepts.slug>/about.md. Les règles de vérification applicables à ce fichier sont décrites ci-dessous."concepts" doit avoir un fichier concept/<concepts.slug>/introduction.md. Les règles de vérification applicables à ce fichier sont décrites ci-dessous."concepts" doit avoir un fichier concept/<concepts.slug>/links.json. Les règles de vérification applicables à ce fichier sont décrites ci-dessous."key_features" est facultative"key_features" doit être un tableau d'une longueur = 6"key_features[].icon" est requise"key_features[].icon" doit utiliser l'une des valeurs d'icône prédéfinies
"key_features[].title" est requise"key_features[].title" doit être une chaîne en Sentence Case⁴ d'une longueur <= 25"key_features[].content" est requise"key_features[].content" doit être une chaîne non vide¹ d'une longueur <= 100"tags" est requise"tags" doit être un tableau de chaînes"tags" ne doivent pas contenir de doublons"tags" doivent utiliser l'une des valeurs de tag prédéfinies
"blurb" est requise"blurb" doit être une chaîne non vide¹ d'une longueur <= 350"source" est facultative"source" doit être une chaîne non vide¹"source_url" est facultative"source_url" doit être une URL"authors" est requise"authors" doit être un tableau non vide"authors" doivent être des chaînes non vides¹"authors" ne doivent pas contenir de doublons"authors" sont traitées sans tenir compte de la casse"contributors" est facultative"contributors" doit être un tableau"contributors" doivent être des chaînes non vides¹"contributors" ne doivent pas contenir de doublons"contributors" sont traitées sans tenir compte de la casse"authors" ou "contributors" (pas de chevauchement)"files.solution" est requise"files.solution" doit être un tableau non vide"files.solution" ne doivent pas contenir de doublons"files.test" est requise"files.test" doit être un tableau non vide"files.test" ne doivent pas contenir de doublons"files.exemplar" est requise"files.exemplar" doit être un tableau non vide"files.exemplar" ne doivent pas contenir de doublons"files.editor" est facultative"files.editor" doit être un tableau"files.editor" ne doivent pas contenir de doublons"files.invalidator" est facultative"files.invalidator" doit être un tableau"files.invalidator" ne doivent pas contenir de doublons"files.solution" doivent exister"files.test" doivent exister"files.exemplar" doivent exister"files.editor" doivent exister"files.invalidator" doivent exister"files.solution", "files.test", "files.exemplar" ou "files.invalidator" (pas de chevauchement)
d ou plsql, les fichiers de "files.solution" et "files.test" peuvent se chevaucher"forked_from" est facultative"forked_from" doit être un tableau"forked_from" doivent être des chaînes au format <track-slug>/<exercise-slug> (par ex. fsharp/bird-watcher)"forked_from" doivent référencer des exercices réellement implémentés"forked_from" ne doivent pas contenir de doublons"language_versions" est facultative"language_versions" doit être une chaîne"representer.version" est facultative"representer.version" doit être un entier >= 1"icon" est facultative"icon" doit être une chaîne en kebab-case²## General, soit ## X. <task>, où X correspond au numéro de tâche du titre dans instructions.md
## 1. Do X
"concepts.slug" de l'un des concepts du config.json du parcours."blurb" est requise"blurb" doit être une chaîne non vide¹ d'une longueur <= 350"source" est facultative"source" doit être une chaîne non vide¹"source_url" est facultative"source_url" doit être une URL"authors" est facultative"authors" doit être un tableau"authors" doivent être des chaînes non vides¹"authors" ne doivent pas contenir de doublons"authors" sont traitées sans tenir compte de la casse"contributors" est facultative"contributors" doit être un tableau"contributors" doivent être des chaînes non vides¹"contributors" ne doivent pas contenir de doublons"contributors" sont traitées sans tenir compte de la casse"authors" ou "contributors" (pas de chevauchement)"files.solution" est requise"files.solution" doit être un tableau non vide"files.solution" ne doivent pas contenir de doublons"files.test" est requise"files.test" doit être un tableau non vide"files.test" ne doivent pas contenir de doublons"files.example" est requise"files.example" doit être un tableau non vide"files.example" ne doivent pas contenir de doublons"files.editor" est facultative"files.editor" doit être un tableau"files.editor" ne doivent pas contenir de doublons"files.invalidator" est facultative"files.invalidator" doit être un tableau"files.invalidator" ne doivent pas contenir de doublons"files.solution" doivent exister"files.test" doivent exister"files.example" doivent exister"files.editor" doivent exister"files.invalidator" doivent exister"files.solution", "files.test", "files.example ou "files.invalidator" (pas de chevauchement)
d ou plsql, les fichiers de "files.solution" et "files.test" peuvent se chevaucher"language_versions" est facultative"language_versions" doit être une chaîne"test_runner" est facultative"test_runner" doit être un booléen"representer.version" est facultative"representer.version" doit être un entier >= 1"icon" est facultative"icon" doit être une chaîne en kebab-case²introduction.md ou un répertoire voisin"introduction.authors" est facultative"introduction.authors" doit être un tableau"introduction.authors" doivent être des chaînes non vides¹"introduction.authors" ne doivent pas contenir de doublons"introduction.authors" sont traitées sans tenir compte de la casse"introduction.authors" n'est pas vide, il doit exister un fichier introduction.md non vide"introduction.contributors" est facultative"introduction.contributors" doit être un tableau"introduction.contributors" doivent être des chaînes non vides¹"introduction.contributors" ne doivent pas contenir de doublons"introduction.contributors" sont traitées sans tenir compte de la casse"introduction.contributors" n'est pas vide, il doit exister un fichier introduction.md non vide"introduction.authors" ou "introduction.contributors" (pas de chevauchement)"approaches" est facultative, sauf s'il existe un répertoire voisin (qui contient les fichiers de l'approche)"approaches" doit être un tableau d'objets"approaches[].uuid" est requise"approaches[].uuid" doit être une chaîne UUID de version 4 unique⁶"approaches[].uuid" de chaque concept ne doit jamais changer"approaches[].slug" est requise"approaches[].slug" doit être une chaîne en kebab-case² d'une longueur <= 255"approaches[].slug" doit avoir un fichier <slug>/content.md non vide correspondant"approaches[].slug" doit avoir un fichier <slug>/snippet.txt non vide correspondant"approaches[].title" est requise"approaches[].title" doit être une chaîne en Title Case³ d'une longueur <= 255"approaches[].blurb" est requise"approaches[].blurb" doit être une chaîne non vide¹ d'une longueur <= 350"approaches[].authors" est requise"approaches[].authors" doit être un tableau non vide"approaches[].authors" doivent être des chaînes non vides¹"approaches[].authors" ne doivent pas contenir de doublons"approaches[].authors" sont traitées sans tenir compte de la casse"approaches[].contributors" est facultative"approaches[].contributors" doit être un tableau"approaches[].contributors" doivent être des chaînes non vides¹"approaches[].contributors" ne doivent pas contenir de doublons"approaches[].contributors" sont traitées sans tenir compte de la casse"approaches[].authors" ou "approaches[].contributors" (pas de chevauchement)"approaches[].tags" est facultative"approaches[].tags.all" est facultative, sauf si "approaches[].tags.any" est vide"approaches[].tags.all" doit être un tableau"approaches[].tags.all" doivent être des chaînes non vides de type tag⁷ d'une longueur <= 255"approaches[].tags.all" ne doivent pas contenir de doublons"approaches[].tags.any" est facultative, sauf si "approaches[].tags.all" est vide"approaches[].tags.any" doit être un tableau"approaches[].tags.any" doivent être des chaînes non vides de type tag⁷ d'une longueur <= 255"approaches[].tags.any" ne doivent pas contenir de doublons"approaches[].tags.not" est facultative"approaches[].tags.not" doit être un tableau"approaches[].tags.not" doivent être des chaînes non vides de type tag⁷ d'une longueur <= 255"approaches[].tags.not" ne doivent pas contenir de doublons"approaches[].slug" correspondante existe dans le fichier .approaches/config.json
"approaches[].slug" correspondante existe dans le fichier .approaches/config.json
approaches.snippet_extension du fichier config.json du parcours"articles" est facultative, sauf s'il existe un répertoire voisin (qui contient les fichiers de l'article)"articles" doit être un tableau d'objets"articles[].uuid" est requise"articles[].uuid" doit être une chaîne UUID de version 4 unique⁶"articles[].uuid" de chaque concept ne doit jamais changer"articles[].slug" est requise"articles[].slug" doit être une chaîne en kebab-case² d'une longueur <= 255"articles[].slug" doit avoir un fichier <slug>/content.md non vide correspondant"articles[].slug" doit avoir un fichier <slug>/snippet.md non vide correspondant"articles[].title" est requise"articles[].title" doit être une chaîne en Title Case³ d'une longueur <= 255"articles[].blurb" est requise"articles[].blurb" doit être une chaîne non vide¹ d'une longueur <= 350"articles[].authors" est requise"articles[].authors" doit être un tableau non vide"articles[].authors" doivent être des chaînes non vides¹"articles[].authors" ne doivent pas contenir de doublons"articles[].authors" sont traitées sans tenir compte de la casse"articles[].contributors" est facultative"articles[].contributors" doit être un tableau"articles[].contributors" doivent être des chaînes non vides¹"articles[].contributors" ne doivent pas contenir de doublons"articles[].contributors" sont traitées sans tenir compte de la casse"articles[].authors" ou "articles[].contributors" (pas de chevauchement)"articles[].slug" correspondante existe dans le fichier .articles/config.json
"articles[].slug" correspondante existe dans le fichier .articles/config.json
"[].url" est requise"[].url" doit être une URL"[].description" est requise"[].description" doit être une chaîne non vide¹"[].icon_url" est facultative"[].icon_url" doit être une URL"blurb" est requise"blurb" doit être une chaîne non vide¹ d'une longueur <= 350"authors" est requise"authors" doit être un tableau"authors" doivent être des chaînes non vides¹"authors" ne doivent pas contenir de doublons"authors" sont traitées sans tenir compte de la casse"contributors" est facultative"contributors" doit être un tableau"contributors" doivent être des chaînes non vides¹"contributors" ne doivent pas contenir de doublons"contributors" sont traitées sans tenir compte de la casse"authors" ou "contributors" (pas de chevauchement)Chaîne non vide : une chaîne qui contient au moins un caractère autre qu'un espace.
Chaîne en kebab-case : une chaîne qui ne contient que des caractères de l'intervalle [a-z0-9], éventuellement séparés par des tirets (par ex. « two-fer »). Elle doit correspondre à l'expression régulière : ^[a-z0-9]+(-[a-z0-9]+)*$
Chaîne en Title Case : une chaîne non vide qui suit les règles du Chicago Manual of Style ci-dessous :
Chaîne en Sentence Case : une chaîne non vide qui suit les règles ci-dessous :
Motif files valide : une chaîne non vide¹ qui désigne l'emplacement d'un fichier utilisé dans un exercice, relativement au répertoire de l'exercice. Un motif peut utiliser l'un des espaces réservés suivants :
%{kebab_slug} : le slug d'exercice en kebab-case (par ex. bit-manipulation)%{snake_slug} : le slug d'exercice en snake_case (par ex. bit_manipulation)%{camel_slug} : le slug d'exercice en camelCase (par ex. bitManipulation)%{pascal_slug} : le slug d'exercice en PascalCase (par ex. BitManipulation)Chaîne UUID de version 4 unique : une chaîne qui remplit toutes les conditions suivantes :
config.json au niveau du parcours, pour un parcours Exercism donnéconfig.json au niveau du parcours d'aucun autre parcours Exercismcanonical-data.json de https://github.com/exercism/problem-specifications^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$
Par exemple, l'UUID ci-dessous a la forme correcte :
d334ffe3-657e-4725-a950-290b284b6d9f
Tu peux exécuter configlet uuid pour générer un UUID approprié.
tag d'analyseur valide : une chaîne non vide¹ au format <category>:<thing>.
La valeur de <category> doit être l'une des suivantes :
paradigm (par ex. paradigm:functional)technique (par ex. technique:recursion)construct (par ex. construct:bitwise-and)uses (par ex. uses:DateTime.add_seconds)La valeur de <thing> doit être une chaîne non vide¹.