Skip to content

Commit 71a9749

Browse files
authored
Merge pull request #121 from makeabilitylab/feat/code-block-standardization
Standardize code blocks on fenced ```lang + markdownlint CI gate (#99)
2 parents b03209f + d2f91fe commit 71a9749

37 files changed

Lines changed: 639 additions & 557 deletions

.github/workflows/content-lint.yml

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
# Runs lightweight checks on the Markdown content. Separate from the deploy
44
# workflow (jekyll.yml) on purpose: a content-convention miss should block a
55
# MERGE, but never take down the live site. This is also the home for future
6-
# content gates (e.g. the #99 code-block standardization lint).
6+
# content gates. Current gates: SEO front matter, media a11y, code-block
7+
# standardization (#99), and html-proofer link/anchor/HTML validation.
78
name: Content lint
89

910
on:
@@ -45,6 +46,27 @@ jobs:
4546
- name: Check media a11y (iframe title, video aria-label, image alt)
4647
run: python scripts/check_a11y.py --ci
4748

49+
code-blocks:
50+
# Enforce #99 code-block standardization on the Markdown SOURCE: every fenced
51+
# block declares a language (MD040), blocks are fenced not indented (MD046),
52+
# and fences use backticks (MD048). Uses markdownlint-cli (NOT cli2) with -c
53+
# so the scoped .markdownlint-code.jsonc fully replaces config instead of
54+
# merging the editor .markdownlint.jsonc back in. House style: ```cpp for all
55+
# Arduino/ESP32 sketches. Deliberate indented demos opt out inline with
56+
# <!-- markdownlint-disable MD046 -->.
57+
runs-on: ubuntu-latest
58+
steps:
59+
- name: Checkout
60+
uses: actions/checkout@v4
61+
62+
- name: Setup Node
63+
uses: actions/setup-node@v4
64+
with:
65+
node-version: "20"
66+
67+
- name: Lint code-block conventions (MD040/MD046/MD048)
68+
run: npx --yes markdownlint-cli@0.48.0 -c .markdownlint-code.jsonc "**/*.md" --ignore "_site" --ignore "node_modules"
69+
4870
link-check:
4971
# Validate the BUILT site with html-proofer: broken internal links, broken
5072
# anchors, missing image alt, and malformed HTML. External links are NOT

.markdownlint-code.jsonc

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{
2+
// Scoped markdownlint config for the CI "code-blocks" gate (issue #99).
3+
//
4+
// This is INTENTIONALLY separate from the editor config (.markdownlint.jsonc):
5+
// it checks ONLY the code-block standardization rules so the gate can't fail
6+
// on the many unrelated style nits (MD009/MD022/MD032/...) that the content
7+
// predates. The CI job runs it via `markdownlint-cli -c` (which fully replaces
8+
// config, rather than markdownlint-cli2 which merges the discovered editor
9+
// config back in). Filename is non-standard on purpose so no tool auto-loads
10+
// it for editing.
11+
"default": false,
12+
13+
// MD040: every fenced code block must declare a language token (e.g. ```cpp,
14+
// ```bash, ```text). cpp is the house style for all Arduino/ESP32 sketches.
15+
"MD040": true,
16+
17+
// MD046: code blocks must be fenced, never indented (an indented block can't
18+
// carry a language token, so it would silently evade MD040). Deliberate
19+
// indented demos opt out inline with <!-- markdownlint-disable MD046 -->.
20+
"MD046": { "style": "fenced" },
21+
22+
// MD048: fences use backticks (```), not tildes (~~~), for consistency.
23+
"MD048": { "style": "backtick" }
24+
}

advancedio/addressable-leds.md

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ The Adafruit NeoPixel library can be installed directly from the Arduino Library
203203

204204
The NeoPixel library API will feel familiar if you've completed the [OLED lesson](oled.md)—it follows the same **buffer → display** pattern:
205205

206-
{% highlight C++ %}
206+
```cpp
207207
#include <Adafruit_NeoPixel.h>
208208

209209
const int LED_PIN = 2; // Any digital pin works — no PWM required!
@@ -219,7 +219,7 @@ void setup() {
219219
strip.setBrightness(50); // Set brightness (0-255). 50 is ~20% bright
220220
strip.show(); // Initialize all pixels to 'off'
221221
}
222-
{% endhighlight C++ %}
222+
```
223223
224224
{: .note }
225225
> Notice the same **buffer → show** pattern from the [OLED lesson](oled.md): `setPixelColor()` writes to a buffer in RAM, and `show()` pushes the data to the LEDs. If you forget to call `show()`, nothing will change on the LEDs—just like forgetting `_display.display()` on the OLED!
@@ -247,19 +247,19 @@ Here are the most commonly used functions from the [Adafruit NeoPixel library](h
247247
248248
Each pixel's color is specified using RGB values from an 8-bit value—0-255 per channel—just like the [RGB LED lesson](../arduino/rgb-led.md). Some examples:
249249
250-
{% highlight C++ %}
250+
```cpp
251251
// Named colors using strip.Color(R, G, B)
252252
uint32_t red = strip.Color(255, 0, 0);
253253
uint32_t green = strip.Color(0, 255, 0);
254254
uint32_t blue = strip.Color(0, 0, 255);
255255
uint32_t white = strip.Color(255, 255, 255);
256256
uint32_t purple = strip.Color(128, 0, 255);
257257
uint32_t off = strip.Color(0, 0, 0);
258-
{% endhighlight C++ %}
258+
```
259259

260260
For animations that cycle through colors, the **HSV** (hue, saturation, value) color space is much more useful than RGB. Remember the [HSL crossfading lesson](../arduino/rgb-led-fade.md)? The same principle applies here. The `ColorHSV()` function lets you smoothly sweep through the entire rainbow by varying just the hue value:
261261

262-
{% highlight C++ %}
262+
```cpp
263263
// Hue ranges from 0 to 65535 (full color wheel)
264264
// 0 = red, ~10922 = yellow, ~21845 = green, ~32768 = cyan,
265265
// ~43690 = blue, ~54613 = magenta, 65535 wraps back to red
@@ -269,7 +269,7 @@ uint32_t color = strip.ColorHSV(hue, 255, 255); // Full sat, full brightness
269269
// Note: ColorHSV returns a value that should be passed through strip.gamma32()
270270
// for perceptually accurate colors:
271271
strip.setPixelColor(i, strip.gamma32(strip.ColorHSV(hue, 255, 255)));
272-
{% endhighlight C++ %}
272+
```
273273

274274
{: .note }
275275
> **What is `gamma32()`?** Human eyes perceive brightness non-linearly—the difference between 0 and 50 looks much bigger than the difference between 200 and 250. The `gamma32()` function applies a correction curve so that color transitions look smooth and natural to our eyes. It's optional but makes a noticeable difference in gradients and fades.
@@ -381,7 +381,7 @@ Now that we understand how addressable LEDs work and have our stick wired up, le
381381

382382
Let's start by simply setting each LED to a different color. This confirms that your wiring is correct and that the library is communicating with all 8 LEDs. This is our equivalent of the [shape drawing activity](oled.md#activity-draw-shapes-and-text) from the OLED lesson—the simplest possible test.
383383

384-
{% highlight C++ %}
384+
```cpp
385385
#include <Adafruit_NeoPixel.h>
386386

387387
const int LED_PIN = 2;
@@ -409,7 +409,7 @@ void setup() {
409409
void loop() {
410410
// Nothing to do — the colors persist until changed
411411
}
412-
{% endhighlight C++ %}
412+
```
413413
414414
If your colors look wrong (*e.g.,* you asked for red but got green), try changing `NEO_GRB` to `NEO_RGB` in the strip constructor. This is the most common issue students encounter!
415415
@@ -423,7 +423,7 @@ Try playing with the colors by changing the RGB values above. Our code for this
423423
424424
Now let's create a classic rainbow animation that cycles smoothly across all 8 LEDs. This introduces the concept of **animation on LED strips**: update pixel colors, call `show()`, wait a bit, repeat. It's the same pattern we used for the [bouncing ball](oled.md#activity-draw-a-bouncing-ball) on the OLED.
425425
426-
{% highlight C++ %}
426+
```cpp
427427
#include <Adafruit_NeoPixel.h>
428428
429429
const int LED_PIN = 2;
@@ -456,7 +456,7 @@ void loop() {
456456
457457
delay(20); // ~50 fps
458458
}
459-
{% endhighlight C++ %}
459+
```
460460

461461
Try changing the `HUE_STEP` constant to `64` (slower rainbow) or `512` (faster rainbow). What happens if you change `setBrightness()` to 255? (Shield your eyes!).
462462

@@ -490,7 +490,7 @@ Use the same LED wiring as before, and add a 10KΩ potentiometer with its wiper
490490

491491
#### The code
492492

493-
{% highlight C++ %}
493+
```cpp
494494
#include <Adafruit_NeoPixel.h>
495495

496496
const int LED_PIN = 2;
@@ -527,7 +527,7 @@ void loop() {
527527

528528
delay(20);
529529
}
530-
{% endhighlight C++ %}
530+
```
531531
532532
As you turn the potentiometer, you should see all 8 LEDs smoothly cycle through the rainbow together.
533533
@@ -549,7 +549,7 @@ Now let's add a **second potentiometer** on `A1` to independently control bright
549549
**Video.** A circuit diagram for the potentiometer-controlled hue and brightness example. You can view and play with this example on [Tinkercad](https://www.tinkercad.com/things/53EaKIvUCsX-neopixel-strip-8-pot-controlled-hue-and-brightness).
550550
{: .fs-1 }
551551
552-
{% highlight C++ %}
552+
```cpp
553553
#include <Adafruit_NeoPixel.h>
554554
555555
const int LED_PIN = 2;
@@ -590,7 +590,7 @@ void loop() {
590590
591591
delay(20);
592592
}
593-
{% endhighlight C++ %}
593+
```
594594

595595
Try turning each knob independently—you can dial in any color at any brightness level. Notice how the `ColorHSV()` function's three parameters (hue, saturation, value) map perfectly to physical controls. What would you use a *third* potentiometer for? (Hint: saturation controls how vivid *vs.* pastel the color looks!)
596596

@@ -608,7 +608,7 @@ For our final activity, let's build a **level meter** (or VU meter)—a bar-grap
608608
609609
We'll color the LEDs from green (low) through yellow (mid) to red (high), like a classic audio level meter.
610610
611-
{% highlight C++ %}
611+
```cpp
612612
#include <Adafruit_NeoPixel.h>
613613
614614
const int LED_PIN = 2;
@@ -653,7 +653,7 @@ void loop() {
653653
654654
delay(30);
655655
}
656-
{% endhighlight C++ %}
656+
```
657657
658658
Turn the potentiometer and watch the LEDs fill up like a progress bar! This is a simple but satisfying example of mapping data to a physical display. Try replacing the potentiometer with a [force-sensitive resistor](../arduino/force-sensitive-resistors.md) or a [photoresistor](../sensors/photoresistors.md) for a more interactive experience.
659659

0 commit comments

Comments
 (0)