Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions content/develop/clients/dotnet/produsage.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ Each item in the checklist below links to the section
for a recommendation. Use the checklist icons to record your
progress in implementing the recommendations.

{{< checklist "dotnetprodlist" >}}
{{< checklist-item "#event-handling" >}}Event handling{{< /checklist-item >}}
{{< checklist-item "#timeouts" >}}Timeouts{{< /checklist-item >}}
{{< checklist-item "#exception-handling" >}}Exception handling{{< /checklist-item >}}
{{< checklist-item "#retries" >}}Retries{{< /checklist-item >}}
{{< /checklist >}}
```checklist {id="dotnetprodlist"}
- [ ] [Event handling](#event-handling)
- [ ] [Timeouts](#timeouts)
- [ ] [Exception handling](#exception-handling)
- [ ] [Retries](#retries)
```

## Recommendations

Expand Down
16 changes: 8 additions & 8 deletions content/develop/clients/go/produsage.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,14 @@ Each item in the checklist below links to the section
for a recommendation. Use the checklist icons to record your
progress in implementing the recommendations.

{{< checklist "goprodlist" >}}
{{< checklist-item "#health-checks" >}}Health checks{{< /checklist-item >}}
{{< checklist-item "#error-handling" >}}Error handling{{< /checklist-item >}}
{{< checklist-item "#monitor-performance-and-errors">}}Monitor performance and errors{{< /checklist-item >}}
{{< checklist-item "#retries" >}}Retries{{< /checklist-item >}}
{{< checklist-item "#timeouts" >}}Timeouts{{< /checklist-item >}}
{{< checklist-item "#seamless-client-experience" >}}Smart client handoffs{{< /checklist-item >}}
{{< /checklist >}}
```checklist {id="goprodlist"}
- [ ] [Health checks](#health-checks)
- [ ] [Error handling](#error-handling)
- [ ] [Monitor performance and errors](#monitor-performance-and-errors)
- [ ] [Retries](#retries)
- [ ] [Timeouts](#timeouts)
- [ ] [Smart client handoffs](#seamless-client-experience)
```

## Recommendations

Expand Down
18 changes: 9 additions & 9 deletions content/develop/clients/jedis/produsage.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,15 @@ Each item in the checklist below links to the section
for a recommendation. Use the checklist icons to record your
progress in implementing the recommendations.

{{< checklist "prodlist" >}}
{{< checklist-item "#connection-pooling" >}}Connection pooling{{< /checklist-item >}}
{{< checklist-item "#connection-retries" >}}Connection retries{{< /checklist-item >}}
{{< checklist-item "#client-side-caching" >}}Client-side caching{{< /checklist-item >}}
{{< checklist-item "#timeouts" >}}Timeouts{{< /checklist-item >}}
{{< checklist-item "#health-checks" >}}Health checks{{< /checklist-item >}}
{{< checklist-item "#exception-handling" >}}Exception handling{{< /checklist-item >}}
{{< checklist-item "#dns-cache-and-redis" >}}DNS cache and Redis{{< /checklist-item >}}
{{< /checklist >}}
```checklist {id="jedisprodlist"}
- [ ] [Connection pooling](#connection-pooling)
- [ ] [Connection retries](#connection-retries)
- [ ] [Client-side caching](#client-side-caching)
- [ ] [Timeouts](#timeouts)
- [ ] [Health checks](#health-checks)
- [ ] [Exception handling](#exception-handling)
- [ ] [DNS cache and Redis](#dns-cache-and-redis)
```

## Recommendations

Expand Down
16 changes: 8 additions & 8 deletions content/develop/clients/lettuce/produsage.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,14 @@ Each item in the checklist below links to the section
for a recommendation. Use the checklist icons to record your
progress in implementing the recommendations.

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

## Recommendations

Expand Down
14 changes: 7 additions & 7 deletions content/develop/clients/nodejs/produsage.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,13 @@ Each item in the checklist below links to the section
for a recommendation. Use the checklist icons to record your
progress in implementing the recommendations.

{{< checklist "nodeprodlist" >}}
{{< checklist-item "#handling-errors" >}}Handling errors{{< /checklist-item >}}
{{< checklist-item "#handling-reconnections" >}}Handling reconnections{{< /checklist-item >}}
{{< checklist-item "#connection-timeouts" >}}Connection timeouts{{< /checklist-item >}}
{{< checklist-item "#command-execution-reliability" >}}Command execution reliability{{< /checklist-item >}}
{{< checklist-item "#seamless-client-experience" >}}Smart client handoffs{{< /checklist-item >}}
{{< /checklist >}}
```checklist {id="nodeprodlist"}
- [ ] [Handling errors](#handling-errors)
- [ ] [Handling reconnections](#handling-reconnections)
- [ ] [Connection timeouts](#connection-timeouts)
- [ ] [Command execution reliability](#command-execution-reliability)
- [ ] [Smart client handoffs](#seamless-client-experience)
```

## Recommendations

Expand Down
16 changes: 8 additions & 8 deletions content/develop/clients/redis-py/produsage.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,14 @@ Each item in the checklist below links to the section
for a recommendation. Use the checklist icons to record your
progress in implementing the recommendations.

{{< checklist "pyprodlist" >}}
{{< checklist-item "#client-side-caching" >}}Client-side caching{{< /checklist-item >}}
{{< checklist-item "#retries" >}}Retries{{< /checklist-item >}}
{{< checklist-item "#health-checks" >}}Health checks{{< /checklist-item >}}
{{< checklist-item "#exception-handling" >}}Exception handling{{< /checklist-item >}}
{{< checklist-item "#timeouts" >}}Timeouts{{< /checklist-item >}}
{{< checklist-item "#seamless-client-experience" >}}Smart client handoffs{{< /checklist-item >}}
{{< /checklist >}}
```checklist {id="pyprodlist"}
- [ ] [Client-side caching](#client-side-caching)
- [ ] [Retries](#retries)
- [ ] [Health checks](#health-checks)
- [ ] [Exception handling](#exception-handling)
- [ ] [Timeouts](#timeouts)
- [ ] [Smart client handoffs](#smart-client-handoffs)
```

## Recommendations

Expand Down
4 changes: 4 additions & 0 deletions layouts/_default/_markup/render-codeblock-checklist.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{{- $id := .Attributes.id | default "checklist" -}}
<pre class="checklist-source" data-checklist-id="{{ $id }}">{{ .Inner | htmlEscape | safeHTML }}</pre>
{{ .Page.Store.Set "hasChecklist" true }}

5 changes: 5 additions & 0 deletions layouts/_default/baseof.html
Original file line number Diff line number Diff line change
Expand Up @@ -79,5 +79,10 @@
{{ partial "toc-js.html" . }}

{{ partial "search-modal.html" . }}

<!-- Checklist functionality -->
{{ if .Page.Store.Get "hasChecklist" }}
<script src="{{ "js/checklist.js" | relURL }}"></script>
{{ end }}
</body>
</html>
189 changes: 189 additions & 0 deletions static/js/checklist.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
document.addEventListener('DOMContentLoaded', () => {
// Find all checklist code blocks
const checklists = document.querySelectorAll('pre.checklist-source');
console.log('Found', checklists.length, 'checklist(s)');

checklists.forEach(pre => {
const checklistId = pre.getAttribute('data-checklist-id');
const markdownContent = pre.textContent;
console.log('Processing checklist:', checklistId);

// Parse markdown and create interactive checklist
createChecklistFromMarkdown(markdownContent, checklistId, pre);
});
});

function createChecklistFromMarkdown(markdown, formId, preElement) {
const lines = markdown.split('\n');
const items = [];

// Parse checklist items from markdown
lines.forEach(line => {
const trimmed = line.trim();
if (trimmed.match(/^- \[[\sx]\]/)) {
items.push(trimmed);
}
});

if (items.length === 0) return;

// Create form
const form = document.createElement('form');
form.id = formId;

const ul = document.createElement('ul');
ul.style.listStyleType = 'none';
ul.style.paddingLeft = '0px';

// Parse each item
items.forEach(item => {
const li = document.createElement('li');

// Create select dropdown
const select = document.createElement('select');
select.onchange = () => clChange(formId);

const options = [
{ value: 'R', label: '❌' },
{ value: 'G', label: '✅' },
{ value: 'A', label: '🔍' },
{ value: 'X', label: '∅' }
];

options.forEach(opt => {
const option = document.createElement('option');
option.value = opt.value;
option.textContent = opt.label;
select.appendChild(option);
});

li.appendChild(select);

// Parse link and text from markdown
// Format: - [ ] [text](#anchor) or - [ ] text
const linkMatch = item.match(/\[([^\]]+)\]\(([^\)]+)\)/);
if (linkMatch) {
const a = document.createElement('a');
a.href = linkMatch[2];
a.textContent = linkMatch[1];
li.appendChild(a);
} else {
// Just text after the checkbox
const text = item.replace(/^- \[[\sx]\]\s*/, '');
li.appendChild(document.createTextNode(text));
}

ul.appendChild(li);
});

form.appendChild(ul);

// Add counters
const countersDiv = document.createElement('div');

// Create counter elements safely without innerHTML
const createCounterLabel = (emoji, countId, totalId, isDisabled = false) => {
const label = document.createElement('label');
label.htmlFor = countId;
label.textContent = emoji + ' = ';

const countOutput = document.createElement('output');
countOutput.name = countId.replace(formId + '-', '');
countOutput.id = countId;
countOutput.textContent = '0';

const fragment = document.createDocumentFragment();
fragment.appendChild(label);
fragment.appendChild(countOutput);

if (!isDisabled) {
fragment.appendChild(document.createTextNode('/'));
const totalOutput = document.createElement('output');
totalOutput.id = totalId;
totalOutput.textContent = '0';
fragment.appendChild(totalOutput);
fragment.appendChild(document.createTextNode(', '));
} else {
fragment.appendChild(document.createTextNode(')'));
}

return fragment;
};

countersDiv.appendChild(createCounterLabel('✅', formId + '-gcount', formId + '-gtotal'));
countersDiv.appendChild(createCounterLabel('❌', formId + '-rcount', formId + '-rtotal'));
countersDiv.appendChild(createCounterLabel('🔍', formId + '-acount', formId + '-atotal'));

const brElement = document.createElement('br');
countersDiv.appendChild(brElement);

const openParen = document.createTextNode('(');
countersDiv.appendChild(openParen);
countersDiv.appendChild(createCounterLabel('∅', formId + '-xcount', '', true));

form.appendChild(countersDiv);

// Replace the entire <pre> element with the interactive form
preElement.replaceWith(form);

// Initialize
let itemString = localStorage.getItem(formId);
if (itemString) {
setCLItemsFromString(formId, itemString);
} else {
clChange(formId);
}
}

function getStringFromCLItems(formId) {
let result = "";
let form = document.getElementById(formId);
let listItems = form.getElementsByTagName("li");

for (let elem of listItems) {
let menu = elem.getElementsByTagName("select")[0];
result += menu.value;
}

return result;
}

function setCLItemsFromString(formId, clString) {
let counts = {R: 0, G: 0, A: 0, X:0};

let form = document.getElementById(formId);
let listItems = form.getElementsByTagName("li");

if (clString.length < listItems.length) {
clString = clString.padEnd(listItems.length, "R");
} else if (clString.length > listItems.length) {
clString = clString.substring(0, listItems.length);
}

for (let i = 0; i < clString.length; i++) {
let char = clString.charAt(i);
counts[char]++;
let menu = listItems[i].getElementsByTagName("select")[0];
menu.value = char;
}

form.elements["gcount"].value = counts["G"];
form.elements["rcount"].value = counts["R"];
form.elements["acount"].value = counts["A"];
form.elements["xcount"].value = counts["X"];

let numClItems = listItems.length - counts["X"];

document.getElementById(formId + "-rtotal").textContent = numClItems;
document.getElementById(formId + "-gtotal").textContent = numClItems;
document.getElementById(formId + "-atotal").textContent = numClItems;

let itemChoices = getStringFromCLItems(formId);
localStorage.setItem(formId, itemChoices);
}

function clChange(formId) {
let itemChoices = getStringFromCLItems(formId);
setCLItemsFromString(formId, itemChoices);
}