configlet lint


El uso principal de configlet es el linting: comprobar si los ficheros de configuración de un track están bien estructurados, tanto sintáctica como semánticamente. Los tracks mal configurados puede que no se sincronicen correctamente, que se vean mal en el sitio web o que ofrezcan una experiencia de usuario mejorable, así que las comprobaciones de configlet desempeñan un papel importante a la hora de mantener la integridad de Exercism.

Uso

El comando lint sirve para hacer linting de un track.

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]

Reglas

Estas son las reglas de linting que se comprueban.

Regla: los ficheros obligatorios están presentes

El linter debe comprobar que todos los ficheros obligatorios estén presentes. Los ficheros que no son específicos de un ejercicio y que deben estar presentes son:

  • config.json
  • docs/ABOUT.md
  • docs/INSTALLATION.md
  • docs/LEARNING.md
  • docs/RESOURCES.md
  • docs/SNIPPET.txt
  • docs/TESTS.md
  • exercises/shared/.docs/help.md
  • exercises/shared/.docs/tests.md

Los ficheros específicos de los ejercicios de concepto que deben estar presentes son:

  • exercises/concept/<slug>/.docs/hints.md
  • exercises/concept/<slug>/.docs/instructions.md
  • exercises/concept/<slug>/.docs/introduction.md
  • exercises/concept/<slug>/.meta/config.json

Habrá una lista similar para los ejercicios de práctica, pero todavía no hemos definido la especificación para ello.

Cada concepto listado en config.json debe tener los siguientes ficheros:

  • concepts/<slug>/about.md
  • concepts/<slug>/introduction.md
  • concepts/<slug>/links.json

Regla: el fichero config.json es válido

El fichero config.json debe cumplir las siguientes comprobaciones:

  • El fichero debe ser JSON válido
  • La clave "language" es obligatoria
  • El valor de "language" debe ser un string¹ no en blanco con longitud <= 255
  • La clave "slug" es obligatoria
  • El valor de "slug" debe ser un string² en kebab-case con longitud <= 255
  • La clave "active" es obligatoria
  • El valor de "active" debe ser un Boolean
  • La clave "blurb" es obligatoria
  • El valor de "blurb" debe ser un string¹ no en blanco con longitud <= 400
  • La clave "version" es obligatoria
  • El valor de "version" debe ser el entero 3
  • La clave "status.concept_exercises" es obligatoria
  • El valor de "status.concept_exercises" debe ser un Boolean
  • La clave "status.test_runner" es obligatoria
  • El valor de "status.test_runner" debe ser un Boolean
  • La clave "status.representer" es obligatoria
  • El valor de "status.representer" debe ser un Boolean
  • La clave "status.analyzer" es obligatoria
  • El valor de "status.analyzer" debe ser un Boolean
  • La clave "online_editor.indent_style" es obligatoria
  • El valor de "online_editor.indent_style" debe ser el string space o tab
  • La clave "online_editor.indent_size" es obligatoria
  • El valor de "online_editor.indent_size" debe ser un entero >= 0 y <= 8
  • La clave "online_editor.highlightjs_language" es opcional
  • El valor de "online_editor.highlightjs_language" debe ser un string¹ no en blanco
  • La clave "files" es opcional
  • El valor de "files" debe ser un objeto
  • La clave "files.solution" es opcional
  • El valor de "files.solution" debe ser un array
  • Los valores de "files.solution" deben ser patrones⁵ válidos
  • Los valores de "files.solution" no deben tener duplicados
  • La clave "files.test" es opcional
  • El valor de "files.test" debe ser un array
  • Los valores de "files.test" deben ser patrones⁵ válidos
  • Los valores de "files.test" no deben tener duplicados
  • La clave "files.example" es opcional
  • El valor de "files.example" debe ser un array
  • Los valores de "files.example" deben ser patrones⁵ válidos
  • Los valores de "files.example" no deben tener duplicados
  • La clave "files.exemplar" es opcional
  • El valor de "files.exemplar" debe ser un array
  • Los valores de "files.exemplar" deben ser patrones⁵ válidos
  • Los valores de "files.exemplar" no deben tener duplicados
  • La clave "files.editor" es opcional
  • El valor de "files.editor" debe ser un array
  • Los valores de "files.editor" deben ser patrones⁵ válidos
  • Los valores de "files.editor" no deben tener duplicados
  • La clave "files.invalidator" es opcional
  • El valor de "files.invalidator" debe ser un array
  • Los valores de "files.invalidator" deben ser patrones⁵ válidos
  • Los valores de "files.invalidator" no deben tener duplicados
  • Los patrones solo pueden aparecer en uno de los arrays "files.solution", "files.test", "files.example", "files.exemplar", "files.editor" o "files.invalidator" (sin solapamiento)
    • Si el track es d o plsql, los ficheros de "files.solution" y "files.test" sí pueden solaparse
    • Los ficheros de "files.example y "files.exemplar" sí pueden solaparse
  • La clave "test_runner.average_run_time" es obligatoria si "status.test_runner" es igual a true
  • El valor de "test_runner.average_run_time" debe ser un entero > 0
  • La clave "approaches.snippet_extension" es obligatoria si el track tiene uno o más enfoques
  • El valor de "approaches.snippet_extension" debe ser un string¹ no en blanco
  • La clave "exercises" es obligatoria
  • La clave "exercises.concept" es obligatoria
  • El valor de "exercises.concept" debe ser un array
  • La clave "exercises.concept[].slug" es obligatoria
  • El valor de "exercises.concept[].slug" debe ser un string² en kebab-case con longitud <= 255
  • El valor de "exercises.concept[].slug" debe ser único en "exercises.concept[].slug" y no puede existir en "exercises.practice[].slug"
  • La clave "exercises.concept[].name" es obligatoria
  • El valor de "exercises.concept[].name" debe ser un string³ en Title Case con longitud <= 255
  • La clave "exercises.concept[].uuid" es obligatoria
  • El valor de "exercises.concept[].uuid" debe ser un string⁶ de UUID versión 4 único
  • El valor de "exercises.concept[].uuid" de cada ejercicio no debe cambiar nunca
  • La clave "exercises.concept[].concepts" es obligatoria
  • El valor de "exercises.concept[].concepts" debe ser un array no vacío de strings si "exercises.concept[].status" no es igual a deprecated
  • El valor de "exercises.concept[].concepts" debe ser un array vacío si "exercises.concept[].status" es igual a deprecated
  • Los valores de "exercises.concept[].concepts" deben ser strings² en kebab-case
  • Los valores de "exercises.concept[].concepts" no deben tener duplicados
  • Los valores de "exercises.concept[].concepts" no deben estar en la propiedad "concepts" de ningún otro ejercicio de concepto
  • Los valores de "exercises.concept[].concepts" deben coincidir con la propiedad "concepts.slug" de uno de los conceptos
  • La clave "exercises.concept[].prerequisites" es obligatoria
  • El valor de "exercises.concept[].prerequisites" debe ser un array no vacío de strings si "exercises.concept[].status" no es igual a deprecated, excepto exactamente un ejercicio al que sí se le permite tener un array vacío como valor
  • El valor de "exercises.concept[].prerequisites" debe ser un array vacío si "exercises.concept[].status" es igual a deprecated
  • Los valores de "exercises.concept[].prerequisites" deben ser strings² en kebab-case
  • Los valores de "exercises.concept[].prerequisites" no deben tener duplicados
  • Los valores de "exercises.concept[].prerequisites" deben coincidir con los valores de la propiedad "concepts" de algún otro ejercicio de concepto
  • Los valores de "exercises.concept[].prerequisites" no deben coincidir con ninguno de los valores de la propiedad "exercises.concept[].concepts" del ejercicio
  • Los valores de "exercises.concept[].prerequisites" deben coincidir con la propiedad "concepts.slug" de uno de los conceptos
  • No debe haber ningún ciclo entre "exercises.concept[].concepts" y "exercises.concept[].prerequisites"
  • La clave "exercises.concept[].status" es opcional
  • El valor de "exercises.concept[].status" debe ser el string wip, beta, active o deprecated
  • La clave "exercises.practice" es obligatoria
  • El valor de "exercises.practice" debe ser un array
  • La clave "exercises.practice[].slug" es obligatoria
  • El valor de "exercises.practice[].slug" debe ser un string² en kebab-case con longitud <= 255
  • El valor de "exercises.practice[].slug" debe ser único en "exercises.practice[].slug" y no puede existir en "exercises.concept[].slug"
  • Debe haber exactamente un valor de "exercises.practice[].slug" que sea el string hello-world
  • La clave "exercises.practice[].name" es obligatoria
  • El valor de "exercises.practice[].name" debe ser un string³ en Title Case con longitud <= 255
  • La clave "exercises.practice[].uuid" es obligatoria
  • El valor de "exercises.practice[].uuid" debe ser un string⁶ de UUID versión 4 único
  • El valor de "exercises.practice[].uuid" de cada ejercicio no debe cambiar nunca
  • La clave "exercises.practice[].difficulty" es obligatoria
  • El valor de "exercises.practice[].difficulty" debe ser un entero >= 1 y <= 10
  • La clave "exercises.practice[].practices" es obligatoria
  • El valor de "exercises.practice[].practices" debe ser un array no vacío de strings si "exercises.practice[].status" no es igual a deprecated
  • El valor de "exercises.practice[].practices" debe ser un array vacío si "exercises.practice[].status" es igual a deprecated
  • Los valores de "exercises.practice[].practices" deben ser strings² en kebab-case
  • Los valores de "exercises.practice[].practices" no deben tener duplicados
  • Los valores de "exercises.practice[].practices" deben coincidir con la propiedad "concepts[].slug" de uno de los conceptos
  • Los valores de "exercises.practice[].practices" deben referirse al slug de un concepto concreto como máximo 10 veces (en todos los ejercicios)
  • La clave "exercises.practice[].prerequisites" es obligatoria
  • El valor de "exercises.practice[].prerequisites" debe ser un array no vacío de strings si "exercises.practice[].status" no es igual a deprecated
  • El valor de "exercises.practice[].prerequisites" debe ser un array vacío si "exercises.practice[].status" es igual a deprecated
  • El valor de "exercises.practice[].prerequisites" debe ser un array vacío si "exercises.practice[].slug" es igual a hello-world
  • Los valores de "exercises.practice[].prerequisites" deben ser strings² en kebab-case
  • Los valores de "exercises.practice[].prerequisites" no deben tener duplicados
  • Los valores de "exercises.practice[].prerequisites" deben coincidir con los valores de "exercises.concept[].concepts" de algún ejercicio de concepto
  • Los valores de "exercises.practice[].prerequisites" deben coincidir con la propiedad "concepts[].slug" de uno de los conceptos
  • La clave "exercises.practice[].status" es opcional
  • El valor de "exercises.practice[].status" debe ser el string wip, beta, active o deprecated
  • El valor de "exercises.practice[].status" debe, si "exercises.practice[].slug" es igual a hello-world, omitirse o ser el string active
  • La clave "exercises.foregone" es opcional
  • El valor de "exercises.foregone" debe ser un array
  • Los valores de "exercises.foregone" deben ser strings² en kebab-case
  • Los valores de "exercises.foregone" no deben tener duplicados
  • Los valores de "exercises.foregone" no deben coincidir con ninguno de los slugs de los ejercicios de concepto o de práctica
  • La clave "concepts" es obligatoria
  • El valor de "concepts" debe ser un array
  • La clave "concepts[].uuid" es obligatoria
  • El valor de "concepts[].uuid" debe ser un string⁶ de UUID versión 4 único
  • El valor de "concepts[].uuid" de cada concepto no debe cambiar nunca
  • La clave "concepts[].slug" es obligatoria
  • El valor de "concepts[].slug" debe ser un string² en kebab-case con longitud <= 255
  • La clave "concepts[].name" es obligatoria
  • El valor de "concepts[].name" debe ser un string³ en Title Case con longitud <= 255
  • La clave "concepts[].tags" es opcional
  • La clave "concepts[].tags.all" es opcional, a menos que "concepts[].tags.any" esté vacío
  • El valor de "concepts[].tags.all" debe ser un array
  • Los valores de "concepts[].tags.all" deben ser strings⁷ de etiqueta no en blanco con longitud <= 255
  • Los valores de "concepts[].tags.all" no deben tener duplicados
  • La clave "concepts[].tags.any" es opcional, a menos que "concepts[].tags.all" esté vacío
  • El valor de "concepts[].tags.any" debe ser un array
  • Los valores de "concepts[].tags.any" deben ser strings⁷ de etiqueta no en blanco con longitud <= 255
  • Los valores de "concepts[].tags.any" no deben tener duplicados
  • La clave "concepts[].tags.not" es opcional
  • El valor de "concepts[].tags.not" debe ser un array
  • Los valores de "concepts[].tags.not" deben ser strings⁷ de etiqueta no en blanco con longitud <= 255
  • Los valores de "concepts[].tags.not" no deben tener duplicados
  • Cada valor de "concepts" debe tener un fichero concept/<concepts.slug>/about.md. Las reglas de linting para este fichero se especifican a continuación.
  • Cada valor de "concepts" debe tener un fichero concept/<concepts.slug>/introduction.md. Las reglas de linting para este fichero se especifican a continuación.
  • Cada valor de "concepts" debe tener un fichero concept/<concepts.slug>/links.json. Las reglas de linting para este fichero se especifican a continuación.
  • La clave "key_features" es opcional
  • El valor de "key_features" debe ser un array con longitud = 6
  • La clave "key_features[].icon" es obligatoria
  • El valor de "key_features[].icon" debe usar uno de los valores de icono predefinidos
  • La clave "key_features[].title" es obligatoria
  • El valor de "key_features[].title" debe ser un string⁴ en Sentence Case con longitud <= 25
  • La clave "key_features[].content" es obligatoria
  • El valor de "key_features[].content" debe ser un string¹ no en blanco con longitud <= 100
  • La clave "tags" es obligatoria
  • El valor de "tags" debe ser un array de strings
  • Los valores de "tags" no deben tener duplicados
  • Los valores de "tags" deben usar uno de los valores de etiqueta predefinidos

Regla: exercises/concept/<slug>/.meta/config.json es válido

  • El fichero debe ser JSON válido
  • La raíz del JSON debe ser un objeto
  • La clave "blurb" es obligatoria
  • El valor de "blurb" debe ser un string¹ no en blanco con longitud <= 350
  • La clave "source" es opcional
  • El valor de "source" debe ser un string¹ no en blanco
  • La clave "source_url" es opcional
  • El valor de "source_url" debe ser una URL
  • La clave "authors" es obligatoria
  • El valor de "authors" debe ser un array no vacío
  • Los valores de "authors" deben ser strings¹ no en blanco
  • Los valores de "authors" no deben tener duplicados
  • Los valores de "authors" se tratan sin distinguir mayúsculas de minúsculas
  • La clave "contributors" es opcional
  • El valor de "contributors" debe ser un array
  • Los valores de "contributors" deben ser strings¹ no en blanco
  • Los valores de "contributors" no deben tener duplicados
  • Los valores de "contributors" se tratan sin distinguir mayúsculas de minúsculas
  • Los usuarios solo pueden aparecer en uno de los arrays "authors" o "contributors" (sin solapamiento)
  • La clave "files.solution" es obligatoria
  • El valor de "files.solution" debe ser un array no vacío
  • Los valores de "files.solution" no deben tener duplicados
  • La clave "files.test" es obligatoria
  • El valor de "files.test" debe ser un array no vacío
  • Los valores de "files.test" no deben tener duplicados
  • La clave "files.exemplar" es obligatoria
  • El valor de "files.exemplar" debe ser un array no vacío
  • Los valores de "files.exemplar" no deben tener duplicados
  • La clave "files.editor" es opcional
  • El valor de "files.editor" debe ser un array
  • Los valores de "files.editor" no deben tener duplicados
  • La clave "files.invalidator" es opcional
  • El valor de "files.invalidator" debe ser un array
  • Los valores de "files.invalidator" no deben tener duplicados
  • Los ficheros listados en "files.solution" deben existir
  • Los ficheros listados en "files.test" deben existir
  • Los ficheros listados en "files.exemplar" deben existir
  • Los ficheros listados en "files.editor" deben existir
  • Los ficheros listados en "files.invalidator" deben existir
  • Los ficheros solo pueden aparecer en uno de los arrays "files.solution", "files.test", "files.exemplar" o "files.invalidator" (sin solapamiento)
    • Si el track es d o plsql, los ficheros de "files.solution" y "files.test" sí pueden solaparse
  • La clave "forked_from" es opcional
  • El valor de "forked_from" debe ser un array
  • Los valores de "forked_from" deben ser strings con el formato <track-slug>/<exercise-slug> (p. ej. fsharp/bird-watcher)
  • Los valores de "forked_from" deben referirse a ejercicios realmente implementados
  • Los valores de "forked_from" no deben tener duplicados
  • La clave "language_versions" es opcional
  • El valor de "language_versions" debe ser un string
  • La clave "representer.version" es opcional
  • El valor de "representer.version" debe ser un entero >= 1
  • La clave "icon" es opcional
  • El valor de "icon" debe ser un string² en kebab-case

Regla: exercises/concept/<slug>/.docs/hints.md es válido

  • El Markdown debe cumplir los estándares de Markdown
  • Todos los encabezados deben ser ## General o ## X. <task>, donde X coincida con el encabezado del número de tarea en instructions.md
  • Todas las pistas deben especificarse como elementos de lista de Markdown
  • Los enlaces deben ser absolutos (no se permiten enlaces relativos)

Regla: exercises/concept/<slug>/.docs/instructions.md es válido

  • El Markdown debe cumplir los estándares de Markdown
  • Todas las tareas deben empezar con un encabezado de nivel dos que empiece por un número seguido de un punto: ## 1. Do X
  • Los enlaces deben ser absolutos (no se permiten enlaces relativos)

Regla: exercises/concept/<slug>/.docs/instructions.md.tpl es válido (si está presente)

Regla: exercises/concept/<slug>/.docs/introduction.md es válido

  • El Markdown debe cumplir los estándares de Markdown
  • Los enlaces deben ser absolutos (no se permiten enlaces relativos)

Regla: exercises/practice/<slug>/.meta/config.json es válido

  • El fichero debe ser JSON válido
  • La raíz del JSON debe ser un objeto
  • La clave "blurb" es obligatoria
  • El valor de "blurb" debe ser un string¹ no en blanco con longitud <= 350
  • La clave "source" es opcional
  • El valor de "source" debe ser un string¹ no en blanco
  • La clave "source_url" es opcional
  • El valor de "source_url" debe ser una URL
  • La clave "authors" es opcional
  • El valor de "authors" debe ser un array
  • Los valores de "authors" deben ser strings¹ no en blanco
  • Los valores de "authors" no deben tener duplicados
  • Los valores de "authors" se tratan sin distinguir mayúsculas de minúsculas
  • La clave "contributors" es opcional
  • El valor de "contributors" debe ser un array
  • Los valores de "contributors" deben ser strings¹ no en blanco
  • Los valores de "contributors" no deben tener duplicados
  • Los valores de "contributors" se tratan sin distinguir mayúsculas de minúsculas
  • Los usuarios solo pueden aparecer en uno de los arrays "authors" o "contributors" (sin solapamiento)
  • La clave "files.solution" es obligatoria
  • El valor de "files.solution" debe ser un array no vacío
  • Los valores de "files.solution" no deben tener duplicados
  • La clave "files.test" es obligatoria
  • El valor de "files.test" debe ser un array no vacío
  • Los valores de "files.test" no deben tener duplicados
  • La clave "files.example" es obligatoria
  • El valor de "files.example" debe ser un array no vacío
  • Los valores de "files.example" no deben tener duplicados
  • La clave "files.editor" es opcional
  • El valor de "files.editor" debe ser un array
  • Los valores de "files.editor" no deben tener duplicados
  • La clave "files.invalidator" es opcional
  • El valor de "files.invalidator" debe ser un array
  • Los valores de "files.invalidator" no deben tener duplicados
  • Los ficheros listados en "files.solution" deben existir
  • Los ficheros listados en "files.test" deben existir
  • Los ficheros listados en "files.example" deben existir
  • Los ficheros listados en "files.editor" deben existir
  • Los ficheros listados en "files.invalidator" deben existir
  • Los ficheros solo pueden aparecer en uno de los arrays "files.solution", "files.test", "files.example o "files.invalidator" (sin solapamiento)
    • Si el track es d o plsql, los ficheros de "files.solution" y "files.test" sí pueden solaparse
  • La clave "language_versions" es opcional
  • El valor de "language_versions" debe ser un string
  • La clave "test_runner" es opcional
  • El valor de "test_runner" debe ser un Boolean
  • La clave "representer.version" es opcional
  • El valor de "representer.version" debe ser un entero >= 1
  • La clave "icon" es opcional
  • El valor de "icon" debe ser un string² en kebab-case

Regla: exercises/{concept|practice}/<slug>/.approaches/config.json es válido

  • La presencia del fichero es opcional, a menos que exista un introduction.md o un directorio hermano
  • El fichero debe ser JSON válido
  • La raíz del JSON debe ser un objeto
  • La clave "introduction.authors" es opcional
  • El valor de "introduction.authors" debe ser un array
  • Los valores de "introduction.authors" deben ser strings¹ no en blanco
  • Los valores de "introduction.authors" no deben tener duplicados
  • Los valores de "introduction.authors" se tratan sin distinguir mayúsculas de minúsculas
  • Si el array "introduction.authors" no está vacío, debe haber un fichero introduction.md no vacío
  • La clave "introduction.contributors" es opcional
  • El valor de "introduction.contributors" debe ser un array
  • Los valores de "introduction.contributors" deben ser strings¹ no en blanco
  • Los valores de "introduction.contributors" no deben tener duplicados
  • Los valores de "introduction.contributors" se tratan sin distinguir mayúsculas de minúsculas
  • Si el array "introduction.contributors" no está vacío, debe haber un fichero introduction.md no vacío
  • Los usuarios solo pueden aparecer en uno de los arrays "introduction.authors" o "introduction.contributors" (sin solapamiento)
  • La clave "approaches" es opcional, a menos que haya un directorio hermano presente (que contiene los ficheros del enfoque)
  • El valor de "approaches" debe ser un array de objetos
  • La clave "approaches[].uuid" es obligatoria
  • El valor de "approaches[].uuid" debe ser un string⁶ de UUID versión 4 único
  • El valor de "approaches[].uuid" de cada concepto no debe cambiar nunca
  • La clave "approaches[].slug" es obligatoria
  • El valor de "approaches[].slug" debe ser un string² en kebab-case con longitud <= 255
  • El valor de "approaches[].slug" debe tener un fichero <slug>/content.md no vacío correspondiente
  • El valor de "approaches[].slug" debe tener un fichero <slug>/snippet.txt no vacío correspondiente
  • La clave "approaches[].title" es obligatoria
  • El valor de "approaches[].title" debe ser un string³ en Title Case con longitud <= 255
  • La clave "approaches[].blurb" es obligatoria
  • El valor de "approaches[].blurb" debe ser un string¹ no en blanco con longitud <= 350
  • La clave "approaches[].authors" es obligatoria
  • El valor de "approaches[].authors" debe ser un array no vacío
  • Los valores de "approaches[].authors" deben ser strings¹ no en blanco
  • Los valores de "approaches[].authors" no deben tener duplicados
  • Los valores de "approaches[].authors" se tratan sin distinguir mayúsculas de minúsculas
  • La clave "approaches[].contributors" es opcional
  • El valor de "approaches[].contributors" debe ser un array
  • Los valores de "approaches[].contributors" deben ser strings¹ no en blanco
  • Los valores de "approaches[].contributors" no deben tener duplicados
  • Los valores de "approaches[].contributors" se tratan sin distinguir mayúsculas de minúsculas
  • Los usuarios solo pueden aparecer en uno de los arrays "approaches[].authors" o "approaches[].contributors" (sin solapamiento)
  • La clave "approaches[].tags" es opcional
  • La clave "approaches[].tags.all" es opcional, a menos que "approaches[].tags.any" esté vacío
  • El valor de "approaches[].tags.all" debe ser un array
  • Los valores de "approaches[].tags.all" deben ser strings⁷ de etiqueta no en blanco con longitud <= 255
  • Los valores de "approaches[].tags.all" no deben tener duplicados
  • La clave "approaches[].tags.any" es opcional, a menos que "approaches[].tags.all" esté vacío
  • El valor de "approaches[].tags.any" debe ser un array
  • Los valores de "approaches[].tags.any" deben ser strings⁷ de etiqueta no en blanco con longitud <= 255
  • Los valores de "approaches[].tags.any" no deben tener duplicados
  • La clave "approaches[].tags.not" es opcional
  • El valor de "approaches[].tags.not" debe ser un array
  • Los valores de "approaches[].tags.not" deben ser strings⁷ de etiqueta no en blanco con longitud <= 255
  • Los valores de "approaches[].tags.not" no deben tener duplicados

Regla: exercises/{concept|practice}/<slug>/.approaches/<approach-slug>/content.md es válido

  • La presencia del fichero es obligatoria si existe una entrada "approaches[].slug" correspondiente en el fichero .approaches/config.json
  • El Markdown debe cumplir los estándares de Markdown
  • Los enlaces deben ser absolutos (no se permiten enlaces relativos)

Regla: exercises/{concept|practice}/<slug>/.approaches/<approach-slug>/snippet.<snippet-extension> es válido

  • La presencia del fichero es obligatoria si existe una entrada "approaches[].slug" correspondiente en el fichero .approaches/config.json
  • El snippet debe tener como máximo 8 líneas
  • La extensión del snippet se toma del valor approaches.snippet_extension del fichero config.json del track

Regla: exercises/{concept|practice}/<slug>/.articles/config.json es válido

  • La presencia del fichero es opcional, a menos que haya un directorio hermano
  • El fichero debe ser JSON válido
  • La raíz del JSON debe ser un objeto
  • La clave "articles" es opcional, a menos que haya un directorio hermano presente (que contiene los ficheros del artículo)
  • El valor de "articles" debe ser un array de objetos
  • La clave "articles[].uuid" es obligatoria
  • El valor de "articles[].uuid" debe ser un string⁶ de UUID versión 4 único
  • El valor de "articles[].uuid" de cada concepto no debe cambiar nunca
  • La clave "articles[].slug" es obligatoria
  • El valor de "articles[].slug" debe ser un string² en kebab-case con longitud <= 255
  • El valor de "articles[].slug" debe tener un fichero <slug>/content.md no vacío correspondiente
  • El valor de "articles[].slug" debe tener un fichero <slug>/snippet.md no vacío correspondiente
  • La clave "articles[].title" es obligatoria
  • El valor de "articles[].title" debe ser un string³ en Title Case con longitud <= 255
  • La clave "articles[].blurb" es obligatoria
  • El valor de "articles[].blurb" debe ser un string¹ no en blanco con longitud <= 350
  • La clave "articles[].authors" es obligatoria
  • El valor de "articles[].authors" debe ser un array no vacío
  • Los valores de "articles[].authors" deben ser strings¹ no en blanco
  • Los valores de "articles[].authors" no deben tener duplicados
  • Los valores de "articles[].authors" se tratan sin distinguir mayúsculas de minúsculas
  • La clave "articles[].contributors" es opcional
  • El valor de "articles[].contributors" debe ser un array
  • Los valores de "articles[].contributors" deben ser strings¹ no en blanco
  • Los valores de "articles[].contributors" no deben tener duplicados
  • Los valores de "articles[].contributors" se tratan sin distinguir mayúsculas de minúsculas
  • Los usuarios solo pueden aparecer en uno de los arrays "articles[].authors" o "articles[].contributors" (sin solapamiento)

Regla: exercises/{concept|practice}/<slug>/.articles/<article-slug>/content.md es válido

  • La presencia del fichero es obligatoria si existe una entrada "articles[].slug" correspondiente en el fichero .articles/config.json
  • El Markdown debe cumplir los estándares de Markdown
  • Los enlaces deben ser absolutos (no se permiten enlaces relativos)

Regla: exercises/{concept|practice}/<slug>/.articles/<article-slug>/snippet.md es válido

  • La presencia del fichero es obligatoria si existe una entrada "articles[].slug" correspondiente en el fichero .articles/config.json
  • El Markdown debe cumplir los estándares de Markdown
  • El snippet debe tener como máximo 8 líneas (se ignoran los marcadores de bloque de código inicial y final)

Regla: exercises/shared/.docs/debug.md es válido

  • La presencia del fichero es opcional
  • El Markdown debe cumplir los estándares de Markdown
  • Los enlaces deben ser absolutos (no se permiten enlaces relativos)

Regla: exercises/shared/.docs/help.md es válido

  • La presencia del fichero es obligatoria
  • El Markdown debe cumplir los estándares de Markdown
  • Los enlaces deben ser absolutos (no se permiten enlaces relativos)

Regla: exercises/shared/.docs/tests.md es válido

  • La presencia del fichero es obligatoria
  • El Markdown debe cumplir los estándares de Markdown
  • Los enlaces deben ser absolutos (no se permiten enlaces relativos)

Regla: concepts/<slug>/about.md es válido

  • El Markdown debe cumplir los estándares de Markdown
  • Los enlaces deben ser absolutos (no se permiten enlaces relativos)

Regla: concepts/<slug>/introduction.md es válido

  • El Markdown debe cumplir los estándares de Markdown
  • Los enlaces deben ser absolutos (no se permiten enlaces relativos)
  • El fichero debe ser JSON válido
  • La raíz del JSON debe ser un array
  • La propiedad "[].url" es obligatoria
  • El valor de "[].url" debe ser una URL
  • La propiedad "[].description" es obligatoria
  • El valor de "[].description" debe ser un string¹ no en blanco
  • La propiedad "[].icon_url" es opcional
  • El valor de "[].icon_url" debe ser una URL

Regla: concept/<slug>/.meta/config.json es válido

  • El fichero debe ser JSON válido
  • La raíz del JSON debe ser un objeto
  • La clave "blurb" es obligatoria
  • El valor de "blurb" debe ser un string¹ no en blanco con longitud <= 350
  • La clave "authors" es obligatoria
  • El valor de "authors" debe ser un array
  • Los valores de "authors" deben ser strings¹ no en blanco
  • Los valores de "authors" no deben tener duplicados
  • Los valores de "authors" se tratan sin distinguir mayúsculas de minúsculas
  • La clave "contributors" es opcional
  • El valor de "contributors" debe ser un array
  • Los valores de "contributors" deben ser strings¹ no en blanco
  • Los valores de "contributors" no deben tener duplicados
  • Los valores de "contributors" se tratan sin distinguir mayúsculas de minúsculas
  • Los usuarios solo pueden aparecer en uno de los arrays "authors" o "contributors" (sin solapamiento)

Regla: docs/ABOUT.md es válido

  • La presencia del fichero es obligatoria
  • El contenido del fichero no debe estar en blanco
  • El Markdown debe cumplir los estándares de Markdown
  • Los enlaces deben ser absolutos (no se permiten enlaces relativos)

Regla: docs/INSTALLATION.md es válido

  • La presencia del fichero es obligatoria
  • El contenido del fichero no debe estar en blanco
  • El Markdown debe cumplir los estándares de Markdown
  • Los enlaces deben ser absolutos (no se permiten enlaces relativos)

Regla: docs/LEARNING.md es válido

  • La presencia del fichero es obligatoria
  • El contenido del fichero no debe estar en blanco
  • El Markdown debe cumplir los estándares de Markdown
  • Los enlaces deben ser absolutos (no se permiten enlaces relativos)

Regla: docs/RESOURCES.md es válido

  • La presencia del fichero es obligatoria
  • El contenido del fichero no debe estar en blanco
  • El Markdown debe cumplir los estándares de Markdown
  • Los enlaces deben ser absolutos (no se permiten enlaces relativos)

Regla: docs/SNIPPET.txt es válido

  • La presencia del fichero es obligatoria
  • El contenido del fichero no debe estar en blanco

Regla: docs/TESTS.md es válido

  • La presencia del fichero es obligatoria
  • El contenido del fichero no debe estar en blanco
  • El Markdown debe cumplir los estándares de Markdown
  • Los enlaces deben ser absolutos (no se permiten enlaces relativos)

Glosario

  1. String no en blanco: un string que contiene al menos un carácter que no sea un espacio en blanco.

  2. String en kebab-case: un string que solo contiene caracteres del rango [a-z0-9], opcionalmente separados por guiones (p. ej. «two-fer»). Debe coincidir con la expresión regular: ^[a-z0-9]+(-[a-z0-9]+)*$

  3. String en Title Case: un string no en blanco que sigue las siguientes pautas del Chicago Manual of Style:

    • Escribe en mayúscula la primera y la última palabra de títulos y subtítulos.
    • Escribe en mayúscula las palabras «importantes» (sustantivos, pronombres, verbos, adjetivos, adverbios y algunas conjunciones).
    • Escribe en minúscula las conjunciones and, but, for, or y nor.
    • Escribe en minúscula los artículos the, a y an.
    • Escribe en minúscula las preposiciones, independientemente de su longitud, salvo cuando vayan acentuadas, se usen como adverbios o adjetivos, o se usen como conjunciones.
    • Escribe en minúscula las palabras to y as.
    • Escribe en minúscula la segunda parte de los nombres de especies en latín.
  4. String en Sentence Case: un string no en blanco que sigue las siguientes pautas:

    • Escribe en mayúscula la primera palabra de la frase, así como los nombres propios y otras palabras según lo exija una regla más específica.
  5. Patrón de files válido: Un string¹ no en blanco que especifica la ubicación de un fichero usado en un ejercicio, relativa al directorio del ejercicio. Un patrón puede usar uno de los siguientes marcadores de posición:

    • %{kebab_slug}: el slug del ejercicio en kebab-case (p. ej. bit-manipulation)
    • %{snake_slug}: el slug del ejercicio en snake_case (p. ej. bit_manipulation)
    • %{camel_slug}: el slug del ejercicio en camelCase (p. ej. bitManipulation)
    • %{pascal_slug}: el slug del ejercicio en PascalCase (p. ej. BitManipulation)
  6. String de UUID versión 4 único: Un string que cumple todas estas condiciones:

    • Solo existe una vez en el fichero config.json a nivel de track de un track de Exercism dado
    • No existe en el fichero config.json a nivel de track de ningún otro track de Exercism
    • No existe en ningún fichero canonical-data.json de https://github.com/exercism/problem-specifications
    • No existe en ningún otro lugar de Exercism
    • Coincide con la expresión regular:
    ^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$
    

    Por ejemplo, el siguiente UUID tiene la forma correcta:

    d334ffe3-657e-4725-a950-290b284b6d9f
    

    Puedes ejecutar configlet uuid para generar un UUID adecuado.

  7. tag de analyzer válido: Un string¹ no en blanco con el formato <category>:<thing>. El valor de <category> debe ser uno de:

  • paradigm (p. ej. paradigm:functional)
  • technique (p. ej. technique:recursion)
  • construct (p. ej. construct:bitwise-and)
  • uses (p. ej. uses:DateTime.add_seconds)

El valor de <thing> debe ser un string¹ no en blanco.