d119d535cc819619e3aecdbdc9238b946ae73d65

Author
Ayman Bagabas <ayman.bagabas@gmail.com>
Committer
GitHub <noreply@github.com>
Date

Message

fix: only use glamour for mk files (#467)

Use Glamour to render readmes when file is markdown formatted

Fixes: https://github.com/charmbracelet/soft-serve/issues/463

Diff

This diff is truncated to protect this page.

  1diff --git a/go.mod b/go.mod
  2index 011ff01e493f28c590440d673cdffe94362318f2..f78d3c0dfe1ba2c975e485386ef8265b9c1bc816 100644
  3--- a/go.mod
  4+++ b/go.mod
  5@@ -3,10 +3,9 @@ module github.com/charmbracelet/soft-serve
  6 go 1.20
  7 
  8 require (
  9-	github.com/alecthomas/chroma v0.10.0
 10 	github.com/charmbracelet/bubbles v0.16.1
 11 	github.com/charmbracelet/bubbletea v0.24.2
 12-	github.com/charmbracelet/glamour v0.6.0
 13+	github.com/charmbracelet/glamour v0.6.1-0.20231207115508-e526301e1404
 14 	github.com/charmbracelet/lipgloss v0.9.1
 15 	github.com/charmbracelet/wish v1.2.0
 16 	github.com/dustin/go-humanize v1.0.1
 17@@ -18,6 +17,7 @@ require (
 18 )
 19 
 20 require (
 21+	github.com/alecthomas/chroma/v2 v2.12.0
 22 	github.com/aymanbagabas/git-module v1.8.4-0.20231101154130-8d27204ac6d2
 23 	github.com/caarlos0/duration v0.0.0-20220103233809-8df7c22fe305
 24 	github.com/caarlos0/env/v10 v10.0.0
 25@@ -58,7 +58,7 @@ require (
 26 	github.com/beorn7/perks v1.0.1 // indirect
 27 	github.com/cespare/xxhash/v2 v2.2.0 // indirect
 28 	github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81 // indirect
 29-	github.com/dlclark/regexp2 v1.4.0 // indirect
 30+	github.com/dlclark/regexp2 v1.10.0 // indirect
 31 	github.com/felixge/httpsnoop v1.0.3 // indirect
 32 	github.com/git-lfs/pktline v0.0.0-20230103162542-ca444d533ef1 // indirect
 33 	github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
 34@@ -72,7 +72,7 @@ require (
 35 	github.com/mattn/go-runewidth v0.0.15 // indirect
 36 	github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect
 37 	github.com/mcuadros/go-version v0.0.0-20190308113854-92cdf37c5b75 // indirect
 38-	github.com/microcosm-cc/bluemonday v1.0.21 // indirect
 39+	github.com/microcosm-cc/bluemonday v1.0.25 // indirect
 40 	github.com/muesli/ansi v0.0.0-20211031195517-c9f0611b6c70 // indirect
 41 	github.com/muesli/cancelreader v0.2.2 // indirect
 42 	github.com/muesli/mango v0.1.0 // indirect
 43@@ -85,8 +85,8 @@ require (
 44 	github.com/rivo/uniseg v0.4.3 // indirect
 45 	github.com/sahilm/fuzzy v0.1.0 // indirect
 46 	github.com/spf13/pflag v1.0.5 // indirect
 47-	github.com/yuin/goldmark v1.5.2 // indirect
 48-	github.com/yuin/goldmark-emoji v1.0.1 // indirect
 49+	github.com/yuin/goldmark v1.5.4 // indirect
 50+	github.com/yuin/goldmark-emoji v1.0.2 // indirect
 51 	golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect
 52 	golang.org/x/mod v0.13.0 // indirect
 53 	golang.org/x/net v0.19.0 // indirect
 54diff --git a/go.sum b/go.sum
 55index 0f79cd9acec46c66c688e37997e2a300318e6ebf..4dd9314e388a16e0ce7a8104a24ec3ee007b106f 100644
 56--- a/go.sum
 57+++ b/go.sum
 58@@ -1,12 +1,13 @@
 59-github.com/alecthomas/chroma v0.10.0 h1:7XDcGkCQopCNKjZHfYrNLraA+M7e0fMiJ/Mfikbfjek=
 60-github.com/alecthomas/chroma v0.10.0/go.mod h1:jtJATyUxlIORhUOFNA9NZDWGAQ8wpxQQqNSB4rjA/1s=
 61+github.com/alecthomas/assert/v2 v2.2.1 h1:XivOgYcduV98QCahG8T5XTezV5bylXe+lBxLG2K2ink=
 62+github.com/alecthomas/chroma/v2 v2.12.0 h1:Wh8qLEgMMsN7mgyG8/qIpegky2Hvzr4By6gEF7cmWgw=
 63+github.com/alecthomas/chroma/v2 v2.12.0/go.mod h1:4TQu7gdfuPjSh76j78ietmqh9LiurGF0EpseFXdKMBw=
 64+github.com/alecthomas/repr v0.2.0 h1:HAzS41CIzNW5syS8Mf9UwXhNH1J9aix/BvDRf1Ml2Yk=
 65 github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
 66 github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
 67 github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
 68 github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
 69 github.com/aymanbagabas/git-module v1.8.4-0.20231101154130-8d27204ac6d2 h1:3w5KT+shE3hzWhORGiu2liVjEoaCEXm9uZP47+Gw4So=
 70 github.com/aymanbagabas/git-module v1.8.4-0.20231101154130-8d27204ac6d2/go.mod h1:d4gQ7/3/S2sPq4NnKdtAgUOVr6XtLpWFtxyVV5/+76U=
 71-github.com/aymanbagabas/go-osc52 v1.0.3/go.mod h1:zT8H+Rk4VSabYN90pWyugflM3ZhpTZNC7cASDfUCdT4=
 72 github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
 73 github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
 74 github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
 75@@ -27,8 +28,8 @@ github.com/charmbracelet/bubbletea v0.24.2 h1:uaQIKx9Ai6Gdh5zpTbGiWpytMU+CfsPp06
 76 github.com/charmbracelet/bubbletea v0.24.2/go.mod h1:XdrNrV4J8GiyshTtx3DNuYkR1FDaJmO3l2nejekbsgg=
 77 github.com/charmbracelet/git-lfs-transfer v0.1.1-0.20231027181609-f7ff6baf2ed0 h1:Wi80d2xNAqvi6r8Udlc9UgPMdrJ+ld5ylKH7d8SQ7gE=
 78 github.com/charmbracelet/git-lfs-transfer v0.1.1-0.20231027181609-f7ff6baf2ed0/go.mod h1:AHLgIZ2TXQCgt3pDNXR6FgmpGHLH1wPM9cEJPHSVaYg=
 79-github.com/charmbracelet/glamour v0.6.0 h1:wi8fse3Y7nfcabbbDuwolqTqMQPMnVPeZhDM273bISc=
 80-github.com/charmbracelet/glamour v0.6.0/go.mod h1:taqWV4swIMMbWALc0m7AfE9JkPSU8om2538k9ITBxOc=
 81+github.com/charmbracelet/glamour v0.6.1-0.20231207115508-e526301e1404 h1:9DOaiLCZq/2uWtTinGX89oLRhua5t3l5jDZpY5EqHEo=
 82+github.com/charmbracelet/glamour v0.6.1-0.20231207115508-e526301e1404/go.mod h1:k2/3AiFXFjEIJK8gXbUQiPEwE8325D7cMwp1XvVCZIU=
 83 github.com/charmbracelet/keygen v0.5.0 h1:XY0fsoYiCSM9axkrU+2ziE6u6YjJulo/b9Dghnw6MZc=
 84 github.com/charmbracelet/keygen v0.5.0/go.mod h1:DfvCgLHxZ9rJxdK0DGw3C/LkV4SgdGbnliHcObV3L+8=
 85 github.com/charmbracelet/lipgloss v0.9.1 h1:PNyd3jvaJbg4jRHKWXnCj1akQm4rh8dbEzN1p/u1KWg=
 86@@ -45,8 +46,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46t
 87 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 88 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
 89 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 90-github.com/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E=
 91-github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
 92+github.com/dlclark/regexp2 v1.10.0 h1:+/GIL799phkJqYW+3YbOd8LCcbHzT0Pbo8zl70MHsq0=
 93+github.com/dlclark/regexp2 v1.10.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
 94 github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
 95 github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
 96 github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk=
 97@@ -85,6 +86,7 @@ github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
 98 github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
 99 github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
100 github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
101+github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
102 github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
103 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
104 github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g=
105@@ -106,14 +108,12 @@ github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69
106 github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
107 github.com/matryer/is v1.4.1 h1:55ehd8zaGABKLXQUe2awZ99BD/PTc2ls+KV/dXphgEQ=
108 github.com/matryer/is v1.4.1/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=
109-github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
110 github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98=
111 github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
112 github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4=
113 github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88=
114 github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
115 github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
116-github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
117 github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
118 github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
119 github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
120@@ -122,8 +122,8 @@ github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvls
121 github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k=
122 github.com/mcuadros/go-version v0.0.0-20190308113854-92cdf37c5b75 h1:Pijfgr7ZuvX7QIQiEwLdRVr3RoMG+i0SbBO1Qu+7yVk=
123 github.com/mcuadros/go-version v0.0.0-20190308113854-92cdf37c5b75/go.mod h1:76rfSfYPWj01Z85hUf/ituArm797mNKcvINh1OlsZKo=
124-github.com/microcosm-cc/bluemonday v1.0.21 h1:dNH3e4PSyE4vNX+KlRGHT5KrSvjeUkoNPwEORjffHJg=
125-github.com/microcosm-cc/bluemonday v1.0.21/go.mod h1:ytNkv4RrDrLJ2pqlsSI46O6IVXmZOBBD4SaJyDwwTkM=
126+github.com/microcosm-cc/bluemonday v1.0.25 h1:4NEwSfiJ+Wva0VxN5B8OwMicaJvD8r9tlJWm9rtloEg=
127+github.com/microcosm-cc/bluemonday v1.0.25/go.mod h1:ZIOjCQp1OrzBBPIJmfX4qDYFuhU02nx4bn030ixfHLE=
128 github.com/muesli/ansi v0.0.0-20211031195517-c9f0611b6c70 h1:kMlmsLSbjkikxQJ1IPwaM+7LJ9ltFu/fi8CRzvSnQmA=
129 github.com/muesli/ansi v0.0.0-20211031195517-c9f0611b6c70/go.mod h1:fQuZ0gauxyBcmsdE3ZT4NasjaRdxmbCS0jRHsrWu3Ho=
130 github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
131@@ -138,7 +138,6 @@ github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s=
132 github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8=
133 github.com/muesli/roff v0.1.0 h1:YD0lalCotmYuF5HhZliKWlIx7IEhiXeSfq7hNjFqGF8=
134 github.com/muesli/roff v0.1.0/go.mod h1:pjAHQM9hdUUwm/krAfrLGgJkXJ+YuhtsfZ42kieB2Ig=
135-github.com/muesli/termenv v0.13.0/go.mod h1:sP1+uffeLaEYpyOTb8pLCUctGcGLnoFjSn4YJK5e2bc=
136 github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo=
137 github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8=
138 github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
139@@ -181,16 +180,15 @@ github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpE
140 github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
141 github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
142 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
143-github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
144 github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
145 github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
146 github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
147 github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
148-github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
149-github.com/yuin/goldmark v1.5.2 h1:ALmeCk/px5FSm1MAcFBAsVKZjDuMVj8Tm7FFIlMJnqU=
150-github.com/yuin/goldmark v1.5.2/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
151-github.com/yuin/goldmark-emoji v1.0.1 h1:ctuWEyzGBwiucEqxzwe0SOYDXPAucOrE9NQC18Wa1os=
152-github.com/yuin/goldmark-emoji v1.0.1/go.mod h1:2w1E6FEWLcDQkoTE+7HU6QF1F6SLlNGjRIBbIZQFqkQ=
153+github.com/yuin/goldmark v1.3.7/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
154+github.com/yuin/goldmark v1.5.4 h1:2uY/xC0roWy8IBEGLgB1ywIoEJFGmRrX21YQcvGZzjU=
155+github.com/yuin/goldmark v1.5.4/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
156+github.com/yuin/goldmark-emoji v1.0.2 h1:c/RgTShNgHTtc6xdz2KKI74jJr6rWi7FPgnP9GAsO5s=
157+github.com/yuin/goldmark-emoji v1.0.2/go.mod h1:RhP/RWpexdp+KHs7ghKnifRoIs/Bq4nDS7tRbCkOwKY=
158diff --git a/pkg/ui/common/common.go b/pkg/ui/common/common.go
159index 3c3eddd303e638f5e509f2575689e6c130d95524..c5e2319599e5d876e27cb27fb8c5afc079b4bf22 100644
160--- a/pkg/ui/common/common.go
161+++ b/pkg/ui/common/common.go
162@@ -4,6 +4,7 @@ import (
163 	"context"
164 	"fmt"
165 
166+	"github.com/alecthomas/chroma/v2/lexers"
167 	"github.com/charmbracelet/lipgloss"
168 	"github.com/charmbracelet/log"
169 	"github.com/charmbracelet/soft-serve/git"
170@@ -106,3 +107,17 @@ func (c *Common) CloneCmd(publicURL, name string) string {
171 	}
172 	return fmt.Sprintf("git clone %s", RepoURL(publicURL, name))
173 }
174+
175+// IsFileMarkdown returns true if the file is markdown.
176+// It uses chroma lexers to analyze and determine the language.
177+func IsFileMarkdown(content, ext string) bool {
178+	var lang string
179+	lexer := lexers.Match(ext)
180+	if lexer == nil {
181+		lexer = lexers.Analyse(content)
182+	}
183+	if lexer != nil && lexer.Config() != nil {
184+		lang = lexer.Config().Name
185+	}
186+	return lang == "markdown"
187+}
188diff --git a/pkg/ui/common/common_test.go b/pkg/ui/common/common_test.go
189new file mode 100644
190index 0000000000000000000000000000000000000000..6ef57e6e69a4ace382ec9c6e3d4be9d2ae02f9be
191--- /dev/null
192+++ b/pkg/ui/common/common_test.go
193@@ -0,0 +1,30 @@
194+package common_test
195+
196+import (
197+	"testing"
198+
199+	"github.com/charmbracelet/soft-serve/pkg/ui/common"
200+)
201+
202+func TestIsFileMarkdown(t *testing.T) {
203+	cases := []struct {
204+		name     string
205+		filename string
206+		content  string // XXX: chroma doesn't correctly analyze mk files
207+		isMkd    bool
208+	}{
209+		{"simple", "README.md", "", true},
210+		{"empty", "", "", false},
211+		{"no extension", "README", "", false},
212+		{"weird extension", "README.foo", "", false},
213+		{"long ext", "README.markdown", "", true},
214+	}
215+
216+	for _, c := range cases {
217+		t.Run(c.name, func(t *testing.T) {
218+			if got := common.IsFileMarkdown(c.content, c.filename); got != c.isMkd {
219+				t.Errorf("IsFileMarkdown(%q, %q) = %v, want %v", c.content, c.filename, got, c.isMkd)
220+			}
221+		})
222+	}
223+}
224diff --git a/pkg/ui/common/format.go b/pkg/ui/common/format.go
225index 96bae8bd34b5be65306dd920eb2a917ea257c6a9..8402737969c26740131a7c26f9fd762be4df76d9 100644
226--- a/pkg/ui/common/format.go
227+++ b/pkg/ui/common/format.go
228@@ -4,7 +4,7 @@ import (
229 	"fmt"
230 	"strings"
231 
232-	"github.com/alecthomas/chroma/lexers"
233+	"github.com/alecthomas/chroma/v2/lexers"
234 	gansi "github.com/charmbracelet/glamour/ansi"
235 	"github.com/charmbracelet/soft-serve/pkg/ui/styles"
236 )
237diff --git a/pkg/ui/components/code/code.go b/pkg/ui/components/code/code.go
238index d90ed7e0e5138d43ecbaaacf625380e7d409805f..5dd0ff83249eb77993aee64e399aa62af8b0c3fe 100644
239--- a/pkg/ui/components/code/code.go
240+++ b/pkg/ui/components/code/code.go
241@@ -5,7 +5,7 @@ import (
242 	"strings"
243 	"sync"
244 
245-	"github.com/alecthomas/chroma/lexers"
246+	"github.com/alecthomas/chroma/v2/lexers"
247 	tea "github.com/charmbracelet/bubbletea"
248 	"github.com/charmbracelet/glamour"
249 	gansi "github.com/charmbracelet/glamour/ansi"
250@@ -89,7 +89,7 @@ func (r *Code) Init() tea.Cmd {
251 	// 4-spaces.
252 	content = strings.ReplaceAll(content, "\t", strings.Repeat(" ", r.TabWidth))
253 
254-	if r.UseGlamour {
255+	if r.UseGlamour && common.IsFileMarkdown(content, r.extension) {
256 		md, err := r.glamourize(w, content)
257 		if err != nil {
258 			return common.ErrorCmd(err)
259@@ -213,7 +213,6 @@ func (r *Code) glamourize(w int, md string) (string, error) {
260 		glamour.WithStyles(r.styleConfig),
261 		glamour.WithWordWrap(w),
262 	)
263-
264 	if err != nil {
265 		return "", err
266 	}
267diff --git a/pkg/ui/pages/repo/files.go b/pkg/ui/pages/repo/files.go
268index 4499d6f0c1fb318e3ffabe62aa32d129de6d9303..fd43969fe7d07644542e105985a6081c18b34b58 100644
269--- a/pkg/ui/pages/repo/files.go
270+++ b/pkg/ui/pages/repo/files.go
271@@ -6,7 +6,6 @@ import (
272 	"path/filepath"
273 	"strings"
274 
275-	"github.com/alecthomas/chroma/lexers"
276 	gitm "github.com/aymanbagabas/git-module"
277 	"github.com/charmbracelet/bubbles/key"
278 	"github.com/charmbracelet/bubbles/spinner"
279@@ -159,7 +158,8 @@ func (f *Files) FullHelp() [][]key.Binding {
280 		actionKeys = append(actionKeys, lineNo)
281 	}
282 	actionKeys = append(actionKeys, blameView)
283-	if f.isSelectedMarkdown() && !f.blameView {
284+	if common.IsFileMarkdown(f.currentContent.content, f.currentContent.ext) &&
285+		!f.blameView {
286 		actionKeys = append(actionKeys, preview)
287 	}
288 	switch f.activeView {
289@@ -240,7 +240,7 @@ func (f *Files) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
290 	case FileContentMsg:
291 		f.activeView = filesViewContent
292 		f.currentContent = msg
293-		f.code.UseGlamour = f.isSelectedMarkdown()
294+		f.code.UseGlamour = common.IsFileMarkdown(f.currentContent.content, f.currentContent.ext)
295 		cmds = append(cmds, f.code.SetContent(msg.content, msg.ext))
296 		f.code.GotoTop()
297 	case FileBlameMsg:
298@@ -293,7 +293,8 @@ func (f *Files) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
299 					cmds = append(cmds, f.code.SetSideNote(""))
300 				}
301 				cmds = append(cmds, f.spinner.Tick)
302-			case key.Matches(msg, preview) && f.isSelectedMarkdown() && !f.blameView:
303+			case key.Matches(msg, preview) &&
304+				common.IsFileMarkdown(f.currentContent.content, f.currentContent.ext) && !f.blameView:
305 				f.code.UseGlamour = !f.code.UseGlamour
306 				cmds = append(cmds, f.code.SetContent(f.currentContent.content, f.currentContent.ext))
307 			}
308@@ -545,15 +546,3 @@ func (f *Files) setItems(items []selector.IdentifiableItem) tea.Cmd {
309 		return FileItemsMsg(items)
310 	}
311 }
312-
313-func (f *Files) isSelectedMarkdown() bool {
314-	var lang string
315-	lexer := lexers.Match(f.currentContent.ext)
316-	if lexer == nil {
317-		lexer = lexers.Analyse(f.currentContent.content)
318-	}
319-	if lexer != nil && lexer.Config() != nil {
320-		lang = lexer.Config().Name
321-	}
322-	return lang == "markdown"
323-}