Skip to content

Commit

Permalink
Add articles documentation (exercism#406)
Browse files Browse the repository at this point in the history
Add articles documentation

Co-authored-by: ee7 <45465154+ee7@users.noreply.github.com>
  • Loading branch information
ErikSchierboom and ee7 authored Nov 15, 2022
1 parent f182326 commit a03e0a9
Show file tree
Hide file tree
Showing 7 changed files with 289 additions and 94 deletions.
7 changes: 7 additions & 0 deletions building/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -562,6 +562,13 @@
"title": "Approaches",
"blurb": "Learn how to write approaches for exercises"
},
{
"uuid": "362853a0-dc4a-43ee-abbb-d4a14cb5b5bb",
"slug": "tracks/articles",
"path": "building/tracks/articles.md",
"title": "Articles",
"blurb": "Learn how to write articles for exercises"
},
{
"uuid": "8db530bb-e11b-4497-b088-5b4c997e09a2",
"slug": "tracks/presentation",
Expand Down
96 changes: 96 additions & 0 deletions building/configlet/lint.md
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,102 @@ The `config.json` file should have the following checks:
- The `"test_runner"` key is optional
- The `"test_runner"` value must be a boolean

### Rule: exercises/{concept|practice}/&lt;slug&gt;/.approaches/config.json is valid

- The file's presence is optional, unless there is a `introduction.md` or a sibling directory
- The file must be valid JSON
- The JSON root must be an object
- The `"introduction.authors"` key is optional
- The `"introduction.authors"` value must be an array
- The `"introduction.authors"` values must be non-blank strings¹
- The `"introduction.authors"` values must not have duplicates
- The `"introduction.authors"` values are treated case-insensitively
- If the `"introduction.authors"` array is non-empty, there must be a non-empty `introduction.md` file
- The `"introduction.contributors"` key is optional
- The `"introduction.contributors"` value must be an array
- The `"introduction.contributors"` values must be non-blank strings¹
- The `"introduction.contributors"` values must not have duplicates
- The `"introduction.contributors"` values are treated case-insensitively
- If the `"introduction.contributors"` array is non-empty, there must be a non-empty `introduction.md` file
- Users can only be listed in either the `"introduction.authors"` or `"introduction.contributors"` array (no overlap)
- The `"approaches"` key is optional, unless there is a sibling directory present (which contains the approach' files)
- The `"approaches"` value must be an array of objects
- The `"approaches[].uuid"` key is required
- The `"approaches[].uuid"` value must be a unique version 4 UUID string⁶
- The `"approaches[].uuid"` value for each concept must never change
- The `"approaches[].slug"` key is required
- The `"approaches[].slug"` value must be a kebab-case string² with length <= 255
- The `"approaches[].slug"` value must have a corresponding non-empty `<slug>/content.md` file
- The `"approaches[].slug"` value must have a corresponding non-empty `<slug>/snippet.txt` file
- The `"approaches[].name"` key is required
- The `"approaches[].name"` value must be a Title Case string³ with length <= 255
- The `"approaches[].blurb"` key is required
- The `"approaches[].blurb"` value must be a non-blank string¹ with length <= 350
- The `"approaches[].authors"` key is required
- The `"approaches[].authors"` value must be a non-empty array
- The `"approaches[].authors"` values must be non-blank strings¹
- The `"approaches[].authors"` values must not have duplicates
- The `"approaches[].authors"` values are treated case-insensitively
- The `"approaches[].contributors"` key is optional
- The `"approaches[].contributors"` value must be an array
- The `"approaches[].contributors"` values must be non-blank strings¹
- The `"approaches[].contributors"` values must not have duplicates
- The `"approaches[].contributors"` values are treated case-insensitively
- Users can only be listed in either the `"approaches[].authors"` or `"approaches[].contributors"` array (no overlap)

### Rule: exercises/{concept|practice}/&lt;slug&gt;/.approaches/&lt;approach-slug&gt;/content.md is valid

- The file's presence is required if a matching `"approaches[].slug"` entry exists in the `.approaches/config.json` file
- The Markdown must conform to the [Markdown standards](/docs/building/markdown/markdown)
- Links must be absolute (relative links are not allowed)

### Rule: exercises/{concept|practice}/&lt;slug&gt;/.approaches/&lt;approach-slug&gt;/snippet.txt is valid

- The file's presence is required if a matching `"approaches[].slug"` entry exists in the `.approaches/config.json` file
- The snippet must have at most 8 lines

### Rule: exercises/{concept|practice}/&lt;slug&gt;/.articles/config.json is valid

- The file's presence is optional, unless there is a sibling directory
- The file must be valid JSON
- The JSON root must be an object
- The `"articles"` key is optional, unless there is a sibling directory present (which contains the article' files)
- The `"articles"` value must be an array of objects
- The `"articles[].uuid"` key is required
- The `"articles[].uuid"` value must be a unique version 4 UUID string⁶
- The `"articles[].uuid"` value for each concept must never change
- The `"articles[].slug"` key is required
- The `"articles[].slug"` value must be a kebab-case string² with length <= 255
- The `"articles[].slug"` value must have a corresponding non-empty `<slug>/content.md` file
- The `"articles[].slug"` value must have a corresponding non-empty `<slug>/snippet.md` file
- The `"articles[].name"` key is required
- The `"articles[].name"` value must be a Title Case string³ with length <= 255
- The `"articles[].blurb"` key is required
- The `"articles[].blurb"` value must be a non-blank string¹ with length <= 350
- The `"articles[].authors"` key is required
- The `"articles[].authors"` value must be a non-empty array
- The `"articles[].authors"` values must be non-blank strings¹
- The `"articles[].authors"` values must not have duplicates
- The `"articles[].authors"` values are treated case-insensitively
- The `"articles[].contributors"` key is optional
- The `"articles[].contributors"` value must be an array
- The `"articles[].contributors"` values must be non-blank strings¹
- The `"articles[].contributors"` values must not have duplicates
- The `"articles[].contributors"` values are treated case-insensitively
- Users can only be listed in either the `"articles[].authors"` or `"articles[].contributors"` array (no overlap)

### Rule: exercises/{concept|practice}/&lt;slug&gt;/.articles/&lt;article-slug&gt;/content.md is valid

- The file's presence is required if a matching `"articles[].slug"` entry exists in the `.articles/config.json` file
- The Markdown must conform to the [Markdown standards](/docs/building/markdown/markdown)
- Links must be absolute (relative links are not allowed)

### Rule: exercises/{concept|practice}/&lt;slug&gt;/.articles/&lt;article-slug&gt;/snippet.md is valid

- The file's presence is required if a matching `"articles[].slug"` entry exists in the `.articles/config.json` file
- The Markdown must conform to the [Markdown standards](/docs/building/markdown/markdown)
- The snippet must have at most 8 lines (leading and trailing code fence markers are ignored)

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

- The file's presence is optional
Expand Down
9 changes: 7 additions & 2 deletions building/tracks/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,13 @@ Tracks have two types of exercises:
- Concept exercises: they are designed to teach one or more concepts to a student. Check the [documentation](/docs/building/tracks/concept-exercises) for more information.
- Practice exercises: they are designed to practice learned concepts. Check the [documentation](/docs/building/tracks/practice-exercises) for more information.

Exercises can have approaches associated with them, which describe the different ways in which an exercise can be solved.
Check the [documentation](/docs/building/tracks/approaches) for more information.
### Dig deeper

Each exercise has an optional Dig Deeper section that can contain:

- [Approaches](/docs/building/tracks/approaches): different ways in which the exercise can be solved
- [Articles](/docs/building/tracks/articles): describe interesting aspects of the exercise
- Community videos: videos that showcase the exercise, usually by having someone solve the exercise from scratch

## Shared files

Expand Down
3 changes: 2 additions & 1 deletion building/tracks/approaches.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,15 @@ An approach should explore how an exercise can be solved a certain way.
- Its contents should either:
- Explore an idiomatic approach
- Explore a non-idiomatic, but interesting approach
- Contain a meta discussion (e.g. comparing the performance of approaches)
- Start with a (full) code sample
- Liberally use code samples in the rest of the document
- Feel free to dig deep into the topic
- Link to useful resources (e.g. documentation)
- The snippet should showcase the core of the approach
- A maximum of 8 lines can be used

If you'd like to compare different approaches, please write an [articles](/docs/building/tracks/articles).

## Approaches overview

- Give context to the problem
Expand Down
19 changes: 19 additions & 0 deletions building/tracks/articles.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Articles

Each exercise can have articles associated with them, which explore some interesting aspect of the exercise.

## Topics

Potential topics an article could explore:

- Comparing the performance of different approaches
- Anything interesting you can come up with!

## General considerations

- If your article is based on some code you've written, consider committing that code (within the article directory)
- An example being an article on performance, for which benchmarking code was written

## What exercises to write articles for?

Any exercise, as long as there is something interesting to explore.
133 changes: 118 additions & 15 deletions building/tracks/concept-exercises.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,14 @@ These files describe approaches for the exercise.
- `.approaches/<approach-slug>/content.md`: description of the approach (optional)
- `.approaches/<approach-slug>/snippet.txt`: snippet showcasing the approach (optional)

### Article files

These files describe articles for the exercise.

- `.articles/config.json`: metadata for the articles (optional)
- `.articles/<article-slug>/content.md`: description of the article (optional)
- `.articles/<article-slug>/snippet.md`: snippet showcasing the article (optional)

### Exercise files

The language-specific files, like the implementation and test files. The names of these files are track-specific.
Expand All @@ -72,11 +80,16 @@ exercises
└── concept
└── cars-assemble
├── .approaches
| ├── performance (approach)
| ├── for-loop
| | ├── content.md
| | └── snippet.txt
| ├── config.json
| └── introduction.md
├── .articles
| ├── performance
| | ├── content.md
| | └── snippet.md
| └── config.json
├── .docs
| ├── introduction.md
| ├── instructions.md
Expand Down Expand Up @@ -403,7 +416,7 @@ If readability is your primary concern (and it usually should be), the LINQ-base

**Presence:** Optional (required when an approach introduction or approach exists)

This file contains meta information on the exercise:
This file contains meta information on the exercise's approaches:

- `introduction`: The GitHub username(s) of the exercise approach introduction's author(s) (optional)

Expand Down Expand Up @@ -432,6 +445,96 @@ This file contains meta information on the exercise:
"approaches": [
{
"uuid": "448fb2b4-18ab-4e55-aa54-ad4ed6d5f7f6",
"slug": "span",
"title": "Use Span<T>",
"blurb": "Use Span<T> to efficiently reverse a string.",
"authors": ["erikschierboom"]
}
]
}
```

---

### File: `.approaches/<approach-slug>/content.md`

**Purpose:** Detailed description of the approach

**Presence:** Optional (required for approaches)

This file contains a detailed description of the approach.
Check the [documentation](/docs/building/tracks/approaches) for more information on what should go in this file.

#### Example

````markdown
# Span

```csharp
Span<char> chars = stackalloc char[input.Length];
for (var i = 0; i < input.Length; i++)
{
chars[input.Length - 1 - i] = input[i];
}
return new string(chars);
```

This `Span<T>` approach uses a `for` loop.
````

---

### File: `.approaches/<approach-slug>/snippet.txt`

**Purpose:** Snippet showcasing the approach

**Presence:** Optional (required for approaches)

This file contains a small snippet that showcases the approach.
The snippet is shown on an exercise's dig deeper page.

Its number of lines must be <= 8.

Check the [documentation](/docs/building/tracks/approaches) for more information on what should go in this file.

#### Example

```csharp
Span<char> chars = stackalloc char[input.Length];
for (var i = 0; i < input.Length; i++)
{
chars[input.Length - 1 - i] = input[i];
}
return new string(chars);
```

---

### File: `.article/config.json`

**Purpose:** Metadata for the articles

**Presence:** Optional (required when an article exists)

This file contains meta information on the exercise's articles:

- `articles`: An array listing the detailed articles (optional)
- `uuid`: a V4 UUID that uniquely identifies the article. The UUID must be unique both within the track as well as across all tracks, and must never change
- `slug`: the article's slug, which is a lowercased, kebab-case string. The slug must be unique across all article slugs within the track. Its length must be <= 255.
- `title`: the article's title. Its length must be <= 255.
- `blurb`: A short description of this article. Its length must be <= 350. Markdown is _not_ supported (required)
- `authors`: The GitHub username(s) of the exercise article's author(s) (required)
- Including reviewers if their reviews substantially change the exercise article (to the extent where it feels like "you got there together")
- `contributors`: The GitHub username(s) of the exercise article's contributor(s) (optional)
- Including reviewers if their reviews are meaningful/actionable/actioned.

#### Example

```json
{
"articles": [
{
"uuid": "6db71962-62d5-448b-a980-c20ae41013ed",
"slug": "performance",
"title": "Optimizing performance",
"blurb": "Explore how to most efficiently reverse a string and what the trade-offs are.",
Expand All @@ -443,14 +546,14 @@ This file contains meta information on the exercise:

---

### File: `.approaches/<approach-slug>/content.md`
### File: `.articles/<article-slug>/content.md`

**Purpose:** Detailed description of the approach

**Presence:** Optional (required for approaches)

This file contains a detailed description of the approach.
Check the [documentation](/docs/building/tracks/approaches) for more information on what should go in this file.
Check the [documentation](/docs/building/tracks/articles) for more information on what should go in this file.

#### Example

Expand All @@ -469,26 +572,26 @@ In this document, we'll find out which approach is the most performant one.

---

### File: `.approaches/<approach-slug>/snippet.txt`
### File: `.articles/<article-slug>/snippet.txt`

**Purpose:** Snippet showcasing the approach

**Presence:** Optional (required for approaches)
**Presence:** Optional (required for articles)

This file contains a small snippet that showcases the approach.
The snippet is shown on an exercise's approaches overview page.
This file contains a small snippet that showcases the article.
The snippet is shown on an exercise's dig deeper page.

Its number of lines must be <= 8.

Check the [documentation](/docs/building/tracks/articles) for more information on what should go in this file.

#### Example

```csharp
Span<char> chars = stackalloc char[input.Length];
for (var i = 0; i < input.Length; i++)
{
chars[input.Length - 1 - i] = input[i];
}
return new string(chars);
```markdown
| Method | Mean | Allocated |
| -----: | --------: | --------: |
| Linq | 29.133 ns | 80 B |
| Array | 4.806 ns | - |
```

---
Expand Down
Loading

0 comments on commit a03e0a9

Please sign in to comment.