Skip to content

Commit 3cea98f

Browse files
committed
Generate linked child topic summaries
This mimics the parent-topic-with-links behavior seen in the original Puppet Bolt documentation site, linking to each child/sub-topic under the parent, with a summary taken from that sub-topic's first paragraph. Parent .md templates must include the child_topics.html to endable this behavior Assisted-by: Claude Opus 4.8 Signed-off-by: Chris Tessmer <chris.tessmer@onyxpoint.com>
1 parent 391491f commit 3cea98f

4 files changed

Lines changed: 98 additions & 0 deletions

File tree

_includes/child_topics.html

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
{%- comment -%}
2+
child_topics.html — auto-generates an overview page's "on this page" list of
3+
sub-topics from the site nav list, so parent-with-link sections don't need a
4+
hand-maintained list of their sub-topics in the page body.
5+
6+
Renders a `<ul>` of child topic links for an overview page whose nav entry
7+
has both `link:` and `items:` (e.g., OpenBolt's "Plans").
8+
9+
For each child: title as a link + first paragraph of the child's rendered
10+
content as a short description. Children that don't resolve to a doc in the
11+
current collection (e.g., missing rake-generated reference pages) render as
12+
a bare link with no description.
13+
14+
Data source: the entry for this page in `_data/nav/<page.nav>.yml`. The
15+
matching `nav_base` (URL prefix) is looked up in `_data/nav_map.yml`.
16+
{%- endcomment -%}
17+
18+
{%- assign nav_base = nil -%}
19+
{%- for entry in site.data.nav_map -%}
20+
{%- if entry.nav_key == page.nav -%}
21+
{%- assign nav_base = entry.base -%}
22+
{%- break -%}
23+
{%- endif -%}
24+
{%- endfor -%}
25+
26+
{%- assign page_subpath = page.url | remove_first: nav_base -%}
27+
28+
{%- comment -%}
29+
Find the nav entry for the current page. Only matches entries with `items:`,
30+
so pages whose nav entry has `link:` but no children (leaf pages) render
31+
nothing here.
32+
{%- endcomment -%}
33+
{%- assign current_section = nil -%}
34+
{%- for item in site.data.nav[page.nav] -%}
35+
{%- if item.link == page_subpath and item.items -%}
36+
{%- assign current_section = item -%}
37+
{%- break -%}
38+
{%- endif -%}
39+
{%- endfor -%}
40+
41+
{%- if current_section -%}
42+
<ul>
43+
{%- for child in current_section.items -%}
44+
{%- assign child_link_first_char = child.link | slice: 0 -%}
45+
{%- if child_link_first_char == '/' -%}
46+
{%- assign child_url = child.link -%}
47+
{%- else -%}
48+
{%- assign child_url = child.link | prepend: nav_base -%}
49+
{%- endif -%}
50+
51+
{%- assign child_doc = nil -%}
52+
{%- for doc in site[page.collection] -%}
53+
{%- if doc.url == child_url -%}
54+
{%- assign child_doc = doc -%}
55+
{%- break -%}
56+
{%- endif -%}
57+
{%- endfor -%}
58+
59+
{%- comment -%}
60+
Extract the child's first intro paragraph for the description.
61+
62+
Every child page begins with `# Heading` then a plain intro paragraph,
63+
so splitting the rendered HTML on `<p>` skips the `<h1>` and lands on the
64+
first real paragraph.
65+
66+
`child_doc.content` is piped through `markdownify` first because Jekyll
67+
only guarantees it holds rendered HTML for docs that happen to be built
68+
before this page; docs built afterward still hold raw Markdown. Running
69+
`markdownify` normalizes both cases to HTML so the `<p>` split is
70+
deterministic regardless of build order.
71+
{%- endcomment -%}
72+
{%- assign first_para = nil -%}
73+
{%- if child_doc -%}
74+
{%- assign child_html = child_doc.content | markdownify -%}
75+
{%- assign after_first_p = child_html | split: '<p>' -%}
76+
{%- if after_first_p.size > 1 -%}
77+
{%- assign first_para = after_first_p[1] | split: '</p>' | first -%}
78+
{%- endif -%}
79+
{%- endif -%}
80+
81+
{%- comment -%}
82+
Title and description share one `<p>` (separated by a `<br>`) so the theme's
83+
`.vp-doc p { margin: 16px 0 }` doesn't stack two paragraph margins between
84+
them, which would push the description well below the link.
85+
{%- endcomment -%}
86+
<li>
87+
<p><a href="{{ child_url }}">{{ child.text }}</a>{% if first_para %}<br>
88+
{{ first_para }}{% endif %}</p>
89+
</li>
90+
{%- endfor -%}
91+
</ul>
92+
{%- endif -%}

docs/_openbolt_5x/bolt_examples.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,5 @@ blog](https://puppet.com/search/?query=bolt&page=1&configure%5BhitsPerPage%5D=20
1919

2020
> **Note:** Do you have a real-world use case for Bolt that you'd like to share? Reach out to us in the #bolt
2121
channel on [Slack](https://slack.puppet.com).
22+
23+
{% include child_topics.html %}

docs/_openbolt_5x/plans.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,5 @@ to do complex task operations, such as running multiple tasks with one command,
1010
computing values for the input for a task, or running certain tasks based on
1111
results of another task. You write plans in the Puppet language. And like tasks,
1212
plans are packaged in modules and can be shared on the Forge.
13+
14+
{% include child_topics.html %}

docs/_openbolt_5x/tasks.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,5 @@ You can write tasks in any programming language that can run on the targets,
1212
such as Bash, Python, or Ruby. Tasks are packaged within modules, so you can
1313
reuse, download, and share tasks on the Forge. Task metadata describes the task,
1414
validates input, and controls how the task runner executes the task.
15+
16+
{% include child_topics.html %}

0 commit comments

Comments
 (0)