Commit c0f4380 h
Changes: 1 file +26 -5
Changes (Side-by-Side)
share/jenny/lib/components.sh +26 -5
render_index () { | |||
| 246 | # not ordered relative to each other -- they are addressed, not published. |
246 | # not ordered relative to each other -- they are addressed, not published. |
| 247 | # Whether one is versioned is a directory convention (pages/study/x/v2/), not |
247 | # Whether one is versioned is a directory convention (pages/study/x/v2/), not |
| 248 | # something jenny knows about. |
248 | # something jenny knows about. |
| 249 | # title_case <text> |
||
| 250 | # Capitalises each word. Used only for labels derived from a path segment -- |
||
| 251 | # "migration driven development" is a slug read aloud, not something anyone |
||
| 252 | # wrote, so presenting it lowercase looks like a mistake. |
||
| 253 | # |
||
| 254 | # A page's own title is never passed through here: the author chose its casing |
||
| 255 | # and "Method, an Introduction" must not become "Method, An Introduction". |
||
| 256 | title_case() { |
||
| 257 | printf '%s' "$1" | "$AWK" '{ |
||
| 258 | for (i = 1; i <= NF; i++) |
||
| 259 | $i = toupper(substr($i, 1, 1)) substr($i, 2) |
||
| 260 | print |
||
| 261 | }' |
||
| 262 | } |
||
| 263 | |
||
| 249 | # generate_section_indexes <pages_dir> |
264 | # generate_section_indexes <pages_dir> |
| 250 | # Writes a listing page for every directory under pages/ that has no index.md |
265 | # Writes a listing page for every directory under pages/ that has no index.md |
| 251 | # of its own, so a breadcrumb segment always leads somewhere. |
266 | # of its own, so a breadcrumb segment always leads somewhere. |
generate_section_indexes() { | |||
| 279 | |
294 | |
| 280 | rel=${dir#"$pages_dir"/} |
295 | rel=${dir#"$pages_dir"/} |
| 281 | name=$(basename "$dir") |
296 | name=$(basename "$dir") |
| 282 | title=$(printf '%s' "$name" | tr '-' ' ') |
||
| 297 | title=$(title_case "$(printf '%s' "$name" | tr '-' ' ')") |
||
| 283 | |
298 | |
| 284 | listing="" |
299 | listing="" |
| 285 | count=0 |
300 | count=0 |
| 286 | # Pages first, then subsections, each alphabetical. Two kinds of thing in |
301 | # Pages first, then subsections, each alphabetical. Two kinds of thing in |
| 287 | # one list, so they are grouped rather than interleaved by name. |
302 | # one list, so they are grouped rather than interleaved by name. |
| 303 | # |
||
| 304 | # One link per row, separated by a blank line: markdown joins adjacent |
||
| 305 | # lines into a single paragraph, so without the blank line every entry |
||
| 306 | # ran together on one row. |
||
| 288 | while IFS= read -r entry; do |
307 | while IFS= read -r entry; do |
| 289 | [ -n "$entry" ] || continue |
308 | [ -n "$entry" ] || continue |
| 290 | [ "$(basename "$entry")" = "index.md" ] && continue |
309 | [ "$(basename "$entry")" = "index.md" ] && continue |
| 291 | slug=$(basename "${entry%.md}") |
310 | slug=$(basename "${entry%.md}") |
| 292 | label=$(get_title "$entry") |
311 | label=$(get_title "$entry") |
| 293 | [ -n "$label" ] || label=$(printf '%s' "$slug" | tr '-' ' ') |
||
| 294 | listing="$listing- [$label](/$rel/$slug) |
||
| 312 | [ -n "$label" ] || label=$(title_case "$(printf '%s' "$slug" | tr '-' ' ')") |
||
| 313 | listing="$listing[$label](/$rel/$slug) |
||
| 314 | |
||
| 295 | " |
315 | " |
| 296 | count=$((count + 1)) |
316 | count=$((count + 1)) |
| 297 | done < <(find "$dir" -maxdepth 1 -type f -name '*.md' | LC_ALL=C sort) |
317 | done < <(find "$dir" -maxdepth 1 -type f -name '*.md' | LC_ALL=C sort) |
generate_section_indexes() { | |||
| 299 | while IFS= read -r entry; do |
319 | while IFS= read -r entry; do |
| 300 | [ -n "$entry" ] || continue |
320 | [ -n "$entry" ] || continue |
| 301 | sub=$(basename "$entry") |
321 | sub=$(basename "$entry") |
| 302 | sublabel=$(printf '%s' "$sub" | tr '-' ' ') |
||
| 303 | listing="$listing- [$sublabel](/$rel/$sub/) |
||
| 322 | sublabel=$(title_case "$(printf '%s' "$sub" | tr '-' ' ')") |
||
| 323 | listing="$listing[$sublabel](/$rel/$sub/) |
||
| 324 | |
||
| 304 | " |
325 | " |
| 305 | count=$((count + 1)) |
326 | count=$((count + 1)) |
| 306 | done < <(find "$dir" -mindepth 1 -maxdepth 1 -type d | LC_ALL=C sort) |
327 | done < <(find "$dir" -mindepth 1 -maxdepth 1 -type d | LC_ALL=C sort) |
Raw
commit c0f4380011ee673d41dc5275ed472e9c000fea9f
Author: Pat Ambrosio <cp.ambrosio@gmail.com>
Date: Thu Aug 27 12:40:48 2026 +0800
List section entries as rows, in title case
The generated listing used a bullet list and lowercase labels taken
straight from the path. Bullets are for a list of things in prose; this is
a directory of pages, so each gets its own row.
The blank line between entries is load-bearing: markdown joins adjacent
lines into one paragraph, so without it every link ran together on a
single row.
Labels derived from a path segment are title cased -- "migration driven
development" is a slug read aloud, not something anyone wrote, and
presenting it lowercase looks like a mistake. A page's own title is never
re-cased: the author chose it, and "Method, an Introduction" must not
become "Method, An Introduction".
Tests cover both halves of that distinction, and that entries render as
separate rows rather than as list items or one run-together line.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WnSAstgnDYdKPwLGv1YZE5
diff --git a/share/jenny/lib/components.sh b/share/jenny/lib/components.sh
index 479c000..9733ea2 100644
--- a/share/jenny/lib/components.sh
+++ b/share/jenny/lib/components.sh
@@ -246,6 +246,21 @@ render_index () {
# not ordered relative to each other -- they are addressed, not published.
# Whether one is versioned is a directory convention (pages/study/x/v2/), not
# something jenny knows about.
+# title_case <text>
+# Capitalises each word. Used only for labels derived from a path segment --
+# "migration driven development" is a slug read aloud, not something anyone
+# wrote, so presenting it lowercase looks like a mistake.
+#
+# A page's own title is never passed through here: the author chose its casing
+# and "Method, an Introduction" must not become "Method, An Introduction".
+title_case() {
+ printf '%s' "$1" | "$AWK" '{
+ for (i = 1; i <= NF; i++)
+ $i = toupper(substr($i, 1, 1)) substr($i, 2)
+ print
+ }'
+}
+
# generate_section_indexes <pages_dir>
# Writes a listing page for every directory under pages/ that has no index.md
# of its own, so a breadcrumb segment always leads somewhere.
@@ -279,19 +294,24 @@ generate_section_indexes() {
rel=${dir#"$pages_dir"/}
name=$(basename "$dir")
- title=$(printf '%s' "$name" | tr '-' ' ')
+ title=$(title_case "$(printf '%s' "$name" | tr '-' ' ')")
listing=""
count=0
# Pages first, then subsections, each alphabetical. Two kinds of thing in
# one list, so they are grouped rather than interleaved by name.
+ #
+ # One link per row, separated by a blank line: markdown joins adjacent
+ # lines into a single paragraph, so without the blank line every entry
+ # ran together on one row.
while IFS= read -r entry; do
[ -n "$entry" ] || continue
[ "$(basename "$entry")" = "index.md" ] && continue
slug=$(basename "${entry%.md}")
label=$(get_title "$entry")
- [ -n "$label" ] || label=$(printf '%s' "$slug" | tr '-' ' ')
- listing="$listing- [$label](/$rel/$slug)
+ [ -n "$label" ] || label=$(title_case "$(printf '%s' "$slug" | tr '-' ' ')")
+ listing="$listing[$label](/$rel/$slug)
+
"
count=$((count + 1))
done < <(find "$dir" -maxdepth 1 -type f -name '*.md' | LC_ALL=C sort)
@@ -299,8 +319,9 @@ generate_section_indexes() {
while IFS= read -r entry; do
[ -n "$entry" ] || continue
sub=$(basename "$entry")
- sublabel=$(printf '%s' "$sub" | tr '-' ' ')
- listing="$listing- [$sublabel](/$rel/$sub/)
+ sublabel=$(title_case "$(printf '%s' "$sub" | tr '-' ' ')")
+ listing="$listing[$sublabel](/$rel/$sub/)
+
"
count=$((count + 1))
done < <(find "$dir" -mindepth 1 -maxdepth 1 -type d | LC_ALL=C sort)