From 74e1a09837d171c792b1bef443dc7f8a6217bf7e Mon Sep 17 00:00:00 2001
From: MaoShizhong <122839503+MaoShizhong@users.noreply.github.com>
Date: Tue, 9 Jul 2024 14:19:06 +0100
Subject: [PATCH 01/14] Add note box heading level test file
---
.../tests/TOP012_test.md | 57 +++++++++++++++++++
1 file changed, 57 insertions(+)
create mode 100644 markdownlint/TOP012_noteBoxHeadingLevel/tests/TOP012_test.md
diff --git a/markdownlint/TOP012_noteBoxHeadingLevel/tests/TOP012_test.md b/markdownlint/TOP012_noteBoxHeadingLevel/tests/TOP012_test.md
new file mode 100644
index 00000000000..b80d66ab2ec
--- /dev/null
+++ b/markdownlint/TOP012_noteBoxHeadingLevel/tests/TOP012_test.md
@@ -0,0 +1,57 @@
+### Introduction
+
+This file should flag with TOP012 errors, and no other linting errors.
+
+### Lesson overview
+
+This section contains a general overview of topics that you will learn in this lesson.
+
+- A LESSON OVERVIEW ITEM.
+
+### Custom section
+
+#### Non-note box level 4 headings will not flag this error
+
+Custom subsection contents.
+
+
+
+#### Level 4 note box heading: Correct and will not flag error
+
+Note box contents.
+
+
+
+
+
+### Level 3 note box heading: Will flag error as it should be level 4
+
+Note box contents.
+
+
+
+
+
+## Level 2 note box heading: Will flag error as it should be level 4
+
+Note box contents.
+
+
+
+### Assignment
+
+ {
+ const headingHashes = heading.markup;
+ if (headingHashes.length === 4) {
+ return;
+ }
+
+ const headingText = heading.line.slice(headingHashes.length + 1);
+ onError({
+ lineNumber: heading.lineNumber,
+ detail: `\n Expected: #### ${headingText}\n Actual: ${headingHashes} ${headingText}\n`,
+ fixInfo: {
+ editColumn: 1,
+ deleteCount: headingHashes.length,
+ insertText: "####",
+ },
+ });
+ });
+ },
+};
From fadf9a132a787ca5366626a402c9f26eec519088 Mon Sep 17 00:00:00 2001
From: MaoShizhong <122839503+MaoShizhong@users.noreply.github.com>
Date: Tue, 9 Jul 2024 14:57:13 +0100
Subject: [PATCH 03/14] Add doc file
---
markdownlint/docs/TOP012.md | 37 +++++++++++++++++++++++++++++++++++++
1 file changed, 37 insertions(+)
create mode 100644 markdownlint/docs/TOP012.md
diff --git a/markdownlint/docs/TOP012.md b/markdownlint/docs/TOP012.md
new file mode 100644
index 00000000000..79597db8429
--- /dev/null
+++ b/markdownlint/docs/TOP012.md
@@ -0,0 +1,37 @@
+# `TOP012`: Note box heading level
+
+Tags: `headings`
+
+Aliases: `note-box-heading-level`
+
+This rule is triggered when a [note box](https://github.com/TheOdinProject/curriculum/blob/main/LAYOUT_STYLE_GUIDE.md#note-boxes) has its heading not set at level 4, which is required by our layout style guide.
+
+```markdown
+
+
+### Non-level 4 note box heading: Will flag a TOP012 error as it should be level 4
+
+Note box contents.
+
+
+```
+
+This can be resolved by changing the note box heading to a level 4 heading:
+
+```markdown
+
+
+#### Level 4 note box heading: Correct and will not flag a TOP012 error
+
+Note box contents.
+
+
+```
+
+This error is fixable with our `fix:*` npm scripts, which will convert the heading to be at level 4.
+
+## Rationale
+
+Consistent use of heading levels for note boxes looks better on the website, and is less confusion as note boxes are not main sections themselves, so should not use a level 3 heading.
+
+The website also uses specific CSS for when note box headings are hovered over. Having non-level 4 headings in these note boxes causes behaviour inconsistent with what we expect.
From 54403c1165fdbe3dcfafc372cc6fba3076edb644 Mon Sep 17 00:00:00 2001
From: MaoShizhong <122839503+MaoShizhong@users.noreply.github.com>
Date: Sun, 25 Aug 2024 16:49:05 +0100
Subject: [PATCH 04/14] Rename to TOP011
Original propose TOP011 closed
---
.markdownlint-cli2.jsonc | 2 +-
.../TOP011_noteBoxHeadingLevel.js} | 6 +++---
.../tests/TOP011_test.md} | 2 +-
markdownlint/docs/{TOP012.md => TOP011.md} | 6 +++---
4 files changed, 8 insertions(+), 8 deletions(-)
rename markdownlint/{TOP012_noteBoxHeadingLevel/TOP012_noteBoxHeadingLevel.js => TOP011_noteBoxHeadingLevel/TOP011_noteBoxHeadingLevel.js} (90%)
rename markdownlint/{TOP012_noteBoxHeadingLevel/tests/TOP012_test.md => TOP011_noteBoxHeadingLevel/tests/TOP011_test.md} (95%)
rename markdownlint/docs/{TOP012.md => TOP011.md} (90%)
diff --git a/.markdownlint-cli2.jsonc b/.markdownlint-cli2.jsonc
index 829ecf3706d..298ab125aad 100644
--- a/.markdownlint-cli2.jsonc
+++ b/.markdownlint-cli2.jsonc
@@ -88,6 +88,6 @@
"./markdownlint/TOP007_useMarkdownLinks/TOP007_useMarkdownLinks.js",
"./markdownlint/TOP008_useBackticksForFencedCodeBlocks/TOP008_useBackticksForFencedCodeBlocks.js",
"./markdownlint/TOP010_useLazyNumbering/TOP010_useLazyNumbering.js",
- "./markdownlint/TOP012_noteBoxHeadingLevel/TOP012_noteBoxHeadingLevel.js"
+ "./markdownlint/TOP011_noteBoxHeadingLevel/TOP011_noteBoxHeadingLevel.js"
]
}
diff --git a/markdownlint/TOP012_noteBoxHeadingLevel/TOP012_noteBoxHeadingLevel.js b/markdownlint/TOP011_noteBoxHeadingLevel/TOP011_noteBoxHeadingLevel.js
similarity index 90%
rename from markdownlint/TOP012_noteBoxHeadingLevel/TOP012_noteBoxHeadingLevel.js
rename to markdownlint/TOP011_noteBoxHeadingLevel/TOP011_noteBoxHeadingLevel.js
index c2f4f5a1278..afa1e482e28 100644
--- a/markdownlint/TOP012_noteBoxHeadingLevel/TOP012_noteBoxHeadingLevel.js
+++ b/markdownlint/TOP011_noteBoxHeadingLevel/TOP011_noteBoxHeadingLevel.js
@@ -1,12 +1,12 @@
module.exports = {
- names: ["TOP012", "note-box-heading-level"],
+ names: ["TOP011", "note-box-heading-level"],
description: "Note box headings must be level 4 (####)",
information: new URL(
- "https://github.com/TheOdinProject/curriculum/blob/main/markdownlint/docs/TOP012.md"
+ "https://github.com/TheOdinProject/curriculum/blob/main/markdownlint/docs/TOP011.md"
),
tags: ["headings"],
parser: "markdownit",
- function: function TOP012(params, onError) {
+ function: function TOP011(params, onError) {
const noteBoxHeadings = params.parsers.markdownit.tokens.filter((token, index, tokens) => {
const previousToken = tokens[index - 1];
diff --git a/markdownlint/TOP012_noteBoxHeadingLevel/tests/TOP012_test.md b/markdownlint/TOP011_noteBoxHeadingLevel/tests/TOP011_test.md
similarity index 95%
rename from markdownlint/TOP012_noteBoxHeadingLevel/tests/TOP012_test.md
rename to markdownlint/TOP011_noteBoxHeadingLevel/tests/TOP011_test.md
index b80d66ab2ec..555c22fba24 100644
--- a/markdownlint/TOP012_noteBoxHeadingLevel/tests/TOP012_test.md
+++ b/markdownlint/TOP011_noteBoxHeadingLevel/tests/TOP011_test.md
@@ -1,6 +1,6 @@
### Introduction
-This file should flag with TOP012 errors, and no other linting errors.
+This file should flag with TOP011 errors, and no other linting errors.
### Lesson overview
diff --git a/markdownlint/docs/TOP012.md b/markdownlint/docs/TOP011.md
similarity index 90%
rename from markdownlint/docs/TOP012.md
rename to markdownlint/docs/TOP011.md
index 79597db8429..3c438d49f63 100644
--- a/markdownlint/docs/TOP012.md
+++ b/markdownlint/docs/TOP011.md
@@ -1,4 +1,4 @@
-# `TOP012`: Note box heading level
+# `TOP011` - Note box heading level
Tags: `headings`
@@ -9,7 +9,7 @@ This rule is triggered when a [note box](https://github.com/TheOdinProject/curri
```markdown
-### Non-level 4 note box heading: Will flag a TOP012 error as it should be level 4
+### Non-level 4 note box heading: Will flag a TOP011 error as it should be level 4
Note box contents.
@@ -21,7 +21,7 @@ This can be resolved by changing the note box heading to a level 4 heading:
```markdown
-#### Level 4 note box heading: Correct and will not flag a TOP012 error
+#### Level 4 note box heading: Correct and will not flag a TOP011 error
Note box contents.
From bbe5767ef11e29318cbc423404d6e2f13b14fa1e Mon Sep 17 00:00:00 2001
From: MaoShizhong <122839503+MaoShizhong@users.noreply.github.com>
Date: Wed, 2 Oct 2024 19:47:24 +0100
Subject: [PATCH 05/14] Rename lint rule
Now made generic for multiple aspects of note box headings
---
.markdownlint-cli2.jsonc | 2 +-
.../TOP011_noteBoxHeadings.js} | 4 ++--
.../tests/TOP011_test.md | 0
markdownlint/docs/TOP011.md | 4 ++--
4 files changed, 5 insertions(+), 5 deletions(-)
rename markdownlint/{TOP011_noteBoxHeadingLevel/TOP011_noteBoxHeadingLevel.js => TOP011_noteBoxHeadings/TOP011_noteBoxHeadings.js} (91%)
rename markdownlint/{TOP011_noteBoxHeadingLevel => TOP011_noteBoxHeadings}/tests/TOP011_test.md (100%)
diff --git a/.markdownlint-cli2.jsonc b/.markdownlint-cli2.jsonc
index 298ab125aad..52794ef44d0 100644
--- a/.markdownlint-cli2.jsonc
+++ b/.markdownlint-cli2.jsonc
@@ -88,6 +88,6 @@
"./markdownlint/TOP007_useMarkdownLinks/TOP007_useMarkdownLinks.js",
"./markdownlint/TOP008_useBackticksForFencedCodeBlocks/TOP008_useBackticksForFencedCodeBlocks.js",
"./markdownlint/TOP010_useLazyNumbering/TOP010_useLazyNumbering.js",
- "./markdownlint/TOP011_noteBoxHeadingLevel/TOP011_noteBoxHeadingLevel.js"
+ "./markdownlint/TOP011_noteBoxHeadings/TOP011_noteBoxHeadings.js"
]
}
diff --git a/markdownlint/TOP011_noteBoxHeadingLevel/TOP011_noteBoxHeadingLevel.js b/markdownlint/TOP011_noteBoxHeadings/TOP011_noteBoxHeadings.js
similarity index 91%
rename from markdownlint/TOP011_noteBoxHeadingLevel/TOP011_noteBoxHeadingLevel.js
rename to markdownlint/TOP011_noteBoxHeadings/TOP011_noteBoxHeadings.js
index afa1e482e28..a2af17ec12f 100644
--- a/markdownlint/TOP011_noteBoxHeadingLevel/TOP011_noteBoxHeadingLevel.js
+++ b/markdownlint/TOP011_noteBoxHeadings/TOP011_noteBoxHeadings.js
@@ -1,6 +1,6 @@
module.exports = {
- names: ["TOP011", "note-box-heading-level"],
- description: "Note box headings must be level 4 (####)",
+ names: ["TOP011", "note-box-headings"],
+ description: "Note boxes have appropriate headings",
information: new URL(
"https://github.com/TheOdinProject/curriculum/blob/main/markdownlint/docs/TOP011.md"
),
diff --git a/markdownlint/TOP011_noteBoxHeadingLevel/tests/TOP011_test.md b/markdownlint/TOP011_noteBoxHeadings/tests/TOP011_test.md
similarity index 100%
rename from markdownlint/TOP011_noteBoxHeadingLevel/tests/TOP011_test.md
rename to markdownlint/TOP011_noteBoxHeadings/tests/TOP011_test.md
diff --git a/markdownlint/docs/TOP011.md b/markdownlint/docs/TOP011.md
index 3c438d49f63..3fa1e1f033f 100644
--- a/markdownlint/docs/TOP011.md
+++ b/markdownlint/docs/TOP011.md
@@ -1,8 +1,8 @@
-# `TOP011` - Note box heading level
+# `TOP011` - Note box headings
Tags: `headings`
-Aliases: `note-box-heading-level`
+Aliases: `note-box-headings`
This rule is triggered when a [note box](https://github.com/TheOdinProject/curriculum/blob/main/LAYOUT_STYLE_GUIDE.md#note-boxes) has its heading not set at level 4, which is required by our layout style guide.
From 55384cc27dd5976bca387462b3599ab9e802d748 Mon Sep 17 00:00:00 2001
From: MaoShizhong <122839503+MaoShizhong@users.noreply.github.com>
Date: Wed, 2 Oct 2024 20:03:48 +0100
Subject: [PATCH 06/14] Amend test file with new TOP011 error examples
---
.../tests/TOP011_test.md | 72 +++++++++++++++++--
1 file changed, 66 insertions(+), 6 deletions(-)
diff --git a/markdownlint/TOP011_noteBoxHeadings/tests/TOP011_test.md b/markdownlint/TOP011_noteBoxHeadings/tests/TOP011_test.md
index 555c22fba24..674663ba70e 100644
--- a/markdownlint/TOP011_noteBoxHeadings/tests/TOP011_test.md
+++ b/markdownlint/TOP011_noteBoxHeadings/tests/TOP011_test.md
@@ -8,15 +8,19 @@ This section contains a general overview of topics that you will learn in this l
- A LESSON OVERVIEW ITEM.
-### Custom section
+### Non-note box heading will not flag any TOP011 errors
-#### Non-note box level 4 headings will not flag this error
-
-Custom subsection contents.
+Custom subsection content
-#### Level 4 note box heading: Correct and will not flag error
+Note boxes without headings will flag a TOP011 "missing header" error.
+
+
+
+
+
+## Level 2 note box heading: Will flag error as it should be level 4
Note box contents.
@@ -32,7 +36,63 @@ Note box contents.
-## Level 2 note box heading: Will flag error as it should be level 4
+#### Note: Correct heading format for standard note boxes
+
+Note box contents.
+
+
+
+
+
+#### Standard note box heading not starting with "Note:"
+
+Note box contents.
+
+
+
+
+
+#### Tip: Correct heading format for tip note boxes
+
+Note box contents.
+
+
+
+
+
+#### Tip note box heading not starting with "Tip:"
+
+Note box contents.
+
+
+
+
+
+#### Warning: Correct heading format for warning note boxes
+
+Note box contents.
+
+
+
+
+
+#### Warning note box heading not starting with "Warning:"
+
+Note box contents.
+
+
+
+
+
+#### Critical: Correct heading format for critical note boxes
+
+Note box contents.
+
+
+
+
+
+#### Critical note box heading not starting with "Critical:"
Note box contents.
From 567c26125fd4ebaa4f8501ada8d517bda9c4d920 Mon Sep 17 00:00:00 2001
From: MaoShizhong <122839503+MaoShizhong@users.noreply.github.com>
Date: Wed, 2 Oct 2024 22:22:31 +0100
Subject: [PATCH 07/14] Enforce level 4 headings for all note boxes
3 different types of note box heading errors now
- missing heading
- incorrect heading level
- incorrect heading start text (type-dependent)
Will help make note boxes more accessible (linkable via heading id
fragment, and note box type not limited to visual differences and div class).
---
.../TOP011_noteBoxHeadings.js | 101 ++++++++++++++----
1 file changed, 83 insertions(+), 18 deletions(-)
diff --git a/markdownlint/TOP011_noteBoxHeadings/TOP011_noteBoxHeadings.js b/markdownlint/TOP011_noteBoxHeadings/TOP011_noteBoxHeadings.js
index a2af17ec12f..afe24b2a3e8 100644
--- a/markdownlint/TOP011_noteBoxHeadings/TOP011_noteBoxHeadings.js
+++ b/markdownlint/TOP011_noteBoxHeadings/TOP011_noteBoxHeadings.js
@@ -1,3 +1,42 @@
+function capitalize(text) {
+ return `${text[0].toUpperCase()}${text.substring(1)}`;
+}
+
+function isNoteBoxOpenTag(token) {
+ return token?.type === "html_block" && token?.content.includes("lesson-note");
+}
+
+function lacksHeading(token, index, tokens) {
+ return isNoteBoxOpenTag(token) && tokens[index + 1]?.type !== "heading_open";
+}
+
+function categoriseHeadingsByNoteBoxType(
+ headings,
+ currentToken,
+ index,
+ tokens
+) {
+ const previousToken = tokens[index - 1];
+ if (
+ currentToken.type !== "heading_open" ||
+ !isNoteBoxOpenTag(previousToken)
+ ) {
+ return headings;
+ }
+
+ // https://regexr.com/86jmp to test the regex below
+ const noteBoxType = capitalize(
+ previousToken.content.match(/(?<=lesson-note--).+?(?=\W)/)?.[0] ?? "note"
+ );
+
+ headings[noteBoxType].push({
+ text: currentToken.line,
+ hashes: currentToken.markup,
+ lineNumber: currentToken.lineNumber,
+ });
+ return headings;
+}
+
module.exports = {
names: ["TOP011", "note-box-headings"],
description: "Note boxes have appropriate headings",
@@ -7,29 +46,55 @@ module.exports = {
tags: ["headings"],
parser: "markdownit",
function: function TOP011(params, onError) {
- const noteBoxHeadings = params.parsers.markdownit.tokens.filter((token, index, tokens) => {
- const previousToken = tokens[index - 1];
+ const { tokens } = params.parsers.markdownit;
+ // console.log(tokens);
+ const noteBoxesWithoutHeadings = tokens.filter(lacksHeading);
+ const noteBoxHeadings = tokens.reduce(categoriseHeadingsByNoteBoxType, {
+ Note: [],
+ Tip: [],
+ Warning: [],
+ Critical: [],
+ });
- const isFollowingNoteBoxOpening =
- previousToken?.line?.startsWith("
{
+ onError({
+ lineNumber: noteBox.lineNumber,
+ detail:
+ "Note box is missing a heading. Note boxes must start with a level 4 heading (####).",
+ });
});
- noteBoxHeadings.forEach((heading) => {
- const headingHashes = heading.markup;
- if (headingHashes.length === 4) {
- return;
+ Object.entries(noteBoxHeadings).forEach(([noteBoxType, headings]) => {
+ headings.forEach(({ text, hashes, lineNumber }) => {
+ if (text.trim().startsWith(`#### ${capitalize(noteBoxType)}:`)) {
+ return;
}
- const headingText = heading.line.slice(headingHashes.length + 1);
- onError({
- lineNumber: heading.lineNumber,
- detail: `\n Expected: #### ${headingText}\n Actual: ${headingHashes} ${headingText}\n`,
- fixInfo: {
- editColumn: 1,
- deleteCount: headingHashes.length,
- insertText: "####",
- },
+ const leadingSpaces = text.indexOf(hashes);
+ const firstWordIndex = leadingSpaces.length + hashes.length + 1;
+ const firstWord = text.slice(firstWordIndex, text.indexOf(":"));
+ const baseErrorInfo = {
+ lineNumber: lineNumber,
+ context: text,
+ };
+
+ if (firstWord !== noteBoxType) {
+ onError({
+ ...baseErrorInfo,
+ detail: `${noteBoxType} box heading text must start with "${noteBoxType}:"`,
+ });
+ }
+ if (hashes.length !== 4) {
+ onError({
+ ...baseErrorInfo,
+ detail: `Expected a level 4 heading (####) but got a level ${hashes.length} heading (${hashes}) instead.`,
+ fixInfo: {
+ editColumn: leadingSpaces + 1,
+ deleteCount: hashes.length,
+ insertText: "####",
+ },
+ });
+ }
});
});
},
From 257e01d2b9f19cada80f4c40be0cf2eabc07abec Mon Sep 17 00:00:00 2001
From: MaoShizhong <122839503+MaoShizhong@users.noreply.github.com>
Date: Wed, 2 Oct 2024 22:42:55 +0100
Subject: [PATCH 08/14] Amend TOP011 docs with new rule intent/rationale
---
markdownlint/docs/TOP011.md | 40 +++++++++++++++++++++++++++++++------
1 file changed, 34 insertions(+), 6 deletions(-)
diff --git a/markdownlint/docs/TOP011.md b/markdownlint/docs/TOP011.md
index 3fa1e1f033f..322b9360ed4 100644
--- a/markdownlint/docs/TOP011.md
+++ b/markdownlint/docs/TOP011.md
@@ -4,12 +4,38 @@ Tags: `headings`
Aliases: `note-box-headings`
-This rule is triggered when a [note box](https://github.com/TheOdinProject/curriculum/blob/main/LAYOUT_STYLE_GUIDE.md#note-boxes) has its heading not set at level 4, which is required by our layout style guide.
+This rule is triggered when a [note box](https://github.com/TheOdinProject/curriculum/blob/main/LAYOUT_STYLE_GUIDE.md#note-boxes) does not open with a level 4 heading and/or the heading text does not start with appropriate note box type (as described in the layout style guide).
```markdown
-### Non-level 4 note box heading: Will flag a TOP011 error as it should be level 4
+This note box does not have a heading, so will flag a TOP011 error.
+
+
+```
+
+```markdown
+
+
+#### Heading not starting with "Warning:"
+
+Note box contents.
+
+
+```
+
+The warning box above does open with a level 4 heading but the heading text does not start with `Warning:`. To resolve this error, the heading text can be changed to:
+
+```markdown
+#### Warning: Heading now starting with "Warning:"
+```
+
+A TOP011 error will also be thrown if the note box heading is not level 4:
+
+```markdown
+
+
+### Note: Non-level 4 note box heading: Will flag a TOP011 error as it should be level 4
Note box contents.
@@ -21,17 +47,19 @@ This can be resolved by changing the note box heading to a level 4 heading:
```markdown
-#### Level 4 note box heading: Correct and will not flag a TOP011 error
+#### Note: Level 4 note box heading: Correct and will not flag a TOP011 error
Note box contents.
```
-This error is fixable with our `fix:*` npm scripts, which will convert the heading to be at level 4.
+Incorrect heading level errors are fixable with our `fix:*` npm scripts, which will convert the heading to be level 4. Missing heading errors and note box type errors are not fixable via our `fix:*` scripts, so must be manually addressed.
## Rationale
-Consistent use of heading levels for note boxes looks better on the website, and is less confusion as note boxes are not main sections themselves, so should not use a level 3 heading.
+Our lesson headings are linkable via ID fragments. By enforcing headings for note boxes, they can be better summarised at a glance while always being linkable to.
+
+While different note box types are distinguishable via border colors and icons, this may not be sufficiently accesible for some people with visual deficiencies. It is more accessible to convey the note box type through the heading text itself.
-The website also uses specific CSS for when note box headings are hovered over. Having non-level 4 headings in these note boxes causes behaviour inconsistent with what we expect.
+Consistent use of heading levels for note boxes also looks better on the website. Since note boxes are not main sections themselves, they should not use level 3 headings. The website also uses specific CSS for when note box headings are hovered over. Having non-level 4 headings in these note boxes causes behaviour inconsistent with what we expect.
From 6e253481d9f9dc2a265c61789d75ff213e397908 Mon Sep 17 00:00:00 2001
From: MaoShizhong <122839503+MaoShizhong@users.noreply.github.com>
Date: Wed, 2 Oct 2024 22:52:36 +0100
Subject: [PATCH 09/14] Enforce note box heading rules in layout style guide
---
LAYOUT_STYLE_GUIDE.md | 19 ++++++++++++++-----
1 file changed, 14 insertions(+), 5 deletions(-)
diff --git a/LAYOUT_STYLE_GUIDE.md b/LAYOUT_STYLE_GUIDE.md
index 3c54729d7a2..1e5f3e6d35d 100644
--- a/LAYOUT_STYLE_GUIDE.md
+++ b/LAYOUT_STYLE_GUIDE.md
@@ -408,9 +408,7 @@ Will result in the following output:
Note boxes can be added by wrapping the content in a `div` with the class `lesson-note`. This will add styling to make the note stand out visually to users.
-For nested markdown inside note boxes to be displayed properly additional `markdown="1" attribute` is needed.
-
-A heading can be added to a note by using a `####` heading. When adding a heading, be sure to provide text that helps describe the note rather than "A note" or "Warning".
+Note boxes will also need a `markdown="1"` attribute to render nested markdown properly.
The opening and closing tags must each be wrapped with a single blank line on either side, or a codeblock delimiter (triple backticks). This applies to any line that contains only a single HTML tag. The only exceptions to this rule are HTML tags inside `html`, `jsx`, `erb`, `ejs`, `javascript` or `ruby` codeblocks.
@@ -422,12 +420,23 @@ Different types of note boxes can be set by adding an extra class together with
- `lesson-note--warning` for warnings about potential issues/pitfalls, and are more severe than a tip
- `lesson-note--critical` for the most important warnings, such as critical information about handling sensitive data
+### Note box headings
+
+For better accessibility, note boxes must open with a level 4 heading (`####`) that starts with the note box variation.
+
+- Standard note boxes (no variation class) must start their heading with `Note:` e.g. `#### Note: HTTP verbs`.
+- Tip note box headings must start with `Tip:`.
+- Warning note box headings must start with `Warning:`.
+- Critical note box headings must start with `Critical:`.
+
+All other normal heading rules apply.
+
#### Example
```markdown
-#### An optional title
+#### Note: A standard note box heading
A sample note box.
@@ -437,7 +446,7 @@ A sample note box.
```markdown
-#### An optional title
+#### Tip: A tip note box heading
A sample note box, variation: tip.
From 3e478e33d3f8e767e6e7ea2c0ea3c30af40c3c2d Mon Sep 17 00:00:00 2001
From: MaoShizhong <122839503+MaoShizhong@users.noreply.github.com>
Date: Wed, 2 Oct 2024 22:55:47 +0100
Subject: [PATCH 10/14] Fix doc typo
---
markdownlint/docs/TOP011.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/markdownlint/docs/TOP011.md b/markdownlint/docs/TOP011.md
index 322b9360ed4..76bf21526fa 100644
--- a/markdownlint/docs/TOP011.md
+++ b/markdownlint/docs/TOP011.md
@@ -60,6 +60,6 @@ Incorrect heading level errors are fixable with our `fix:*` npm scripts, which w
Our lesson headings are linkable via ID fragments. By enforcing headings for note boxes, they can be better summarised at a glance while always being linkable to.
-While different note box types are distinguishable via border colors and icons, this may not be sufficiently accesible for some people with visual deficiencies. It is more accessible to convey the note box type through the heading text itself.
+While different note box types are distinguishable via border colors and icons, this may not be sufficiently accessible for some people with visual deficiencies. It is more accessible to convey the note box type through the heading text itself.
Consistent use of heading levels for note boxes also looks better on the website. Since note boxes are not main sections themselves, they should not use level 3 headings. The website also uses specific CSS for when note box headings are hovered over. Having non-level 4 headings in these note boxes causes behaviour inconsistent with what we expect.
From 2e2ec7ea14b8e4c39345a6ba6789655b94eef052 Mon Sep 17 00:00:00 2001
From: MaoShizhong <122839503+MaoShizhong@users.noreply.github.com>
Date: Thu, 3 Oct 2024 01:29:59 +0100
Subject: [PATCH 11/14] Remove debug logging
---
markdownlint/TOP011_noteBoxHeadings/TOP011_noteBoxHeadings.js | 1 -
1 file changed, 1 deletion(-)
diff --git a/markdownlint/TOP011_noteBoxHeadings/TOP011_noteBoxHeadings.js b/markdownlint/TOP011_noteBoxHeadings/TOP011_noteBoxHeadings.js
index afe24b2a3e8..f5b612215b5 100644
--- a/markdownlint/TOP011_noteBoxHeadings/TOP011_noteBoxHeadings.js
+++ b/markdownlint/TOP011_noteBoxHeadings/TOP011_noteBoxHeadings.js
@@ -47,7 +47,6 @@ module.exports = {
parser: "markdownit",
function: function TOP011(params, onError) {
const { tokens } = params.parsers.markdownit;
- // console.log(tokens);
const noteBoxesWithoutHeadings = tokens.filter(lacksHeading);
const noteBoxHeadings = tokens.reduce(categoriseHeadingsByNoteBoxType, {
Note: [],
From 55fbe6879d394e7bfa4c4eb040d54c65332b5614 Mon Sep 17 00:00:00 2001
From: MaoShizhong <122839503+MaoShizhong@users.noreply.github.com>
Date: Sat, 19 Oct 2024 14:21:35 +0100
Subject: [PATCH 12/14] Fix note box headings in lesson template/example
To follow this new lint rule.
---
templates/lesson-example.md | 6 +++---
templates/lesson-template.md | 8 +++++---
2 files changed, 8 insertions(+), 6 deletions(-)
diff --git a/templates/lesson-example.md b/templates/lesson-example.md
index 0a2712c83b6..b5820b3d8e3 100644
--- a/templates/lesson-example.md
+++ b/templates/lesson-example.md
@@ -8,8 +8,8 @@ Now that you understand the basic syntax of HTML and CSS, we’re going to get s
This section contains a general overview of topics that you will learn in this lesson.
-- What the box model is
-- Margins, padding, and borders
+- What the box model is.
+- Margins, padding, and borders.
### The box model
@@ -17,7 +17,7 @@ The first important concept that you need to understand to be successful in CSS
-#### Everything is a box
+#### Note: Everything is a box
Every single thing on a webpage is a rectangular box. These boxes can have other boxes in them and can sit alongside one another.
diff --git a/templates/lesson-template.md b/templates/lesson-template.md
index 7e9bd8b8cf3..72850df9c98 100644
--- a/templates/lesson-template.md
+++ b/templates/lesson-template.md
@@ -16,7 +16,7 @@ CUSTOM SECTION CONTENT.
-#### A sample title
+#### Note: A sample title
A sample note box.
@@ -24,7 +24,7 @@ A sample note box.
-#### level 4 heading for title is recommended
+#### Tip: A level 4 heading as a title is required
A sample note box, variation: tip.
@@ -32,7 +32,7 @@ A sample note box, variation: tip.
-#### But title is also optional
+#### Warning: And must start with the note box type
A sample note box, variation: warning.
@@ -40,6 +40,8 @@ A sample note box, variation: warning.
+#### Critical: Otherwise you'll get a lint error
+
A sample note box, variation: critical.
From 8da54075a605bccaddf8980929a5f0538182f61e Mon Sep 17 00:00:00 2001
From: MaoShizhong <122839503+MaoShizhong@users.noreply.github.com>
Date: Sat, 19 Oct 2024 14:23:43 +0100
Subject: [PATCH 13/14] Enforce space after :
---
.../TOP011_noteBoxHeadings/TOP011_noteBoxHeadings.js | 4 ++--
markdownlint/TOP011_noteBoxHeadings/tests/TOP011_test.md | 8 ++++----
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/markdownlint/TOP011_noteBoxHeadings/TOP011_noteBoxHeadings.js b/markdownlint/TOP011_noteBoxHeadings/TOP011_noteBoxHeadings.js
index f5b612215b5..7f4f531d112 100644
--- a/markdownlint/TOP011_noteBoxHeadings/TOP011_noteBoxHeadings.js
+++ b/markdownlint/TOP011_noteBoxHeadings/TOP011_noteBoxHeadings.js
@@ -65,7 +65,7 @@ module.exports = {
Object.entries(noteBoxHeadings).forEach(([noteBoxType, headings]) => {
headings.forEach(({ text, hashes, lineNumber }) => {
- if (text.trim().startsWith(`#### ${capitalize(noteBoxType)}:`)) {
+ if (text.trim().startsWith(`#### ${capitalize(noteBoxType)}: `)) {
return;
}
@@ -80,7 +80,7 @@ module.exports = {
if (firstWord !== noteBoxType) {
onError({
...baseErrorInfo,
- detail: `${noteBoxType} box heading text must start with "${noteBoxType}:"`,
+ detail: `${noteBoxType} box heading text must start with "${noteBoxType}: "`,
});
}
if (hashes.length !== 4) {
diff --git a/markdownlint/TOP011_noteBoxHeadings/tests/TOP011_test.md b/markdownlint/TOP011_noteBoxHeadings/tests/TOP011_test.md
index 674663ba70e..a453ef7b7aa 100644
--- a/markdownlint/TOP011_noteBoxHeadings/tests/TOP011_test.md
+++ b/markdownlint/TOP011_noteBoxHeadings/tests/TOP011_test.md
@@ -44,7 +44,7 @@ Note box contents.
-#### Standard note box heading not starting with "Note:"
+#### Standard note box heading not starting with "Note: "
Note box contents.
@@ -60,7 +60,7 @@ Note box contents.
-#### Tip note box heading not starting with "Tip:"
+#### Tip note box heading not starting with "Tip: "
Note box contents.
@@ -76,7 +76,7 @@ Note box contents.
-#### Warning note box heading not starting with "Warning:"
+#### Warning note box heading not starting with "Warning: "
Note box contents.
@@ -92,7 +92,7 @@ Note box contents.
-#### Critical note box heading not starting with "Critical:"
+#### Critical note box heading not starting with "Critical: "
Note box contents.
From f191baf303d135c2d1376a2230a9a9f544ae2545 Mon Sep 17 00:00:00 2001
From: MaoShizhong <122839503+MaoShizhong@users.noreply.github.com>
Date: Tue, 19 Nov 2024 12:41:23 +0000
Subject: [PATCH 14/14] Use US spelling
Fix formatting
---
.../TOP011_noteBoxHeadings/TOP011_noteBoxHeadings.js | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/markdownlint/TOP011_noteBoxHeadings/TOP011_noteBoxHeadings.js b/markdownlint/TOP011_noteBoxHeadings/TOP011_noteBoxHeadings.js
index 7f4f531d112..77fac4fba59 100644
--- a/markdownlint/TOP011_noteBoxHeadings/TOP011_noteBoxHeadings.js
+++ b/markdownlint/TOP011_noteBoxHeadings/TOP011_noteBoxHeadings.js
@@ -10,11 +10,11 @@ function lacksHeading(token, index, tokens) {
return isNoteBoxOpenTag(token) && tokens[index + 1]?.type !== "heading_open";
}
-function categoriseHeadingsByNoteBoxType(
+function categorizeHeadingsByNoteBoxType(
headings,
currentToken,
index,
- tokens
+ tokens,
) {
const previousToken = tokens[index - 1];
if (
@@ -26,7 +26,7 @@ function categoriseHeadingsByNoteBoxType(
// https://regexr.com/86jmp to test the regex below
const noteBoxType = capitalize(
- previousToken.content.match(/(?<=lesson-note--).+?(?=\W)/)?.[0] ?? "note"
+ previousToken.content.match(/(?<=lesson-note--).+?(?=\W)/)?.[0] ?? "note",
);
headings[noteBoxType].push({
@@ -41,14 +41,14 @@ module.exports = {
names: ["TOP011", "note-box-headings"],
description: "Note boxes have appropriate headings",
information: new URL(
- "https://github.com/TheOdinProject/curriculum/blob/main/markdownlint/docs/TOP011.md"
+ "https://github.com/TheOdinProject/curriculum/blob/main/markdownlint/docs/TOP011.md",
),
tags: ["headings"],
parser: "markdownit",
function: function TOP011(params, onError) {
const { tokens } = params.parsers.markdownit;
const noteBoxesWithoutHeadings = tokens.filter(lacksHeading);
- const noteBoxHeadings = tokens.reduce(categoriseHeadingsByNoteBoxType, {
+ const noteBoxHeadings = tokens.reduce(categorizeHeadingsByNoteBoxType, {
Note: [],
Tip: [],
Warning: [],
@@ -67,7 +67,7 @@ module.exports = {
headings.forEach(({ text, hashes, lineNumber }) => {
if (text.trim().startsWith(`#### ${capitalize(noteBoxType)}: `)) {
return;
- }
+ }
const leadingSpaces = text.indexOf(hashes);
const firstWordIndex = leadingSpaces.length + hashes.length + 1;