Il principale utilizzo di configlet è il linting: controllare se i file di configurazione di una traccia sono strutturati correttamente, sia sintatticamente che semanticamente. Le tracce configurate male potrebbero non sincronizzarsi correttamente, apparire sbagliate sul sito web o offrire un'esperienza utente non ottimale, quindi i controlli di configlet svolgono un ruolo importante nel preservare l'integrità di Exercism.
Il comando lint può essere usato per fare il linting di una traccia.
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]
Queste sono le regole di linting che vengono controllate.
Il linter dovrebbe controllare se tutti i file obbligatori sono presenti. I file non specifici di un esercizio che devono essere presenti sono:
config.jsondocs/ABOUT.mddocs/INSTALLATION.mddocs/LEARNING.mddocs/RESOURCES.mddocs/SNIPPET.txtdocs/TESTS.mdexercises/shared/.docs/help.mdexercises/shared/.docs/tests.mdI file specifici degli esercizi concettuali che devono essere presenti sono:
exercises/concept/<slug>/.docs/hints.mdexercises/concept/<slug>/.docs/instructions.mdexercises/concept/<slug>/.docs/introduction.mdexercises/concept/<slug>/.meta/config.jsonCi sarà un elenco simile per gli esercizi pratici, ma non abbiamo ancora definito la specifica per questo.
Ogni concetto elencato nel config.json dovrebbe avere i seguenti file:
concepts/<slug>/about.mdconcepts/<slug>/introduction.mdconcepts/<slug>/links.jsonIl file config.json dovrebbe superare i seguenti controlli:
"language" è obbligatoria"language" deve essere una stringa non vuota¹ con lunghezza <= 255"slug" è obbligatoria"slug" deve essere una stringa in kebab-case² con lunghezza <= 255"active" è obbligatoria"active" deve essere un booleano"blurb" è obbligatoria"blurb" deve essere una stringa non vuota¹ con lunghezza <= 400"version" è obbligatoria"version" deve essere il numero intero 3
"status.concept_exercises" è obbligatoria"status.concept_exercises" deve essere un booleano"status.test_runner" è obbligatoria"status.test_runner" deve essere un booleano"status.representer" è obbligatoria"status.representer" deve essere un booleano"status.analyzer" è obbligatoria"status.analyzer" deve essere un booleano"online_editor.indent_style" è obbligatoria"online_editor.indent_style" deve essere la stringa space o tab
"online_editor.indent_size" è obbligatoria"online_editor.indent_size" deve essere un numero intero >= 0 e <= 8"online_editor.highlightjs_language" è opzionale"online_editor.highlightjs_language" deve essere una stringa non vuota¹"files" è opzionale"files" deve essere un oggetto"files.solution" è opzionale"files.solution" deve essere un array"files.solution" devono essere pattern validi⁵"files.solution" non devono avere duplicati"files.test" è opzionale"files.test" deve essere un array"files.test" devono essere pattern validi⁵"files.test" non devono avere duplicati"files.example" è opzionale"files.example" deve essere un array"files.example" devono essere pattern validi⁵"files.example" non devono avere duplicati"files.exemplar" è opzionale"files.exemplar" deve essere un array"files.exemplar" devono essere pattern validi⁵"files.exemplar" non devono avere duplicati"files.editor" è opzionale"files.editor" deve essere un array"files.editor" devono essere pattern validi⁵"files.editor" non devono avere duplicati"files.invalidator" è opzionale"files.invalidator" deve essere un array"files.invalidator" devono essere pattern validi⁵"files.invalidator" non devono avere duplicati"files.solution", "files.test", "files.example", "files.exemplar", "files.editor" o "files.invalidator" (nessuna sovrapposizione)
d o plsql, i file di "files.solution" e "files.test" possono sovrapporsi"files.example e "files.exemplar" possono sovrapporsi"test_runner.average_run_time" è obbligatoria se "status.test_runner" è uguale a true
"test_runner.average_run_time" deve essere un numero intero > 0"approaches.snippet_extension" è obbligatoria se la traccia ha uno o più approcci"approaches.snippet_extension" deve essere una stringa non vuota¹"exercises" è obbligatoria"exercises.concept" è obbligatoria"exercises.concept" deve essere un array"exercises.concept[].slug" è obbligatoria"exercises.concept[].slug" deve essere una stringa in kebab-case² con lunghezza <= 255"exercises.concept[].slug" deve essere univoco in "exercises.concept[].slug" e non può esistere in "exercises.practice[].slug"
"exercises.concept[].name" è obbligatoria"exercises.concept[].name" deve essere una stringa in Title Case³ con lunghezza <= 255"exercises.concept[].uuid" è obbligatoria"exercises.concept[].uuid" deve essere una stringa UUID versione 4 univoca⁶"exercises.concept[].uuid" di ogni esercizio non deve mai cambiare"exercises.concept[].concepts" è obbligatoria"exercises.concept[].concepts" deve essere un array non vuoto di stringhe se "exercises.concept[].status" non è uguale a deprecated
"exercises.concept[].concepts" deve essere un array vuoto se "exercises.concept[].status" è uguale a deprecated
"exercises.concept[].concepts" devono essere stringhe in kebab-case²"exercises.concept[].concepts" non devono avere duplicati"exercises.concept[].concepts" non devono trovarsi nella proprietà "concepts" di nessun altro esercizio concettuale"exercises.concept[].concepts" devono corrispondere alla proprietà "concepts.slug" di uno dei concetti"exercises.concept[].prerequisites" è obbligatoria"exercises.concept[].prerequisites" deve essere un array non vuoto di stringhe se "exercises.concept[].status" non è uguale a deprecated, tranne che per esattamente un esercizio a cui è consentito avere un array vuoto come valore"exercises.concept[].prerequisites" deve essere un array vuoto se "exercises.concept[].status" è uguale a deprecated
"exercises.concept[].prerequisites" devono essere stringhe in kebab-case²"exercises.concept[].prerequisites" non devono avere duplicati"exercises.concept[].prerequisites" devono corrispondere ai valori della proprietà "concepts" di un altro esercizio concettuale"exercises.concept[].prerequisites" non devono corrispondere a nessuno dei valori nella proprietà "exercises.concept[].concepts" dell'esercizio"exercises.concept[].prerequisites" devono corrispondere alla proprietà "concepts.slug" di uno dei concetti"exercises.concept[].concepts" e "exercises.concept[].prerequisites"
"exercises.concept[].status" è opzionale"exercises.concept[].status" deve essere la stringa wip, beta, active o deprecated
"exercises.practice" è obbligatoria"exercises.practice" deve essere un array"exercises.practice[].slug" è obbligatoria"exercises.practice[].slug" deve essere una stringa in kebab-case² con lunghezza <= 255"exercises.practice[].slug" deve essere univoco in "exercises.practice[].slug" e non può esistere in "exercises.concept[].slug"
"exercises.practice[].slug" che è la stringa hello-world
"exercises.practice[].name" è obbligatoria"exercises.practice[].name" deve essere una stringa in Title Case³ con lunghezza <= 255"exercises.practice[].uuid" è obbligatoria"exercises.practice[].uuid" deve essere una stringa UUID versione 4 univoca⁶"exercises.practice[].uuid" di ogni esercizio non deve mai cambiare"exercises.practice[].difficulty" è obbligatoria"exercises.practice[].difficulty" deve essere un numero intero >= 1 e <= 10"exercises.practice[].practices" è obbligatoria"exercises.practice[].practices" deve essere un array non vuoto di stringhe se "exercises.practice[].status" non è uguale a deprecated
"exercises.practice[].practices" deve essere un array vuoto se "exercises.practice[].status" è uguale a deprecated
"exercises.practice[].practices" devono essere stringhe in kebab-case²"exercises.practice[].practices" non devono avere duplicati"exercises.practice[].practices" devono corrispondere alla proprietà "concepts[].slug" di uno dei concetti"exercises.practice[].practices" devono riferirsi allo slug di un singolo concetto al massimo 10 volte (in tutti gli esercizi)"exercises.practice[].prerequisites" è obbligatoria"exercises.practice[].prerequisites" deve essere un array non vuoto di stringhe se "exercises.practice[].status" non è uguale a deprecated
"exercises.practice[].prerequisites" deve essere un array vuoto se "exercises.practice[].status" è uguale a deprecated
"exercises.practice[].prerequisites" deve essere un array vuoto se "exercises.practice[].slug" è uguale a hello-world
"exercises.practice[].prerequisites" devono essere stringhe in kebab-case²"exercises.practice[].prerequisites" non devono avere duplicati"exercises.practice[].prerequisites" devono corrispondere ai valori di "exercises.concept[].concepts" di un esercizio concettuale"exercises.practice[].prerequisites" devono corrispondere alla proprietà "concepts[].slug" di uno dei concetti"exercises.practice[].status" è opzionale"exercises.practice[].status" deve essere la stringa wip, beta, active o deprecated
"exercises.practice[].status", se "exercises.practice[].slug" è uguale a hello-world, deve essere omesso oppure essere la stringa active
"exercises.foregone" è opzionale"exercises.foregone" deve essere un array"exercises.foregone" devono essere stringhe in kebab-case²"exercises.foregone" non devono avere duplicati"exercises.foregone" non devono corrispondere a nessuno degli slug degli esercizi concettuali o pratici"concepts" è obbligatoria"concepts" deve essere un array"concepts[].uuid" è obbligatoria"concepts[].uuid" deve essere una stringa UUID versione 4 univoca⁶"concepts[].uuid" di ogni concetto non deve mai cambiare"concepts[].slug" è obbligatoria"concepts[].slug" deve essere una stringa in kebab-case² con lunghezza <= 255"concepts[].name" è obbligatoria"concepts[].name" deve essere una stringa in Title Case³ con lunghezza <= 255"concepts[].tags" è opzionale"concepts[].tags.all" è opzionale, a meno che "concepts[].tags.any" sia vuoto"concepts[].tags.all" deve essere un array"concepts[].tags.all" devono essere stringhe tag⁷ non vuote con lunghezza <= 255"concepts[].tags.all" non devono avere duplicati"concepts[].tags.any" è opzionale, a meno che "concepts[].tags.all" sia vuoto"concepts[].tags.any" deve essere un array"concepts[].tags.any" devono essere stringhe tag⁷ non vuote con lunghezza <= 255"concepts[].tags.any" non devono avere duplicati"concepts[].tags.not" è opzionale"concepts[].tags.not" deve essere un array"concepts[].tags.not" devono essere stringhe tag⁷ non vuote con lunghezza <= 255"concepts[].tags.not" non devono avere duplicati"concepts" deve avere un file concept/<concepts.slug>/about.md. Le regole di linting per questo file sono specificate di seguito."concepts" deve avere un file concept/<concepts.slug>/introduction.md. Le regole di linting per questo file sono specificate di seguito."concepts" deve avere un file concept/<concepts.slug>/links.json. Le regole di linting per questo file sono specificate di seguito."key_features" è opzionale"key_features" deve essere un array con lunghezza = 6"key_features[].icon" è obbligatoria"key_features[].icon" deve usare uno dei valori di icona predefiniti
"key_features[].title" è obbligatoria"key_features[].title" deve essere una stringa in Sentence Case⁴ con lunghezza <= 25"key_features[].content" è obbligatoria"key_features[].content" deve essere una stringa non vuota¹ con lunghezza <= 100"tags" è obbligatoria"tags" deve essere un array di stringhe"tags" non devono avere duplicati"tags" devono usare uno dei valori di tag predefiniti
"blurb" è obbligatoria"blurb" deve essere una stringa non vuota¹ con lunghezza <= 350"source" è opzionale"source" deve essere una stringa non vuota¹"source_url" è opzionale"source_url" deve essere un URL"authors" è obbligatoria"authors" deve essere un array non vuoto"authors" devono essere stringhe non vuote¹"authors" non devono avere duplicati"authors" sono trattati senza distinzione tra maiuscole e minuscole"contributors" è opzionale"contributors" deve essere un array"contributors" devono essere stringhe non vuote¹"contributors" non devono avere duplicati"contributors" sono trattati senza distinzione tra maiuscole e minuscole"authors" o "contributors" (nessuna sovrapposizione)"files.solution" è obbligatoria"files.solution" deve essere un array non vuoto"files.solution" non devono avere duplicati"files.test" è obbligatoria"files.test" deve essere un array non vuoto"files.test" non devono avere duplicati"files.exemplar" è obbligatoria"files.exemplar" deve essere un array non vuoto"files.exemplar" non devono avere duplicati"files.editor" è opzionale"files.editor" deve essere un array"files.editor" non devono avere duplicati"files.invalidator" è opzionale"files.invalidator" deve essere un array"files.invalidator" non devono avere duplicati"files.solution" devono esistere"files.test" devono esistere"files.exemplar" devono esistere"files.editor" devono esistere"files.invalidator" devono esistere"files.solution", "files.test", "files.exemplar" o "files.invalidator" (nessuna sovrapposizione)
d o plsql, i file di "files.solution" e "files.test" possono sovrapporsi"forked_from" è opzionale"forked_from" deve essere un array"forked_from" devono essere stringhe formattate come <track-slug>/<exercise-slug> (ad es. fsharp/bird-watcher)"forked_from" devono riferirsi a esercizi effettivamente implementati"forked_from" non devono avere duplicati"language_versions" è opzionale"language_versions" deve essere una stringa"representer.version" è opzionale"representer.version" deve essere un numero intero >= 1"icon" è opzionale"icon" deve essere una stringa in kebab-case²## General oppure ## X. <task>, dove X corrisponde all'intestazione del numero del task nelle instructions.md
## 1. Do X
"concepts.slug" di uno dei concetti nel config.json della traccia."blurb" è obbligatoria"blurb" deve essere una stringa non vuota¹ con lunghezza <= 350"source" è opzionale"source" deve essere una stringa non vuota¹"source_url" è opzionale"source_url" deve essere un URL"authors" è opzionale"authors" deve essere un array"authors" devono essere stringhe non vuote¹"authors" non devono avere duplicati"authors" sono trattati senza distinzione tra maiuscole e minuscole"contributors" è opzionale"contributors" deve essere un array"contributors" devono essere stringhe non vuote¹"contributors" non devono avere duplicati"contributors" sono trattati senza distinzione tra maiuscole e minuscole"authors" o "contributors" (nessuna sovrapposizione)"files.solution" è obbligatoria"files.solution" deve essere un array non vuoto"files.solution" non devono avere duplicati"files.test" è obbligatoria"files.test" deve essere un array non vuoto"files.test" non devono avere duplicati"files.example" è obbligatoria"files.example" deve essere un array non vuoto"files.example" non devono avere duplicati"files.editor" è opzionale"files.editor" deve essere un array"files.editor" non devono avere duplicati"files.invalidator" è opzionale"files.invalidator" deve essere un array"files.invalidator" non devono avere duplicati"files.solution" devono esistere"files.test" devono esistere"files.example" devono esistere"files.editor" devono esistere"files.invalidator" devono esistere"files.solution", "files.test", "files.example o "files.invalidator" (nessuna sovrapposizione)
d o plsql, i file di "files.solution" e "files.test" possono sovrapporsi"language_versions" è opzionale"language_versions" deve essere una stringa"test_runner" è opzionale"test_runner" deve essere un booleano"representer.version" è opzionale"representer.version" deve essere un numero intero >= 1"icon" è opzionale"icon" deve essere una stringa in kebab-case²introduction.md o una directory adiacente"introduction.authors" è opzionale"introduction.authors" deve essere un array"introduction.authors" devono essere stringhe non vuote¹"introduction.authors" non devono avere duplicati"introduction.authors" sono trattati senza distinzione tra maiuscole e minuscole"introduction.authors" non è vuoto, deve esserci un file introduction.md non vuoto"introduction.contributors" è opzionale"introduction.contributors" deve essere un array"introduction.contributors" devono essere stringhe non vuote¹"introduction.contributors" non devono avere duplicati"introduction.contributors" sono trattati senza distinzione tra maiuscole e minuscole"introduction.contributors" non è vuoto, deve esserci un file introduction.md non vuoto"introduction.authors" o "introduction.contributors" (nessuna sovrapposizione)"approaches" è opzionale, a meno che non sia presente una directory adiacente (che contiene i file degli approcci)"approaches" deve essere un array di oggetti"approaches[].uuid" è obbligatoria"approaches[].uuid" deve essere una stringa UUID versione 4 univoca⁶"approaches[].uuid" di ogni concetto non deve mai cambiare"approaches[].slug" è obbligatoria"approaches[].slug" deve essere una stringa in kebab-case² con lunghezza <= 255"approaches[].slug" deve avere un file <slug>/content.md non vuoto corrispondente"approaches[].slug" deve avere un file <slug>/snippet.txt non vuoto corrispondente"approaches[].title" è obbligatoria"approaches[].title" deve essere una stringa in Title Case³ con lunghezza <= 255"approaches[].blurb" è obbligatoria"approaches[].blurb" deve essere una stringa non vuota¹ con lunghezza <= 350"approaches[].authors" è obbligatoria"approaches[].authors" deve essere un array non vuoto"approaches[].authors" devono essere stringhe non vuote¹"approaches[].authors" non devono avere duplicati"approaches[].authors" sono trattati senza distinzione tra maiuscole e minuscole"approaches[].contributors" è opzionale"approaches[].contributors" deve essere un array"approaches[].contributors" devono essere stringhe non vuote¹"approaches[].contributors" non devono avere duplicati"approaches[].contributors" sono trattati senza distinzione tra maiuscole e minuscole"approaches[].authors" o "approaches[].contributors" (nessuna sovrapposizione)"approaches[].tags" è opzionale"approaches[].tags.all" è opzionale, a meno che "approaches[].tags.any" sia vuoto"approaches[].tags.all" deve essere un array"approaches[].tags.all" devono essere stringhe tag⁷ non vuote con lunghezza <= 255"approaches[].tags.all" non devono avere duplicati"approaches[].tags.any" è opzionale, a meno che "approaches[].tags.all" sia vuoto"approaches[].tags.any" deve essere un array"approaches[].tags.any" devono essere stringhe tag⁷ non vuote con lunghezza <= 255"approaches[].tags.any" non devono avere duplicati"approaches[].tags.not" è opzionale"approaches[].tags.not" deve essere un array"approaches[].tags.not" devono essere stringhe tag⁷ non vuote con lunghezza <= 255"approaches[].tags.not" non devono avere duplicati"approaches[].slug" corrispondente nel file .approaches/config.json
"approaches[].slug" corrispondente nel file .approaches/config.json
approaches.snippet_extension nel file config.json della traccia"articles" è opzionale, a meno che non sia presente una directory adiacente (che contiene i file degli articoli)"articles" deve essere un array di oggetti"articles[].uuid" è obbligatoria"articles[].uuid" deve essere una stringa UUID versione 4 univoca⁶"articles[].uuid" di ogni concetto non deve mai cambiare"articles[].slug" è obbligatoria"articles[].slug" deve essere una stringa in kebab-case² con lunghezza <= 255"articles[].slug" deve avere un file <slug>/content.md non vuoto corrispondente"articles[].slug" deve avere un file <slug>/snippet.md non vuoto corrispondente"articles[].title" è obbligatoria"articles[].title" deve essere una stringa in Title Case³ con lunghezza <= 255"articles[].blurb" è obbligatoria"articles[].blurb" deve essere una stringa non vuota¹ con lunghezza <= 350"articles[].authors" è obbligatoria"articles[].authors" deve essere un array non vuoto"articles[].authors" devono essere stringhe non vuote¹"articles[].authors" non devono avere duplicati"articles[].authors" sono trattati senza distinzione tra maiuscole e minuscole"articles[].contributors" è opzionale"articles[].contributors" deve essere un array"articles[].contributors" devono essere stringhe non vuote¹"articles[].contributors" non devono avere duplicati"articles[].contributors" sono trattati senza distinzione tra maiuscole e minuscole"articles[].authors" o "articles[].contributors" (nessuna sovrapposizione)"articles[].slug" corrispondente nel file .articles/config.json
"articles[].slug" corrispondente nel file .articles/config.json
"[].url" è obbligatoria"[].url" deve essere un URL"[].description" è obbligatoria"[].description" deve essere una stringa non vuota¹"[].icon_url" è opzionale"[].icon_url" deve essere un URL"blurb" è obbligatoria"blurb" deve essere una stringa non vuota¹ con lunghezza <= 350"authors" è obbligatoria"authors" deve essere un array"authors" devono essere stringhe non vuote¹"authors" non devono avere duplicati"authors" sono trattati senza distinzione tra maiuscole e minuscole"contributors" è opzionale"contributors" deve essere un array"contributors" devono essere stringhe non vuote¹"contributors" non devono avere duplicati"contributors" sono trattati senza distinzione tra maiuscole e minuscole"authors" o "contributors" (nessuna sovrapposizione)Stringa non vuota: una stringa che contiene almeno un carattere diverso da uno spazio bianco.
Stringa in kebab-case: una stringa che contiene solo caratteri nell'intervallo [a-z0-9], facoltativamente separati da trattini (ad es. «two-fer»). Deve corrispondere all'espressione regolare: ^[a-z0-9]+(-[a-z0-9]+)*$
Stringa in Title Case: una stringa non vuota che segue le linee guida del Chicago Manual of Style riportate di seguito:
Stringa in Sentence Case: una stringa non vuota che segue le linee guida riportate di seguito:
Pattern files valido: una stringa non vuota¹ che specifica la posizione di un file usato in un esercizio, relativa alla directory dell'esercizio. Un pattern può usare uno dei seguenti segnaposto:
%{kebab_slug}: lo slug dell'esercizio in kebab-case (ad es. bit-manipulation)%{snake_slug}: lo slug dell'esercizio in snake_case (ad es. bit_manipulation)%{camel_slug}: lo slug dell'esercizio in camelCase (ad es. bitManipulation)%{pascal_slug}: lo slug dell'esercizio in PascalCase (ad es. BitManipulation)Stringa UUID versione 4 univoca: una stringa che soddisfa tutte queste condizioni:
config.json a livello di traccia di una data traccia di Exercismconfig.json a livello di traccia di nessun'altra traccia di Exercismcanonical-data.json in 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}$
Ad esempio, l'UUID riportato di seguito ha la forma corretta:
d334ffe3-657e-4725-a950-290b284b6d9f
Puoi eseguire configlet uuid per generare un UUID adatto.
tag dell'analyzer valido: una stringa non vuota¹ formattata come <category>:<thing>.
Il valore di <category> deve essere uno dei seguenti:
paradigm (ad es. paradigm:functional)technique (ad es. technique:recursion)construct (ad es. construct:bitwise-and)uses (ad es. uses:DateTime.add_seconds)Il valore di <thing> deve essere una stringa non vuota¹.