diff --git a/README.md b/README.md index 130e6b8..0e403da 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,10 @@ To install go-grip, simply: go install github.com/chrishrb/go-grip@latest ``` +> [!TIP] +> You can also use nix flakes to install this plugin. +> More useful information [here](https://nixos.wiki/wiki/Flakes). + ## 🔨 Usage To render the `README.md` file simply execute: @@ -58,11 +62,6 @@ To terminate the current server simply press `CTRL-C`. ## 🐛 Known TODOs / Bugs -* [ ] GitHub alert block - ```md - > [!NOTE] - > Useful information that users should know, even when skimming content. - ``` * [ ] Checkboxes (like in this todo list) * [ ] Tests and refactoring diff --git a/pkg/parser.go b/pkg/parser.go index a8807c9..91fcbd9 100644 --- a/pkg/parser.go +++ b/pkg/parser.go @@ -1,8 +1,13 @@ package pkg import ( + "bytes" + "fmt" + "html/template" "io" "log" + "path/filepath" + "strings" "github.com/alecthomas/chroma/v2/quick" "github.com/gomarkdown/markdown" @@ -11,26 +16,38 @@ import ( "github.com/gomarkdown/markdown/parser" ) +var blockquotes = []string{"Note", "Tip", "Important", "Warning", "Caution"} + func (client *Client) MdToHTML(bytes []byte) []byte { extensions := parser.CommonExtensions | parser.AutoHeadingIDs p := parser.NewWithExtensions(extensions) doc := p.Parse(bytes) htmlFlags := html.CommonFlags - opts := html.RendererOptions{Flags: htmlFlags, RenderNodeHook: client.renderHookCodeBlock} + opts := html.RendererOptions{Flags: htmlFlags, RenderNodeHook: client.renderHook} renderer := html.NewRenderer(opts) return markdown.Render(doc, renderer) } -func (client *Client) renderHookCodeBlock(w io.Writer, node ast.Node, entering bool) (ast.WalkStatus, bool) { - block, ok := node.(*ast.CodeBlock) - if !ok { - return ast.GoToNext, false +func (client *Client) renderHook(w io.Writer, node ast.Node, entering bool) (ast.WalkStatus, bool) { + switch node.(type) { + case *ast.BlockQuote: + return renderHookBlockquote(w, node, entering) + case *ast.Text: + return renderHookText(w, node) + case *ast.CodeBlock: + return renderHookCodeBlock(w, node, client.Dark) } + return ast.GoToNext, false +} + +func renderHookCodeBlock(w io.Writer, node ast.Node, dark bool) (ast.WalkStatus, bool) { + block := node.(*ast.CodeBlock) + var style string - switch client.Dark { + switch dark { case true: style = "github-dark" default: @@ -41,6 +58,81 @@ func (client *Client) renderHookCodeBlock(w io.Writer, node ast.Node, entering b if err != nil { log.Println("Error:", err) } + return ast.GoToNext, true +} + +func renderHookBlockquote(w io.Writer, node ast.Node, entering bool) (ast.WalkStatus, bool) { + block := node.(*ast.BlockQuote) + + paragraph, ok := (block.GetChildren()[0]).(*ast.Paragraph) + if !ok { + return ast.GoToNext, false + } + + t, ok := (paragraph.GetChildren()[0]).(*ast.Text) + if !ok { + return ast.GoToNext, false + } + + // Get the text content of the blockquote + content := string(t.Literal) + + var alert string + for _, b := range blockquotes { + if strings.HasPrefix(content, fmt.Sprintf("[!%s]", strings.ToUpper(b))) { + alert = strings.ToLower(b) + } + } + + if alert == "" { + return ast.GoToNext, false + } + + // Set the message type based on the content of the blockquote + if entering { + s, _ := createBlockquoteStart(alert) + io.WriteString(w, s) + } else { + io.WriteString(w, "") + } return ast.GoToNext, true } + +func renderHookText(w io.Writer, node ast.Node) (ast.WalkStatus, bool) { + block := node.(*ast.Text) + + paragraph, ok := block.GetParent().(*ast.Paragraph) + if !ok { + return ast.GoToNext, false + } + + _, ok = paragraph.GetParent().(*ast.BlockQuote) + if !ok { + return ast.GoToNext, false + } + + // Remove prefixes + for _, b := range blockquotes { + content, found := strings.CutPrefix(string(block.Literal), fmt.Sprintf("[!%s]", strings.ToUpper(b))) + if found { + io.WriteString(w, content) + return ast.GoToNext, true + } + } + + return ast.GoToNext, false +} + +func createBlockquoteStart(alert string) (string, error) { + lp := filepath.Join("templates/alert", fmt.Sprintf("%s.html", alert)) + tmpl, err := template.ParseFiles(lp) + if err != nil { + return "", err + } + var tpl bytes.Buffer + if err := tmpl.Execute(&tpl, alert); err != nil { + return "", err + } + return tpl.String(), nil +} diff --git a/templates/alert/caution.html b/templates/alert/caution.html new file mode 100644 index 0000000..28c602f --- /dev/null +++ b/templates/alert/caution.html @@ -0,0 +1,8 @@ +
+

+ Caution +

diff --git a/templates/alert/important.html b/templates/alert/important.html new file mode 100644 index 0000000..f72c8ee --- /dev/null +++ b/templates/alert/important.html @@ -0,0 +1,9 @@ +
+

+ Important +

diff --git a/templates/alert/note.html b/templates/alert/note.html new file mode 100644 index 0000000..4753e82 --- /dev/null +++ b/templates/alert/note.html @@ -0,0 +1,8 @@ +
+

+ Note +

diff --git a/templates/alert/tip.html b/templates/alert/tip.html new file mode 100644 index 0000000..c7669fd --- /dev/null +++ b/templates/alert/tip.html @@ -0,0 +1,9 @@ +
+

+ Tip +

diff --git a/templates/alert/warning.html b/templates/alert/warning.html new file mode 100644 index 0000000..8d9343c --- /dev/null +++ b/templates/alert/warning.html @@ -0,0 +1,8 @@ +
+

+ Warning +