Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,14 +151,14 @@ pages:
columns:
- size: full
widgets:
$include: rss.yml
- $include: rss.yml
- name: News
columns:
- size: full
widgets:
- type: group
widgets:
$include: rss.yml
- $include: rss.yml
- type: reddit
subreddit: news
```
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ go 1.24.4

require (
github.com/fsnotify/fsnotify v1.9.0
github.com/gomarkdown/markdown v0.0.0-20260217112301-37c66b85d6ab
github.com/mmcdole/gofeed v1.3.0
github.com/shirou/gopsutil/v4 v4.25.5
github.com/tidwall/gjson v1.18.0
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
github.com/gomarkdown/markdown v0.0.0-20260217112301-37c66b85d6ab h1:VYNivV7P8IRHUam2swVUNkhIdp0LRRFKe4hXNnoZKTc=
github.com/gomarkdown/markdown v0.0.0-20260217112301-37c66b85d6ab/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
Expand Down
27 changes: 27 additions & 0 deletions internal/glance/static/css/widget-markdown.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
.widget-markdown h1 {
font-size: 1.875rem;
}

.widget-markdown h2 {
font-size: 1.5rem;
}

.widget-markdown h3 {
font-size: 1.25rem;
}

.widget-markdown h4 {
font-size: 1.125rem;
}

.widget-markdown h5 {
font-size: 1rem;
}

.widget-markdown h6 {
font-size: 0.875rem;
}

.widget-markdown a {
text-decoration: underline;
}
2 changes: 2 additions & 0 deletions internal/glance/static/css/widgets.css
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
@import "widget-videos.css";
@import "widget-weather.css";
@import "widget-todo.css";
@import "widget-markdown.css";

@import "forum-posts.css";

.widget-error-header {
Expand Down
7 changes: 7 additions & 0 deletions internal/glance/templates/markdown.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{{ template "widget-base.html" . }}

{{ define "widget-content" }}
<div class="widget-markdown">
{{ .CompiledHTML }}
</div>
{{ end }}
62 changes: 62 additions & 0 deletions internal/glance/widget-markdown.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package glance

import (
"fmt"
"html/template"
"os"

"github.com/gomarkdown/markdown"
"github.com/gomarkdown/markdown/html"
"github.com/gomarkdown/markdown/parser"
)

var markdownWidgetTemplate = mustParseTemplate("markdown.html", "widget-base.html")

type markdownWidget struct {
widgetBase `yaml:",inline"`
CompiledHTML template.HTML `yaml:"-"`
Source string `yaml:"source"`
File string `yaml:"file"`
}

func (widget *markdownWidget) initialize() error {
widget.WIP = true

if widget.Title == "" {
widget.Title = "Markdown"
}

widget.withTitle(widget.Title).withError(nil)

var content string

if widget.File != "" {
fileContent, err := os.ReadFile(widget.File)
if err != nil {
return fmt.Errorf("failed to read markdown file: %w", err)
}
content = string(fileContent)
} else if widget.Source != "" {
content = widget.Source
} else {
return fmt.Errorf("either 'source' or 'file' must be specified")
}

// Parse markdown with standard extensions
extensions := parser.CommonExtensions | parser.AutoHeadingIDs
p := parser.NewWithExtensions(extensions)
doc := p.Parse([]byte(content))

// Render to HTML
renderer := html.NewRenderer(html.RendererOptions{
Flags: html.CommonFlags | html.HrefTargetBlank,
})

widget.CompiledHTML = template.HTML(markdown.Render(doc, renderer))

return nil
}

func (widget *markdownWidget) Render() template.HTML {
return widget.renderTemplate(widget, markdownWidgetTemplate)
}
2 changes: 2 additions & 0 deletions internal/glance/widget.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ func newWidget(widgetType string) (widget, error) {
w = &iframeWidget{}
case "html":
w = &htmlWidget{}
case "markdown":
w = &markdownWidget{}
case "hacker-news":
w = &hackerNewsWidget{}
case "releases":
Expand Down