Skip to content

Commit c5783d9

Browse files
DOC-5922 added AI-friendly render hook for checklists
1 parent 9b89f4f commit c5783d9

File tree

3 files changed

+168
-0
lines changed

3 files changed

+168
-0
lines changed
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: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
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: '&#x274C;' },
48+
{ value: 'G', label: '&#9989;' },
49+
{ value: 'A', label: '&#x1F50D;' },
50+
{ value: 'X', label: '&#x2205;' }
51+
];
52+
53+
options.forEach(opt => {
54+
const option = document.createElement('option');
55+
option.value = opt.value;
56+
option.innerHTML = 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+
countersDiv.innerHTML = `
84+
<label for="${formId}-gcount">&#9989; = </label>
85+
<output name="gcount" id="${formId}-gcount">0</output>/<output id="${formId}-gtotal">0</output>,
86+
<label for="${formId}-rcount">&#x274C; = </label>
87+
<output name="rcount" id="${formId}-rcount">0</output>/<output id="${formId}-rtotal">0</output>,
88+
<label for="${formId}-acount">&#x1F50D; = </label>
89+
<output name="acount" id="${formId}-acount">0</output>/<output id="${formId}-atotal">0</output>
90+
<br/>
91+
(<label for="${formId}-xcount">&#x2205; = </label>
92+
<output name="xcount" id="${formId}-xcount">0</output>)
93+
`;
94+
form.appendChild(countersDiv);
95+
96+
// Replace the entire <pre> element with the interactive form
97+
preElement.replaceWith(form);
98+
99+
// Initialize
100+
let itemString = localStorage.getItem(formId);
101+
if (itemString) {
102+
setCLItemsFromString(formId, itemString);
103+
} else {
104+
clChange(formId);
105+
}
106+
}
107+
108+
function getStringFromCLItems(formId) {
109+
let result = "";
110+
let form = document.getElementById(formId);
111+
let listItems = form.getElementsByTagName("li");
112+
113+
for (let elem of listItems) {
114+
let menu = elem.getElementsByTagName("select")[0];
115+
result += menu.value;
116+
}
117+
118+
return result;
119+
}
120+
121+
function setCLItemsFromString(formId, clString) {
122+
let counts = {R: 0, G: 0, A: 0, X:0};
123+
124+
let form = document.getElementById(formId);
125+
let listItems = form.getElementsByTagName("li");
126+
127+
if (clString.length < listItems.length) {
128+
clString = clString.padEnd(listItems.length, "R");
129+
} else if (clString.length > listItems.length) {
130+
clString = clString.substring(0, listItems.length);
131+
}
132+
133+
for (let i = 0; i < clString.length; i++) {
134+
let char = clString.charAt(i);
135+
counts[char]++;
136+
let menu = listItems[i].getElementsByTagName("select")[0];
137+
menu.value = char;
138+
}
139+
140+
form.elements["gcount"].value = counts["G"];
141+
form.elements["rcount"].value = counts["R"];
142+
form.elements["acount"].value = counts["A"];
143+
form.elements["xcount"].value = counts["X"];
144+
145+
let numClItems = listItems.length - counts["X"];
146+
147+
document.getElementById(formId + "-rtotal").textContent = numClItems;
148+
document.getElementById(formId + "-gtotal").textContent = numClItems;
149+
document.getElementById(formId + "-atotal").textContent = numClItems;
150+
151+
let itemChoices = getStringFromCLItems(formId);
152+
localStorage.setItem(formId, itemChoices);
153+
}
154+
155+
function clChange(formId) {
156+
let itemChoices = getStringFromCLItems(formId);
157+
setCLItemsFromString(formId, itemChoices);
158+
}
159+

0 commit comments

Comments
 (0)