exercism / exercism/configlet

lint: implement remaining linting rules

Open
#249 0 comments 2 reactions 0 assignees View on GitHub
cmd: lint kind: feature priority: high
Dominant language
Nim
Stars
23
Forks
17
Avg merge
13h 57m
Merged PRs (30d)
1

Description

This issue will try to track which linting rules are implemented in the latest `configlet` **release**, and to what extent. This issue was last updated for [`configlet 4.0.0-alpha.34`](https://github.com/exercism/configlet/releases/tag/4.0.0-alpha.34).

The list below is from [the spec](https://github.com/exercism/docs/blob/main/building/configlet/lint.md) (up to date with https://github.com/exercism/docs/commit/322d63ecdbf643351b080c7397caceb3ccd5bc94). When we change the spec, we should remember to make the same changes in the below.

For the near future, I will handle the implementation of the JSON rules.

A ticked checkbox means that the item is fully implemented. An empty checkbox means the item is unimplemented or only partially implemented.

Backlog:
https://github.com/exercism/configlet/compare/4.0.0-alpha.34...4.0.0-beta.2

```sh
git log 4.0.0-alpha.34..4.0.0-beta.2 --oneline -- src/lint*
```

152a9536 lint, sync, fmt: support the `files.invalidator` field
0832f812 lint(exercises): check `files.editor` field
4ab7a531 remove trailing whitespace
d0cd08cc lint: error on missing concept/exercise files
a71637f7 lint: add annotation for key features in config.json
09d5108c lint: add annotation for tags in config.json
cf70d5fa validators: pass error annotation to `hasValidRuneLength`
856ad411 lint: link to docs on exercism.org, not GitHub
aa22e359 lint: allow overlap of solution and test files for `d` and `plsql` tracks
fea7bccd lint: allow overlap of `files.example` and `files.exemplar` values
3a55f57a lint: support error annotations
fe3e7e49 lint: clarify the need to update configlet
3171b116 lint: refactor final output message
816a1186 lint: advise that warnings may not become errors
fd78c1b8 lint(track_config): optimize concept cycle checking slightly
1fd2a46f sync: handle docs, metadata, and filepaths

---

### Rule: required files are present

The linter should check if all the required files are present. The non-exercise specific files that must be present are:

- [x] `config.json`
- [x] `docs/ABOUT.md`
- [x] `docs/INSTALLATION.md`
- [x] `docs/LEARNING.md`
- [x] `docs/RESOURCES.md`
- [x] `docs/SNIPPET.txt`
- [x] `docs/TESTS.md`
- [x] `exercises/shared/.docs/help.md`
- [x] `exercises/shared/.docs/tests.md`

The Concept Exercise specific files that must be present are:

- [x] `exercises/concept//.docs/hints.md`
- [x] `exercises/concept//.docs/instructions.md`
- [x] `exercises/concept//.docs/introduction.md`
- [x] `exercises/concept//.meta/config.json`

The Practice Exercise specific files that must be present are at least (**not yet in the spec**):

- [x] `exercises/practice//.docs/instructions.md`
- [x] `exercises/practice//.meta/config.json`

Each concept listed in the `config.json` should have the following files:

- [x] `concepts//about.md`
- [x] `concepts//introduction.md`
- [x] `concepts//links.json`

### Rule: `config.json` file is valid

The `config.json` file should have the following checks:

- [x] The file must be valid JSON
- [x] The `"language"` key is required
- [x] The `"language"` value must be a non-blank string¹ with length <= 255
- [x] The `"slug"` key is required
- [x] The `"slug"` value must be a kebab-case string² with length <= 255
- [x] The `"active"` key is required
- [x] The `"active"` value must be a boolean
- [x] The `"blurb"` key is required
- [x] The `"blurb"` value must be a non-blank string¹ with length <= 400
- [x] The `"version"` key is required
- [x] The `"version"` value must be the integer `3`
- [x] The `"status.concept_exercises"` key is required
- [x] The `"status.concept_exercises"` value must be a boolean
- [x] The `"status.test_runner"` key is required
- [x] The `"status.test_runner"` value must be a boolean
- [x] The `"status.representer"` key is required
- [x] The `"status.representer"` value must be a boolean
- [x] The `"status.analyzer"` key is required
- [x] The `"status.analyzer"` value must be a boolean
- [x] The `"online_editor.indent_style"` key is required
- [x] The `"online_editor.indent_style"` value must be the string `space` or `tab`
- [x] The `"online_editor.indent_size"` key is required
- [x] The `"online_editor.indent_size"` value must be an integer >= 0 and <= 8
- [x] The `"online_editor.highlightjs_language"` key is required
- [x] The `"online_editor.highlightjs_language"` value must be a non-blank string¹
- [x] The `"files"` key is optional
- [x] The `"files"` value must be an object
- [x] The `"files.solution`" key is optional
- [x] The `"files.solution`" value must be an array
- [x] The `"files.solution`" values must be valid patterns⁵
- [x] The `"files.solution`" values must not have duplicates
- [x] The `"files.test`" key is optional
- [x] The `"files.test`" value must be an array
- [x] The `"files.test`" values must be valid patterns⁵
- [x] The `"files.test`" values must not have duplicates
- [x] The `"files.example`" key is optional
- [x] The `"files.example`" value must be an array
- [x] The `"files.example`" values must be valid patterns⁵
- [x] The `"files.example`" values must not have duplicates
- [x] The `"files.exemplar"` key is optional
- [x] The `"files.exemplar"` value must be an array
- [x] The `"files.exemplar"` values must be valid patterns⁵
- [x] The `"files.exemplar"` values must not have duplicates
- [x] The `"files.editor`" key is optional
- [x] The `"files.editor`" value must be an array
- [x] The `"files.editor`" values must be valid patterns⁵
- [x] The `"files.editor`" values must not have duplicates
- [ ] The `"files.invalidator`" key is optional
- [ ] The `"files.invalidator`" value must be an array
- [ ] The `"files.invalidator`" values must be valid patterns⁵
- [ ] The `"files.invalidator`" values must not have duplicates
- [ ] Patterns can only be listed in either the `"files.solution"`, `"files.test"`, `"files.example"`, `"files.exemplar"`, `"files.editor"` or `"files.invalidator"` array (no overlap)
- [ ] If the track is `d` or `plsql`, the `"files.solution"` and `"files.test"` files _can_ overlap
- [ ] The `"files.example"` and `"files.exemplar"` files _can_ overlap
- [x] The `"test_runner.average_run_time"` key is required if `status.test_runner` is equal to `true`
- [x] The `"test_runner.average_run_time"` value must be a floating-point number > 0 with one decimal point of precision
- [x] The `"exercises"` key is required
- [x] The `"exercises.concept"` key is required
- [x] The `"exercises.concept"` value must be an array
- [x] The `"exercises.concept[].slug"` key is required
- [x] The `"exercises.concept[].slug"` value must be a kebab-case string² with length <= 255
- [x] The `"exercises.concept[].slug"` value must be unique in `"exercises.concept[].slug"` and may not exist in `"exercises.practice[].slug"`
- [x] The `"exercises.concept[].name"` key is required
- [ ] The `"exercises.concept[].name"` value must be a Title Case string³ with length <= 255
- [x] The `"exercises.concept[].uuid"` key is required
- [ ] The `"exercises.concept[].uuid"` value must be a unique version 4 UUID string⁶
- [ ] The `"exercises.concept[].uuid"` value for each exercise must never change
- [x] The `"exercises.concept[].concepts"` key is required
- [x] The `"exercises.concept[].concepts"` value must be a non-empty array of strings if `"exercises.concept[].status"` is not equal to `deprecated`
- [x] The `"exercises.concept[].concepts"` value must be an empty array if `"exercises.concept[].status"` is equal to `deprecated`
- [x] The `"exercises.concept[].concepts"` values must be kebab-case strings²
- [x] The `"exercises.concept[].concepts"` values must not have duplicates
- [x] The `"exercises.concept[].concepts"` values must not be in any other concept exercise's `"concepts"` property
- [x] The `"exercises.concept[].concepts"` values must match the `"concepts.slug"` property of one of the concepts
- [x] The `"exercises.concept[].prerequisites"` key is required
- [x] The `"exercises.concept[].prerequisites"` value must be a non-empty array of strings if `"exercises.concept[].status"` is not equal to `deprecated`, except for exactly one exercise which _is_ allowed to have an empty array as its value
- [x] The `"exercises.concept[].prerequisites"` value must be an empty array if `"exercises.concept[].status"` is equal to `deprecated`
- [x] The `"exercises.concept[].prerequisites"` values must be kebab-case strings²
- [x] The `"exercises.concept[].prerequisites"` values must not have duplicates
- [x] The `"exercises.concept[].prerequisites"` values must match any other concept exercise's `"concepts"` property values
- [x] The `"exercises.concept[].prerequisites"` values must not match any of the values in the exercise's `"exercises.concept[].concepts"` property
- [x] The `"exercises.concept[].prerequisites"` values must match the `"concepts.slug"` property of one of the concepts
- [x] There must not be any cycles between `"exercises.concept[].concepts"` and `"exercises.concept[].prerequisites"`
- [x] The `"exercises.concept[].status"` key is optional
- [x] The `"exercises.concept[].status"` value must be the string `wip`, `beta`, `active` or `deprecated`
- [x] The `"exercises.practice"` key is required
- [x] The `"exercises.practice"` value must be an array
- [x] The `"exercises.practice[].slug"` key is required
- [x] The `"exercises.practice[].slug"` value must be a kebab-case string² with length <= 255
- [x] The `"exercises.practice[].slug"` value must be unique in `"exercises.practice[].slug"` and may not exist in `"exercises.concept[].slug"`
- [x] There must be exactly one `"exercises.practice[].slug"` value that is the string `hello-world`
- [x] The `"exercises.practice[].name"` key is required
- [ ] The `"exercises.practice[].name"` value must be a Title Case string³ with length <= 255
- [x] The `"exercises.practice[].uuid"` key is required
- [ ] The `"exercises.practice[].uuid"` value must be a unique version 4 UUID string⁶
- [ ] The `"exercises.practice[].uuid"` value for each exercise must never change
- [x] The `"exercises.practice[].difficulty"` key is required
- [x] The `"exercises.practice[].difficulty"` value must be an integer >= 1 and <= 10
- [x] The `"exercises.practice[].practices"` key is required
- [ ] The `"exercises.practice[].practices"` value must be a non-empty array of strings if `"exercises.practice[].status"` is not equal to `deprecated` (TODO: enable this supported check)
- [x] The `"exercises.practice[].practices"` value must be an empty array if `"exercises.practice[].status"` is equal to `deprecated`
- [x] The `"exercises.practice[].practices"` values must be kebab-case strings²
- [x] The `"exercises.practice[].practices"` values must not have duplicates
- [x] The `"exercises.practice[].practices"` values must match the `"concepts[].slug"` property of one of the concepts (TODO: this is currently implemented as a warning, and will become an error)
- [x] The `"exercises.practice[].practices"` values must refer to an individual concept's slug at most 10 times (across all exercises) (TODO: this is currently implemented as a warning, and will become an error)
- [x] The `"exercises.practice[].prerequisites"` key is required
- [ ] The `"exercises.practice[].prerequisites"` value must be a non-empty array of strings if `"exercises.practice[].status"` is not equal to `deprecated` (TODO: enable this supported check)
- [x] The `"exercises.practice[].prerequisites"` value must be an empty array if `"exercises.practice[].status"` is equal to `deprecated`
- [x] The `"exercises.practice[].prerequisites"` value must be an empty array if `"exercises.practice[].slug"` is equal to `hello-world`
- [x] The `"exercises.practice[].prerequisites"` values must be kebab-case strings²
- [x] The `"exercises.practice[].prerequisites"` values must not have duplicates
- [x] The `"exercises.practice[].prerequisites"` values must match any concept exercise's `"exercises.concept[].concepts"` values (TODO: this is currently implemented as a warning, and will become an error)
- [x] The `"exercises.practice[].prerequisites"` values must match the `"concepts[].slug"` property of one of the concepts (TODO: this is currently implemented as a warning, and will become an error)
- [x] The `"exercises.practice[].status"` key is optional
- [x] The `"exercises.practice[].status"` value must be the string `wip`, `beta`, `active` or `deprecated`
- [x] The `"exercises.practice[].status"` value must, if `"exercises.practice[].slug"` is equal to `hello-world`, be either omitted or the string `active`
- [x] The `"exercises.foregone"` key is optional
- [x] The `"exercises.foregone"` value must be an array
- [x] The `"exercises.foregone"` values must be kebab-case strings²
- [x] The `"exercises.foregone"` values must not have duplicates
- [x] The `"exercises.foregone"` values must not match any of the concept or practice exercise slugs
- [x] The `"concepts"` key is required
- [x] The `"concepts"` value must be an array
- [x] The `"concepts[].uuid"` key is required
- [ ] The `"concepts[].uuid"` value must be a unique version 4 UUID string⁶
- [ ] The `"concepts[].uuid"` value for each concept must never change
- [x] The `"concepts[].slug"` key is required
- [x] The `"concepts[].slug"` value must be a kebab-case string² with length <= 255
- [x] The `"concepts[].name"` key is required
- [ ] The `"concepts[].name"` value must be a Title Case string³ with length <= 255
- [ ] Each `"concepts"` value must have a `concept//about.md` file. Linting rules for this file are specified below.
- [ ] Each `"concepts"` value must have a `concept//introduction.md` file. Linting rules for this file are specified below.
- [ ] Each `"concepts"` value must have a `concept//links.json` file. Linting rules for this file are specified below.
- [x] The `"key_features"` key is optional
- [x] The `"key_features"` value must be an array with length = 6
- [x] The `"key_features[].icon"` key is required
- [x] The `"key_features[].icon"` value must use one of the [pre-defined icon values](https://github.com/exercism/docs/blob/main/building/tracks/config-json.md#key-features)
- [x] The `"key_features[].title"` key is required
- [ ] The `"key_features[].title"` value must be a Sentence Case string⁴ with length <= 25
- [x] The `"key_features[].content"` key is required
- [x] The `"key_features[].content"` value must be a non-blank string¹ with length <= 100
- [x] The `"tags"` key is required
- [x] The `"tags"` value must be an array of strings
- [x] The `"tags"` values must not have duplicates
- [x] The `"tags"` values must use one of the [pre-defined tag values](https://github.com/exercism/docs/blob/main/building/tracks/config-json.md#tags)

### Rule: `exercises/concept//.meta/config.json` is valid

- [x] The file must be valid JSON
- [x] The JSON root must be an object
- [x] The `"blurb"` key is required
- [x] The `"blurb"` value must be a non-blank string¹ with length <= 350
- [x] The `"source"` key is optional
- [x] The `"source"` value must be a non-blank string¹
- [x] The `"source_url"` key is optional
- [ ] The `"source_url"` value must be a URL
- [x] The `"authors"` key is required
- [x] The `"authors"` value must be a non-empty array
- [x] The `"authors"` values must be non-blank strings¹
- [x] The `"authors"` values must not have duplicates
- [ ] The `"authors"` values are treated case-insensitively
- [x] The `"contributors"` key is optional
- [x] The `"contributors"` value must be an array
- [x] The `"contributors"` values must be non-blank strings¹
- [x] The `"contributors"` values must not have duplicates
- [ ] The `"contributors"` values are treated case-insensitively
- [ ] Users can only be listed in either the `"authors"` or `"contributors"` array (no overlap)
- [x] The `"files.solution"` key is required
- [x] The `"files.solution"` value must be a non-empty array
- [x] The `"files.solution"` values must not have duplicates
- [x] The `"files.test"` key is required
- [x] The `"files.test"` value must be a non-empty array
- [x] The `"files.test"` values must not have duplicates
- [x] The `"files.exemplar"` key is required
- [x] The `"files.exemplar"` value must be a non-empty array
- [x] The `"files.exemplar"` values must not have duplicates
- [ ] The `"files.editor"` key is optional
- [ ] The `"files.editor"` value must be an array
- [ ] The `"files.editor"` values must not have duplicates
- [ ] The `"files.invalidator"` key is optional
- [ ] The `"files.invalidator"` value must be an array
- [ ] The `"files.invalidator"` values must not have duplicates
- [x] The files listed in the `"files.solution"` must exist
- [x] The files listed in the `"files.test"` must exist
- [x] The files listed in the `"files.exemplar"` must exist
- [ ] The files listed in the `"files.editor"` must exist
- [ ] The files listed in the `"files.invalidator"` must exist
- [ ] Files can only be listed in either the `"files.solution"`, `"files.test"`, `"files.exemplar"` or `"files.invalidator"` array (no overlap)
- [ ] If the track is `d` or `plsql`, the `"files.solution"` and `"files.test"` files _can_ overlap
- [x] The `"forked_from"` key is optional
- [x] The `"forked_from"` value must be an array
- [ ] The `"forked_from"` values must be strings formatted as `/` (e.g. `fsharp/bird-watcher`)
- [ ] The `"forked_from"` values must refer to actually implemented exercises
- [x] The `"forked_from"` values must not have duplicates
- [x] The `"language_versions"` key is optional
- [x] The `"language_versions"` value must be a string
- [x] The `"icon"` key is optional
- [x] The `"icon"` value must be a kebab-case string²

### Rule: `exercises/concept//.docs/hints.md` is valid

- [ ] The Markdown must conform to the [Markdown standards](https://github.com/exercism/docs/blob/main/building/markdown/markdown.md)
- [ ] All headings must be either `## General` or `## X. ` where `X` matches the task number heading in the `instructions.md`
- [ ] All hints must be specified as Markdown list items
- [ ] Links must be absolute (relative links are not allowed)

### Rule: `exercises/concept//.docs/instructions.md` is valid

- [ ] The Markdown must conform to the [Markdown standards](https://github.com/exercism/docs/blob/main/building/markdown/markdown.md)
- [ ] All tasks must start with a level two heading that starts with a number followed by a dot: `## 1. Do X`
- [ ] Links must be absolute (relative links are not allowed)

### Rule: `exercises/concept//.docs/instructions.md.tpl` is valid (if present)

- [ ] Each [concept placeholders](https://github.com/exercism/docs/blob/main/building/tracks/concept-exercises.md#file-docsintroductionmdtpl)'s concept must match the `"concepts.slug"` property of one of the concepts in the track's `config.json`.

### Rule: `exercises/concept//.docs/introduction.md` is valid

- [ ] The Markdown must conform to the [Markdown standards](https://github.com/exercism/docs/blob/main/building/markdown/markdown.md)
- [ ] Links must be absolute (relative links are not allowed)

### Rule: `exercises/practice//.meta/config.json` is valid

- [x] The file must be valid JSON
- [x] The JSON root must be an object
- [x] The `"blurb"` key is required
- [x] The `"blurb"` value must be a non-blank string¹ with length <= 350
- [x] The `"source"` key is optional
- [x] The `"source"` value must be a non-blank string¹
- [x] The `"source_url"` key is optional
- [ ] The `"source_url"` value must be a URL
- [x] The `"authors"` key is optional
- [x] The `"authors"` value must be an array
- [x] The `"authors"` values must be non-blank strings¹
- [x] The `"authors"` values must not have duplicates
- [ ] The `"authors"` values are treated case-insensitively
- [x] The `"contributors"` key is optional
- [x] The `"contributors"` value must be an array
- [x] The `"contributors"` values must be non-blank strings¹
- [x] The `"contributors"` values must not have duplicates
- [ ] The `"contributors"` values are treated case-insensitively
- [ ] Users can only be listed in either the `"authors"` or `"contributors"` array (no overlap)
- [x] The `"files.solution"` key is required
- [x] The `"files.solution"` value must be a non-empty array
- [x] The `"files.solution"` values must not have duplicates
- [x] The `"files.test"` key is required
- [x] The `"files.test"` value must be a non-empty array
- [x] The `"files.test"` values must not have duplicates
- [x] The `"files.example"` key is required
- [x] The `"files.example"` value must be a non-empty array
- [x] The `"files.example"` values must not have duplicates
- [ ] The `"files.editor"` key is optional
- [ ] The `"files.editor"` value must be an array
- [ ] The `"files.editor"` values must not have duplicates
- [ ] The `"files.invalidator"` key is optional
- [ ] The `"files.invalidator"` value must be an array
- [ ] The `"files.invalidator"` values must not have duplicates
- [x] The files listed in the `"files.solution"` must exist
- [x] The files listed in the `"files.test"` must exist
- [x] The files listed in the `"files.example"` must exist
- [ ] The files listed in the `"files.editor"` must exist
- [ ] The files listed in the `"files.invalidator"` must exist
- [ ] Files can only be listed in either the `"files.solution"`, `"files.test"`, `"files.example` or `"files.invalidator"` array (no overlap)
- [ ] If the track is `d` or `plsql`, the `"files.solution"` and `"files.test"` files _can_ overlap
- [x] The `"language_versions"` key is optional
- [x] The `"language_versions"` value must be a string
- [x] The `"test_runner"` key is optional
- [x] The `"test_runner"` value must be a boolean

### Rule: `exercises/shared/.docs/debug.md` is valid

- [x] The file's presence is optional
- [ ] The Markdown must conform to the [Markdown standards](https://github.com/exercism/docs/blob/main/building/markdown/markdown.md)
- [ ] Links must be absolute (relative links are not allowed)

### Rule: `exercises/shared/.docs/help.md` is valid

- [x] The file's presence is required
- [ ] The Markdown must conform to the [Markdown standards](https://github.com/exercism/docs/blob/main/building/markdown/markdown.md)
- [ ] Links must be absolute (relative links are not allowed)

### Rule: `exercises/shared/.docs/tests.md` is valid

- [x] The file's presence is required
- [ ] The Markdown must conform to the [Markdown standards](https://github.com/exercism/docs/blob/main/building/markdown/markdown.md)
- [ ] Links must be absolute (relative links are not allowed)

### Rule: `concepts//about.md` is valid

- [ ] The Markdown must conform to the [Markdown standards](https://github.com/exercism/docs/blob/main/building/markdown/markdown.md)
- [ ] Links must be absolute (relative links are not allowed)

### Rule: `concepts//introduction.md` is valid

- [ ] The Markdown must conform to the [Markdown standards](https://github.com/exercism/docs/blob/main/building/markdown/markdown.md)
- [ ] Links must be absolute (relative links are not allowed)

### Rule: `concept//links.json` is valid

- [x] The file must be valid JSON
- [x] The JSON root must be an array
- [x] The `"[].url"` property is required
- [ ] The `"[].url"` value must be an URL
- [x] The `"[].description"` property is required
- [x] The `"[].description"` value must be a non-blank string¹
- [x] The `"[].icon_url"` property is optional
- [ ] The `"[].icon_url"` value must be an URL

### Rule: `concept//.meta/config.json` is valid

- [x] The file must be valid JSON
- [x] The JSON root must be an object
- [x] The `"blurb"` key is required
- [x] The `"blurb"` value must be a non-blank string¹ with length <= 350
- [x] The `"authors"` key is required
- [x] The `"authors"` value must be an array
- [x] The `"authors"` values must be non-blank strings¹
- [x] The `"authors"` values must not have duplicates
- [ ] The `"authors"` values are treated case-insensitively
- [x] The `"contributors"` key is optional
- [x] The `"contributors"` value must be an array
- [x] The `"contributors"` values must be non-blank strings¹
- [x] The `"contributors"` values must not have duplicates
- [ ] The `"contributors"` values are treated case-insensitively
- [ ] Users can only be listed in either the `"authors"` or `"contributors"` array (no overlap)

### Rule: `docs/ABOUT.md` is valid

- [x] The file's presence is required
- [ ] The file's contents must be non-blank
- [ ] The Markdown must conform to the [Markdown standards](https://github.com/exercism/docs/blob/main/building/markdown/markdown.md)
- [ ] Links must be absolute (relative links are not allowed)

### Rule: `docs/INSTALLATION.md` is valid

- [x] The file's presence is required
- [ ] The file's contents must be non-blank
- [ ] The Markdown must conform to the [Markdown standards](https://github.com/exercism/docs/blob/main/building/markdown/markdown.md)
- [ ] Links must be absolute (relative links are not allowed)

### Rule: `docs/LEARNING.md` is valid

- [x] The file's presence is required
- [ ] The file's contents must be non-blank
- [ ] The Markdown must conform to the [Markdown standards](https://github.com/exercism/docs/blob/main/building/markdown/markdown.md)
- [ ] Links must be absolute (relative links are not allowed)

### Rule: `docs/RESOURCES.md` is valid

- [x] The file's presence is required
- [ ] The file's contents must be non-blank
- [ ] The Markdown must conform to the [Markdown standards](https://github.com/exercism/docs/blob/main/building/markdown/markdown.md)
- [ ] Links must be absolute (relative links are not allowed)

### Rule: `docs/SNIPPET.txt` is valid

- [x] The file's presence is required
- [ ] The file's contents must be non-blank

### Rule: `docs/TESTS.md` is valid

- [x] The file's presence is required
- [ ] The file's contents must be non-blank
- [ ] The Markdown must conform to the [Markdown standards](https://github.com/exercism/docs/blob/main/building/markdown/markdown.md)
- [ ] Links must be absolute (relative links are not allowed)

---

### Glossary

1. Non-blank string: a string that contains at least one non-whitespace character.
2. kebab-case string: a string that contains only characters in the range `[a-z0-9]`, optionally separated by dashes (e.g. "two-fer"). It must match the regular expression: `^[a-z0-9]+(-[a-z0-9]+)*$`
3. Title Case string: a non-blank string that follows the below guidelines (from the Chicago Manual of Style, see https://en.wikipedia.org/wiki/Title_case):
> - Capitalize the first and last words of titles and subtitles.
> - Capitalize "major" words (nouns, pronouns, verbs, adjectives, adverbs, and some conjunctions).
> - Lowercase the conjunctions _and_, _but_, _for_, _or_, and _nor_.
> - Lowercase the articles _the_, _a_, and _an_.
> - Lowercase prepositions, regardless of length, except when they are stressed, are used adverbially or adjectivally, or are used as conjunctions.
> - Lowercase the words _to_ and _as_.
> - Lowercase the second part of Latin species names.
4. Sentence Case string: a non-blank string that follows the below guidelines (see https://en.wikipedia.org/wiki/Letter_case#Sentence_case):
> - Capitalize the first word of the sentence, as well as proper nouns and other words as required by a more specific rule.
5. Valid `files` pattern: A non-blank string¹ that specifies a location of a file used in an exercise, relative to the exercise's directory. A pattern may use one of the following placeholders:
- `%{kebab_slug}`: the `kebab-case` exercise slug (e.g. `bit-manipulation`)
- `%{snake_slug}`: the `snake_case` exercise slug (e.g. `bit_manipulation`)
- `%{camel_slug}`: the `camelCase` exercise slug (e.g. `bitManipulation`)
- `%{pascal_slug}`: the `PascalCase` exercise slug (e.g. `BitManipulation`)
6. Unique version 4 UUID string: A string that satisfies all of these conditions:
- It only exists once in the track-level `config.json` file of a given Exercism track
- It does not exist in the track-level `config.json` file of any other Exercism track
- It does not exist in any `canonical-data.json` file in https://github.com/exercism/problem-specifications
- It does not exist anywhere else on Exercism
- It matches the regular expression:
```
^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$
```
For example, the below UUID has the correct form:
```
d334ffe3-657e-4725-a950-290b284b6d9f
```
You can run `configlet uuid` to generate a suitable UUID.

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.