configlet lint


configlet의 주된 용도는 린트예요. 트랙의 설정 파일이 구문적으로나 의미적으로 올바르게 구성되어 있는지 확인하는 거죠. 설정이 잘못된 트랙은 제대로 동기화되지 않을 수 있고, 웹사이트에서 이상하게 보일 수 있으며, 사용자 경험이 좋지 않을 수도 있어요. 그래서 configlet의 검사는 Exercism의 무결성을 유지하는 데 중요한 역할을 해요.

사용법

lint 명령으로 트랙을 린트할 수 있어요.

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]

규칙

다음은 검사하는 린트 규칙이에요.

규칙: 필수 파일이 있는지 확인

린터는 필수 파일이 모두 있는지 확인해야 해요. 연습 문제와 무관하게 반드시 있어야 하는 파일은 다음과 같아요:

  • 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

개념 연습 문제에만 해당하며 반드시 있어야 하는 파일은 다음과 같아요:

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

실습 연습 문제에도 비슷한 목록이 있을 예정이지만, 아직 그 명세는 정의하지 않았어요.

config.json에 나열된 각 개념에는 다음 파일이 있어야 해요:

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

규칙: config.json 파일이 유효한지 확인

config.json 파일은 다음 사항을 검사해야 해요:

  • 파일은 유효한 JSON이어야 해요
  • "language" 키는 필수예요
  • "language" 값은 길이가 255 이하인 비어 있지 않은 문자열¹이어야 해요
  • "slug" 키는 필수예요
  • "slug" 값은 길이가 255 이하인 kebab-case 문자열²이어야 해요
  • "active" 키는 필수예요
  • "active" 값은 불리언이어야 해요
  • "blurb" 키는 필수예요
  • "blurb" 값은 길이가 400 이하인 비어 있지 않은 문자열¹이어야 해요
  • "version" 키는 필수예요
  • "version" 값은 정수 3이어야 해요
  • "status.concept_exercises" 키는 필수예요
  • "status.concept_exercises" 값은 불리언이어야 해요
  • "status.test_runner" 키는 필수예요
  • "status.test_runner" 값은 불리언이어야 해요
  • "status.representer" 키는 필수예요
  • "status.representer" 값은 불리언이어야 해요
  • "status.analyzer" 키는 필수예요
  • "status.analyzer" 값은 불리언이어야 해요
  • "online_editor.indent_style" 키는 필수예요
  • "online_editor.indent_style" 값은 문자열 space 또는 tab이어야 해요
  • "online_editor.indent_size" 키는 필수예요
  • "online_editor.indent_size" 값은 0 이상 8 이하의 정수여야 해요
  • "online_editor.highlightjs_language" 키는 선택 사항이에요
  • "online_editor.highlightjs_language" 값은 비어 있지 않은 문자열¹이어야 해요
  • "files" 키는 선택 사항이에요
  • "files" 값은 객체여야 해요
  • "files.solution" 키는 선택 사항이에요
  • "files.solution" 값은 배열이어야 해요
  • "files.solution" 값은 유효한 패턴⁵이어야 해요
  • "files.solution" 값에 중복이 없어야 해요
  • "files.test" 키는 선택 사항이에요
  • "files.test" 값은 배열이어야 해요
  • "files.test" 값은 유효한 패턴⁵이어야 해요
  • "files.test" 값에 중복이 없어야 해요
  • "files.example" 키는 선택 사항이에요
  • "files.example" 값은 배열이어야 해요
  • "files.example" 값은 유효한 패턴⁵이어야 해요
  • "files.example" 값에 중복이 없어야 해요
  • "files.exemplar" 키는 선택 사항이에요
  • "files.exemplar" 값은 배열이어야 해요
  • "files.exemplar" 값은 유효한 패턴⁵이어야 해요
  • "files.exemplar" 값에 중복이 없어야 해요
  • "files.editor" 키는 선택 사항이에요
  • "files.editor" 값은 배열이어야 해요
  • "files.editor" 값은 유효한 패턴⁵이어야 해요
  • "files.editor" 값에 중복이 없어야 해요
  • "files.invalidator" 키는 선택 사항이에요
  • "files.invalidator" 값은 배열이어야 해요
  • "files.invalidator" 값은 유효한 패턴⁵이어야 해요
  • "files.invalidator" 값에 중복이 없어야 해요
  • 패턴은 "files.solution", "files.test", "files.example", "files.exemplar", "files.editor", "files.invalidator" 배열 중 한 곳에만 나열할 수 있어요 (중복 불가)
    • 트랙이 d 또는 plsql이면 "files.solution"과 "files.test" 파일은 겹칠 수 있어요
    • "files.example과 "files.exemplar" 파일은 겹칠 수 있어요
  • "test_runner.average_run_time" 키는 "status.test_runner"가 true이면 필수예요
  • "test_runner.average_run_time" 값은 0보다 큰 정수여야 해요
  • "approaches.snippet_extension" 키는 트랙에 접근법이 하나 이상 있으면 필수예요
  • "approaches.snippet_extension" 값은 비어 있지 않은 문자열¹이어야 해요
  • "exercises" 키는 필수예요
  • "exercises.concept" 키는 필수예요
  • "exercises.concept" 값은 배열이어야 해요
  • "exercises.concept[].slug" 키는 필수예요
  • "exercises.concept[].slug" 값은 길이가 255 이하인 kebab-case 문자열²이어야 해요
  • "exercises.concept[].slug" 값은 "exercises.concept[].slug"에서 고유해야 하며 "exercises.practice[].slug"에는 존재해서는 안 돼요
  • "exercises.concept[].name" 키는 필수예요
  • "exercises.concept[].name" 값은 길이가 255 이하인 Title Case 문자열³이어야 해요
  • "exercises.concept[].uuid" 키는 필수예요
  • "exercises.concept[].uuid" 값은 고유한 버전 4 UUID 문자열⁶이어야 해요
  • 각 연습 문제의 "exercises.concept[].uuid" 값은 절대 바뀌어서는 안 돼요
  • "exercises.concept[].concepts" 키는 필수예요
  • "exercises.concept[].concepts" 값은 "exercises.concept[].status"가 deprecated가 아니면 비어 있지 않은 문자열 배열이어야 해요
  • "exercises.concept[].concepts" 값은 "exercises.concept[].status"가 deprecated이면 빈 배열이어야 해요
  • "exercises.concept[].concepts" 값은 kebab-case 문자열²이어야 해요
  • "exercises.concept[].concepts" 값에 중복이 없어야 해요
  • "exercises.concept[].concepts" 값은 다른 어떤 개념 연습 문제의 "concepts" 속성에도 있어서는 안 돼요
  • "exercises.concept[].concepts" 값은 개념 중 하나의 "concepts.slug" 속성과 일치해야 해요
  • "exercises.concept[].prerequisites" 키는 필수예요
  • "exercises.concept[].prerequisites" 값은 "exercises.concept[].status"가 deprecated가 아니면 비어 있지 않은 문자열 배열이어야 해요. 단, 값으로 빈 배열을 가지는 것이 _허용_되는 연습 문제가 정확히 하나 있어요
  • "exercises.concept[].prerequisites" 값은 "exercises.concept[].status"가 deprecated이면 빈 배열이어야 해요
  • "exercises.concept[].prerequisites" 값은 kebab-case 문자열²이어야 해요
  • "exercises.concept[].prerequisites" 값에 중복이 없어야 해요
  • "exercises.concept[].prerequisites" 값은 다른 개념 연습 문제의 "concepts" 속성 값과 일치해야 해요
  • "exercises.concept[].prerequisites" 값은 해당 연습 문제의 "exercises.concept[].concepts" 속성 값 중 어느 것과도 일치해서는 안 돼요
  • "exercises.concept[].prerequisites" 값은 개념 중 하나의 "concepts.slug" 속성과 일치해야 해요
  • "exercises.concept[].concepts"와 "exercises.concept[].prerequisites" 사이에 순환이 있어서는 안 돼요
  • "exercises.concept[].status" 키는 선택 사항이에요
  • "exercises.concept[].status" 값은 문자열 wip, beta, active 또는 deprecated여야 해요
  • "exercises.practice" 키는 필수예요
  • "exercises.practice" 값은 배열이어야 해요
  • "exercises.practice[].slug" 키는 필수예요
  • "exercises.practice[].slug" 값은 길이가 255 이하인 kebab-case 문자열²이어야 해요
  • "exercises.practice[].slug" 값은 "exercises.practice[].slug"에서 고유해야 하며 "exercises.concept[].slug"에는 존재해서는 안 돼요
  • hello-world라는 문자열인 "exercises.practice[].slug" 값이 정확히 하나 있어야 해요
  • "exercises.practice[].name" 키는 필수예요
  • "exercises.practice[].name" 값은 길이가 255 이하인 Title Case 문자열³이어야 해요
  • "exercises.practice[].uuid" 키는 필수예요
  • "exercises.practice[].uuid" 값은 고유한 버전 4 UUID 문자열⁶이어야 해요
  • 각 연습 문제의 "exercises.practice[].uuid" 값은 절대 바뀌어서는 안 돼요
  • "exercises.practice[].difficulty" 키는 필수예요
  • "exercises.practice[].difficulty" 값은 1 이상 10 이하의 정수여야 해요
  • "exercises.practice[].practices" 키는 필수예요
  • "exercises.practice[].practices" 값은 "exercises.practice[].status"가 deprecated가 아니면 비어 있지 않은 문자열 배열이어야 해요
  • "exercises.practice[].practices" 값은 "exercises.practice[].status"가 deprecated이면 빈 배열이어야 해요
  • "exercises.practice[].practices" 값은 kebab-case 문자열²이어야 해요
  • "exercises.practice[].practices" 값에 중복이 없어야 해요
  • "exercises.practice[].practices" 값은 개념 중 하나의 "concepts[].slug" 속성과 일치해야 해요
  • "exercises.practice[].practices" 값은 개별 개념의 슬러그를 (모든 연습 문제를 통틀어) 최대 10번까지만 참조해야 해요
  • "exercises.practice[].prerequisites" 키는 필수예요
  • "exercises.practice[].prerequisites" 값은 "exercises.practice[].status"가 deprecated가 아니면 비어 있지 않은 문자열 배열이어야 해요
  • "exercises.practice[].prerequisites" 값은 "exercises.practice[].status"가 deprecated이면 빈 배열이어야 해요
  • "exercises.practice[].prerequisites" 값은 "exercises.practice[].slug"가 hello-world이면 빈 배열이어야 해요
  • "exercises.practice[].prerequisites" 값은 kebab-case 문자열²이어야 해요
  • "exercises.practice[].prerequisites" 값에 중복이 없어야 해요
  • "exercises.practice[].prerequisites" 값은 어떤 개념 연습 문제의 "exercises.concept[].concepts" 값과 일치해야 해요
  • "exercises.practice[].prerequisites" 값은 개념 중 하나의 "concepts[].slug" 속성과 일치해야 해요
  • "exercises.practice[].status" 키는 선택 사항이에요
  • "exercises.practice[].status" 값은 문자열 wip, beta, active 또는 deprecated여야 해요
  • "exercises.practice[].status" 값은 "exercises.practice[].slug"가 hello-world이면 생략하거나 문자열 active여야 해요
  • "exercises.foregone" 키는 선택 사항이에요
  • "exercises.foregone" 값은 배열이어야 해요
  • "exercises.foregone" 값은 kebab-case 문자열²이어야 해요
  • "exercises.foregone" 값에 중복이 없어야 해요
  • "exercises.foregone" 값은 어떤 개념 또는 실습 연습 문제의 슬러그와도 일치해서는 안 돼요
  • "concepts" 키는 필수예요
  • "concepts" 값은 배열이어야 해요
  • "concepts[].uuid" 키는 필수예요
  • "concepts[].uuid" 값은 고유한 버전 4 UUID 문자열⁶이어야 해요
  • 각 개념의 "concepts[].uuid" 값은 절대 바뀌어서는 안 돼요
  • "concepts[].slug" 키는 필수예요
  • "concepts[].slug" 값은 길이가 255 이하인 kebab-case 문자열²이어야 해요
  • "concepts[].name" 키는 필수예요
  • "concepts[].name" 값은 길이가 255 이하인 Title Case 문자열³이어야 해요
  • "concepts[].tags" 키는 선택 사항이에요
  • "concepts[].tags.all" 키는 선택 사항이에요. 단, "concepts[].tags.any"가 비어 있으면 반드시 있어야 해요
  • "concepts[].tags.all" 값은 배열이어야 해요
  • "concepts[].tags.all" 값은 길이가 255 이하인 비어 있지 않은 태그⁷ 문자열이어야 해요
  • "concepts[].tags.all" 값에 중복이 없어야 해요
  • "concepts[].tags.any" 키는 선택 사항이에요. 단, "concepts[].tags.all"이 비어 있으면 반드시 있어야 해요
  • "concepts[].tags.any" 값은 배열이어야 해요
  • "concepts[].tags.any" 값은 길이가 255 이하인 비어 있지 않은 태그⁷ 문자열이어야 해요
  • "concepts[].tags.any" 값에 중복이 없어야 해요
  • "concepts[].tags.not" 키는 선택 사항이에요
  • "concepts[].tags.not" 값은 배열이어야 해요
  • "concepts[].tags.not" 값은 길이가 255 이하인 비어 있지 않은 태그⁷ 문자열이어야 해요
  • "concepts[].tags.not" 값에 중복이 없어야 해요
  • 각 "concepts" 값에는 concept/<concepts.slug>/about.md 파일이 있어야 해요. 이 파일의 린트 규칙은 아래에 설명되어 있어요.
  • 각 "concepts" 값에는 concept/<concepts.slug>/introduction.md 파일이 있어야 해요. 이 파일의 린트 규칙은 아래에 설명되어 있어요.
  • 각 "concepts" 값에는 concept/<concepts.slug>/links.json 파일이 있어야 해요. 이 파일의 린트 규칙은 아래에 설명되어 있어요.
  • "key_features" 키는 선택 사항이에요
  • "key_features" 값은 길이가 6인 배열이어야 해요
  • "key_features[].icon" 키는 필수예요
  • "key_features[].icon" 값은 미리 정의된 아이콘 값 중 하나를 사용해야 해요
  • "key_features[].title" 키는 필수예요
  • "key_features[].title" 값은 길이가 25 이하인 Sentence Case 문자열⁴이어야 해요
  • "key_features[].content" 키는 필수예요
  • "key_features[].content" 값은 길이가 100 이하인 비어 있지 않은 문자열¹이어야 해요
  • "tags" 키는 필수예요
  • "tags" 값은 문자열 배열이어야 해요
  • "tags" 값에 중복이 없어야 해요
  • "tags" 값은 미리 정의된 태그 값 중 하나를 사용해야 해요

규칙: exercises/concept/<slug>/.meta/config.json 파일이 유효한지 확인

  • 파일은 유효한 JSON이어야 해요
  • JSON 루트는 객체여야 해요
  • "blurb" 키는 필수예요
  • "blurb" 값은 길이가 350 이하인 비어 있지 않은 문자열¹이어야 해요
  • "source" 키는 선택 사항이에요
  • "source" 값은 비어 있지 않은 문자열¹이어야 해요
  • "source_url" 키는 선택 사항이에요
  • "source_url" 값은 URL이어야 해요
  • "authors" 키는 필수예요
  • "authors" 값은 비어 있지 않은 배열이어야 해요
  • "authors" 값은 비어 있지 않은 문자열¹이어야 해요
  • "authors" 값에 중복이 없어야 해요
  • "authors" 값은 대소문자를 구분하지 않아요
  • "contributors" 키는 선택 사항이에요
  • "contributors" 값은 배열이어야 해요
  • "contributors" 값은 비어 있지 않은 문자열¹이어야 해요
  • "contributors" 값에 중복이 없어야 해요
  • "contributors" 값은 대소문자를 구분하지 않아요
  • 사용자는 "authors" 또는 "contributors" 배열 중 한 곳에만 나열할 수 있어요 (중복 불가)
  • "files.solution" 키는 필수예요
  • "files.solution" 값은 비어 있지 않은 배열이어야 해요
  • "files.solution" 값에 중복이 없어야 해요
  • "files.test" 키는 필수예요
  • "files.test" 값은 비어 있지 않은 배열이어야 해요
  • "files.test" 값에 중복이 없어야 해요
  • "files.exemplar" 키는 필수예요
  • "files.exemplar" 값은 비어 있지 않은 배열이어야 해요
  • "files.exemplar" 값에 중복이 없어야 해요
  • "files.editor" 키는 선택 사항이에요
  • "files.editor" 값은 배열이어야 해요
  • "files.editor" 값에 중복이 없어야 해요
  • "files.invalidator" 키는 선택 사항이에요
  • "files.invalidator" 값은 배열이어야 해요
  • "files.invalidator" 값에 중복이 없어야 해요
  • "files.solution"에 나열된 파일이 존재해야 해요
  • "files.test"에 나열된 파일이 존재해야 해요
  • "files.exemplar"에 나열된 파일이 존재해야 해요
  • "files.editor"에 나열된 파일이 존재해야 해요
  • "files.invalidator"에 나열된 파일이 존재해야 해요
  • 파일은 "files.solution", "files.test", "files.exemplar", "files.invalidator" 배열 중 한 곳에만 나열할 수 있어요 (중복 불가)
    • 트랙이 d 또는 plsql이면 "files.solution"과 "files.test" 파일은 겹칠 수 있어요
  • "forked_from" 키는 선택 사항이에요
  • "forked_from" 값은 배열이어야 해요
  • "forked_from" 값은 <track-slug>/<exercise-slug> 형식의 문자열이어야 해요 (예: fsharp/bird-watcher)
  • "forked_from" 값은 실제로 구현된 연습 문제를 가리켜야 해요
  • "forked_from" 값에 중복이 없어야 해요
  • "language_versions" 키는 선택 사항이에요
  • "language_versions" 값은 문자열이어야 해요
  • "representer.version" 키는 선택 사항이에요
  • "representer.version" 값은 1 이상의 정수여야 해요
  • "icon" 키는 선택 사항이에요
  • "icon" 값은 kebab-case 문자열²이어야 해요

규칙: exercises/concept/<slug>/.docs/hints.md 파일이 유효한지 확인

  • Markdown은 Markdown 표준을 따라야 해요
  • 모든 제목은 ## General 또는 ## X. <task>여야 하며, 여기서 X는 instructions.md의 작업 번호 제목과 일치해야 해요
  • 모든 힌트는 Markdown 목록 항목으로 작성해야 해요
  • 링크는 절대 링크여야 해요 (상대 링크는 허용되지 않아요)

규칙: exercises/concept/<slug>/.docs/instructions.md 파일이 유효한지 확인

  • Markdown은 Markdown 표준을 따라야 해요
  • 모든 작업은 숫자와 마침표로 시작하는 2단계 제목으로 시작해야 해요: ## 1. Do X
  • 링크는 절대 링크여야 해요 (상대 링크는 허용되지 않아요)

규칙: exercises/concept/<slug>/.docs/instructions.md.tpl 파일이 유효한지 확인 (있는 경우)

  • 각 개념 자리 표시자의 개념은 트랙의 config.json에 있는 개념 중 하나의 "concepts.slug" 속성과 일치해야 해요.

규칙: exercises/concept/<slug>/.docs/introduction.md 파일이 유효한지 확인

  • Markdown은 Markdown 표준을 따라야 해요
  • 링크는 절대 링크여야 해요 (상대 링크는 허용되지 않아요)

규칙: exercises/practice/<slug>/.meta/config.json 파일이 유효한지 확인

  • 파일은 유효한 JSON이어야 해요
  • JSON 루트는 객체여야 해요
  • "blurb" 키는 필수예요
  • "blurb" 값은 길이가 350 이하인 비어 있지 않은 문자열¹이어야 해요
  • "source" 키는 선택 사항이에요
  • "source" 값은 비어 있지 않은 문자열¹이어야 해요
  • "source_url" 키는 선택 사항이에요
  • "source_url" 값은 URL이어야 해요
  • "authors" 키는 선택 사항이에요
  • "authors" 값은 배열이어야 해요
  • "authors" 값은 비어 있지 않은 문자열¹이어야 해요
  • "authors" 값에 중복이 없어야 해요
  • "authors" 값은 대소문자를 구분하지 않아요
  • "contributors" 키는 선택 사항이에요
  • "contributors" 값은 배열이어야 해요
  • "contributors" 값은 비어 있지 않은 문자열¹이어야 해요
  • "contributors" 값에 중복이 없어야 해요
  • "contributors" 값은 대소문자를 구분하지 않아요
  • 사용자는 "authors" 또는 "contributors" 배열 중 한 곳에만 나열할 수 있어요 (중복 불가)
  • "files.solution" 키는 필수예요
  • "files.solution" 값은 비어 있지 않은 배열이어야 해요
  • "files.solution" 값에 중복이 없어야 해요
  • "files.test" 키는 필수예요
  • "files.test" 값은 비어 있지 않은 배열이어야 해요
  • "files.test" 값에 중복이 없어야 해요
  • "files.example" 키는 필수예요
  • "files.example" 값은 비어 있지 않은 배열이어야 해요
  • "files.example" 값에 중복이 없어야 해요
  • "files.editor" 키는 선택 사항이에요
  • "files.editor" 값은 배열이어야 해요
  • "files.editor" 값에 중복이 없어야 해요
  • "files.invalidator" 키는 선택 사항이에요
  • "files.invalidator" 값은 배열이어야 해요
  • "files.invalidator" 값에 중복이 없어야 해요
  • "files.solution"에 나열된 파일이 존재해야 해요
  • "files.test"에 나열된 파일이 존재해야 해요
  • "files.example"에 나열된 파일이 존재해야 해요
  • "files.editor"에 나열된 파일이 존재해야 해요
  • "files.invalidator"에 나열된 파일이 존재해야 해요
  • 파일은 "files.solution", "files.test", "files.example, "files.invalidator" 배열 중 한 곳에만 나열할 수 있어요 (중복 불가)
    • 트랙이 d 또는 plsql이면 "files.solution"과 "files.test" 파일은 겹칠 수 있어요
  • "language_versions" 키는 선택 사항이에요
  • "language_versions" 값은 문자열이어야 해요
  • "test_runner" 키는 선택 사항이에요
  • "test_runner" 값은 불리언이어야 해요
  • "representer.version" 키는 선택 사항이에요
  • "representer.version" 값은 1 이상의 정수여야 해요
  • "icon" 키는 선택 사항이에요
  • "icon" 값은 kebab-case 문자열²이어야 해요

규칙: exercises/{concept|practice}/<slug>/.approaches/config.json 파일이 유효한지 확인

  • 이 파일은 선택 사항이에요. 단, introduction.md나 형제 디렉터리가 있으면 반드시 있어야 해요
  • 파일은 유효한 JSON이어야 해요
  • JSON 루트는 객체여야 해요
  • "introduction.authors" 키는 선택 사항이에요
  • "introduction.authors" 값은 배열이어야 해요
  • "introduction.authors" 값은 비어 있지 않은 문자열¹이어야 해요
  • "introduction.authors" 값에 중복이 없어야 해요
  • "introduction.authors" 값은 대소문자를 구분하지 않아요
  • "introduction.authors" 배열이 비어 있지 않으면 비어 있지 않은 introduction.md 파일이 있어야 해요
  • "introduction.contributors" 키는 선택 사항이에요
  • "introduction.contributors" 값은 배열이어야 해요
  • "introduction.contributors" 값은 비어 있지 않은 문자열¹이어야 해요
  • "introduction.contributors" 값에 중복이 없어야 해요
  • "introduction.contributors" 값은 대소문자를 구분하지 않아요
  • "introduction.contributors" 배열이 비어 있지 않으면 비어 있지 않은 introduction.md 파일이 있어야 해요
  • 사용자는 "introduction.authors" 또는 "introduction.contributors" 배열 중 한 곳에만 나열할 수 있어요 (중복 불가)
  • "approaches" 키는 선택 사항이에요. 단, 형제 디렉터리(접근법 파일을 담고 있는)가 있으면 반드시 있어야 해요
  • "approaches" 값은 객체 배열이어야 해요
  • "approaches[].uuid" 키는 필수예요
  • "approaches[].uuid" 값은 고유한 버전 4 UUID 문자열⁶이어야 해요
  • 각 개념의 "approaches[].uuid" 값은 절대 바뀌어서는 안 돼요
  • "approaches[].slug" 키는 필수예요
  • "approaches[].slug" 값은 길이가 255 이하인 kebab-case 문자열²이어야 해요
  • "approaches[].slug" 값에 대응하는 비어 있지 않은 <slug>/content.md 파일이 있어야 해요
  • "approaches[].slug" 값에 대응하는 비어 있지 않은 <slug>/snippet.txt 파일이 있어야 해요
  • "approaches[].title" 키는 필수예요
  • "approaches[].title" 값은 길이가 255 이하인 Title Case 문자열³이어야 해요
  • "approaches[].blurb" 키는 필수예요
  • "approaches[].blurb" 값은 길이가 350 이하인 비어 있지 않은 문자열¹이어야 해요
  • "approaches[].authors" 키는 필수예요
  • "approaches[].authors" 값은 비어 있지 않은 배열이어야 해요
  • "approaches[].authors" 값은 비어 있지 않은 문자열¹이어야 해요
  • "approaches[].authors" 값에 중복이 없어야 해요
  • "approaches[].authors" 값은 대소문자를 구분하지 않아요
  • "approaches[].contributors" 키는 선택 사항이에요
  • "approaches[].contributors" 값은 배열이어야 해요
  • "approaches[].contributors" 값은 비어 있지 않은 문자열¹이어야 해요
  • "approaches[].contributors" 값에 중복이 없어야 해요
  • "approaches[].contributors" 값은 대소문자를 구분하지 않아요
  • 사용자는 "approaches[].authors" 또는 "approaches[].contributors" 배열 중 한 곳에만 나열할 수 있어요 (중복 불가)
  • "approaches[].tags" 키는 선택 사항이에요
  • "approaches[].tags.all" 키는 선택 사항이에요. 단, "approaches[].tags.any"가 비어 있으면 반드시 있어야 해요
  • "approaches[].tags.all" 값은 배열이어야 해요
  • "approaches[].tags.all" 값은 길이가 255 이하인 비어 있지 않은 태그⁷ 문자열이어야 해요
  • "approaches[].tags.all" 값에 중복이 없어야 해요
  • "approaches[].tags.any" 키는 선택 사항이에요. 단, "approaches[].tags.all"이 비어 있으면 반드시 있어야 해요
  • "approaches[].tags.any" 값은 배열이어야 해요
  • "approaches[].tags.any" 값은 길이가 255 이하인 비어 있지 않은 태그⁷ 문자열이어야 해요
  • "approaches[].tags.any" 값에 중복이 없어야 해요
  • "approaches[].tags.not" 키는 선택 사항이에요
  • "approaches[].tags.not" 값은 배열이어야 해요
  • "approaches[].tags.not" 값은 길이가 255 이하인 비어 있지 않은 태그⁷ 문자열이어야 해요
  • "approaches[].tags.not" 값에 중복이 없어야 해요

규칙: exercises/{concept|practice}/<slug>/.approaches/<approach-slug>/content.md 파일이 유효한지 확인

  • .approaches/config.json 파일에 일치하는 "approaches[].slug" 항목이 있으면 이 파일이 있어야 해요
  • Markdown은 Markdown 표준을 따라야 해요
  • 링크는 절대 링크여야 해요 (상대 링크는 허용되지 않아요)

규칙: exercises/{concept|practice}/<slug>/.approaches/<approach-slug>/snippet.<snippet-extension> 파일이 유효한지 확인

  • .approaches/config.json 파일에 일치하는 "approaches[].slug" 항목이 있으면 이 파일이 있어야 해요
  • 스니펫은 최대 8줄이어야 해요
  • 스니펫 확장자는 트랙의 config.json 파일에 있는 approaches.snippet_extension 값에서 가져와요

규칙: exercises/{concept|practice}/<slug>/.articles/config.json 파일이 유효한지 확인

  • 이 파일은 선택 사항이에요. 단, 형제 디렉터리가 있으면 반드시 있어야 해요
  • 파일은 유효한 JSON이어야 해요
  • JSON 루트는 객체여야 해요
  • "articles" 키는 선택 사항이에요. 단, 형제 디렉터리(아티클 파일을 담고 있는)가 있으면 반드시 있어야 해요
  • "articles" 값은 객체 배열이어야 해요
  • "articles[].uuid" 키는 필수예요
  • "articles[].uuid" 값은 고유한 버전 4 UUID 문자열⁶이어야 해요
  • 각 개념의 "articles[].uuid" 값은 절대 바뀌어서는 안 돼요
  • "articles[].slug" 키는 필수예요
  • "articles[].slug" 값은 길이가 255 이하인 kebab-case 문자열²이어야 해요
  • "articles[].slug" 값에 대응하는 비어 있지 않은 <slug>/content.md 파일이 있어야 해요
  • "articles[].slug" 값에 대응하는 비어 있지 않은 <slug>/snippet.md 파일이 있어야 해요
  • "articles[].title" 키는 필수예요
  • "articles[].title" 값은 길이가 255 이하인 Title Case 문자열³이어야 해요
  • "articles[].blurb" 키는 필수예요
  • "articles[].blurb" 값은 길이가 350 이하인 비어 있지 않은 문자열¹이어야 해요
  • "articles[].authors" 키는 필수예요
  • "articles[].authors" 값은 비어 있지 않은 배열이어야 해요
  • "articles[].authors" 값은 비어 있지 않은 문자열¹이어야 해요
  • "articles[].authors" 값에 중복이 없어야 해요
  • "articles[].authors" 값은 대소문자를 구분하지 않아요
  • "articles[].contributors" 키는 선택 사항이에요
  • "articles[].contributors" 값은 배열이어야 해요
  • "articles[].contributors" 값은 비어 있지 않은 문자열¹이어야 해요
  • "articles[].contributors" 값에 중복이 없어야 해요
  • "articles[].contributors" 값은 대소문자를 구분하지 않아요
  • 사용자는 "articles[].authors" 또는 "articles[].contributors" 배열 중 한 곳에만 나열할 수 있어요 (중복 불가)

규칙: exercises/{concept|practice}/<slug>/.articles/<article-slug>/content.md 파일이 유효한지 확인

  • .articles/config.json 파일에 일치하는 "articles[].slug" 항목이 있으면 이 파일이 있어야 해요
  • Markdown은 Markdown 표준을 따라야 해요
  • 링크는 절대 링크여야 해요 (상대 링크는 허용되지 않아요)

규칙: exercises/{concept|practice}/<slug>/.articles/<article-slug>/snippet.md 파일이 유효한지 확인

  • .articles/config.json 파일에 일치하는 "articles[].slug" 항목이 있으면 이 파일이 있어야 해요
  • Markdown은 Markdown 표준을 따라야 해요
  • 스니펫은 최대 8줄이어야 해요 (앞뒤의 코드 펜스 표시는 무시해요)

규칙: exercises/shared/.docs/debug.md 파일이 유효한지 확인

  • 이 파일은 선택 사항이에요
  • Markdown은 Markdown 표준을 따라야 해요
  • 링크는 절대 링크여야 해요 (상대 링크는 허용되지 않아요)

규칙: exercises/shared/.docs/help.md 파일이 유효한지 확인

  • 이 파일이 있어야 해요
  • Markdown은 Markdown 표준을 따라야 해요
  • 링크는 절대 링크여야 해요 (상대 링크는 허용되지 않아요)

규칙: exercises/shared/.docs/tests.md 파일이 유효한지 확인

  • 이 파일이 있어야 해요
  • Markdown은 Markdown 표준을 따라야 해요
  • 링크는 절대 링크여야 해요 (상대 링크는 허용되지 않아요)

규칙: concepts/<slug>/about.md 파일이 유효한지 확인

  • Markdown은 Markdown 표준을 따라야 해요
  • 링크는 절대 링크여야 해요 (상대 링크는 허용되지 않아요)

규칙: concepts/<slug>/introduction.md 파일이 유효한지 확인

  • Markdown은 Markdown 표준을 따라야 해요
  • 링크는 절대 링크여야 해요 (상대 링크는 허용되지 않아요)
  • 파일은 유효한 JSON이어야 해요
  • JSON 루트는 배열이어야 해요
  • "[].url" 속성은 필수예요
  • "[].url" 값은 URL이어야 해요
  • "[].description" 속성은 필수예요
  • "[].description" 값은 비어 있지 않은 문자열¹이어야 해요
  • "[].icon_url" 속성은 선택 사항이에요
  • "[].icon_url" 값은 URL이어야 해요

규칙: concept/<slug>/.meta/config.json 파일이 유효한지 확인

  • 파일은 유효한 JSON이어야 해요
  • JSON 루트는 객체여야 해요
  • "blurb" 키는 필수예요
  • "blurb" 값은 길이가 350 이하인 비어 있지 않은 문자열¹이어야 해요
  • "authors" 키는 필수예요
  • "authors" 값은 배열이어야 해요
  • "authors" 값은 비어 있지 않은 문자열¹이어야 해요
  • "authors" 값에 중복이 없어야 해요
  • "authors" 값은 대소문자를 구분하지 않아요
  • "contributors" 키는 선택 사항이에요
  • "contributors" 값은 배열이어야 해요
  • "contributors" 값은 비어 있지 않은 문자열¹이어야 해요
  • "contributors" 값에 중복이 없어야 해요
  • "contributors" 값은 대소문자를 구분하지 않아요
  • 사용자는 "authors" 또는 "contributors" 배열 중 한 곳에만 나열할 수 있어요 (중복 불가)

규칙: docs/ABOUT.md 파일이 유효한지 확인

  • 이 파일이 있어야 해요
  • 파일 내용이 비어 있지 않아야 해요
  • Markdown은 Markdown 표준을 따라야 해요
  • 링크는 절대 링크여야 해요 (상대 링크는 허용되지 않아요)

규칙: docs/INSTALLATION.md 파일이 유효한지 확인

  • 이 파일이 있어야 해요
  • 파일 내용이 비어 있지 않아야 해요
  • Markdown은 Markdown 표준을 따라야 해요
  • 링크는 절대 링크여야 해요 (상대 링크는 허용되지 않아요)

규칙: docs/LEARNING.md 파일이 유효한지 확인

  • 이 파일이 있어야 해요
  • 파일 내용이 비어 있지 않아야 해요
  • Markdown은 Markdown 표준을 따라야 해요
  • 링크는 절대 링크여야 해요 (상대 링크는 허용되지 않아요)

규칙: docs/RESOURCES.md 파일이 유효한지 확인

  • 이 파일이 있어야 해요
  • 파일 내용이 비어 있지 않아야 해요
  • Markdown은 Markdown 표준을 따라야 해요
  • 링크는 절대 링크여야 해요 (상대 링크는 허용되지 않아요)

규칙: docs/SNIPPET.txt 파일이 유효한지 확인

  • 이 파일이 있어야 해요
  • 파일 내용이 비어 있지 않아야 해요

규칙: docs/TESTS.md 파일이 유효한지 확인

  • 이 파일이 있어야 해요
  • 파일 내용이 비어 있지 않아야 해요
  • Markdown은 Markdown 표준을 따라야 해요
  • 링크는 절대 링크여야 해요 (상대 링크는 허용되지 않아요)

용어 설명

  1. 비어 있지 않은 문자열: 공백이 아닌 문자를 하나 이상 포함하는 문자열이에요.

  2. kebab-case 문자열: [a-z0-9] 범위의 문자만 포함하고, 선택적으로 대시로 구분되는 문자열이에요 (예: "two-fer"). 다음 정규 표현식과 일치해야 해요: ^[a-z0-9]+(-[a-z0-9]+)*$

  3. Title Case 문자열: 아래 시카고 매뉴얼 오브 스타일의 지침을 따르는 비어 있지 않은 문자열이에요:

    • 제목과 부제목의 첫 단어와 마지막 단어는 대문자로 시작해요.
    • "주요" 단어(명사, 대명사, 동사, 형용사, 부사, 그리고 일부 접속사)는 대문자로 시작해요.
    • 접속사 and, but, for, or, _nor_는 소문자로 써요.
    • 관사 the, a, _an_은 소문자로 써요.
    • 전치사는 길이와 상관없이 소문자로 써요. 단, 강조되거나 부사적 또는 형용사적으로 쓰이거나 접속사로 쓰일 때는 예외예요.
    • _to_와 _as_는 소문자로 써요.
    • 라틴어 종명의 두 번째 부분은 소문자로 써요.
  4. Sentence Case 문자열: 아래 지침을 따르는 비어 있지 않은 문자열이에요:

    • 문장의 첫 단어와 고유 명사, 그리고 더 구체적인 규칙이 요구하는 다른 단어들은 대문자로 시작해요.
  5. 유효한 files 패턴: 연습 문제에서 사용하는 파일의 위치를 연습 문제 디렉터리 기준으로 지정하는 비어 있지 않은 문자열¹이에요. 패턴에는 다음 자리 표시자 중 하나를 사용할 수 있어요:

    • %{kebab_slug}: kebab-case 연습 문제 슬러그예요 (예: bit-manipulation)
    • %{snake_slug}: snake_case 연습 문제 슬러그예요 (예: bit_manipulation)
    • %{camel_slug}: camelCase 연습 문제 슬러그예요 (예: bitManipulation)
    • %{pascal_slug}: PascalCase 연습 문제 슬러그예요 (예: BitManipulation)
  6. 고유한 버전 4 UUID 문자열: 다음 조건을 모두 만족하는 문자열이에요:

    • 주어진 Exercism 트랙의 트랙 수준 config.json 파일에 한 번만 존재해요
    • 다른 어떤 Exercism 트랙의 트랙 수준 config.json 파일에도 존재하지 않아요
    • https://github.com/exercism/problem-specifications의 어떤 canonical-data.json 파일에도 존재하지 않아요
    • Exercism의 다른 어디에도 존재하지 않아요
    • 다음 정규 표현식과 일치해요:
    ^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$
    

    예를 들어, 아래 UUID는 올바른 형식이에요:

    d334ffe3-657e-4725-a950-290b284b6d9f
    

    configlet uuid를 실행하면 적절한 UUID를 생성할 수 있어요.

  7. 유효한 분석기 tag: <category>:<thing> 형식으로 작성된 비어 있지 않은 문자열¹이에요. <category> 값은 다음 중 하나여야 해요:

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

<thing> 값은 비어 있지 않은 문자열¹이어야 해요.