Skip to content

Commit 2c3e53b

Browse files
authored
Merge pull request #12 from museslabs/image-rendering
Markdown engine / Image rendering
2 parents 27b2fa4 + 163b347 commit 2c3e53b

28 files changed

+1756
-866
lines changed

README.md

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -106,45 +106,47 @@ Kyma presentations use a simple format with slides separated by `----` and optio
106106

107107
This is the content of the first slide
108108

109-
---
109+
----
110110

111111
---
112-
113-
## transition: swipeLeft
112+
transition: swipeLeft
113+
---
114114

115115
# Second Slide
116116

117117
This slide will appear with a swipe left transition
118118

119-
---
119+
----
120120

121121
---
122-
123122
transition: slideUp
124123
style:
125124
border: rounded
126125
border_color: "#9999CC"
127126
layout: center
128127
theme: dracula
129-
130128
---
131129

132130
# Third Slide
133131

134132
This slide has custom styling with Dracula theme
135133

136-
---
134+
----
137135

138136
---
139-
140137
style:
141138
theme: /path/to/custom-theme.json
142-
143139
---
144140

145141
# Fourth Slide
146142

147143
This slide uses a custom JSON theme file
144+
145+
----
146+
147+
# Image with 20x10 size
148+
149+
![alt text|20x10](./image.png)
148150
```
149151

150152
### Available Transitions
@@ -291,4 +293,4 @@ All contributions are welcome! If you're planning a significant change or you're
291293
- ~~Support for custom JSON theme files~~ ✅ **Done!**
292294
- Create grid-based slide layouts with transitions for each pane
293295
- Add more transition effects
294-
- Support image rendering in terminals (e.g., via the Kitty protocol)
296+
- ~~Support image rendering in terminals (e.g., via the Kitty protocol)~~ ✅ **Done!**

cmd/root.go

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,12 @@ package cmd
22

33
import (
44
"fmt"
5+
"log/slog"
56
"os"
67
"path/filepath"
78
"strings"
89
"time"
910

10-
"log/slog"
11-
1211
tea "github.com/charmbracelet/bubbletea"
1312
"github.com/fsnotify/fsnotify"
1413
"github.com/spf13/cobra"
@@ -27,9 +26,11 @@ var (
2726
)
2827

2928
func init() {
30-
rootCmd.Flags().BoolVarP(&static, "static", "s", false, "Disable live reload (watch mode is enabled by default)")
29+
rootCmd.Flags().
30+
BoolVarP(&static, "static", "s", false, "Disable live reload (watch mode is enabled by default)")
3131
rootCmd.Flags().StringVarP(&configPath, "config", "c", "", "Path to config file")
32-
rootCmd.Flags().StringVarP(&logPath, "log", "l", "", "Path to log file (default: ~/.config/kyma/logs/<timestamp>.kyma.log)")
32+
rootCmd.Flags().
33+
StringVarP(&logPath, "log", "l", "", "Path to log file (default: ~/.config/kyma/logs/<timestamp>.kyma.log)")
3334
rootCmd.Flags().BoolVarP(&notes, "notes", "n", false, "Run in speaker notes mode")
3435
rootCmd.AddCommand(versionCmd)
3536
}
@@ -174,20 +175,38 @@ func watchFileChanges(
174175

175176
data, err := os.ReadFile(filename)
176177
if err != nil {
177-
slog.Error("Failed to read file during reload", "error", err, "filename", filename)
178+
slog.Error(
179+
"Failed to read file during reload",
180+
"error",
181+
err,
182+
"filename",
183+
filename,
184+
)
178185
p.Send(tui.UpdateSlidesMsg{NewRoot: createErrorSlide(err, "none")})
179186
return
180187
}
181188

182189
if err := config.Load(configPath); err != nil {
183-
slog.Error("Failed to reload config", "error", err, "config_path", configPath)
190+
slog.Error(
191+
"Failed to reload config",
192+
"error",
193+
err,
194+
"config_path",
195+
configPath,
196+
)
184197
p.Send(tui.UpdateSlidesMsg{NewRoot: createErrorSlide(err, "none")})
185198
return
186199
}
187200

188201
newRoot, err := parseSlides(string(data))
189202
if err != nil {
190-
slog.Error("Failed to parse slides during reload", "error", err, "filename", filename)
203+
slog.Error(
204+
"Failed to parse slides during reload",
205+
"error",
206+
err,
207+
"filename",
208+
filename,
209+
)
191210
p.Send(tui.UpdateSlidesMsg{NewRoot: createErrorSlide(err, "none")})
192211
return
193212
}
@@ -224,9 +243,9 @@ func parseSlides(data string) (*tui.Slide, error) {
224243
return nil, err
225244
}
226245

227-
root := &tui.Slide{
228-
Data: rootSlide,
229-
Properties: p,
246+
root, err := tui.NewSlide(rootSlide, p)
247+
if err != nil {
248+
return nil, err
230249
}
231250

232251
curr := root
@@ -237,11 +256,11 @@ func parseSlides(data string) (*tui.Slide, error) {
237256
return nil, err
238257
}
239258

240-
curr.Next = &tui.Slide{
241-
Data: slide,
242-
Prev: curr,
243-
Properties: p,
259+
curr.Next, err = tui.NewSlide(slide, p)
260+
if err != nil {
261+
return nil, err
244262
}
263+
curr.Next.Prev = curr
245264
curr = curr.Next
246265
}
247266

go.mod

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,40 @@
11
module github.com/museslabs/kyma
22

3-
go 1.24.1
3+
go 1.24.3
44

55
require (
66
github.com/charmbracelet/bubbles v0.21.0
77
github.com/charmbracelet/bubbletea v1.3.4
88
github.com/charmbracelet/glamour v0.8.0
99
github.com/charmbracelet/harmonica v0.2.0
1010
github.com/charmbracelet/lipgloss v1.1.0
11+
github.com/charmbracelet/x/ansi v0.8.0
1112
github.com/fsnotify/fsnotify v1.8.0
1213
github.com/go-viper/mapstructure/v2 v2.2.1
1314
github.com/goccy/go-yaml v1.17.1
1415
github.com/mattn/go-runewidth v0.0.16
1516
github.com/muesli/reflow v0.3.0
17+
github.com/ploMP4/chafa-go v0.2.0
1618
github.com/spf13/cobra v1.9.1
1719
github.com/spf13/viper v1.20.1
1820
)
1921

20-
require golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect
22+
require (
23+
github.com/aymanbagabas/go-udiff v0.3.1 // indirect
24+
github.com/charmbracelet/x/exp/golden v0.0.0-20250714123521-bc8a1995e079 // indirect
25+
golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect
26+
)
2127

2228
require (
2329
github.com/alecthomas/chroma/v2 v2.15.0
2430
github.com/atotto/clipboard v0.1.4 // indirect
2531
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
2632
github.com/aymerick/douceur v0.2.0 // indirect
2733
github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc // indirect
28-
github.com/charmbracelet/x/ansi v0.8.0
2934
github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd // indirect
3035
github.com/charmbracelet/x/term v0.2.1 // indirect
3136
github.com/dlclark/regexp2 v1.11.5 // indirect
37+
github.com/ebitengine/purego v0.8.3 // indirect
3238
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
3339
github.com/gorilla/css v1.0.1 // indirect
3440
github.com/inconshreveable/mousetrap v1.1.0 // indirect
@@ -53,10 +59,10 @@ require (
5359
github.com/yuin/goldmark-emoji v1.0.5 // indirect
5460
go.uber.org/atomic v1.9.0 // indirect
5561
go.uber.org/multierr v1.9.0 // indirect
56-
golang.org/x/net v0.37.0 // indirect
57-
golang.org/x/sync v0.12.0 // indirect
58-
golang.org/x/sys v0.31.0 // indirect
59-
golang.org/x/term v0.30.0 // indirect
60-
golang.org/x/text v0.23.0 // indirect
62+
golang.org/x/net v0.42.0 // indirect
63+
golang.org/x/sync v0.16.0 // indirect
64+
golang.org/x/sys v0.34.0 // indirect
65+
golang.org/x/term v0.33.0 // indirect
66+
golang.org/x/text v0.27.0 // indirect
6167
gopkg.in/yaml.v3 v3.0.1 // indirect
6268
)

go.sum

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiE
1010
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
1111
github.com/aymanbagabas/go-udiff v0.2.0 h1:TK0fH4MteXUDspT88n8CKzvK0X9O2xu9yQjWpi6yML8=
1212
github.com/aymanbagabas/go-udiff v0.2.0/go.mod h1:RE4Ex0qsGkTAJoQdQQCA0uG+nAzJO/pI/QwceO5fgrA=
13+
github.com/aymanbagabas/go-udiff v0.3.1 h1:LV+qyBQ2pqe0u42ZsUEtPiCaUoqgA9gYRDs3vj1nolY=
14+
github.com/aymanbagabas/go-udiff v0.3.1/go.mod h1:G0fsKmG+P6ylD0r6N/KgQD/nWzgfnl8ZBcNLgcbrw8E=
1315
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
1416
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
1517
github.com/charmbracelet/bubbles v0.21.0 h1:9TdC97SdRVg/1aaXNVWfFH3nnLAwOXr8Fn6u6mfQdFs=
@@ -30,6 +32,8 @@ github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd h1:vy0G
3032
github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs=
3133
github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91 h1:payRxjMjKgx2PaCWLZ4p3ro9y97+TVLZNaRZgJwSVDQ=
3234
github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U=
35+
github.com/charmbracelet/x/exp/golden v0.0.0-20250714123521-bc8a1995e079 h1:HDsCK4LvvlqM6Jc+skOte2IdO7GPpLmj1SGTHbZqt8I=
36+
github.com/charmbracelet/x/exp/golden v0.0.0-20250714123521-bc8a1995e079/go.mod h1:IfZAMTHB6XkZSeXUqriemErjAWCCzT0LwjKFYCZyw0I=
3337
github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ=
3438
github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg=
3539
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
@@ -38,6 +42,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
3842
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
3943
github.com/dlclark/regexp2 v1.11.5 h1:Q/sSnsKerHeCkc/jSTNq1oCm7KiVgUMZRDUoRu0JQZQ=
4044
github.com/dlclark/regexp2 v1.11.5/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
45+
github.com/ebitengine/purego v0.8.3 h1:K+0AjQp63JEZTEMZiwsI9g0+hAMNohwUOtY0RPGexmc=
46+
github.com/ebitengine/purego v0.8.3/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
4147
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4=
4248
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM=
4349
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
@@ -83,6 +89,10 @@ github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc
8389
github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk=
8490
github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M=
8591
github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=
92+
github.com/ploMP4/chafa-go v0.1.0 h1:na1uideVGSzclKdInQLkv/7v+37cUWXYqPK8Jhs9v7Q=
93+
github.com/ploMP4/chafa-go v0.1.0/go.mod h1:IFfnozJSo6uj7UrnfsPnIWhLuOpqkIi+XNqDEg9hbAY=
94+
github.com/ploMP4/chafa-go v0.2.0 h1:5t34lQrMa14u7jZjezG8rm3NE0f8Erw6ZFLmzqbv1Ik=
95+
github.com/ploMP4/chafa-go v0.2.0/go.mod h1:IFfnozJSo6uj7UrnfsPnIWhLuOpqkIi+XNqDEg9hbAY=
8696
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
8797
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
8898
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
@@ -127,18 +137,18 @@ go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI=
127137
go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ=
128138
golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI=
129139
golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=
130-
golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c=
131-
golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
132-
golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
133-
golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
140+
golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs=
141+
golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8=
142+
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
143+
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
134144
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
135145
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
136-
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
137-
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
138-
golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y=
139-
golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g=
140-
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
141-
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
146+
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
147+
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
148+
golang.org/x/term v0.33.0 h1:NuFncQrRcaRvVmgRkvM3j/F00gWIAlcmlB8ACEKmGIg=
149+
golang.org/x/term v0.33.0/go.mod h1:s18+ql9tYWp1IfpV9DmCtQDDSRBUjKaw9M1eAv5UeF0=
150+
golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
151+
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
142152
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
143153
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
144154
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

internal/config/style.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ func (s StyleConfig) Apply(width, height int) SlideStyle {
114114
style := s.Layout.
115115
Border(s.Border).
116116
BorderForeground(lipgloss.Color(borderColor)).
117-
Width(width - 4).
117+
Width(width - 2).
118118
Height(height - 2)
119119

120120
return SlideStyle{

0 commit comments

Comments
 (0)