Testing of the @doc-json output
1let css = {|
2:root {
3 --bg-color: #f8f9fa;
4 --sidebar-bg: #fff;
5 --content-bg: #fff;
6 --text-color: #24292f;
7 --text-muted: #656d76;
8 --link-color: #0969da;
9 --link-hover: #0550ae;
10 --border-color: #d1d9e0;
11 --code-bg: #f6f8fa;
12 --code-border: #d1d9e0;
13 --highlight-bg: rgba(9, 105, 218, 0.08);
14 --highlight-border: #0969da;
15 --include-bg: rgba(0, 0, 0, 0.02);
16 --sidebar-width: 280px;
17 --header-height: 56px;
18 --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.04);
19 --shadow-md: 0 3px 6px rgba(0, 0, 0, 0.08);
20
21 /* x-ocaml interactive cells */
22 --xo-bg: var(--code-bg);
23 --xo-text: var(--text-color);
24 --xo-gutter-bg: var(--code-bg);
25 --xo-gutter-text: var(--text-muted);
26 --xo-gutter-border: var(--border-color);
27 --xo-stdout-bg: rgba(9, 105, 218, 0.06);
28 --xo-stdout-text: var(--link-color);
29 --xo-stderr-bg: rgba(218, 9, 9, 0.06);
30 --xo-stderr-text: #cf222e;
31 --xo-meta-bg: var(--code-bg);
32 --xo-meta-text: var(--text-muted);
33 --xo-tooltip-bg: var(--content-bg);
34 --xo-tooltip-text: var(--text-color);
35 --xo-tooltip-border: var(--border-color);
36 --xo-btn-bg: var(--code-bg);
37 --xo-btn-border: var(--border-color);
38 --xo-btn-text: var(--text-muted);
39 --xo-btn-hover-bg: var(--text-muted);
40 --xo-btn-hover-text: var(--content-bg);
41}
42
43@media (prefers-color-scheme: dark) {
44 :root {
45 --bg-color: #0d1117;
46 --sidebar-bg: #161b22;
47 --content-bg: #161b22;
48 --text-color: #e6edf3;
49 --text-muted: #8b949e;
50 --link-color: #58a6ff;
51 --link-hover: #79c0ff;
52 --border-color: #30363d;
53 --code-bg: #21262d;
54 --code-border: #30363d;
55 --highlight-bg: rgba(88, 166, 255, 0.12);
56 --highlight-border: #58a6ff;
57 --include-bg: rgba(255, 255, 255, 0.02);
58 --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.2);
59 --shadow-md: 0 3px 6px rgba(0, 0, 0, 0.3);
60
61 /* x-ocaml interactive cells - dark overrides */
62 --xo-stdout-bg: rgba(88, 166, 255, 0.08);
63 --xo-stdout-text: #79c0ff;
64 --xo-stderr-bg: rgba(248, 81, 73, 0.08);
65 --xo-stderr-text: #f85149;
66 --xo-meta-text: var(--text-muted);
67 }
68}
69
70* {
71 box-sizing: border-box;
72 margin: 0;
73 padding: 0;
74}
75
76body {
77 font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
78 font-size: 16px;
79 line-height: 1.6;
80 color: var(--text-color);
81 background: var(--bg-color);
82}
83
84/* Site Header */
85.docsite-header {
86 position: fixed;
87 top: 0;
88 left: 0;
89 right: 0;
90 height: var(--header-height);
91 background: var(--sidebar-bg);
92 border-bottom: 1px solid var(--border-color);
93 box-shadow: var(--shadow-sm);
94 display: flex;
95 align-items: center;
96 padding: 0 24px;
97 z-index: 100;
98}
99
100.docsite-header-brand {
101 font-weight: 600;
102 font-size: 1.2rem;
103 color: var(--text-color);
104 text-decoration: none;
105 letter-spacing: -0.01em;
106}
107
108.docsite-header-brand:hover {
109 color: var(--link-color);
110}
111
112/* Search */
113.docsite-search-container {
114 flex: 1;
115 max-width: 400px;
116 margin: 0 40px;
117}
118
119.search-wrapper {
120 position: relative;
121}
122
123.search-input {
124 width: 100%;
125 padding: 8px 12px 8px 36px;
126 font-size: 14px;
127 border: 1px solid var(--border-color);
128 border-radius: 6px;
129 background: var(--bg-color);
130 color: var(--text-color);
131 transition: border-color 0.2s, box-shadow 0.2s;
132}
133
134.search-input:focus {
135 outline: none;
136 border-color: var(--link-color);
137 box-shadow: 0 0 0 3px rgba(59, 110, 165, 0.15);
138}
139
140.search-input::placeholder {
141 color: var(--text-muted);
142}
143
144.search-icon {
145 position: absolute;
146 left: 12px;
147 top: 50%;
148 transform: translateY(-50%);
149 color: var(--text-muted);
150 pointer-events: none;
151}
152
153.search-shortcut {
154 position: absolute;
155 right: 8px;
156 top: 50%;
157 transform: translateY(-50%);
158 padding: 2px 6px;
159 font-size: 11px;
160 font-family: monospace;
161 background: var(--code-bg);
162 border: 1px solid var(--border-color);
163 border-radius: 3px;
164 color: var(--text-muted);
165}
166
167.search-results {
168 position: absolute;
169 top: calc(100% + 4px);
170 left: 0;
171 right: 0;
172 max-height: 400px;
173 overflow-y: auto;
174 background: var(--content-bg);
175 border: 1px solid var(--border-color);
176 border-radius: 8px;
177 box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12), 0 0 0 1px rgba(0, 0, 0, 0.04);
178 z-index: 1000;
179 display: none;
180}
181
182.search-results.active {
183 display: block;
184}
185
186.search-result {
187 display: block;
188 padding: 10px 14px;
189 color: var(--text-color);
190 text-decoration: none;
191 border-bottom: 1px solid var(--border-color);
192}
193
194.search-result:last-child {
195 border-bottom: none;
196}
197
198.search-result:hover,
199.search-result:focus {
200 background: var(--highlight-bg);
201 outline: none;
202}
203
204.search-result .entry-name {
205 font-weight: 500;
206}
207
208.search-result .entry-kind {
209 font-size: 0.85em;
210 color: var(--text-muted);
211 margin-left: 8px;
212}
213
214.search-no-result {
215 padding: 16px;
216 text-align: center;
217 color: var(--text-muted);
218}
219
220.search-busy::after {
221 content: "";
222 display: inline-block;
223 width: 16px;
224 height: 16px;
225 border: 2px solid var(--border-color);
226 border-top-color: var(--link-color);
227 border-radius: 50%;
228 animation: spin 0.8s linear infinite;
229 position: absolute;
230 right: 40px;
231 top: 50%;
232 transform: translateY(-50%);
233}
234
235@keyframes spin {
236 to { transform: translateY(-50%) rotate(360deg); }
237}
238
239/* Layout */
240.docsite-layout {
241 display: flex;
242 margin-top: var(--header-height);
243 min-height: calc(100vh - var(--header-height));
244}
245
246/* Sidebar */
247.docsite-sidebar {
248 position: fixed;
249 top: var(--header-height);
250 left: 0;
251 width: var(--sidebar-width);
252 height: calc(100vh - var(--header-height));
253 background: var(--sidebar-bg);
254 border-right: 1px solid var(--border-color);
255 overflow-y: auto;
256 padding: 8px 0;
257 z-index: 50;
258 scrollbar-width: thin;
259 scrollbar-color: var(--border-color) transparent;
260}
261
262.docsite-sidebar::-webkit-scrollbar {
263 width: 6px;
264}
265
266.docsite-sidebar::-webkit-scrollbar-track {
267 background: transparent;
268}
269
270.docsite-sidebar::-webkit-scrollbar-thumb {
271 background: var(--border-color);
272 border-radius: 3px;
273}
274
275.docsite-sidebar::-webkit-scrollbar-thumb:hover {
276 background: var(--text-muted);
277}
278
279.sidebar-nav {
280 padding: 0 8px;
281}
282
283.sidebar-section {
284 margin-bottom: 4px;
285}
286
287.sidebar-link {
288 display: block;
289 padding: 3px 8px;
290 color: var(--text-color);
291 text-decoration: none;
292 border-radius: 3px;
293 font-size: 13px;
294 line-height: 1.4;
295}
296
297.sidebar-link:hover:not(.active) {
298 background: var(--bg-color);
299}
300
301.sidebar-link.active {
302 background: var(--highlight-bg);
303 color: var(--link-color);
304 font-weight: 600;
305}
306
307.sidebar-group {
308 margin-left: 0;
309}
310
311.sidebar-group-header {
312 display: flex;
313 align-items: center;
314 padding: 3px 8px;
315 cursor: pointer;
316 font-size: 13px;
317 font-weight: 500;
318 color: var(--text-color);
319 border-radius: 3px;
320 user-select: none;
321}
322
323.sidebar-group-header:hover {
324 background: var(--bg-color);
325}
326
327.sidebar-toggle {
328 width: 14px;
329 height: 14px;
330 margin-right: 4px;
331 flex-shrink: 0;
332 transition: transform 0.2s;
333}
334
335.sidebar-toggle-spacer {
336 display: inline-block;
337 width: 14px;
338 height: 14px;
339 margin-right: 4px;
340 flex-shrink: 0;
341}
342
343.sidebar-leaf {
344 display: flex;
345 align-items: center;
346}
347
348/* Package selector */
349.package-selector {
350 padding: 8px;
351 border-bottom: 1px solid var(--border-color);
352 margin-bottom: 4px;
353}
354
355.package-selector select {
356 width: 100%;
357 padding: 6px 10px;
358 font-size: 13px;
359 font-weight: 500;
360 border: 1px solid var(--border-color);
361 border-radius: 6px;
362 background: var(--content-bg);
363 color: var(--text-color);
364 cursor: pointer;
365 appearance: none;
366 background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23666' stroke-width='2'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
367 background-repeat: no-repeat;
368 background-position: right 10px center;
369 padding-right: 32px;
370}
371
372.package-selector select:hover {
373 border-color: var(--link-color);
374}
375
376.package-selector select:focus {
377 outline: none;
378 border-color: var(--link-color);
379 box-shadow: 0 0 0 3px rgba(59, 110, 165, 0.15);
380}
381
382.sidebar-group.collapsed .sidebar-toggle {
383 transform: rotate(-90deg);
384}
385
386.sidebar-group.collapsed .sidebar-children {
387 display: none;
388}
389
390.sidebar-children {
391 margin-left: 8px;
392 border-left: 1px solid var(--border-color);
393 padding-left: 4px;
394}
395
396/* Sidebar entry type indicators */
397.sidebar-kind {
398 display: inline-flex;
399 align-items: center;
400 justify-content: center;
401 width: 16px;
402 height: 16px;
403 margin-right: 5px;
404 border-radius: 3px;
405 font-size: 9px;
406 font-weight: 700;
407 flex-shrink: 0;
408}
409
410.sidebar-kind-package {
411 background: #8250df;
412 color: white;
413}
414
415.sidebar-kind-module {
416 background: #bf8700;
417 color: white;
418}
419
420.sidebar-kind-page {
421 background: #1a7f37;
422 color: white;
423}
424
425.sidebar-kind-leaf-page {
426 background: #57606a;
427 color: white;
428}
429
430.sidebar-kind-class,
431.sidebar-kind-class-type {
432 background: #0550ae;
433 color: white;
434}
435
436.sidebar-kind-library {
437 background: #6e7781;
438 color: white;
439}
440
441.sidebar-group-header .sidebar-kind {
442 margin-left: 0;
443}
444
445.sidebar-link .sidebar-kind {
446 margin-left: 0;
447}
448
449/* Non-link labels in sidebar (e.g. library headings) */
450.sidebar-label {
451 color: var(--text-muted);
452 font-size: 13px;
453 line-height: 1.4;
454}
455
456/* Main Content */
457.docsite-main {
458 flex: 1;
459 margin-left: var(--sidebar-width);
460 padding: 24px 40px 60px;
461 max-width: calc(100% - var(--sidebar-width));
462 background: var(--content-bg);
463 min-height: calc(100vh - var(--header-height));
464}
465
466/* Breadcrumbs */
467.odoc-nav {
468 display: flex;
469 align-items: center;
470 flex-wrap: wrap;
471 gap: 4px;
472 padding: 12px 0;
473 margin-bottom: 16px;
474 font-size: 14px;
475 border-bottom: 1px solid var(--border-color);
476}
477
478.breadcrumb-item {
479 color: var(--link-color);
480 text-decoration: none;
481}
482
483.breadcrumb-item:hover {
484 text-decoration: underline;
485}
486
487.breadcrumb-separator {
488 color: var(--text-muted);
489 margin: 0 4px;
490}
491
492.breadcrumb-current {
493 color: var(--text-color);
494 font-weight: 500;
495}
496
497/* Content Styles */
498.odoc-content {
499 max-width: 900px;
500}
501
502.odoc-content h1 {
503 font-size: 2rem;
504 font-weight: 600;
505 margin-bottom: 16px;
506 padding-bottom: 8px;
507 border-bottom: 2px solid var(--border-color);
508}
509
510.odoc-content h2 {
511 font-size: 1.5rem;
512 font-weight: 600;
513 margin-top: 32px;
514 margin-bottom: 12px;
515 padding-bottom: 6px;
516 border-bottom: 1px solid var(--border-color);
517}
518
519.odoc-content h3 {
520 font-size: 1.25rem;
521 font-weight: 600;
522 margin-top: 24px;
523 margin-bottom: 8px;
524}
525
526.odoc-content h4, .odoc-content h5, .odoc-content h6 {
527 font-size: 1.1rem;
528 font-weight: 600;
529 margin-top: 20px;
530 margin-bottom: 8px;
531}
532
533.odoc-content p {
534 margin-bottom: 16px;
535}
536
537.odoc-content a {
538 color: var(--link-color);
539 text-decoration: none;
540}
541
542.odoc-content a:hover {
543 text-decoration: underline;
544}
545
546.odoc-content code {
547 font-family: "SF Mono", Consolas, "Liberation Mono", Menlo, monospace;
548 font-size: 0.9em;
549 background: var(--code-bg);
550 padding: 2px 6px;
551 border-radius: 4px;
552 border: 1px solid var(--code-border);
553}
554
555.odoc-content pre {
556 background: var(--code-bg);
557 border: 1px solid var(--code-border);
558 border-radius: 8px;
559 padding: 16px;
560 overflow-x: auto;
561 margin-bottom: 16px;
562 box-shadow: var(--shadow-sm);
563}
564
565.odoc-content pre code {
566 background: none;
567 border: none;
568 padding: 0;
569 font-size: 0.875rem;
570 line-height: 1.5;
571}
572
573.odoc-content ul, .odoc-content ol {
574 margin-bottom: 16px;
575 padding-left: 24px;
576}
577
578.odoc-content li {
579 margin-bottom: 4px;
580}
581
582.odoc-content blockquote {
583 border-left: 4px solid var(--link-color);
584 margin: 16px 0;
585 padding: 8px 16px;
586 background: var(--code-bg);
587 color: var(--text-muted);
588}
589
590.odoc-content table {
591 width: 100%;
592 border-collapse: collapse;
593 margin-bottom: 16px;
594}
595
596.odoc-content th, .odoc-content td {
597 padding: 10px 12px;
598 border: 1px solid var(--border-color);
599 text-align: left;
600}
601
602.odoc-content th {
603 background: var(--code-bg);
604 font-weight: 600;
605}
606
607/* odoc-specific styles */
608.odoc-spec {
609 margin: 16px 0;
610 padding: 12px 16px;
611 background: var(--code-bg);
612 border: 1px solid var(--code-border);
613 border-radius: 8px;
614 border-left: 3px solid var(--link-color);
615 box-shadow: var(--shadow-sm);
616}
617
618.odoc-spec code {
619 background: none;
620 border: none;
621 padding: 0;
622 font-size: inherit;
623}
624
625.spec {
626 font-family: "SF Mono", Consolas, monospace;
627 font-size: 0.9rem;
628}
629
630.spec-doc {
631 margin-top: 8px;
632 padding-top: 8px;
633 border-top: 1px solid var(--border-color);
634 font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif;
635 font-size: 0.95rem;
636}
637
638/* Hide OCaml comment delimiters in documentation */
639.comment-delim {
640 display: none;
641}
642
643.odoc-spec ol {
644 list-style: none;
645 margin: 0;
646 padding: 0;
647}
648
649.odoc-spec li {
650 margin: 4px 0;
651}
652
653.def-doc {
654 display: inline;
655 margin-left: 8px;
656 color: var(--text-muted);
657 font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif;
658 font-size: 0.9rem;
659}
660
661.def-doc p {
662 display: inline;
663 margin: 0;
664}
665
666/* Include blocks */
667.odoc-include {
668 margin: 16px 0;
669 margin-left: 12px;
670 padding: 12px;
671 border: 1px solid var(--border-color);
672 border-left: 3px solid var(--text-muted);
673 border-radius: 8px;
674 background: var(--include-bg);
675}
676
677.odoc-include > details {
678 margin: 0;
679}
680
681.odoc-include > details > summary {
682 padding: 8px 0;
683 cursor: pointer;
684 font-family: "SF Mono", Consolas, monospace;
685 font-size: 0.9rem;
686 list-style: none;
687}
688
689.odoc-include > details > summary::-webkit-details-marker {
690 display: none;
691}
692
693.odoc-include > details > summary::before {
694 content: "\25B6";
695 display: inline-block;
696 margin-right: 8px;
697 transition: transform 0.2s;
698 font-size: 0.7em;
699 color: var(--text-muted);
700}
701
702.odoc-include > details[open] > summary::before {
703 transform: rotate(90deg);
704}
705
706.anchor {
707 color: var(--text-muted);
708 text-decoration: none;
709 margin-left: 4px;
710 opacity: 0;
711 transition: opacity 0.15s;
712}
713
714h1:hover .anchor, h2:hover .anchor, h3:hover .anchor,
715h4:hover .anchor, h5:hover .anchor, h6:hover .anchor,
716.spec:hover .anchor {
717 opacity: 1;
718}
719
720.anchor:hover {
721 color: var(--link-color);
722}
723
724/* Highlight target element from URL hash */
725:target,
726.hash-highlight {
727 position: relative;
728 background: var(--highlight-bg);
729 border-radius: 4px;
730 box-shadow: inset 3px 0 0 var(--highlight-border);
731 padding-left: 12px;
732 margin-left: -12px;
733}
734
735.hash-highlight {
736 animation: highlight-pulse 1.5s ease-out;
737}
738
739@keyframes highlight-pulse {
740 0% {
741 background: rgba(9, 105, 218, 0.2);
742 box-shadow: inset 3px 0 0 var(--highlight-border), 0 0 12px rgba(9, 105, 218, 0.3);
743 }
744 100% {
745 background: var(--highlight-bg);
746 box-shadow: inset 3px 0 0 var(--highlight-border);
747 }
748}
749
750@media (prefers-color-scheme: dark) {
751 @keyframes highlight-pulse {
752 0% {
753 background: rgba(88, 166, 255, 0.25);
754 box-shadow: inset 3px 0 0 var(--highlight-border), 0 0 12px rgba(88, 166, 255, 0.3);
755 }
756 100% {
757 background: var(--highlight-bg);
758 box-shadow: inset 3px 0 0 var(--highlight-border);
759 }
760 }
761}
762
763@keyframes highlight-fade {
764 0% { background-color: var(--highlight-bg); }
765 100% { background-color: transparent; }
766}
767
768/* Table of Contents (in-page) */
769.odoc-tocs {
770 position: fixed;
771 right: 24px;
772 top: calc(var(--header-height) + 24px);
773 width: 200px;
774 max-height: calc(100vh - var(--header-height) - 48px);
775 overflow-y: auto;
776 font-size: 13px;
777 padding: 16px;
778 background: var(--sidebar-bg);
779 border: 1px solid var(--border-color);
780 border-radius: 8px;
781 box-shadow: var(--shadow-sm);
782}
783
784.odoc-tocs .odoc-toc-title {
785 font-weight: 600;
786 margin-bottom: 12px;
787 color: var(--text-color);
788 font-size: 12px;
789 letter-spacing: 0.02em;
790}
791
792.odoc-tocs ul {
793 list-style: none;
794 margin: 0;
795 padding: 0;
796 border-left: 1px solid var(--border-color);
797}
798
799.odoc-tocs li {
800 margin: 0;
801}
802
803.odoc-tocs a {
804 color: var(--text-muted);
805 text-decoration: none;
806 display: block;
807 padding: 4px 0 4px 12px;
808 margin-left: -1px;
809 border-left: 2px solid transparent;
810 transition: color 0.15s, border-color 0.15s;
811}
812
813.odoc-tocs a:hover {
814 color: var(--link-color);
815 border-left-color: var(--link-color);
816}
817
818.odoc-tocs ul ul {
819 margin-left: 12px;
820 border-left: none;
821}
822
823.odoc-tocs ul ul a {
824 padding-left: 12px;
825 font-size: 12px;
826}
827
828@media (max-width: 1400px) {
829 .odoc-tocs {
830 display: none;
831 }
832}
833
834/* Responsive */
835@media (max-width: 768px) {
836 :root {
837 --sidebar-width: 0;
838 }
839
840 .docsite-sidebar {
841 transform: translateX(-100%);
842 transition: transform 0.3s;
843 }
844
845 .docsite-sidebar.open {
846 transform: translateX(0);
847 width: 280px;
848 }
849
850 .docsite-main {
851 margin-left: 0;
852 max-width: 100%;
853 padding: 16px 20px;
854 }
855
856 .menu-toggle {
857 display: block;
858 }
859}
860
861.menu-toggle {
862 display: none;
863 background: none;
864 border: none;
865 padding: 8px;
866 cursor: pointer;
867 color: var(--text-color);
868}
869|}