explicode 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,439 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <title>{{TITLE}}</title>
6
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
7
+ <link rel="stylesheet" href="ghmd.css" />
8
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.css" />
9
+ </head>
10
+ <body>
11
+ <div id="app"></div>
12
+ <script>
13
+ var githubBase = '{{GITHUB_BASE}}';
14
+ var repoUrl = githubBase ? githubBase.replace(/\/blob\/[^\/]+$/, '') : '';
15
+
16
+ var explicodePlugin = function(hook) {
17
+ var closedFolders = new Set();
18
+ var foldersInitialized = false;
19
+ var TRANSITION = '280ms cubic-bezier(0.4,0,0.2,1)';
20
+ var currentFilePath = 'README.md';
21
+
22
+ hook.beforeEach(function(content, next) {
23
+ var hash = window.location.hash.replace(/^#\/?/, '').replace(/\?.*$/, '');
24
+ if (!hash) {
25
+ currentFilePath = 'README.md';
26
+ } else {
27
+ if (hash.endsWith('.md')) {
28
+ var withoutMd = hash.slice(0, -3);
29
+ var dotIdx = withoutMd.lastIndexOf('.');
30
+ var ext = dotIdx !== -1 ? withoutMd.slice(dotIdx + 1).toLowerCase() : '';
31
+ currentFilePath = (ext && ext !== 'md') ? withoutMd : hash;
32
+ } else {
33
+ currentFilePath = hash;
34
+ }
35
+ }
36
+ next(content);
37
+ });
38
+
39
+ hook.mounted(function() {
40
+ var builtIn = document.querySelector('.sidebar-toggle');
41
+ if (builtIn) builtIn.style.display = 'none';
42
+
43
+ var sidebar = document.querySelector('.sidebar');
44
+ sidebar.style.overflow = 'hidden';
45
+ sidebar.style.display = 'flex';
46
+ sidebar.style.flexDirection = 'column';
47
+ sidebar.style.padding = '0';
48
+
49
+ var scrollWrap = document.createElement('div');
50
+ scrollWrap.className = 'xp-sidebar-scroll';
51
+ var nodes = Array.from(sidebar.childNodes);
52
+ nodes.forEach(function(n) {
53
+ if (n.nodeName !== 'H1') scrollWrap.appendChild(n);
54
+ });
55
+ sidebar.appendChild(scrollWrap);
56
+
57
+ var footer = document.createElement('div');
58
+ footer.className = 'xp-sidebar-footer';
59
+ var wmSpan = document.createElement('span');
60
+ wmSpan.innerHTML = 'Made with <a href="https://explicode.com" target="_blank"><strong>Explicode</strong></a>';
61
+ footer.appendChild(wmSpan);
62
+ sidebar.appendChild(footer);
63
+
64
+ var toggle = document.createElement('button');
65
+ toggle.id = 'xp-toggle';
66
+ toggle.setAttribute('aria-label', 'Toggle sidebar');
67
+ toggle.innerHTML = '&#x2039;';
68
+ document.body.appendChild(toggle);
69
+
70
+ var mobileBtn = document.createElement('button');
71
+ mobileBtn.id = 'xp-mobile-btn';
72
+ mobileBtn.setAttribute('aria-label', 'Toggle sidebar');
73
+ mobileBtn.innerHTML =
74
+ '<span class="xp-mb-bars"><span></span><span></span><span></span></span>' +
75
+ '<span class="xp-mb-close">&#x2715;</span>';
76
+ document.body.appendChild(mobileBtn);
77
+
78
+ var drag = document.createElement('div');
79
+ drag.className = 'xp-drag';
80
+ document.body.appendChild(drag);
81
+
82
+ var isMobile = function() { return window.innerWidth < 600; };
83
+
84
+ function getSidebarWidth() {
85
+ return parseInt(sidebar.style.width) || sidebar.offsetWidth || 270;
86
+ }
87
+
88
+ function updateDragVisibility(open) {
89
+ if (isMobile() || !open) {
90
+ drag.style.transition = 'opacity 120ms ease';
91
+ drag.style.opacity = '0';
92
+ drag.style.pointerEvents = 'none';
93
+ } else {
94
+ drag.style.transition = 'opacity 200ms ease 260ms';
95
+ drag.style.opacity = '1';
96
+ drag.style.pointerEvents = '';
97
+ }
98
+ }
99
+
100
+ function syncPositions(w, animate) {
101
+ if (isMobile()) return;
102
+ var content = document.querySelector('.content');
103
+ var dur = animate ? TRANSITION : 'none';
104
+ sidebar.style.transition = 'transform ' + dur + ', width ' + dur;
105
+ if (content) { content.style.transition = 'left ' + dur; content.style.left = w + 'px'; }
106
+ drag.style.left = w + 'px';
107
+ toggle.style.left = (w - 1) + 'px';
108
+ }
109
+
110
+ function setMobileBtnIcon(open) {
111
+ mobileBtn.setAttribute('data-open', open ? 'true' : 'false');
112
+ }
113
+
114
+ function setOpen(open, animate) {
115
+ var w = getSidebarWidth();
116
+ var mobile = isMobile();
117
+ var dur = animate ? TRANSITION : 'none';
118
+ var content = document.querySelector('.content');
119
+
120
+ if (open) {
121
+ document.body.classList.remove('close');
122
+ toggle.innerHTML = '&#x2039;';
123
+ if (mobile) {
124
+ sidebar.style.transition = 'transform ' + dur;
125
+ sidebar.style.transform = 'translateX(0)';
126
+ setMobileBtnIcon(true);
127
+ if (content) { content.style.left = ''; }
128
+ } else {
129
+ syncPositions(w, animate);
130
+ }
131
+ } else {
132
+ document.body.classList.add('close');
133
+ toggle.innerHTML = '&#x203a;';
134
+ if (mobile) {
135
+ sidebar.style.transition = 'transform ' + dur;
136
+ sidebar.style.transform = 'translateX(-100%)';
137
+ setMobileBtnIcon(false);
138
+ if (content) { content.style.left = ''; }
139
+ } else {
140
+ sidebar.style.transition = 'transform ' + dur;
141
+ toggle.style.transition = 'left ' + dur;
142
+ toggle.style.left = '0px';
143
+ if (content) { content.style.transition = 'left ' + dur; content.style.left = '0'; }
144
+ }
145
+ }
146
+ updateDragVisibility(open);
147
+ }
148
+
149
+ toggle.addEventListener('click', function() {
150
+ var isOpen = !document.body.classList.contains('close');
151
+ setOpen(!isOpen, true);
152
+ });
153
+
154
+ mobileBtn.addEventListener('click', function() {
155
+ var isOpen = !document.body.classList.contains('close');
156
+ setOpen(!isOpen, true);
157
+ });
158
+
159
+ var lastMobile = isMobile();
160
+ window.addEventListener('resize', function() {
161
+ var nowMobile = isMobile();
162
+ var isOpen = !document.body.classList.contains('close');
163
+ var w = getSidebarWidth();
164
+
165
+ if (nowMobile !== lastMobile) {
166
+ lastMobile = nowMobile;
167
+ if (nowMobile) {
168
+ var content = document.querySelector('.content');
169
+ if (content) content.style.left = '';
170
+ if (!isOpen) {
171
+ sidebar.style.transition = 'none';
172
+ sidebar.style.transform = 'translateX(-100%)';
173
+ setMobileBtnIcon(false);
174
+ } else {
175
+ sidebar.style.transform = 'translateX(0)';
176
+ setMobileBtnIcon(true);
177
+ }
178
+ } else {
179
+ sidebar.style.transform = '';
180
+ if (isOpen) {
181
+ syncPositions(w, false);
182
+ } else {
183
+ var content = document.querySelector('.content');
184
+ if (content) content.style.left = '0';
185
+ toggle.style.left = '0px';
186
+ }
187
+ }
188
+ } else if (!nowMobile && isOpen) {
189
+ syncPositions(w, false);
190
+ }
191
+ updateDragVisibility(isOpen);
192
+ });
193
+
194
+ if (isMobile()) {
195
+ lastMobile = true;
196
+ sidebar.style.transition = 'none';
197
+ sidebar.style.transform = 'translateX(-100%)';
198
+ document.body.classList.add('close');
199
+ setMobileBtnIcon(false);
200
+ var content = document.querySelector('.content');
201
+ if (content) content.style.left = '';
202
+ } else {
203
+ syncPositions(getSidebarWidth(), false);
204
+ }
205
+ updateDragVisibility(!document.body.classList.contains('close'));
206
+
207
+ var startX, startW;
208
+ drag.addEventListener('mousedown', function(e) {
209
+ if (isMobile()) return;
210
+ e.preventDefault();
211
+ startX = e.clientX;
212
+ startW = getSidebarWidth();
213
+ document.body.style.userSelect = 'none';
214
+ document.body.style.cursor = 'col-resize';
215
+ sidebar.style.transition = 'none';
216
+ var content = document.querySelector('.content');
217
+ if (content) content.style.transition = 'none';
218
+ drag.style.transition = 'none';
219
+ toggle.style.transition = 'none';
220
+
221
+ function onMove(e) {
222
+ var w = Math.max(180, Math.min(600, startW + e.clientX - startX));
223
+ var content = document.querySelector('.content');
224
+ sidebar.style.width = w + 'px';
225
+ if (content) content.style.left = w + 'px';
226
+ drag.style.left = w + 'px';
227
+ toggle.style.left = (w - 1) + 'px';
228
+ }
229
+ function onUp() {
230
+ document.body.style.userSelect = '';
231
+ document.body.style.cursor = '';
232
+ document.removeEventListener('mousemove', onMove);
233
+ document.removeEventListener('mouseup', onUp);
234
+ }
235
+ document.addEventListener('mousemove', onMove);
236
+ document.addEventListener('mouseup', onUp);
237
+ });
238
+ });
239
+
240
+ hook.doneEach(function() {
241
+ var sidebar = document.querySelector('.sidebar');
242
+
243
+ if (repoUrl) {
244
+ var h1 = sidebar.querySelector('h1');
245
+ if (h1) {
246
+ var titleA = h1.querySelector('a');
247
+ if (titleA) titleA.target = '_blank';
248
+ }
249
+ }
250
+
251
+ var scrollWrap = sidebar.querySelector('.xp-sidebar-scroll');
252
+ if (!scrollWrap) {
253
+ scrollWrap = document.createElement('div');
254
+ scrollWrap.className = 'xp-sidebar-scroll';
255
+ var footer = sidebar.querySelector('.xp-sidebar-footer');
256
+ var nodes = Array.from(sidebar.childNodes).filter(function(n) {
257
+ return !n.classList || !n.classList.contains('xp-sidebar-footer');
258
+ });
259
+ nodes.forEach(function(n) { scrollWrap.appendChild(n); });
260
+ sidebar.insertBefore(scrollWrap, footer || null);
261
+ }
262
+
263
+ var drag = document.querySelector('.xp-drag');
264
+ var toggle = document.getElementById('xp-toggle');
265
+ var isOpen = !document.body.classList.contains('close');
266
+ if (drag && toggle) {
267
+ var w = parseInt(sidebar.style.width) || sidebar.offsetWidth || 270;
268
+ if (isOpen && window.innerWidth >= 600) {
269
+ drag.style.left = w + 'px';
270
+ toggle.style.left = (w - 1) + 'px';
271
+ drag.style.opacity = '1';
272
+ drag.style.pointerEvents = '';
273
+ } else {
274
+ drag.style.left = w + 'px';
275
+ toggle.style.left = '0px';
276
+ drag.style.opacity = '0';
277
+ drag.style.pointerEvents = 'none';
278
+ }
279
+ }
280
+
281
+ function updateGhBtn() {
282
+ var existing = document.getElementById('xp-gh-page-btn');
283
+ if (existing) existing.remove();
284
+ if (!githubBase || !currentFilePath) return;
285
+ var btn = document.createElement('a');
286
+ btn.id = 'xp-gh-page-btn';
287
+ btn.href = githubBase + '/' + currentFilePath;
288
+ btn.target = '_blank';
289
+ btn.rel = 'noopener noreferrer';
290
+ btn.setAttribute('aria-label', 'View on GitHub');
291
+ btn.title = 'View on GitHub';
292
+ btn.innerHTML = '<svg viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z"/></svg>';
293
+ document.body.appendChild(btn);
294
+ }
295
+ updateGhBtn();
296
+
297
+ var nav = sidebar.querySelector('.sidebar-nav');
298
+ if (!nav) return;
299
+
300
+ nav.querySelectorAll('li').forEach(function(li) {
301
+ li.classList.remove('collapse');
302
+ var ul = li.querySelector(':scope > ul');
303
+ if (ul && !ul.closest('[data-xp-folder-ul]')) ul.style.display = '';
304
+ });
305
+
306
+ nav.querySelectorAll('li').forEach(function(li) {
307
+ if (li.dataset.xpFolder) return;
308
+ var labelEl = li.querySelector(':scope > p > strong') || li.querySelector(':scope > strong');
309
+ if (!labelEl) return;
310
+ var subUl = li.querySelector(':scope > ul');
311
+ if (!subUl) return;
312
+ subUl.setAttribute('data-xp-folder-ul', '1');
313
+
314
+ var folderName = labelEl.textContent.trim();
315
+
316
+ li.dataset.xpFolder = '1';
317
+ li.classList.remove('collapse');
318
+ subUl.setAttribute('data-xp-folder-ul', '1');
319
+
320
+ var btn = document.createElement('button');
321
+ btn.className = 'xp-folder-btn';
322
+
323
+ var iconSpan = document.createElement('span');
324
+ var labelSpan = document.createElement('span');
325
+ labelSpan.className = 'xp-folder-label';
326
+ labelSpan.textContent = folderName;
327
+
328
+ btn.appendChild(iconSpan);
329
+ btn.appendChild(labelSpan);
330
+
331
+ var wrapper = labelEl.closest('p') || labelEl;
332
+ li.insertBefore(btn, wrapper);
333
+ wrapper.remove();
334
+
335
+ var isOpen = foldersInitialized ? !closedFolders.has(folderName) : false;
336
+ btn.setAttribute('data-open', isOpen ? 'true' : 'false');
337
+ iconSpan.className = 'xp-folder-icon ' + (isOpen ? 'xp-folder-open' : 'xp-folder-closed');
338
+ subUl.style.display = isOpen ? '' : 'none';
339
+
340
+ btn.addEventListener('click', function() {
341
+ var open = btn.getAttribute('data-open') === 'true';
342
+ var nowOpen = !open;
343
+ btn.setAttribute('data-open', nowOpen ? 'true' : 'false');
344
+ iconSpan.className = 'xp-folder-icon ' + (nowOpen ? 'xp-folder-open' : 'xp-folder-closed');
345
+ subUl.style.display = nowOpen ? '' : 'none';
346
+ if (nowOpen) closedFolders.delete(folderName);
347
+ else closedFolders.add(folderName);
348
+ });
349
+ });
350
+
351
+ foldersInitialized = true;
352
+
353
+ nav.querySelectorAll('a').forEach(function(a) {
354
+ if (a.dataset.xpIcon) return;
355
+ if (a.closest('.app-sub-sidebar')) return;
356
+ a.dataset.xpIcon = '1';
357
+ var icon = document.createElement('span');
358
+ icon.className = 'xp-item-icon xp-file-icon';
359
+ a.insertBefore(icon, a.firstChild);
360
+ });
361
+
362
+ nav.querySelectorAll('.app-sub-sidebar a').forEach(function(a) {
363
+ if (a.dataset.xpIcon) return;
364
+ a.dataset.xpIcon = '1';
365
+ var icon = document.createElement('span');
366
+ icon.className = 'xp-item-icon xp-hash-icon';
367
+ a.insertBefore(icon, a.firstChild);
368
+ });
369
+
370
+ nav.querySelectorAll('a').forEach(function(a) {
371
+ if (a.dataset.xpMobileClose) return;
372
+ a.dataset.xpMobileClose = '1';
373
+ a.addEventListener('click', function() {
374
+ if (window.innerWidth < 600) {
375
+ setTimeout(function() {
376
+ document.body.classList.add('close');
377
+ var sb = document.querySelector('.sidebar');
378
+ if (sb) {
379
+ sb.style.transition = 'transform 280ms cubic-bezier(0.4,0,0.2,1)';
380
+ sb.style.transform = 'translateX(-100%)';
381
+ }
382
+ var mb = document.getElementById('xp-mobile-btn');
383
+ if (mb) mb.setAttribute('data-open', 'false');
384
+ var tg = document.getElementById('xp-toggle');
385
+ if (tg) tg.innerHTML = '&#x203a;';
386
+ }, 10);
387
+ }
388
+ });
389
+ });
390
+
391
+ if (githubBase) {
392
+ nav.querySelectorAll('span.xp-unrendered[data-path]').forEach(function(span) {
393
+ if (span.dataset.xpGh) return;
394
+ span.dataset.xpGh = '1';
395
+ span.style.cursor = 'pointer';
396
+ span.addEventListener('click', function() {
397
+ window.open(githubBase + '/' + span.dataset.path, '_blank', 'noopener noreferrer');
398
+ });
399
+ });
400
+ }
401
+ });
402
+ };
403
+
404
+ var titleLockPlugin = function(hook) {
405
+ hook.doneEach(function() { document.title = '{{TITLE}}'; });
406
+ };
407
+
408
+ window.$docsify = {
409
+ name: '{{TITLE}}',
410
+ nameLink: repoUrl || '/',
411
+ repo: '',
412
+ loadSidebar: true,
413
+ subMaxLevel: 2,
414
+ auto2top: true,
415
+ plugins: [explicodePlugin, titleLockPlugin],
416
+ };
417
+ </script>
418
+ <script src="https://cdn.jsdelivr.net/npm/docsify@4/lib/docsify.min.js"></script>
419
+ <script src="https://cdn.jsdelivr.net/npm/prismjs@1/components/prism-python.min.js"></script>
420
+ <script src="https://cdn.jsdelivr.net/npm/prismjs@1/components/prism-javascript.min.js"></script>
421
+ <script src="https://cdn.jsdelivr.net/npm/prismjs@1/components/prism-typescript.min.js"></script>
422
+ <script src="https://cdn.jsdelivr.net/npm/prismjs@1/components/prism-jsx.min.js"></script>
423
+ <script src="https://cdn.jsdelivr.net/npm/prismjs@1/components/prism-tsx.min.js"></script>
424
+ <script src="https://cdn.jsdelivr.net/npm/prismjs@1/components/prism-java.min.js"></script>
425
+ <script src="https://cdn.jsdelivr.net/npm/prismjs@1/components/prism-c.min.js"></script>
426
+ <script src="https://cdn.jsdelivr.net/npm/prismjs@1/components/prism-cpp.min.js"></script>
427
+ <script src="https://cdn.jsdelivr.net/npm/prismjs@1/components/prism-csharp.min.js"></script>
428
+ <script src="https://cdn.jsdelivr.net/npm/prismjs@1/components/prism-rust.min.js"></script>
429
+ <script src="https://cdn.jsdelivr.net/npm/prismjs@1/components/prism-go.min.js"></script>
430
+ <script src="https://cdn.jsdelivr.net/npm/prismjs@1/components/prism-swift.min.js"></script>
431
+ <script src="https://cdn.jsdelivr.net/npm/prismjs@1/components/prism-kotlin.min.js"></script>
432
+ <script src="https://cdn.jsdelivr.net/npm/prismjs@1/components/prism-scala.min.js"></script>
433
+ <script src="https://cdn.jsdelivr.net/npm/prismjs@1/components/prism-dart.min.js"></script>
434
+ <script src="https://cdn.jsdelivr.net/npm/prismjs@1/components/prism-php.min.js"></script>
435
+ <script src="https://cdn.jsdelivr.net/npm/prismjs@1/components/prism-sql.min.js"></script>
436
+ <script src="https://cdn.jsdelivr.net/npm/katex.min.js"></script>
437
+ <script src="https://cdn.jsdelivr.net/npm/docsify-katex@1/dist/docsify-katex.js"></script>
438
+ </body>
439
+ </html>
package/package.json ADDED
@@ -0,0 +1,16 @@
1
+ {
2
+ "name": "explicode",
3
+ "version": "1.0.0",
4
+ "description": "Turn your codebase into documentation.",
5
+ "bin": {
6
+ "explicode": "./cli.js"
7
+ },
8
+ "files": [
9
+ "cli.js",
10
+ "index.template.html",
11
+ "ghmd-dark.css",
12
+ "ghmd-light.css"
13
+ ],
14
+ "engines": { "node": ">=16" },
15
+ "license": "MIT"
16
+ }