Skip to content

Commit 28c01b2

Browse files
Merge pull request #2351 from redis/DOC-5922-markdown-checklist
DOC-5922 Markdown checklist format
2 parents 706d440 + 2a1372b commit 28c01b2

File tree

9 files changed

+244
-46
lines changed

9 files changed

+244
-46
lines changed

content/develop/clients/dotnet/produsage.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,12 @@ Each item in the checklist below links to the section
2424
for a recommendation. Use the checklist icons to record your
2525
progress in implementing the recommendations.
2626

27-
{{< checklist "dotnetprodlist" >}}
28-
{{< checklist-item "#event-handling" >}}Event handling{{< /checklist-item >}}
29-
{{< checklist-item "#timeouts" >}}Timeouts{{< /checklist-item >}}
30-
{{< checklist-item "#exception-handling" >}}Exception handling{{< /checklist-item >}}
31-
{{< checklist-item "#retries" >}}Retries{{< /checklist-item >}}
32-
{{< /checklist >}}
27+
```checklist {id="dotnetprodlist"}
28+
- [ ] [Event handling](#event-handling)
29+
- [ ] [Timeouts](#timeouts)
30+
- [ ] [Exception handling](#exception-handling)
31+
- [ ] [Retries](#retries)
32+
```
3333

3434
## Recommendations
3535

content/develop/clients/go/produsage.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,14 @@ Each item in the checklist below links to the section
2424
for a recommendation. Use the checklist icons to record your
2525
progress in implementing the recommendations.
2626

27-
{{< checklist "goprodlist" >}}
28-
{{< checklist-item "#health-checks" >}}Health checks{{< /checklist-item >}}
29-
{{< checklist-item "#error-handling" >}}Error handling{{< /checklist-item >}}
30-
{{< checklist-item "#monitor-performance-and-errors">}}Monitor performance and errors{{< /checklist-item >}}
31-
{{< checklist-item "#retries" >}}Retries{{< /checklist-item >}}
32-
{{< checklist-item "#timeouts" >}}Timeouts{{< /checklist-item >}}
33-
{{< checklist-item "#seamless-client-experience" >}}Smart client handoffs{{< /checklist-item >}}
34-
{{< /checklist >}}
27+
```checklist {id="goprodlist"}
28+
- [ ] [Health checks](#health-checks)
29+
- [ ] [Error handling](#error-handling)
30+
- [ ] [Monitor performance and errors](#monitor-performance-and-errors)
31+
- [ ] [Retries](#retries)
32+
- [ ] [Timeouts](#timeouts)
33+
- [ ] [Smart client handoffs](#seamless-client-experience)
34+
```
3535

3636
## Recommendations
3737

content/develop/clients/jedis/produsage.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,15 @@ Each item in the checklist below links to the section
2424
for a recommendation. Use the checklist icons to record your
2525
progress in implementing the recommendations.
2626

27-
{{< checklist "prodlist" >}}
28-
{{< checklist-item "#connection-pooling" >}}Connection pooling{{< /checklist-item >}}
29-
{{< checklist-item "#connection-retries" >}}Connection retries{{< /checklist-item >}}
30-
{{< checklist-item "#client-side-caching" >}}Client-side caching{{< /checklist-item >}}
31-
{{< checklist-item "#timeouts" >}}Timeouts{{< /checklist-item >}}
32-
{{< checklist-item "#health-checks" >}}Health checks{{< /checklist-item >}}
33-
{{< checklist-item "#exception-handling" >}}Exception handling{{< /checklist-item >}}
34-
{{< checklist-item "#dns-cache-and-redis" >}}DNS cache and Redis{{< /checklist-item >}}
35-
{{< /checklist >}}
27+
```checklist {id="jedisprodlist"}
28+
- [ ] [Connection pooling](#connection-pooling)
29+
- [ ] [Connection retries](#connection-retries)
30+
- [ ] [Client-side caching](#client-side-caching)
31+
- [ ] [Timeouts](#timeouts)
32+
- [ ] [Health checks](#health-checks)
33+
- [ ] [Exception handling](#exception-handling)
34+
- [ ] [DNS cache and Redis](#dns-cache-and-redis)
35+
```
3636

3737
## Recommendations
3838

content/develop/clients/lettuce/produsage.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,14 @@ Each item in the checklist below links to the section
2424
for a recommendation. Use the checklist icons to record your
2525
progress in implementing the recommendations.
2626

27-
{{< checklist "lettuceprodlist" >}}
28-
{{< checklist-item "#timeouts" >}}Timeouts{{< /checklist-item >}}
29-
{{< checklist-item "#cluster-topology-refresh">}}Cluster topology refresh{{< /checklist-item >}}
30-
{{< checklist-item "#dns-cache-and-redis" >}}DNS cache and Redis{{< /checklist-item >}}
31-
{{< checklist-item "#exception-handling" >}}Exception handling{{< /checklist-item >}}
32-
{{< checklist-item "#connection-and-execution-reliability" >}}Connection and execution reliability{{< /checklist-item >}}
33-
{{< checklist-item "#seamless-client-experience" >}}Smart client handoffs{{< /checklist-item >}}
34-
{{< /checklist >}}
27+
```checklist {id="lettuceprodlist"}
28+
- [ ] [Timeouts](#timeouts)
29+
- [ ] [Cluster topology refresh](#cluster-topology-refresh)
30+
- [ ] [DNS cache and Redis](#dns-cache-and-redis)
31+
- [ ] [Exception handling](#exception-handling)
32+
- [ ] [Connection and execution reliability](#connection-and-execution-reliability)
33+
- [ ] [Smart client handoffs](#seamless-client-experience)
34+
```
3535

3636
## Recommendations
3737

content/develop/clients/nodejs/produsage.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,13 @@ Each item in the checklist below links to the section
2424
for a recommendation. Use the checklist icons to record your
2525
progress in implementing the recommendations.
2626

27-
{{< checklist "nodeprodlist" >}}
28-
{{< checklist-item "#handling-errors" >}}Handling errors{{< /checklist-item >}}
29-
{{< checklist-item "#handling-reconnections" >}}Handling reconnections{{< /checklist-item >}}
30-
{{< checklist-item "#connection-timeouts" >}}Connection timeouts{{< /checklist-item >}}
31-
{{< checklist-item "#command-execution-reliability" >}}Command execution reliability{{< /checklist-item >}}
32-
{{< checklist-item "#seamless-client-experience" >}}Smart client handoffs{{< /checklist-item >}}
33-
{{< /checklist >}}
27+
```checklist {id="nodeprodlist"}
28+
- [ ] [Handling errors](#handling-errors)
29+
- [ ] [Handling reconnections](#handling-reconnections)
30+
- [ ] [Connection timeouts](#connection-timeouts)
31+
- [ ] [Command execution reliability](#command-execution-reliability)
32+
- [ ] [Smart client handoffs](#seamless-client-experience)
33+
```
3434

3535
## Recommendations
3636

content/develop/clients/redis-py/produsage.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,14 @@ Each item in the checklist below links to the section
2424
for a recommendation. Use the checklist icons to record your
2525
progress in implementing the recommendations.
2626

27-
{{< checklist "pyprodlist" >}}
28-
{{< checklist-item "#client-side-caching" >}}Client-side caching{{< /checklist-item >}}
29-
{{< checklist-item "#retries" >}}Retries{{< /checklist-item >}}
30-
{{< checklist-item "#health-checks" >}}Health checks{{< /checklist-item >}}
31-
{{< checklist-item "#exception-handling" >}}Exception handling{{< /checklist-item >}}
32-
{{< checklist-item "#timeouts" >}}Timeouts{{< /checklist-item >}}
33-
{{< checklist-item "#seamless-client-experience" >}}Smart client handoffs{{< /checklist-item >}}
34-
{{< /checklist >}}
27+
```checklist {id="pyprodlist"}
28+
- [ ] [Client-side caching](#client-side-caching)
29+
- [ ] [Retries](#retries)
30+
- [ ] [Health checks](#health-checks)
31+
- [ ] [Exception handling](#exception-handling)
32+
- [ ] [Timeouts](#timeouts)
33+
- [ ] [Smart client handoffs](#smart-client-handoffs)
34+
```
3535

3636
## Recommendations
3737

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{{- $id := .Attributes.id | default "checklist" -}}
2+
<pre class="checklist-source" data-checklist-id="{{ $id }}">{{ .Inner | htmlEscape | safeHTML }}</pre>
3+
{{ .Page.Store.Set "hasChecklist" true }}
4+

layouts/_default/baseof.html

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,5 +79,10 @@
7979
{{ partial "toc-js.html" . }}
8080

8181
{{ partial "search-modal.html" . }}
82+
83+
<!-- Checklist functionality -->
84+
{{ if .Page.Store.Get "hasChecklist" }}
85+
<script src="{{ "js/checklist.js" | relURL }}"></script>
86+
{{ end }}
8287
</body>
8388
</html>

static/js/checklist.js

Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
document.addEventListener('DOMContentLoaded', () => {
2+
// Find all checklist code blocks
3+
const checklists = document.querySelectorAll('pre.checklist-source');
4+
console.log('Found', checklists.length, 'checklist(s)');
5+
6+
checklists.forEach(pre => {
7+
const checklistId = pre.getAttribute('data-checklist-id');
8+
const markdownContent = pre.textContent;
9+
console.log('Processing checklist:', checklistId);
10+
11+
// Parse markdown and create interactive checklist
12+
createChecklistFromMarkdown(markdownContent, checklistId, pre);
13+
});
14+
});
15+
16+
function createChecklistFromMarkdown(markdown, formId, preElement) {
17+
const lines = markdown.split('\n');
18+
const items = [];
19+
20+
// Parse checklist items from markdown
21+
lines.forEach(line => {
22+
const trimmed = line.trim();
23+
if (trimmed.match(/^- \[[\sx]\]/)) {
24+
items.push(trimmed);
25+
}
26+
});
27+
28+
if (items.length === 0) return;
29+
30+
// Create form
31+
const form = document.createElement('form');
32+
form.id = formId;
33+
34+
const ul = document.createElement('ul');
35+
ul.style.listStyleType = 'none';
36+
ul.style.paddingLeft = '0px';
37+
38+
// Parse each item
39+
items.forEach(item => {
40+
const li = document.createElement('li');
41+
42+
// Create select dropdown
43+
const select = document.createElement('select');
44+
select.onchange = () => clChange(formId);
45+
46+
const options = [
47+
{ value: 'R', label: '❌' },
48+
{ value: 'G', label: '✅' },
49+
{ value: 'A', label: '🔍' },
50+
{ value: 'X', label: '∅' }
51+
];
52+
53+
options.forEach(opt => {
54+
const option = document.createElement('option');
55+
option.value = opt.value;
56+
option.textContent = opt.label;
57+
select.appendChild(option);
58+
});
59+
60+
li.appendChild(select);
61+
62+
// Parse link and text from markdown
63+
// Format: - [ ] [text](#anchor) or - [ ] text
64+
const linkMatch = item.match(/\[([^\]]+)\]\(([^\)]+)\)/);
65+
if (linkMatch) {
66+
const a = document.createElement('a');
67+
a.href = linkMatch[2];
68+
a.textContent = linkMatch[1];
69+
li.appendChild(a);
70+
} else {
71+
// Just text after the checkbox
72+
const text = item.replace(/^- \[[\sx]\]\s*/, '');
73+
li.appendChild(document.createTextNode(text));
74+
}
75+
76+
ul.appendChild(li);
77+
});
78+
79+
form.appendChild(ul);
80+
81+
// Add counters
82+
const countersDiv = document.createElement('div');
83+
84+
// Create counter elements safely without innerHTML
85+
const createCounterLabel = (emoji, countId, totalId, isDisabled = false) => {
86+
const label = document.createElement('label');
87+
label.htmlFor = countId;
88+
label.textContent = emoji + ' = ';
89+
90+
const countOutput = document.createElement('output');
91+
countOutput.name = countId.replace(formId + '-', '');
92+
countOutput.id = countId;
93+
countOutput.textContent = '0';
94+
95+
const fragment = document.createDocumentFragment();
96+
fragment.appendChild(label);
97+
fragment.appendChild(countOutput);
98+
99+
if (!isDisabled) {
100+
fragment.appendChild(document.createTextNode('/'));
101+
const totalOutput = document.createElement('output');
102+
totalOutput.id = totalId;
103+
totalOutput.textContent = '0';
104+
fragment.appendChild(totalOutput);
105+
fragment.appendChild(document.createTextNode(', '));
106+
} else {
107+
fragment.appendChild(document.createTextNode(')'));
108+
}
109+
110+
return fragment;
111+
};
112+
113+
countersDiv.appendChild(createCounterLabel('✅', formId + '-gcount', formId + '-gtotal'));
114+
countersDiv.appendChild(createCounterLabel('❌', formId + '-rcount', formId + '-rtotal'));
115+
countersDiv.appendChild(createCounterLabel('🔍', formId + '-acount', formId + '-atotal'));
116+
117+
const brElement = document.createElement('br');
118+
countersDiv.appendChild(brElement);
119+
120+
const openParen = document.createTextNode('(');
121+
countersDiv.appendChild(openParen);
122+
countersDiv.appendChild(createCounterLabel('∅', formId + '-xcount', '', true));
123+
124+
form.appendChild(countersDiv);
125+
126+
// Replace the entire <pre> element with the interactive form
127+
preElement.replaceWith(form);
128+
129+
// Initialize
130+
let itemString = localStorage.getItem(formId);
131+
if (itemString) {
132+
setCLItemsFromString(formId, itemString);
133+
} else {
134+
clChange(formId);
135+
}
136+
}
137+
138+
function getStringFromCLItems(formId) {
139+
let result = "";
140+
let form = document.getElementById(formId);
141+
let listItems = form.getElementsByTagName("li");
142+
143+
for (let elem of listItems) {
144+
let menu = elem.getElementsByTagName("select")[0];
145+
result += menu.value;
146+
}
147+
148+
return result;
149+
}
150+
151+
function setCLItemsFromString(formId, clString) {
152+
let counts = {R: 0, G: 0, A: 0, X:0};
153+
154+
let form = document.getElementById(formId);
155+
let listItems = form.getElementsByTagName("li");
156+
157+
if (clString.length < listItems.length) {
158+
clString = clString.padEnd(listItems.length, "R");
159+
} else if (clString.length > listItems.length) {
160+
clString = clString.substring(0, listItems.length);
161+
}
162+
163+
for (let i = 0; i < clString.length; i++) {
164+
let char = clString.charAt(i);
165+
counts[char]++;
166+
let menu = listItems[i].getElementsByTagName("select")[0];
167+
menu.value = char;
168+
}
169+
170+
form.elements["gcount"].value = counts["G"];
171+
form.elements["rcount"].value = counts["R"];
172+
form.elements["acount"].value = counts["A"];
173+
form.elements["xcount"].value = counts["X"];
174+
175+
let numClItems = listItems.length - counts["X"];
176+
177+
document.getElementById(formId + "-rtotal").textContent = numClItems;
178+
document.getElementById(formId + "-gtotal").textContent = numClItems;
179+
document.getElementById(formId + "-atotal").textContent = numClItems;
180+
181+
let itemChoices = getStringFromCLItems(formId);
182+
localStorage.setItem(formId, itemChoices);
183+
}
184+
185+
function clChange(formId) {
186+
let itemChoices = getStringFromCLItems(formId);
187+
setCLItemsFromString(formId, itemChoices);
188+
}
189+

0 commit comments

Comments
 (0)