diff --git a/content/develop/clients/dotnet/produsage.md b/content/develop/clients/dotnet/produsage.md index 1dc8d5a8d0..7792a6449f 100644 --- a/content/develop/clients/dotnet/produsage.md +++ b/content/develop/clients/dotnet/produsage.md @@ -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 diff --git a/content/develop/clients/go/produsage.md b/content/develop/clients/go/produsage.md index 80b11cfa0f..695ffd1015 100644 --- a/content/develop/clients/go/produsage.md +++ b/content/develop/clients/go/produsage.md @@ -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 diff --git a/content/develop/clients/jedis/produsage.md b/content/develop/clients/jedis/produsage.md index 7b6a4fe293..4aa92ed6a5 100644 --- a/content/develop/clients/jedis/produsage.md +++ b/content/develop/clients/jedis/produsage.md @@ -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 diff --git a/content/develop/clients/lettuce/produsage.md b/content/develop/clients/lettuce/produsage.md index 3e636a8141..6c4dcb1766 100644 --- a/content/develop/clients/lettuce/produsage.md +++ b/content/develop/clients/lettuce/produsage.md @@ -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 diff --git a/content/develop/clients/nodejs/produsage.md b/content/develop/clients/nodejs/produsage.md index 992dc7c37e..74dc20f0dd 100644 --- a/content/develop/clients/nodejs/produsage.md +++ b/content/develop/clients/nodejs/produsage.md @@ -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 diff --git a/content/develop/clients/redis-py/produsage.md b/content/develop/clients/redis-py/produsage.md index 89859cd3c6..eea12f9a05 100644 --- a/content/develop/clients/redis-py/produsage.md +++ b/content/develop/clients/redis-py/produsage.md @@ -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 diff --git a/layouts/_default/_markup/render-codeblock-checklist.html b/layouts/_default/_markup/render-codeblock-checklist.html new file mode 100644 index 0000000000..cd0f490bac --- /dev/null +++ b/layouts/_default/_markup/render-codeblock-checklist.html @@ -0,0 +1,4 @@ +{{- $id := .Attributes.id | default "checklist" -}} +
{{ .Inner | htmlEscape | safeHTML }}
+{{ .Page.Store.Set "hasChecklist" true }} + diff --git a/layouts/_default/baseof.html b/layouts/_default/baseof.html index a15d1e0625..bce33e0547 100644 --- a/layouts/_default/baseof.html +++ b/layouts/_default/baseof.html @@ -79,5 +79,10 @@ {{ partial "toc-js.html" . }} {{ partial "search-modal.html" . }} + + + {{ if .Page.Store.Get "hasChecklist" }} + + {{ end }} diff --git a/static/js/checklist.js b/static/js/checklist.js new file mode 100644 index 0000000000..37ba3dc489 --- /dev/null +++ b/static/js/checklist.js @@ -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
 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);
+}
+