@typefm/react-markdown-viewer 0.1.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.
Files changed (85) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +217 -0
  3. package/dist/ErrorBoundary.d.ts +25 -0
  4. package/dist/ErrorBoundary.d.ts.map +1 -0
  5. package/dist/ErrorBoundary.js +29 -0
  6. package/dist/ErrorBoundary.js.map +1 -0
  7. package/dist/MarkdownViewer.d.ts +41 -0
  8. package/dist/MarkdownViewer.d.ts.map +1 -0
  9. package/dist/MarkdownViewer.js +69 -0
  10. package/dist/MarkdownViewer.js.map +1 -0
  11. package/dist/index.d.ts +17 -0
  12. package/dist/index.d.ts.map +1 -0
  13. package/dist/index.js +21 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/lib/cache-manager.d.ts +59 -0
  16. package/dist/lib/cache-manager.d.ts.map +1 -0
  17. package/dist/lib/cache-manager.js +160 -0
  18. package/dist/lib/cache-manager.js.map +1 -0
  19. package/dist/lib/cursor-controller.d.ts +13 -0
  20. package/dist/lib/cursor-controller.d.ts.map +1 -0
  21. package/dist/lib/cursor-controller.js +93 -0
  22. package/dist/lib/cursor-controller.js.map +1 -0
  23. package/dist/lib/defaults/code-block.d.ts +71 -0
  24. package/dist/lib/defaults/code-block.d.ts.map +1 -0
  25. package/dist/lib/defaults/code-block.js +104 -0
  26. package/dist/lib/defaults/code-block.js.map +1 -0
  27. package/dist/lib/defaults/image.d.ts +41 -0
  28. package/dist/lib/defaults/image.d.ts.map +1 -0
  29. package/dist/lib/defaults/image.js +45 -0
  30. package/dist/lib/defaults/image.js.map +1 -0
  31. package/dist/lib/defaults/link.d.ts +45 -0
  32. package/dist/lib/defaults/link.d.ts.map +1 -0
  33. package/dist/lib/defaults/link.js +76 -0
  34. package/dist/lib/defaults/link.js.map +1 -0
  35. package/dist/lib/defaults/math.d.ts +51 -0
  36. package/dist/lib/defaults/math.d.ts.map +1 -0
  37. package/dist/lib/defaults/math.js +119 -0
  38. package/dist/lib/defaults/math.js.map +1 -0
  39. package/dist/lib/defaults/table.d.ts +18 -0
  40. package/dist/lib/defaults/table.d.ts.map +1 -0
  41. package/dist/lib/defaults/table.js +19 -0
  42. package/dist/lib/defaults/table.js.map +1 -0
  43. package/dist/lib/highlighter.d.ts +81 -0
  44. package/dist/lib/highlighter.d.ts.map +1 -0
  45. package/dist/lib/highlighter.js +421 -0
  46. package/dist/lib/highlighter.js.map +1 -0
  47. package/dist/lib/hook-utils.d.ts +32 -0
  48. package/dist/lib/hook-utils.d.ts.map +1 -0
  49. package/dist/lib/hook-utils.js +42 -0
  50. package/dist/lib/hook-utils.js.map +1 -0
  51. package/dist/lib/html.d.ts +2 -0
  52. package/dist/lib/html.d.ts.map +1 -0
  53. package/dist/lib/html.js +12 -0
  54. package/dist/lib/html.js.map +1 -0
  55. package/dist/lib/morph.d.ts +57 -0
  56. package/dist/lib/morph.d.ts.map +1 -0
  57. package/dist/lib/morph.js +204 -0
  58. package/dist/lib/morph.js.map +1 -0
  59. package/dist/lib/parser.d.ts +32 -0
  60. package/dist/lib/parser.d.ts.map +1 -0
  61. package/dist/lib/parser.js +645 -0
  62. package/dist/lib/parser.js.map +1 -0
  63. package/dist/lib/wasm-init.d.ts +33 -0
  64. package/dist/lib/wasm-init.d.ts.map +1 -0
  65. package/dist/lib/wasm-init.js +69 -0
  66. package/dist/lib/wasm-init.js.map +1 -0
  67. package/dist/styles/alerts.css +294 -0
  68. package/dist/styles/dotted.svg +3 -0
  69. package/dist/styles/hljs.css +332 -0
  70. package/dist/styles/index.css +17 -0
  71. package/dist/styles/katex.css +74 -0
  72. package/dist/styles/viewer.css +975 -0
  73. package/dist/types/hooks.d.ts +207 -0
  74. package/dist/types/hooks.d.ts.map +1 -0
  75. package/dist/types/hooks.js +7 -0
  76. package/dist/types/hooks.js.map +1 -0
  77. package/dist/useMarkdownViewer.d.ts +18 -0
  78. package/dist/useMarkdownViewer.d.ts.map +1 -0
  79. package/dist/useMarkdownViewer.js +403 -0
  80. package/dist/useMarkdownViewer.js.map +1 -0
  81. package/dist/utils.d.ts +20 -0
  82. package/dist/utils.d.ts.map +1 -0
  83. package/dist/utils.js +18 -0
  84. package/dist/utils.js.map +1 -0
  85. package/package.json +78 -0
@@ -0,0 +1,975 @@
1
+ /**
2
+ * Markdown Viewer - Core Styles (GitHub-style)
3
+ *
4
+ * Styles based on GitHub's Primer design system for markdown rendering.
5
+ * Supports light/dark themes and streaming cursor animation.
6
+ *
7
+ * Theme Support:
8
+ * - Automatic: Uses prefers-color-scheme media query
9
+ * - Manual: Add .dark class or data-theme="dark" to parent element
10
+ *
11
+ * Customization:
12
+ * Override CSS variables on .markdown-viewer:
13
+ *
14
+ * .markdown-viewer {
15
+ * --bgColor-default: #ffffff;
16
+ * --borderColor-default: #d1d9e0;
17
+ * --cursor-color: #f5a1ff;
18
+ * }
19
+ */
20
+
21
+ /* ============================================
22
+ Root Container & CSS Variables (Light Theme)
23
+ Based on GitHub Primer design tokens
24
+ ============================================ */
25
+ .markdown-viewer {
26
+ display: block;
27
+ width: 100%;
28
+ min-width: 0;
29
+ box-sizing: border-box;
30
+
31
+ /* Base sizing tokens */
32
+ --base-size-4: 4px;
33
+ --base-size-8: 8px;
34
+ --base-size-16: 16px;
35
+ --base-size-24: 24px;
36
+ --base-size-40: 40px;
37
+
38
+ /* Typography tokens */
39
+ --base-text-weight-normal: 400;
40
+ --base-text-weight-medium: 500;
41
+ --base-text-weight-semibold: 600;
42
+ --fontStack-sansSerif: -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
43
+ --fontStack-monospace: ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace;
44
+
45
+ /* Background colors */
46
+ --bgColor-default: #ffffff;
47
+ --bgColor-muted: #f6f8fa;
48
+ --bgColor-neutral-muted: rgba(175, 184, 193, 0.2);
49
+ --bgColor-attention-muted: #fff8c5;
50
+
51
+ /* Border colors */
52
+ --borderColor-default: #d1d9e0;
53
+ --borderColor-muted: #d1d9e0b3;
54
+
55
+ /* Foreground colors */
56
+ --fgColor-default: #1f2328;
57
+ --fgColor-muted: #59636e;
58
+ --fgColor-accent: #0969da;
59
+
60
+ /* Cursor */
61
+ --cursor-color: #f5a1ff;
62
+ --cursor-border-radius: 2px;
63
+ }
64
+
65
+ /* ============================================
66
+ Markdown Content Container
67
+ ============================================ */
68
+ .markdown-viewer .markdown {
69
+ -ms-text-size-adjust: 100%;
70
+ -webkit-text-size-adjust: 100%;
71
+ contain: layout style;
72
+ isolation: isolate;
73
+ font-family: var(--fontStack-sansSerif);
74
+ font-size: 16px;
75
+ font-weight: var(--base-text-weight-normal);
76
+ line-height: 1.5;
77
+ color: var(--fgColor-default);
78
+ min-width: 0;
79
+ box-sizing: border-box;
80
+ word-wrap: break-word;
81
+ overflow-wrap: break-word;
82
+ }
83
+
84
+ /* Block element margins (GitHub pattern) */
85
+ .markdown-viewer .markdown p,
86
+ .markdown-viewer .markdown blockquote,
87
+ .markdown-viewer .markdown ul,
88
+ .markdown-viewer .markdown ol,
89
+ .markdown-viewer .markdown dl,
90
+ .markdown-viewer .markdown table,
91
+ .markdown-viewer .markdown pre,
92
+ .markdown-viewer .markdown details {
93
+ margin-top: 0;
94
+ margin-bottom: var(--base-size-16);
95
+ }
96
+
97
+ /* First/last child margin removal */
98
+ .markdown-viewer .markdown > *:first-child {
99
+ margin-top: 0 !important;
100
+ }
101
+
102
+ .markdown-viewer .markdown > *:last-child {
103
+ margin-bottom: 0 !important;
104
+ }
105
+
106
+ /* ============================================
107
+ Typography - Headings
108
+ ============================================ */
109
+ .markdown-viewer .markdown h1,
110
+ .markdown-viewer .markdown h2,
111
+ .markdown-viewer .markdown h3,
112
+ .markdown-viewer .markdown h4,
113
+ .markdown-viewer .markdown h5,
114
+ .markdown-viewer .markdown h6 {
115
+ margin-top: var(--base-size-24);
116
+ margin-bottom: var(--base-size-16);
117
+ font-weight: var(--base-text-weight-semibold);
118
+ line-height: 1.25;
119
+ }
120
+
121
+ .markdown-viewer .markdown h1 {
122
+ padding-bottom: 0.3em;
123
+ font-size: 2em;
124
+ border-bottom: 1px solid var(--borderColor-muted);
125
+ }
126
+
127
+ .markdown-viewer .markdown h2 {
128
+ padding-bottom: 0.3em;
129
+ font-size: 1.5em;
130
+ border-bottom: 1px solid var(--borderColor-muted);
131
+ }
132
+
133
+ .markdown-viewer .markdown h3 {
134
+ font-size: 1.25em;
135
+ }
136
+
137
+ .markdown-viewer .markdown h4 {
138
+ font-size: 1em;
139
+ }
140
+
141
+ .markdown-viewer .markdown h5 {
142
+ font-size: 0.875em;
143
+ }
144
+
145
+ .markdown-viewer .markdown h6 {
146
+ font-size: 0.85em;
147
+ color: var(--fgColor-muted);
148
+ }
149
+
150
+ /* Code inside headings */
151
+ .markdown-viewer .markdown h1 tt,
152
+ .markdown-viewer .markdown h1 code,
153
+ .markdown-viewer .markdown h2 tt,
154
+ .markdown-viewer .markdown h2 code,
155
+ .markdown-viewer .markdown h3 tt,
156
+ .markdown-viewer .markdown h3 code,
157
+ .markdown-viewer .markdown h4 tt,
158
+ .markdown-viewer .markdown h4 code,
159
+ .markdown-viewer .markdown h5 tt,
160
+ .markdown-viewer .markdown h5 code,
161
+ .markdown-viewer .markdown h6 tt,
162
+ .markdown-viewer .markdown h6 code {
163
+ padding: 0 0.2em;
164
+ font-size: inherit;
165
+ }
166
+
167
+ /* ============================================
168
+ Typography - Inline Formatting
169
+ ============================================ */
170
+ .markdown-viewer .markdown strong,
171
+ .markdown-viewer .markdown b {
172
+ font-weight: var(--base-text-weight-semibold);
173
+ }
174
+
175
+ .markdown-viewer .markdown em,
176
+ .markdown-viewer .markdown i {
177
+ font-style: italic;
178
+ font-synthesis: style;
179
+ }
180
+
181
+ .markdown-viewer .markdown mark {
182
+ background-color: var(--bgColor-attention-muted);
183
+ color: var(--fgColor-default);
184
+ border-radius: 0.125rem;
185
+ padding: 0.125rem 0.25rem;
186
+ }
187
+
188
+ .markdown-viewer .markdown small {
189
+ font-size: 90%;
190
+ }
191
+
192
+ .markdown-viewer .markdown sub,
193
+ .markdown-viewer .markdown sup {
194
+ font-size: 75%;
195
+ line-height: 0;
196
+ position: relative;
197
+ vertical-align: baseline;
198
+ }
199
+
200
+ .markdown-viewer .markdown sub {
201
+ bottom: -0.25em;
202
+ }
203
+
204
+ .markdown-viewer .markdown sup {
205
+ top: -0.5em;
206
+ }
207
+
208
+ /* ============================================
209
+ Horizontal Rule
210
+ ============================================ */
211
+ .markdown-viewer .markdown hr {
212
+ box-sizing: content-box;
213
+ overflow: hidden;
214
+ border: 0;
215
+ height: 0.25em;
216
+ padding: 0;
217
+ margin: var(--base-size-24) 0;
218
+ background-color: var(--borderColor-muted);
219
+ }
220
+
221
+ /* ============================================
222
+ Blockquotes
223
+ ============================================ */
224
+ .markdown-viewer .markdown blockquote {
225
+ margin-left: 0;
226
+ padding: 0 1em;
227
+ color: var(--fgColor-muted);
228
+ border-left: 0.25em solid var(--borderColor-default);
229
+ }
230
+
231
+ .markdown-viewer .markdown blockquote > :first-child {
232
+ margin-top: 0;
233
+ }
234
+
235
+ .markdown-viewer .markdown blockquote > :last-child {
236
+ margin-bottom: 0;
237
+ }
238
+
239
+ /* ============================================
240
+ Links
241
+ ============================================ */
242
+ .markdown-viewer .markdown a {
243
+ display: inline;
244
+ max-width: 100%;
245
+ overflow: hidden;
246
+ text-overflow: ellipsis;
247
+ vertical-align: top;
248
+ color: var(--fgColor-accent);
249
+ text-decoration: underline;
250
+ text-underline-offset: 0.2rem;
251
+ background-color: transparent;
252
+ }
253
+
254
+ .markdown-viewer .markdown a:not([href]) {
255
+ color: inherit;
256
+ text-decoration: none;
257
+ }
258
+
259
+ /* ============================================
260
+ Images
261
+ ============================================ */
262
+ .markdown-viewer .markdown img {
263
+ border-style: none;
264
+ max-width: 100%;
265
+ box-sizing: content-box;
266
+ background-color: var(--bgColor-default);
267
+ }
268
+
269
+ .markdown-viewer .markdown img[align="right"] {
270
+ padding-left: 20px;
271
+ }
272
+
273
+ .markdown-viewer .markdown img[align="left"] {
274
+ padding-right: 20px;
275
+ }
276
+
277
+ /* ============================================
278
+ Code - Inline Code
279
+ ============================================ */
280
+ .markdown-viewer .markdown code,
281
+ .markdown-viewer .markdown tt,
282
+ .markdown-viewer .markdown samp {
283
+ font-family: var(--fontStack-monospace);
284
+ font-size: 85%;
285
+ }
286
+
287
+ .markdown-viewer .markdown code,
288
+ .markdown-viewer .markdown tt {
289
+ padding: 0.2em 0.4em;
290
+ margin: 0;
291
+ white-space: break-spaces;
292
+ background-color: var(--bgColor-neutral-muted);
293
+ border-radius: 6px;
294
+ }
295
+
296
+ .markdown-viewer .markdown code br,
297
+ .markdown-viewer .markdown tt br {
298
+ display: none;
299
+ }
300
+
301
+ .markdown-viewer .markdown del {
302
+ text-decoration: line-through;
303
+ }
304
+
305
+ .markdown-viewer .markdown del code {
306
+ text-decoration: inherit;
307
+ }
308
+
309
+ /* ============================================
310
+ Code - Pre/Code Blocks
311
+ ============================================ */
312
+ .markdown-viewer .markdown pre {
313
+ position: relative;
314
+ margin-top: 0;
315
+ margin-bottom: 0;
316
+ font-family: var(--fontStack-monospace);
317
+ word-wrap: normal;
318
+ tab-size: 2;
319
+ -moz-tab-size: 2;
320
+ }
321
+
322
+ .markdown-viewer .markdown pre code {
323
+ font-size: 100%;
324
+ }
325
+
326
+ .markdown-viewer .markdown pre > code {
327
+ display: block;
328
+ padding: 0;
329
+ margin: 0;
330
+ word-break: normal;
331
+ white-space: pre;
332
+ background: transparent;
333
+ border: 0;
334
+ overflow: visible;
335
+ line-height: inherit;
336
+ /* Ensure empty code blocks have height for cursor visibility */
337
+ min-height: 1.4em;
338
+ }
339
+
340
+ /* Highlighted code blocks */
341
+ .markdown-viewer .markdown .highlight pre {
342
+ margin-bottom: 0;
343
+ word-break: normal;
344
+ }
345
+
346
+ .markdown-viewer .markdown .highlight pre,
347
+ .markdown-viewer .markdown pre {
348
+ padding: var(--base-size-16);
349
+ overflow: auto;
350
+ font-size: 85%;
351
+ line-height: 1.45;
352
+ color: var(--fgColor-default);
353
+ background-color: var(--bgColor-muted);
354
+ border-radius: 6px;
355
+ }
356
+
357
+ .markdown-viewer .markdown pre code,
358
+ .markdown-viewer .markdown pre tt {
359
+ display: inline;
360
+ padding: 0;
361
+ margin: 0;
362
+ overflow: visible;
363
+ line-height: inherit;
364
+ word-wrap: normal;
365
+ background-color: transparent;
366
+ border: 0;
367
+ }
368
+
369
+ /* ============================================
370
+ Code Block Wrapper (with Copy Button)
371
+ ============================================ */
372
+ .markdown-viewer .markdown .code-block-wrapper {
373
+ position: relative;
374
+ max-width: 100%;
375
+ }
376
+
377
+ .markdown-viewer .markdown .code-block-wrapper pre {
378
+ margin-bottom: var(--base-size-16);
379
+ }
380
+
381
+ /* Copy button - hidden by default, shown on hover */
382
+ .markdown-viewer .markdown .copy-btn {
383
+ position: absolute;
384
+ top: var(--base-size-8);
385
+ right: var(--base-size-8);
386
+ display: flex;
387
+ align-items: center;
388
+ justify-content: center;
389
+ padding: var(--base-size-4);
390
+ border: 1px solid var(--borderColor-default);
391
+ border-radius: 6px;
392
+ background: var(--bgColor-default);
393
+ color: var(--fgColor-muted);
394
+ cursor: pointer;
395
+ opacity: 0;
396
+ transition:
397
+ opacity 0.15s ease,
398
+ background 0.15s ease,
399
+ color 0.15s ease;
400
+ z-index: 1;
401
+ }
402
+
403
+ .markdown-viewer .markdown .code-block-wrapper:hover .copy-btn {
404
+ opacity: 1;
405
+ }
406
+
407
+ .markdown-viewer .markdown .copy-btn:hover {
408
+ background: var(--bgColor-muted);
409
+ color: var(--fgColor-default);
410
+ }
411
+
412
+ .markdown-viewer .markdown .copy-btn:active {
413
+ transform: scale(0.95);
414
+ }
415
+
416
+ /* Copy button icons */
417
+ .markdown-viewer .markdown .copy-btn .copy-icon,
418
+ .markdown-viewer .markdown .copy-btn .check-icon {
419
+ flex-shrink: 0;
420
+ }
421
+
422
+ .markdown-viewer .markdown .copy-btn .check-icon {
423
+ display: none;
424
+ }
425
+
426
+ .markdown-viewer .markdown .copy-btn.copied .copy-icon {
427
+ display: none;
428
+ }
429
+
430
+ .markdown-viewer .markdown .copy-btn.copied .check-icon {
431
+ display: block;
432
+ color: #22c55e;
433
+ }
434
+
435
+ .markdown-viewer .markdown .copy-btn.copied {
436
+ opacity: 1;
437
+ }
438
+
439
+ /* Code line wrapping for syntax highlighting */
440
+ .markdown-viewer .markdown .code-line {
441
+ display: inline-block;
442
+ }
443
+
444
+ /* ============================================
445
+ Keyboard Keys
446
+ ============================================ */
447
+ .markdown-viewer .markdown kbd {
448
+ display: inline-block;
449
+ padding: var(--base-size-4);
450
+ font: 11px var(--fontStack-monospace);
451
+ line-height: 10px;
452
+ color: var(--fgColor-default);
453
+ vertical-align: middle;
454
+ background-color: var(--bgColor-muted);
455
+ border: solid 1px var(--borderColor-muted);
456
+ border-bottom-color: var(--borderColor-muted);
457
+ border-radius: 6px;
458
+ box-shadow: inset 0 -1px 0 var(--borderColor-muted);
459
+ }
460
+
461
+ /* ============================================
462
+ Color Boxes (for CSS color values)
463
+ ============================================ */
464
+ .markdown-viewer .markdown .color-box {
465
+ position: relative;
466
+ top: -0.1em;
467
+ display: inline-block;
468
+ margin-right: 0.1em;
469
+ height: 0.8em;
470
+ width: 0.8em;
471
+ border-radius: 2px;
472
+ border: 1px solid rgba(107, 114, 128, 0.3);
473
+ vertical-align: middle;
474
+ }
475
+
476
+ /* ============================================
477
+ Definition Lists
478
+ ============================================ */
479
+ .markdown-viewer .markdown dl {
480
+ padding: 0;
481
+ }
482
+
483
+ .markdown-viewer .markdown dl dt {
484
+ padding: 0;
485
+ margin-top: var(--base-size-16);
486
+ font-size: 1em;
487
+ font-style: italic;
488
+ font-weight: var(--base-text-weight-semibold);
489
+ }
490
+
491
+ .markdown-viewer .markdown dl dd {
492
+ padding: 0 var(--base-size-16);
493
+ margin-left: 0;
494
+ margin-bottom: var(--base-size-16);
495
+ }
496
+
497
+ /* ============================================
498
+ Lists - Ordered & Unordered
499
+ ============================================ */
500
+ .markdown-viewer .markdown ul,
501
+ .markdown-viewer .markdown ol {
502
+ padding-left: 2em;
503
+ /* margin-top/bottom inherited from block element rule above */
504
+ }
505
+
506
+ /* Nested ordered lists stay decimal (GitHub style) */
507
+ .markdown-viewer .markdown ol ol,
508
+ .markdown-viewer .markdown ul ol {
509
+ list-style-type: decimal;
510
+ }
511
+
512
+ .markdown-viewer .markdown ul ul,
513
+ .markdown-viewer .markdown ul ol,
514
+ .markdown-viewer .markdown ol ol,
515
+ .markdown-viewer .markdown ol ul {
516
+ margin-top: 0;
517
+ margin-bottom: 0;
518
+ }
519
+
520
+ .markdown-viewer .markdown li + li {
521
+ margin-top: 0.25em;
522
+ }
523
+
524
+ .markdown-viewer .markdown li > p {
525
+ margin-top: var(--base-size-16);
526
+ }
527
+
528
+ .markdown-viewer .markdown ol[type="a s"] {
529
+ list-style-type: lower-alpha;
530
+ }
531
+
532
+ .markdown-viewer .markdown ol[type="A s"] {
533
+ list-style-type: upper-alpha;
534
+ }
535
+
536
+ .markdown-viewer .markdown ol[type="i s"] {
537
+ list-style-type: lower-roman;
538
+ }
539
+
540
+ .markdown-viewer .markdown ol[type="I s"] {
541
+ list-style-type: upper-roman;
542
+ }
543
+
544
+ .markdown-viewer .markdown ol[type="1"] {
545
+ list-style-type: decimal;
546
+ }
547
+
548
+ .markdown-viewer .markdown div > ol:not([type]) {
549
+ list-style-type: decimal;
550
+ }
551
+
552
+ /* ============================================
553
+ Task Lists (Checkboxes)
554
+ ============================================ */
555
+ .markdown-viewer .markdown .task-list-item label {
556
+ font-weight: var(--base-text-weight-normal);
557
+ }
558
+
559
+ .markdown-viewer .markdown .task-list-item.enabled label {
560
+ cursor: pointer;
561
+ }
562
+
563
+ .markdown-viewer .markdown .task-list-item + .task-list-item {
564
+ margin-top: var(--base-size-4);
565
+ }
566
+
567
+ .markdown-viewer .markdown .task-list-item-checkbox {
568
+ margin: 0 0.2em 0.25em -1.4em;
569
+ vertical-align: middle;
570
+ }
571
+
572
+ /* Task lists have same indentation as regular lists (GitHub style) */
573
+ .markdown-viewer .markdown ul.contains-task-list {
574
+ padding-left: 2em;
575
+ }
576
+
577
+ .markdown-viewer .markdown .task-list-item {
578
+ list-style-type: none;
579
+ margin-left: 0;
580
+ }
581
+
582
+ /* Nested lists keep normal indentation */
583
+ .markdown-viewer .markdown li > ul,
584
+ .markdown-viewer .markdown li > ol {
585
+ margin-left: 0;
586
+ padding-left: 2em;
587
+ }
588
+
589
+ /* ============================================
590
+ Tables
591
+ ============================================ */
592
+ .markdown-viewer .markdown .table-wrapper {
593
+ position: relative;
594
+ width: fit-content;
595
+ max-width: 100%;
596
+ margin-bottom: 24px;
597
+ }
598
+
599
+ .markdown-viewer .markdown .table-wrapper::after {
600
+ content: '';
601
+ position: absolute;
602
+ top: 6px;
603
+ left: 6px;
604
+ right: -6px;
605
+ bottom: -6px;
606
+ z-index: -1;
607
+ border-radius: 6px;
608
+ background-image: url('./dotted.svg');
609
+ background-size: 7px 13px;
610
+ opacity: 0.2;
611
+ }
612
+
613
+ :is(.dark, [data-theme="dark"]) .markdown-viewer .markdown .table-wrapper::after {
614
+ background-image: url("data:image/svg+xml,%3Csvg width='7' height='13' viewBox='0 0 7 13' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M5.58984 12.2344V10.7051H6.52734V12.2344H5.58984ZM1.86328 12.2344V10.7051H2.79492V12.2344H1.86328ZM3.72656 10.0957V8.56641H4.6582V10.0957H3.72656ZM0 10.0957V8.56641H0.925781V10.0957H0ZM5.58984 7.95117V6.42188H6.52734V7.95117H5.58984ZM1.86328 7.95117V6.42188H2.79492V7.95117H1.86328ZM3.72656 5.8125V4.2832H4.6582V5.8125H3.72656ZM0 5.8125V4.2832H0.925781V5.8125H0ZM5.58984 3.66797V2.13867H6.52734V3.66797H5.58984ZM1.86328 3.66797V2.13867H2.79492V3.66797H1.86328ZM3.72656 1.5293V0H4.6582V1.5293H3.72656ZM0 1.5293V0H0.925781V1.5293H0Z' fill='white'/%3E%3C/svg%3E");
615
+ }
616
+
617
+ @media (prefers-color-scheme: dark) {
618
+ .markdown-viewer:not(:is(.dark, [data-theme="dark"], [data-theme="light"]) *) .markdown .table-wrapper::after {
619
+ background-image: url("data:image/svg+xml,%3Csvg width='7' height='13' viewBox='0 0 7 13' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M5.58984 12.2344V10.7051H6.52734V12.2344H5.58984ZM1.86328 12.2344V10.7051H2.79492V12.2344H1.86328ZM3.72656 10.0957V8.56641H4.6582V10.0957H3.72656ZM0 10.0957V8.56641H0.925781V10.0957H0ZM5.58984 7.95117V6.42188H6.52734V7.95117H5.58984ZM1.86328 7.95117V6.42188H2.79492V7.95117H1.86328ZM3.72656 5.8125V4.2832H4.6582V5.8125H3.72656ZM0 5.8125V4.2832H0.925781V5.8125H0ZM5.58984 3.66797V2.13867H6.52734V3.66797H5.58984ZM1.86328 3.66797V2.13867H2.79492V3.66797H1.86328ZM3.72656 1.5293V0H4.6582V1.5293H3.72656ZM0 1.5293V0H0.925781V1.5293H0Z' fill='white'/%3E%3C/svg%3E");
620
+ }
621
+ }
622
+
623
+ .markdown-viewer .markdown table {
624
+ border-spacing: 0;
625
+ border-collapse: collapse;
626
+ display: block;
627
+ width: max-content;
628
+ max-width: 100%;
629
+ overflow: auto;
630
+ font-variant: tabular-nums;
631
+ }
632
+
633
+ .markdown-viewer .markdown table th {
634
+ font-weight: var(--base-text-weight-semibold);
635
+ background-color: var(--bgColor-muted);
636
+ background-image: url('./dotted.svg');
637
+ background-size: 7px 13px;
638
+ background-blend-mode: overlay;
639
+ }
640
+
641
+ .markdown-viewer .markdown table th,
642
+ .markdown-viewer .markdown table td {
643
+ padding: 6px 13px;
644
+ border: 1px solid var(--borderColor-default);
645
+ }
646
+
647
+ .markdown-viewer .markdown table td > :last-child {
648
+ margin-bottom: 0;
649
+ }
650
+
651
+ .markdown-viewer .markdown table tr {
652
+ background-color: var(--bgColor-default);
653
+ border-top: 1px solid var(--borderColor-muted);
654
+ }
655
+
656
+ .markdown-viewer .markdown table tr:nth-child(2n) {
657
+ background-color: var(--bgColor-muted);
658
+ }
659
+
660
+ .markdown-viewer .markdown table img {
661
+ background-color: transparent;
662
+ }
663
+
664
+ /* ============================================
665
+ Details/Summary (Collapsible)
666
+ ============================================ */
667
+ .markdown-viewer .markdown details,
668
+ .markdown-viewer .markdown figcaption,
669
+ .markdown-viewer .markdown figure {
670
+ display: block;
671
+ }
672
+
673
+ .markdown-viewer .markdown summary {
674
+ display: list-item;
675
+ cursor: pointer;
676
+ }
677
+
678
+ .markdown-viewer .markdown figure {
679
+ margin: 1em var(--base-size-40);
680
+ }
681
+
682
+ /* Headings inside summary */
683
+ .markdown-viewer .markdown summary h1,
684
+ .markdown-viewer .markdown summary h2,
685
+ .markdown-viewer .markdown summary h3,
686
+ .markdown-viewer .markdown summary h4,
687
+ .markdown-viewer .markdown summary h5,
688
+ .markdown-viewer .markdown summary h6 {
689
+ display: inline-block;
690
+ }
691
+
692
+ .markdown-viewer .markdown summary h1,
693
+ .markdown-viewer .markdown summary h2 {
694
+ padding-bottom: 0;
695
+ border-bottom: 0;
696
+ }
697
+
698
+ /* ============================================
699
+ Footnotes
700
+ ============================================ */
701
+ .markdown-viewer .markdown .footnotes {
702
+ margin-top: var(--base-size-16);
703
+ }
704
+
705
+ .markdown-viewer .markdown .footnotes::before {
706
+ content: "Footnotes";
707
+ display: block;
708
+ font-size: 24px; /* 1.5em of 16px base */
709
+ font-weight: var(--base-text-weight-semibold);
710
+ line-height: 1.25;
711
+ color: var(--fgColor-default);
712
+ padding-bottom: 0.3em;
713
+ margin-bottom: var(--base-size-16);
714
+ border-bottom: 1px solid var(--borderColor-muted);
715
+ }
716
+
717
+ .markdown-viewer .markdown .footnotes ol {
718
+ padding-left: var(--base-size-16);
719
+ }
720
+
721
+ .markdown-viewer .markdown .footnotes ol ul {
722
+ display: block;
723
+ padding-left: 2em;
724
+ margin-top: var(--base-size-16);
725
+ }
726
+
727
+ .markdown-viewer .markdown .footnotes li {
728
+ position: relative;
729
+ }
730
+
731
+ .markdown-viewer .markdown .footnotes li:target::before {
732
+ position: absolute;
733
+ top: calc(var(--base-size-8) * -1);
734
+ right: calc(var(--base-size-8) * -1);
735
+ bottom: calc(var(--base-size-8) * -1);
736
+ left: calc(var(--base-size-24) * -1);
737
+ pointer-events: none;
738
+ content: "";
739
+ border: 2px solid var(--fgColor-accent);
740
+ border-radius: 6px;
741
+ }
742
+
743
+ .markdown-viewer .markdown .footnotes li:target {
744
+ color: var(--fgColor-default);
745
+ }
746
+
747
+ .markdown-viewer .markdown [data-footnote-ref] {
748
+ font-size: 75%;
749
+ line-height: 0;
750
+ position: relative;
751
+ vertical-align: baseline;
752
+ top: -0.5em;
753
+ color: var(--fgColor-accent);
754
+ text-decoration: underline;
755
+ }
756
+
757
+ /* GitHub wraps footnote refs with brackets [1] */
758
+ .markdown-viewer .markdown [data-footnote-ref]::before {
759
+ content: '[';
760
+ }
761
+
762
+ .markdown-viewer .markdown [data-footnote-ref]::after {
763
+ content: ']';
764
+ }
765
+
766
+ .markdown-viewer .markdown .footnote-ref {
767
+ font-size: 75%;
768
+ line-height: 0;
769
+ position: relative;
770
+ vertical-align: baseline;
771
+ top: -0.5em;
772
+ }
773
+
774
+ .markdown-viewer .markdown .footnote-ref > a {
775
+ display: inline;
776
+ color: var(--fgColor-accent);
777
+ text-decoration: underline;
778
+ }
779
+
780
+ .markdown-viewer .markdown a.footnote-backref {
781
+ font-family: monospace;
782
+ }
783
+
784
+ /* section.footnotes - same styles as .footnotes for compatibility */
785
+ .markdown-viewer .markdown section.footnotes {
786
+ margin-top: var(--base-size-16);
787
+ }
788
+
789
+ .markdown-viewer .markdown section.footnotes::before {
790
+ content: "Footnotes";
791
+ display: block;
792
+ font-size: 24px;
793
+ font-weight: var(--base-text-weight-semibold);
794
+ line-height: 1.25;
795
+ color: var(--fgColor-default);
796
+ padding-bottom: 0.3em;
797
+ margin-bottom: var(--base-size-16);
798
+ border-bottom: 1px solid var(--borderColor-muted);
799
+ }
800
+
801
+ .markdown-viewer .markdown section.footnotes ol {
802
+ padding-left: var(--base-size-16);
803
+ }
804
+
805
+ .markdown-viewer .markdown section.footnotes ol ul {
806
+ display: block;
807
+ padding-left: 2em;
808
+ margin-top: var(--base-size-16);
809
+ }
810
+
811
+ /* ============================================
812
+ Emoji
813
+ ============================================ */
814
+ .markdown-viewer .markdown .emoji,
815
+ .markdown-viewer .markdown g-emoji {
816
+ display: inline-block;
817
+ min-width: 1ch;
818
+ font-family: "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
819
+ font-size: 1em;
820
+ font-style: normal !important;
821
+ font-weight: var(--base-text-weight-normal);
822
+ line-height: 1;
823
+ vertical-align: -0.075em;
824
+ }
825
+
826
+ .markdown-viewer .markdown .emoji {
827
+ max-width: none;
828
+ vertical-align: text-top;
829
+ background-color: transparent;
830
+ }
831
+
832
+ /* ============================================
833
+ Abbreviations
834
+ ============================================ */
835
+ .markdown-viewer .markdown abbr[title] {
836
+ border-bottom: none;
837
+ text-decoration: underline dotted;
838
+ }
839
+
840
+ /* ============================================
841
+ Streaming Cursor
842
+ Animated cursor shown during streaming mode
843
+ ============================================ */
844
+ .markdown-viewer .markdown .cursor {
845
+ display: inline-block;
846
+ vertical-align: baseline;
847
+ line-height: inherit;
848
+ }
849
+
850
+ .markdown-viewer .markdown .cursor::after {
851
+ content: "";
852
+ display: inline-block;
853
+ width: 0.6em;
854
+ min-height: 1em !important;
855
+ background-color: var(--cursor-color);
856
+ vertical-align: middle;
857
+
858
+ /* Safari fix: GPU acceleration prevents ghost shadows */
859
+ transform: translateY(-0.08em) translateZ(0);
860
+
861
+ /* Hint browser to optimize for movement and filter repaints */
862
+ will-change: transform, filter;
863
+
864
+ border-radius: var(--cursor-border-radius);
865
+ pointer-events: none !important;
866
+ filter: drop-shadow(0 0 6px var(--cursor-color));
867
+
868
+ /* Blink animation controlled by cursor controller via CSS variables.
869
+ --cursor-blink-name toggles between cursor-blink and cursor-blink- to restart animation.
870
+ --cursor-blink-duration controls speed (default 1s).
871
+ --cursor-blink-delay controls delay before blinking starts (default 1s). */
872
+ animation: var(--cursor-blink-name, cursor-blink)
873
+ var(--cursor-blink-duration, 1s) step-end var(--cursor-blink-delay, 1s)
874
+ infinite;
875
+ }
876
+
877
+ /* ============================================
878
+ Cursor Blink Animation Keyframes
879
+ Two identical keyframes allow animation restart by toggling between them
880
+ ============================================ */
881
+ @keyframes cursor-blink {
882
+ 0%,
883
+ 100% {
884
+ opacity: 1;
885
+ }
886
+ 50% {
887
+ opacity: 0;
888
+ }
889
+ }
890
+
891
+ @keyframes cursor-blink- {
892
+ 0%,
893
+ 100% {
894
+ opacity: 1;
895
+ }
896
+ 50% {
897
+ opacity: 0;
898
+ }
899
+ }
900
+
901
+ /* ============================================
902
+ Cursor States
903
+ ============================================ */
904
+
905
+ /* Active cursor (receiving updates) - no blink, solid */
906
+ .markdown-viewer .markdown .cursor.cursor-active::after {
907
+ animation: none;
908
+ opacity: 1;
909
+ }
910
+
911
+ /* Unfocused state - hollow frame cursor */
912
+ .markdown-viewer:not(:focus-within) .markdown .cursor::after {
913
+ background-color: transparent;
914
+ box-shadow: inset 0 0 0 1px var(--cursor-color);
915
+ filter: drop-shadow(0 0 4px var(--cursor-color));
916
+ }
917
+
918
+ /* ============================================
919
+ Dark Theme
920
+ Activated by:
921
+ 1. Parent element with .dark class (Tailwind pattern)
922
+ 2. Parent element with data-theme="dark" attribute
923
+ 3. OS-level dark mode preference (prefers-color-scheme)
924
+ ============================================ */
925
+
926
+ /* Dark theme via parent class or attribute */
927
+ :is(.dark, [data-theme="dark"]) .markdown-viewer {
928
+ color-scheme: dark;
929
+
930
+ /* Background colors */
931
+ --bgColor-default: #0d1117;
932
+ --bgColor-muted: #151b23;
933
+ --bgColor-neutral-muted: rgba(110, 118, 129, 0.4);
934
+ --bgColor-attention-muted: #bb800926;
935
+
936
+ /* Border colors */
937
+ --borderColor-default: #3d444d;
938
+ --borderColor-muted: #3d444db3;
939
+
940
+ /* Foreground colors */
941
+ --fgColor-default: #f0f6fc;
942
+ --fgColor-muted: #9198a1;
943
+ --fgColor-accent: #4493f8;
944
+
945
+ /* Cursor */
946
+ --cursor-color: #ab65f7;
947
+ }
948
+
949
+ /* ============================================
950
+ Dark Theme via OS Preference
951
+ Fallback when no explicit theme class is set
952
+ ============================================ */
953
+ @media (prefers-color-scheme: dark) {
954
+ .markdown-viewer:not(:is(.dark, [data-theme="dark"], [data-theme="light"]) *) {
955
+ color-scheme: dark;
956
+
957
+ /* Background colors */
958
+ --bgColor-default: #0d1117;
959
+ --bgColor-muted: #151b23;
960
+ --bgColor-neutral-muted: rgba(110, 118, 129, 0.4);
961
+ --bgColor-attention-muted: #bb800926;
962
+
963
+ /* Border colors */
964
+ --borderColor-default: #3d444d;
965
+ --borderColor-muted: #3d444db3;
966
+
967
+ /* Foreground colors */
968
+ --fgColor-default: #f0f6fc;
969
+ --fgColor-muted: #9198a1;
970
+ --fgColor-accent: #4493f8;
971
+
972
+ /* Cursor */
973
+ --cursor-color: #ab65f7;
974
+ }
975
+ }