umanggarg Claude Sonnet 4.6 commited on
Commit
f101481
Β·
1 Parent(s): fe68c6a

Add remark-gfm: render markdown tables properly

Browse files

Without remark-gfm, react-markdown doesn't parse GFM tables β€” they
render as raw pipe-separated text. Added the plugin and basic table
styles (bordered cells, alternating row bg, header highlight).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

ui/package-lock.json CHANGED
@@ -13,7 +13,8 @@
13
  "react": "^19.2.4",
14
  "react-dom": "^19.2.4",
15
  "react-markdown": "^10.1.0",
16
- "react-syntax-highlighter": "^16.1.1"
 
17
  },
18
  "devDependencies": {
19
  "@eslint/js": "^9.39.4",
@@ -3501,6 +3502,15 @@
3501
  "yallist": "^3.0.2"
3502
  }
3503
  },
 
 
 
 
 
 
 
 
 
3504
  "node_modules/marked": {
3505
  "version": "16.4.2",
3506
  "resolved": "https://registry.npmjs.org/marked/-/marked-16.4.2.tgz",
@@ -3512,6 +3522,32 @@
3512
  "node": ">= 20"
3513
  }
3514
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3515
  "node_modules/mdast-util-from-markdown": {
3516
  "version": "2.0.3",
3517
  "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.3.tgz",
@@ -3535,6 +3571,101 @@
3535
  "url": "https://opencollective.com/unified"
3536
  }
3537
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3538
  "node_modules/mdast-util-mdx-expression": {
3539
  "version": "2.0.1",
3540
  "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.1.tgz",
@@ -3752,6 +3883,120 @@
3752
  "micromark-util-types": "^2.0.0"
3753
  }
3754
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3755
  "node_modules/micromark-factory-destination": {
3756
  "version": "2.0.1",
3757
  "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz",
@@ -4499,6 +4744,23 @@
4499
  "url": "https://github.com/sponsors/wooorm"
4500
  }
4501
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4502
  "node_modules/remark-parse": {
4503
  "version": "11.0.0",
4504
  "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz",
@@ -4530,6 +4792,20 @@
4530
  "url": "https://opencollective.com/unified"
4531
  }
4532
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4533
  "node_modules/resolve-from": {
4534
  "version": "4.0.0",
4535
  "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
 
13
  "react": "^19.2.4",
14
  "react-dom": "^19.2.4",
15
  "react-markdown": "^10.1.0",
16
+ "react-syntax-highlighter": "^16.1.1",
17
+ "remark-gfm": "^4.0.1"
18
  },
19
  "devDependencies": {
20
  "@eslint/js": "^9.39.4",
 
3502
  "yallist": "^3.0.2"
3503
  }
3504
  },
3505
+ "node_modules/markdown-table": {
3506
+ "version": "3.0.4",
3507
+ "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.4.tgz",
3508
+ "integrity": "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==",
3509
+ "funding": {
3510
+ "type": "github",
3511
+ "url": "https://github.com/sponsors/wooorm"
3512
+ }
3513
+ },
3514
  "node_modules/marked": {
3515
  "version": "16.4.2",
3516
  "resolved": "https://registry.npmjs.org/marked/-/marked-16.4.2.tgz",
 
3522
  "node": ">= 20"
3523
  }
3524
  },
3525
+ "node_modules/mdast-util-find-and-replace": {
3526
+ "version": "3.0.2",
3527
+ "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.2.tgz",
3528
+ "integrity": "sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==",
3529
+ "dependencies": {
3530
+ "@types/mdast": "^4.0.0",
3531
+ "escape-string-regexp": "^5.0.0",
3532
+ "unist-util-is": "^6.0.0",
3533
+ "unist-util-visit-parents": "^6.0.0"
3534
+ },
3535
+ "funding": {
3536
+ "type": "opencollective",
3537
+ "url": "https://opencollective.com/unified"
3538
+ }
3539
+ },
3540
+ "node_modules/mdast-util-find-and-replace/node_modules/escape-string-regexp": {
3541
+ "version": "5.0.0",
3542
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz",
3543
+ "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==",
3544
+ "engines": {
3545
+ "node": ">=12"
3546
+ },
3547
+ "funding": {
3548
+ "url": "https://github.com/sponsors/sindresorhus"
3549
+ }
3550
+ },
3551
  "node_modules/mdast-util-from-markdown": {
3552
  "version": "2.0.3",
3553
  "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.3.tgz",
 
3571
  "url": "https://opencollective.com/unified"
3572
  }
3573
  },
3574
+ "node_modules/mdast-util-gfm": {
3575
+ "version": "3.1.0",
3576
+ "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-3.1.0.tgz",
3577
+ "integrity": "sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==",
3578
+ "dependencies": {
3579
+ "mdast-util-from-markdown": "^2.0.0",
3580
+ "mdast-util-gfm-autolink-literal": "^2.0.0",
3581
+ "mdast-util-gfm-footnote": "^2.0.0",
3582
+ "mdast-util-gfm-strikethrough": "^2.0.0",
3583
+ "mdast-util-gfm-table": "^2.0.0",
3584
+ "mdast-util-gfm-task-list-item": "^2.0.0",
3585
+ "mdast-util-to-markdown": "^2.0.0"
3586
+ },
3587
+ "funding": {
3588
+ "type": "opencollective",
3589
+ "url": "https://opencollective.com/unified"
3590
+ }
3591
+ },
3592
+ "node_modules/mdast-util-gfm-autolink-literal": {
3593
+ "version": "2.0.1",
3594
+ "resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-2.0.1.tgz",
3595
+ "integrity": "sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==",
3596
+ "dependencies": {
3597
+ "@types/mdast": "^4.0.0",
3598
+ "ccount": "^2.0.0",
3599
+ "devlop": "^1.0.0",
3600
+ "mdast-util-find-and-replace": "^3.0.0",
3601
+ "micromark-util-character": "^2.0.0"
3602
+ },
3603
+ "funding": {
3604
+ "type": "opencollective",
3605
+ "url": "https://opencollective.com/unified"
3606
+ }
3607
+ },
3608
+ "node_modules/mdast-util-gfm-footnote": {
3609
+ "version": "2.1.0",
3610
+ "resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-2.1.0.tgz",
3611
+ "integrity": "sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==",
3612
+ "dependencies": {
3613
+ "@types/mdast": "^4.0.0",
3614
+ "devlop": "^1.1.0",
3615
+ "mdast-util-from-markdown": "^2.0.0",
3616
+ "mdast-util-to-markdown": "^2.0.0",
3617
+ "micromark-util-normalize-identifier": "^2.0.0"
3618
+ },
3619
+ "funding": {
3620
+ "type": "opencollective",
3621
+ "url": "https://opencollective.com/unified"
3622
+ }
3623
+ },
3624
+ "node_modules/mdast-util-gfm-strikethrough": {
3625
+ "version": "2.0.0",
3626
+ "resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-2.0.0.tgz",
3627
+ "integrity": "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==",
3628
+ "dependencies": {
3629
+ "@types/mdast": "^4.0.0",
3630
+ "mdast-util-from-markdown": "^2.0.0",
3631
+ "mdast-util-to-markdown": "^2.0.0"
3632
+ },
3633
+ "funding": {
3634
+ "type": "opencollective",
3635
+ "url": "https://opencollective.com/unified"
3636
+ }
3637
+ },
3638
+ "node_modules/mdast-util-gfm-table": {
3639
+ "version": "2.0.0",
3640
+ "resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-2.0.0.tgz",
3641
+ "integrity": "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==",
3642
+ "dependencies": {
3643
+ "@types/mdast": "^4.0.0",
3644
+ "devlop": "^1.0.0",
3645
+ "markdown-table": "^3.0.0",
3646
+ "mdast-util-from-markdown": "^2.0.0",
3647
+ "mdast-util-to-markdown": "^2.0.0"
3648
+ },
3649
+ "funding": {
3650
+ "type": "opencollective",
3651
+ "url": "https://opencollective.com/unified"
3652
+ }
3653
+ },
3654
+ "node_modules/mdast-util-gfm-task-list-item": {
3655
+ "version": "2.0.0",
3656
+ "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-2.0.0.tgz",
3657
+ "integrity": "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==",
3658
+ "dependencies": {
3659
+ "@types/mdast": "^4.0.0",
3660
+ "devlop": "^1.0.0",
3661
+ "mdast-util-from-markdown": "^2.0.0",
3662
+ "mdast-util-to-markdown": "^2.0.0"
3663
+ },
3664
+ "funding": {
3665
+ "type": "opencollective",
3666
+ "url": "https://opencollective.com/unified"
3667
+ }
3668
+ },
3669
  "node_modules/mdast-util-mdx-expression": {
3670
  "version": "2.0.1",
3671
  "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.1.tgz",
 
3883
  "micromark-util-types": "^2.0.0"
3884
  }
3885
  },
3886
+ "node_modules/micromark-extension-gfm": {
3887
+ "version": "3.0.0",
3888
+ "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz",
3889
+ "integrity": "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==",
3890
+ "dependencies": {
3891
+ "micromark-extension-gfm-autolink-literal": "^2.0.0",
3892
+ "micromark-extension-gfm-footnote": "^2.0.0",
3893
+ "micromark-extension-gfm-strikethrough": "^2.0.0",
3894
+ "micromark-extension-gfm-table": "^2.0.0",
3895
+ "micromark-extension-gfm-tagfilter": "^2.0.0",
3896
+ "micromark-extension-gfm-task-list-item": "^2.0.0",
3897
+ "micromark-util-combine-extensions": "^2.0.0",
3898
+ "micromark-util-types": "^2.0.0"
3899
+ },
3900
+ "funding": {
3901
+ "type": "opencollective",
3902
+ "url": "https://opencollective.com/unified"
3903
+ }
3904
+ },
3905
+ "node_modules/micromark-extension-gfm-autolink-literal": {
3906
+ "version": "2.1.0",
3907
+ "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz",
3908
+ "integrity": "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==",
3909
+ "dependencies": {
3910
+ "micromark-util-character": "^2.0.0",
3911
+ "micromark-util-sanitize-uri": "^2.0.0",
3912
+ "micromark-util-symbol": "^2.0.0",
3913
+ "micromark-util-types": "^2.0.0"
3914
+ },
3915
+ "funding": {
3916
+ "type": "opencollective",
3917
+ "url": "https://opencollective.com/unified"
3918
+ }
3919
+ },
3920
+ "node_modules/micromark-extension-gfm-footnote": {
3921
+ "version": "2.1.0",
3922
+ "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz",
3923
+ "integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==",
3924
+ "dependencies": {
3925
+ "devlop": "^1.0.0",
3926
+ "micromark-core-commonmark": "^2.0.0",
3927
+ "micromark-factory-space": "^2.0.0",
3928
+ "micromark-util-character": "^2.0.0",
3929
+ "micromark-util-normalize-identifier": "^2.0.0",
3930
+ "micromark-util-sanitize-uri": "^2.0.0",
3931
+ "micromark-util-symbol": "^2.0.0",
3932
+ "micromark-util-types": "^2.0.0"
3933
+ },
3934
+ "funding": {
3935
+ "type": "opencollective",
3936
+ "url": "https://opencollective.com/unified"
3937
+ }
3938
+ },
3939
+ "node_modules/micromark-extension-gfm-strikethrough": {
3940
+ "version": "2.1.0",
3941
+ "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.1.0.tgz",
3942
+ "integrity": "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==",
3943
+ "dependencies": {
3944
+ "devlop": "^1.0.0",
3945
+ "micromark-util-chunked": "^2.0.0",
3946
+ "micromark-util-classify-character": "^2.0.0",
3947
+ "micromark-util-resolve-all": "^2.0.0",
3948
+ "micromark-util-symbol": "^2.0.0",
3949
+ "micromark-util-types": "^2.0.0"
3950
+ },
3951
+ "funding": {
3952
+ "type": "opencollective",
3953
+ "url": "https://opencollective.com/unified"
3954
+ }
3955
+ },
3956
+ "node_modules/micromark-extension-gfm-table": {
3957
+ "version": "2.1.1",
3958
+ "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.1.tgz",
3959
+ "integrity": "sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==",
3960
+ "dependencies": {
3961
+ "devlop": "^1.0.0",
3962
+ "micromark-factory-space": "^2.0.0",
3963
+ "micromark-util-character": "^2.0.0",
3964
+ "micromark-util-symbol": "^2.0.0",
3965
+ "micromark-util-types": "^2.0.0"
3966
+ },
3967
+ "funding": {
3968
+ "type": "opencollective",
3969
+ "url": "https://opencollective.com/unified"
3970
+ }
3971
+ },
3972
+ "node_modules/micromark-extension-gfm-tagfilter": {
3973
+ "version": "2.0.0",
3974
+ "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz",
3975
+ "integrity": "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==",
3976
+ "dependencies": {
3977
+ "micromark-util-types": "^2.0.0"
3978
+ },
3979
+ "funding": {
3980
+ "type": "opencollective",
3981
+ "url": "https://opencollective.com/unified"
3982
+ }
3983
+ },
3984
+ "node_modules/micromark-extension-gfm-task-list-item": {
3985
+ "version": "2.1.0",
3986
+ "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.1.0.tgz",
3987
+ "integrity": "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==",
3988
+ "dependencies": {
3989
+ "devlop": "^1.0.0",
3990
+ "micromark-factory-space": "^2.0.0",
3991
+ "micromark-util-character": "^2.0.0",
3992
+ "micromark-util-symbol": "^2.0.0",
3993
+ "micromark-util-types": "^2.0.0"
3994
+ },
3995
+ "funding": {
3996
+ "type": "opencollective",
3997
+ "url": "https://opencollective.com/unified"
3998
+ }
3999
+ },
4000
  "node_modules/micromark-factory-destination": {
4001
  "version": "2.0.1",
4002
  "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz",
 
4744
  "url": "https://github.com/sponsors/wooorm"
4745
  }
4746
  },
4747
+ "node_modules/remark-gfm": {
4748
+ "version": "4.0.1",
4749
+ "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.1.tgz",
4750
+ "integrity": "sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==",
4751
+ "dependencies": {
4752
+ "@types/mdast": "^4.0.0",
4753
+ "mdast-util-gfm": "^3.0.0",
4754
+ "micromark-extension-gfm": "^3.0.0",
4755
+ "remark-parse": "^11.0.0",
4756
+ "remark-stringify": "^11.0.0",
4757
+ "unified": "^11.0.0"
4758
+ },
4759
+ "funding": {
4760
+ "type": "opencollective",
4761
+ "url": "https://opencollective.com/unified"
4762
+ }
4763
+ },
4764
  "node_modules/remark-parse": {
4765
  "version": "11.0.0",
4766
  "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz",
 
4792
  "url": "https://opencollective.com/unified"
4793
  }
4794
  },
4795
+ "node_modules/remark-stringify": {
4796
+ "version": "11.0.0",
4797
+ "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-11.0.0.tgz",
4798
+ "integrity": "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==",
4799
+ "dependencies": {
4800
+ "@types/mdast": "^4.0.0",
4801
+ "mdast-util-to-markdown": "^2.0.0",
4802
+ "unified": "^11.0.0"
4803
+ },
4804
+ "funding": {
4805
+ "type": "opencollective",
4806
+ "url": "https://opencollective.com/unified"
4807
+ }
4808
+ },
4809
  "node_modules/resolve-from": {
4810
  "version": "4.0.0",
4811
  "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
ui/package.json CHANGED
@@ -15,7 +15,8 @@
15
  "react": "^19.2.4",
16
  "react-dom": "^19.2.4",
17
  "react-markdown": "^10.1.0",
18
- "react-syntax-highlighter": "^16.1.1"
 
19
  },
20
  "devDependencies": {
21
  "@eslint/js": "^9.39.4",
 
15
  "react": "^19.2.4",
16
  "react-dom": "^19.2.4",
17
  "react-markdown": "^10.1.0",
18
+ "react-syntax-highlighter": "^16.1.1",
19
+ "remark-gfm": "^4.0.1"
20
  },
21
  "devDependencies": {
22
  "@eslint/js": "^9.39.4",
ui/src/components/Message.jsx CHANGED
@@ -1,5 +1,6 @@
1
  import { useState, useCallback, Suspense, lazy, forwardRef } from "react";
2
  import ReactMarkdown from "react-markdown";
 
3
  import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
4
  import { oneDark } from "react-syntax-highlighter/dist/esm/styles/prism";
5
  import SourceCard from "./SourceCard";
@@ -394,7 +395,7 @@ const Message = forwardRef(function Message({ msg, onDiagramThis, onRetry, showR
394
 
395
  {/* Answer bubble */}
396
  <div className="bubble" style={{ position: "relative", display: msg.rateLimited ? "none" : undefined }}>
397
- <ReactMarkdown components={mdComponents}>
398
  {msg.content || " "}
399
  </ReactMarkdown>
400
  {/* Show cursor whenever streaming, not just when no tool active */}
 
1
  import { useState, useCallback, Suspense, lazy, forwardRef } from "react";
2
  import ReactMarkdown from "react-markdown";
3
+ import remarkGfm from "remark-gfm";
4
  import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
5
  import { oneDark } from "react-syntax-highlighter/dist/esm/styles/prism";
6
  import SourceCard from "./SourceCard";
 
395
 
396
  {/* Answer bubble */}
397
  <div className="bubble" style={{ position: "relative", display: msg.rateLimited ? "none" : undefined }}>
398
+ <ReactMarkdown components={mdComponents} remarkPlugins={[remarkGfm]}>
399
  {msg.content || " "}
400
  </ReactMarkdown>
401
  {/* Show cursor whenever streaming, not just when no tool active */}
ui/src/index.css CHANGED
@@ -706,6 +706,28 @@ textarea:focus-visible {
706
  0 4px 12px rgba(212, 132, 90, 0.30);
707
  }
708
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
709
  /* ── Message bubbles ──────────────────────────────────────── */
710
  .bubble {
711
  padding: 14px 18px;
 
706
  0 4px 12px rgba(212, 132, 90, 0.30);
707
  }
708
 
709
+ /* ── GFM table styles (remark-gfm renders <table> inside .bubble) ── */
710
+ .bubble table {
711
+ border-collapse: collapse;
712
+ width: 100%;
713
+ font-size: 13px;
714
+ margin: 12px 0;
715
+ }
716
+ .bubble th, .bubble td {
717
+ border: 1px solid var(--border);
718
+ padding: 6px 10px;
719
+ text-align: left;
720
+ line-height: 1.5;
721
+ }
722
+ .bubble th {
723
+ background: rgba(237,228,206,0.06);
724
+ font-weight: 600;
725
+ color: var(--text);
726
+ }
727
+ .bubble tr:nth-child(even) td {
728
+ background: rgba(237,228,206,0.03);
729
+ }
730
+
731
  /* ── Message bubbles ──────────────────────────────────────── */
732
  .bubble {
733
  padding: 14px 18px;