From 3b38f3bca0d8d76660d1f00097468637ab689035 Mon Sep 17 00:00:00 2001 From: Elliot Waddington Date: Fri, 12 Apr 2024 13:35:01 +0100 Subject: [PATCH 1/6] feat: add markdown glamour styles --- cmd/overmind-theme-dark.json | 101 +++++++++++++++++++++++++++++++++++ cmd/overmind-theme.json | 101 +++++++++++++++++++++++++++++++++++ cmd/theme.go | 8 ++- 3 files changed, 209 insertions(+), 1 deletion(-) create mode 100644 cmd/overmind-theme-dark.json create mode 100644 cmd/overmind-theme.json diff --git a/cmd/overmind-theme-dark.json b/cmd/overmind-theme-dark.json new file mode 100644 index 00000000..390ca759 --- /dev/null +++ b/cmd/overmind-theme-dark.json @@ -0,0 +1,101 @@ +{ + "document": { + "block_prefix": "\n", + "block_suffix": "\n", + "color": "#bababa", + "indent": 2 + }, + "block_quote": { + "italic": true, + "indent": 1, + "indent_token": "│ " + }, + "paragraph": {}, + "list": { + "level_indent": 2 + }, + "heading": { + "bold": true, + "color": "#fafafa", + "block_suffix": "\n" + }, + "h1": { + "background_color": "#7a70eb", + "color": "#ffffff", + "prefix": " ", + "suffix": " " + }, + "h2": {}, + "h3": { + "color": "#8c8c8c" + }, + "h4": { + "prefix": "#### " + }, + "h5": { + "prefix": "##### " + }, + "h6": { + "prefix": "###### ", + "bold": false + }, + "text": {}, + "strikethrough": { + "crossed_out": true + }, + "emph": { + "italic": true + }, + "strong": { + "bold": true + }, + "hr": { + "color": "#bababa", + "format": "\n--------\n" + }, + "item": { + "block_prefix": "• " + }, + "enumeration": { + "block_prefix": ". " + }, + "task": { + "ticked": "[✓] ", + "unticked": "[ ] " + }, + "link": { + "color": "#688ede", + "underline": true, + "block_prefix": "(", + "block_suffix": ")" + }, + "link_text": { + "bold": true + }, + "image": { + "color": "#688ede", + "underline": true, + "block_prefix": "(", + "block_suffix": ")" + }, + "image_text": { + "color": "#688ede" + }, + "code": {}, + "code_block": { + "margin": 4, + "theme": "solarized-light" + }, + "table": { + "center_separator": "┼", + "column_separator": "│", + "row_separator": "─" + }, + "definition_list": {}, + "definition_term": {}, + "definition_description": { + "block_prefix": "\n🠶 " + }, + "html_block": {}, + "html_span": {} +} diff --git a/cmd/overmind-theme.json b/cmd/overmind-theme.json new file mode 100644 index 00000000..8e24dc96 --- /dev/null +++ b/cmd/overmind-theme.json @@ -0,0 +1,101 @@ +{ + "document": { + "block_prefix": "\n", + "block_suffix": "\n", + "color": "#383838", + "indent": 2 + }, + "block_quote": { + "italic": true, + "indent": 1, + "indent_token": "│ " + }, + "paragraph": {}, + "list": { + "level_indent": 2 + }, + "heading": { + "bold": true, + "color": "#141414", + "block_suffix": "\n" + }, + "h1": { + "background_color": "#655add", + "color": "#ffffff", + "prefix": " ", + "suffix": " " + }, + "h2": {}, + "h3": { + "color": "#616161" + }, + "h4": { + "prefix": "#### " + }, + "h5": { + "prefix": "##### " + }, + "h6": { + "prefix": "###### ", + "bold": false + }, + "text": {}, + "strikethrough": { + "crossed_out": true + }, + "emph": { + "italic": true + }, + "strong": { + "bold": true + }, + "hr": { + "color": "#383838", + "format": "\n--------\n" + }, + "item": { + "block_prefix": "• " + }, + "enumeration": { + "block_prefix": ". " + }, + "task": { + "ticked": "[✓] ", + "unticked": "[ ] " + }, + "link": { + "color": "#4f81ee", + "underline": true, + "block_prefix": "(", + "block_suffix": ")" + }, + "link_text": { + "bold": true + }, + "image": { + "color": "#4f81ee", + "underline": true, + "block_prefix": "(", + "block_suffix": ")" + }, + "image_text": { + "color": "#4f81ee" + }, + "code": {}, + "code_block": { + "margin": 4, + "theme": "solarized-light" + }, + "table": { + "center_separator": "┼", + "column_separator": "│", + "row_separator": "─" + }, + "definition_list": {}, + "definition_term": {}, + "definition_description": { + "block_prefix": "\n🠶 " + }, + "html_block": {}, + "html_span": {} +} diff --git a/cmd/theme.go b/cmd/theme.go index 4d5ca1d8..b781acd6 100644 --- a/cmd/theme.go +++ b/cmd/theme.go @@ -3,6 +3,7 @@ package cmd import ( "github.com/charmbracelet/glamour" "github.com/charmbracelet/lipgloss" + "github.com/muesli/termenv" ) type LogoPalette struct { @@ -117,8 +118,13 @@ var deletedLineStyle = lipgloss.NewStyle().Background(lipgloss.Color(ColorPalett var containerStyle = lipgloss.NewStyle().PaddingLeft(2).PaddingTop(2) func markdownToString(markdown string) string { + themePath := "./overmind-theme.json" + hasDarkBackground := termenv.HasDarkBackground() + if hasDarkBackground { + themePath = "./overmind-theme-dark.json" + } r, _ := glamour.NewTermRenderer( - glamour.WithAutoStyle(), + glamour.WithStylesFromJSONFile(themePath), ) out, _ := r.Render(markdown) return out From 57ff1a6b45e442d19bec077f1f7cc5731857123f Mon Sep 17 00:00:00 2001 From: Elliot Waddington Date: Fri, 12 Apr 2024 14:20:07 +0100 Subject: [PATCH 2/6] add embeds and error handling --- cmd/theme.go | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/cmd/theme.go b/cmd/theme.go index b781acd6..0ff2d912 100644 --- a/cmd/theme.go +++ b/cmd/theme.go @@ -1,6 +1,9 @@ package cmd import ( + _ "embed" + "fmt" + "github.com/charmbracelet/glamour" "github.com/charmbracelet/lipgloss" "github.com/muesli/termenv" @@ -117,15 +120,27 @@ var addedLineStyle = lipgloss.NewStyle().Foreground(lipgloss.Color(ColorPalette. var deletedLineStyle = lipgloss.NewStyle().Background(lipgloss.Color(ColorPalette.Light.BgDanger)).Foreground(lipgloss.Color(ColorPalette.Light.LabelControl)) var containerStyle = lipgloss.NewStyle().PaddingLeft(2).PaddingTop(2) +//go:embed overmind-theme.json +var overmindTheme string + +//go:embed overmind-theme-dark.json +var overmindThemeDark string + func markdownToString(markdown string) string { - themePath := "./overmind-theme.json" + themePath := overmindTheme hasDarkBackground := termenv.HasDarkBackground() if hasDarkBackground { - themePath = "./overmind-theme-dark.json" + themePath = overmindThemeDark } - r, _ := glamour.NewTermRenderer( + r, err := glamour.NewTermRenderer( glamour.WithStylesFromJSONFile(themePath), ) - out, _ := r.Render(markdown) + if err != nil { + panic(fmt.Errorf("failed to initialize terminal renderer: %w", err)) + } + out, err := r.Render(markdown) + if err != nil { + panic(fmt.Errorf("failed to render markdown: %w", err)) + } return out } From 1ff9472aa848981a6865ac67b6584fb299824a27 Mon Sep 17 00:00:00 2001 From: Elliot Waddington Date: Fri, 12 Apr 2024 13:35:01 +0100 Subject: [PATCH 3/6] feat: add markdown glamour styles --- cmd/overmind-theme-dark.json | 101 +++++++++++++++++++++++++++++++++++ cmd/overmind-theme.json | 101 +++++++++++++++++++++++++++++++++++ cmd/theme.go | 8 ++- 3 files changed, 209 insertions(+), 1 deletion(-) create mode 100644 cmd/overmind-theme-dark.json create mode 100644 cmd/overmind-theme.json diff --git a/cmd/overmind-theme-dark.json b/cmd/overmind-theme-dark.json new file mode 100644 index 00000000..390ca759 --- /dev/null +++ b/cmd/overmind-theme-dark.json @@ -0,0 +1,101 @@ +{ + "document": { + "block_prefix": "\n", + "block_suffix": "\n", + "color": "#bababa", + "indent": 2 + }, + "block_quote": { + "italic": true, + "indent": 1, + "indent_token": "│ " + }, + "paragraph": {}, + "list": { + "level_indent": 2 + }, + "heading": { + "bold": true, + "color": "#fafafa", + "block_suffix": "\n" + }, + "h1": { + "background_color": "#7a70eb", + "color": "#ffffff", + "prefix": " ", + "suffix": " " + }, + "h2": {}, + "h3": { + "color": "#8c8c8c" + }, + "h4": { + "prefix": "#### " + }, + "h5": { + "prefix": "##### " + }, + "h6": { + "prefix": "###### ", + "bold": false + }, + "text": {}, + "strikethrough": { + "crossed_out": true + }, + "emph": { + "italic": true + }, + "strong": { + "bold": true + }, + "hr": { + "color": "#bababa", + "format": "\n--------\n" + }, + "item": { + "block_prefix": "• " + }, + "enumeration": { + "block_prefix": ". " + }, + "task": { + "ticked": "[✓] ", + "unticked": "[ ] " + }, + "link": { + "color": "#688ede", + "underline": true, + "block_prefix": "(", + "block_suffix": ")" + }, + "link_text": { + "bold": true + }, + "image": { + "color": "#688ede", + "underline": true, + "block_prefix": "(", + "block_suffix": ")" + }, + "image_text": { + "color": "#688ede" + }, + "code": {}, + "code_block": { + "margin": 4, + "theme": "solarized-light" + }, + "table": { + "center_separator": "┼", + "column_separator": "│", + "row_separator": "─" + }, + "definition_list": {}, + "definition_term": {}, + "definition_description": { + "block_prefix": "\n🠶 " + }, + "html_block": {}, + "html_span": {} +} diff --git a/cmd/overmind-theme.json b/cmd/overmind-theme.json new file mode 100644 index 00000000..8e24dc96 --- /dev/null +++ b/cmd/overmind-theme.json @@ -0,0 +1,101 @@ +{ + "document": { + "block_prefix": "\n", + "block_suffix": "\n", + "color": "#383838", + "indent": 2 + }, + "block_quote": { + "italic": true, + "indent": 1, + "indent_token": "│ " + }, + "paragraph": {}, + "list": { + "level_indent": 2 + }, + "heading": { + "bold": true, + "color": "#141414", + "block_suffix": "\n" + }, + "h1": { + "background_color": "#655add", + "color": "#ffffff", + "prefix": " ", + "suffix": " " + }, + "h2": {}, + "h3": { + "color": "#616161" + }, + "h4": { + "prefix": "#### " + }, + "h5": { + "prefix": "##### " + }, + "h6": { + "prefix": "###### ", + "bold": false + }, + "text": {}, + "strikethrough": { + "crossed_out": true + }, + "emph": { + "italic": true + }, + "strong": { + "bold": true + }, + "hr": { + "color": "#383838", + "format": "\n--------\n" + }, + "item": { + "block_prefix": "• " + }, + "enumeration": { + "block_prefix": ". " + }, + "task": { + "ticked": "[✓] ", + "unticked": "[ ] " + }, + "link": { + "color": "#4f81ee", + "underline": true, + "block_prefix": "(", + "block_suffix": ")" + }, + "link_text": { + "bold": true + }, + "image": { + "color": "#4f81ee", + "underline": true, + "block_prefix": "(", + "block_suffix": ")" + }, + "image_text": { + "color": "#4f81ee" + }, + "code": {}, + "code_block": { + "margin": 4, + "theme": "solarized-light" + }, + "table": { + "center_separator": "┼", + "column_separator": "│", + "row_separator": "─" + }, + "definition_list": {}, + "definition_term": {}, + "definition_description": { + "block_prefix": "\n🠶 " + }, + "html_block": {}, + "html_span": {} +} diff --git a/cmd/theme.go b/cmd/theme.go index 4d5ca1d8..b781acd6 100644 --- a/cmd/theme.go +++ b/cmd/theme.go @@ -3,6 +3,7 @@ package cmd import ( "github.com/charmbracelet/glamour" "github.com/charmbracelet/lipgloss" + "github.com/muesli/termenv" ) type LogoPalette struct { @@ -117,8 +118,13 @@ var deletedLineStyle = lipgloss.NewStyle().Background(lipgloss.Color(ColorPalett var containerStyle = lipgloss.NewStyle().PaddingLeft(2).PaddingTop(2) func markdownToString(markdown string) string { + themePath := "./overmind-theme.json" + hasDarkBackground := termenv.HasDarkBackground() + if hasDarkBackground { + themePath = "./overmind-theme-dark.json" + } r, _ := glamour.NewTermRenderer( - glamour.WithAutoStyle(), + glamour.WithStylesFromJSONFile(themePath), ) out, _ := r.Render(markdown) return out From b7d90180e2e3245de5df1d86005136ba53cda001 Mon Sep 17 00:00:00 2001 From: Elliot Waddington Date: Fri, 12 Apr 2024 14:20:07 +0100 Subject: [PATCH 4/6] add embeds and error handling --- cmd/theme.go | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/cmd/theme.go b/cmd/theme.go index b781acd6..0ff2d912 100644 --- a/cmd/theme.go +++ b/cmd/theme.go @@ -1,6 +1,9 @@ package cmd import ( + _ "embed" + "fmt" + "github.com/charmbracelet/glamour" "github.com/charmbracelet/lipgloss" "github.com/muesli/termenv" @@ -117,15 +120,27 @@ var addedLineStyle = lipgloss.NewStyle().Foreground(lipgloss.Color(ColorPalette. var deletedLineStyle = lipgloss.NewStyle().Background(lipgloss.Color(ColorPalette.Light.BgDanger)).Foreground(lipgloss.Color(ColorPalette.Light.LabelControl)) var containerStyle = lipgloss.NewStyle().PaddingLeft(2).PaddingTop(2) +//go:embed overmind-theme.json +var overmindTheme string + +//go:embed overmind-theme-dark.json +var overmindThemeDark string + func markdownToString(markdown string) string { - themePath := "./overmind-theme.json" + themePath := overmindTheme hasDarkBackground := termenv.HasDarkBackground() if hasDarkBackground { - themePath = "./overmind-theme-dark.json" + themePath = overmindThemeDark } - r, _ := glamour.NewTermRenderer( + r, err := glamour.NewTermRenderer( glamour.WithStylesFromJSONFile(themePath), ) - out, _ := r.Render(markdown) + if err != nil { + panic(fmt.Errorf("failed to initialize terminal renderer: %w", err)) + } + out, err := r.Render(markdown) + if err != nil { + panic(fmt.Errorf("failed to render markdown: %w", err)) + } return out } From 55b3c62adfdd730854615d05704810c571565275 Mon Sep 17 00:00:00 2001 From: David Schmitt Date: Mon, 15 Apr 2024 09:04:08 +0200 Subject: [PATCH 5/6] Add basic test for markdownToString --- cmd/theme_test.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 cmd/theme_test.go diff --git a/cmd/theme_test.go b/cmd/theme_test.go new file mode 100644 index 00000000..ab5cd5e9 --- /dev/null +++ b/cmd/theme_test.go @@ -0,0 +1,15 @@ +package cmd + +import ( + "testing" +) + +func TestMarkdownToString(t *testing.T) { + // TODO: change this test data to use something that actually gets rendered to ANSI sequences and capture the correct output. + markdown := "This is a test markdown" + expectedOutput := "This is a test markdown" + got := markdownToString(markdown) + if got != expectedOutput { + t.Errorf("Expected %q, but got %q", expectedOutput, got) + } +} From ecdae14a4a36c9144101192aa2c2bbfa3aad1a52 Mon Sep 17 00:00:00 2001 From: Elliot Waddington Date: Tue, 16 Apr 2024 15:49:42 +0200 Subject: [PATCH 6/6] embed theme as bytes to use with WithStylesFromJSONBytes --- cmd/theme.go | 11 ++++++----- cmd/theme_test.go | 6 +++--- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/cmd/theme.go b/cmd/theme.go index 0ff2d912..4928d571 100644 --- a/cmd/theme.go +++ b/cmd/theme.go @@ -121,19 +121,20 @@ var deletedLineStyle = lipgloss.NewStyle().Background(lipgloss.Color(ColorPalett var containerStyle = lipgloss.NewStyle().PaddingLeft(2).PaddingTop(2) //go:embed overmind-theme.json -var overmindTheme string +var overmindTheme []byte //go:embed overmind-theme-dark.json -var overmindThemeDark string +var overmindThemeDark []byte func markdownToString(markdown string) string { - themePath := overmindTheme + themeToUse := overmindTheme hasDarkBackground := termenv.HasDarkBackground() if hasDarkBackground { - themePath = overmindThemeDark + themeToUse = overmindThemeDark } + r, err := glamour.NewTermRenderer( - glamour.WithStylesFromJSONFile(themePath), + glamour.WithStylesFromJSONBytes(themeToUse), ) if err != nil { panic(fmt.Errorf("failed to initialize terminal renderer: %w", err)) diff --git a/cmd/theme_test.go b/cmd/theme_test.go index ab5cd5e9..51b55583 100644 --- a/cmd/theme_test.go +++ b/cmd/theme_test.go @@ -5,9 +5,9 @@ import ( ) func TestMarkdownToString(t *testing.T) { - // TODO: change this test data to use something that actually gets rendered to ANSI sequences and capture the correct output. - markdown := "This is a test markdown" - expectedOutput := "This is a test markdown" + markdown := `# some random markdown` + expectedOutput := "\n\x1b[38;2;255;255;255;48;2;121;112;235;1m\x1b[0m\x1b[38;2;255;255;255;48;2;121;112;235;1m\x1b[0m \x1b[38;2;255;255;255;48;2;121;112;235;1m \x1b[0m\x1b[38;2;255;255;255;48;2;121;112;235;1msome random\x1b[0m\x1b[38;2;255;255;255;48;2;121;112;235;1m markdown\x1b[0m\x1b[38;2;255;255;255;48;2;121;112;235;1m \x1b[0m\x1b[38;2;186;186;186m\x1b[38;2;186;186;186m \x1b[0m\x1b[38;2;186;186;186m \x1b[0m\x1b[38;2;186;186;186m \x1b[0m\x1b[38;2;186;186;186m \x1b[0m\x1b[38;2;186;186;186m \x1b[0m\x1b[38;2;186;186;186m \x1b[0m\x1b[38;2;186;186;186m \x1b[0m\x1b[38;2;186;186;186m \x1b[0m\x1b[38;2;186;186;186m \x1b[0m\x1b[38;2;186;186;186m \x1b[0m\x1b[38;2;186;186;186m \x1b[0m\x1b[38;2;186;186;186m \x1b[0m\x1b[38;2;186;186;186m \x1b[0m\x1b[38;2;186;186;186m \x1b[0m\x1b[38;2;186;186;186m \x1b[0m\x1b[38;2;186;186;186m \x1b[0m\x1b[38;2;186;186;186m \x1b[0m\x1b[38;2;186;186;186m \x1b[0m\x1b[38;2;186;186;186m \x1b[0m\x1b[38;2;186;186;186m \x1b[0m\x1b[38;2;186;186;186m \x1b[0m\x1b[38;2;186;186;186m \x1b[0m\x1b[38;2;186;186;186m \x1b[0m\x1b[38;2;186;186;186m \x1b[0m\x1b[38;2;186;186;186m \x1b[0m\x1b[38;2;186;186;186m \x1b[0m\x1b[38;2;186;186;186m \x1b[0m\x1b[38;2;186;186;186m \x1b[0m\x1b[38;2;186;186;186m \x1b[0m\x1b[38;2;186;186;186m \x1b[0m\x1b[38;2;186;186;186m \x1b[0m\x1b[38;2;186;186;186m \x1b[0m\x1b[38;2;186;186;186m \x1b[0m\x1b[38;2;186;186;186m \x1b[0m\x1b[38;2;186;186;186m \x1b[0m\x1b[38;2;186;186;186m \x1b[0m\x1b[38;2;186;186;186m \x1b[0m\x1b[38;2;186;186;186m \x1b[0m\x1b[38;2;186;186;186m \x1b[0m\x1b[38;2;186;186;186m \x1b[0m\x1b[38;2;186;186;186m \x1b[0m\x1b[38;2;186;186;186m \x1b[0m\x1b[38;2;186;186;186m \x1b[0m\x1b[38;2;186;186;186m \x1b[0m\x1b[38;2;186;186;186m \x1b[0m\x1b[38;2;186;186;186m \x1b[0m\x1b[38;2;186;186;186m \x1b[0m\x1b[38;2;186;186;186m \x1b[0m\x1b[38;2;186;186;186m \x1b[0m\x1b[38;2;186;186;186m \x1b[0m\x1b[38;2;186;186;186m \x1b[0m\x1b[38;2;186;186;186m \x1b[0m\x1b[0m\n\x1b[0m\n" + got := markdownToString(markdown) if got != expectedOutput { t.Errorf("Expected %q, but got %q", expectedOutput, got)