add basic features
This commit is contained in:
33
Makefile
Normal file
33
Makefile
Normal file
@@ -0,0 +1,33 @@
|
||||
.PHONY: all format lint clean
|
||||
|
||||
GOCMD=go
|
||||
LDFLAGS="-s -w ${LDFLAGS_OPT}"
|
||||
|
||||
all: build format lint ## Format, lint and build
|
||||
|
||||
build: ## Build
|
||||
go build -o bin/go-grip main.go
|
||||
|
||||
test: ## Test
|
||||
${GOCMD} test ./...
|
||||
|
||||
compile: ## Compile for every OS and Platform
|
||||
echo "Compiling for every OS and Platform"
|
||||
GOOS=darwin GOARCH=amd64 go build -o bin/go-grip-darwin-amd64 main.go
|
||||
GOOS=darwin GOARCH=arm64 go build -o bin/go-grip-darwin-arm64 main.go
|
||||
GOOS=linux GOARCH=amd64 go build -o bin/go-grip-linux-amd64 main.go
|
||||
GOOS=linux GOARCH=arm64 go build -o bin/go-grip-linux-arm64 main.go
|
||||
GOOS=windows GOARCH=amd64 go build -o bin/go-grip-windows-amd64 main.go
|
||||
GOOS=windows GOARCH=arm64 go build -o bin/go-grip-windows-arm64 main.go
|
||||
|
||||
format: ## Format code
|
||||
${GOCMD} fmt ./...
|
||||
|
||||
lint: ## Run linter
|
||||
golangci-lint run
|
||||
|
||||
clean: ## Cleanup build dir
|
||||
rm -r bin/
|
||||
|
||||
help: ## Display this help screen
|
||||
@grep -h -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
|
||||
16
README.md
Normal file
16
README.md
Normal file
@@ -0,0 +1,16 @@
|
||||
<br />
|
||||
<div align="center">
|
||||
<a href="#">
|
||||
<img src=".github/assets/nix-dots.png" alt="Logo" height="80">
|
||||
</a>
|
||||
</div>
|
||||
|
||||
# go-grip
|
||||
|
||||
## Getting started on macOS
|
||||
|
||||
To get started on a bare `macOS` installation, first install Nix:
|
||||
|
||||
```
|
||||
curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install
|
||||
```
|
||||
49
cmd/root.go
49
cmd/root.go
@@ -1,34 +1,31 @@
|
||||
/*
|
||||
Copyright © 2024 NAME HERE <EMAIL ADDRESS>
|
||||
|
||||
*/
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/chrishrb/go-grip/pkg"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
|
||||
|
||||
// rootCmd represents the base command when called without any subcommands
|
||||
var rootCmd = &cobra.Command{
|
||||
Use: "go-grip",
|
||||
Short: "A brief description of your application",
|
||||
Long: `A longer description that spans multiple lines and likely contains
|
||||
examples and usage of using your application. For example:
|
||||
Use: "go-grip [file]",
|
||||
Short: "Render markdown document as html",
|
||||
Args: cobra.MatchAll(cobra.MinimumNArgs(1), cobra.OnlyValidArgs),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
dark, _ := cmd.Flags().GetBool("dark")
|
||||
browser, _ := cmd.Flags().GetBool("browser")
|
||||
port, _ := cmd.Flags().GetInt("port")
|
||||
|
||||
Cobra is a CLI library for Go that empowers applications.
|
||||
This application is a tool to generate the needed files
|
||||
to quickly create a Cobra application.`,
|
||||
// Uncomment the following line if your bare application
|
||||
// has an action associated with it:
|
||||
// Run: func(cmd *cobra.Command, args []string) { },
|
||||
client := pkg.Client{Dark: dark, OpenBrowser: browser, Port: port}
|
||||
|
||||
bytes, err := client.MdToHTML(args[0])
|
||||
cobra.CheckErr(err)
|
||||
|
||||
err = client.Serve(bytes)
|
||||
cobra.CheckErr(err)
|
||||
},
|
||||
}
|
||||
|
||||
// Execute adds all child commands to the root command and sets flags appropriately.
|
||||
// This is called by main.main(). It only needs to happen once to the rootCmd.
|
||||
func Execute() {
|
||||
err := rootCmd.Execute()
|
||||
if err != nil {
|
||||
@@ -37,15 +34,7 @@ func Execute() {
|
||||
}
|
||||
|
||||
func init() {
|
||||
// Here you will define your flags and configuration settings.
|
||||
// Cobra supports persistent flags, which, if defined here,
|
||||
// will be global for your application.
|
||||
|
||||
// rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.go-grip.yaml)")
|
||||
|
||||
// Cobra also supports local flags, which will only run
|
||||
// when this action is called directly.
|
||||
rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
|
||||
rootCmd.Flags().BoolP("dark", "d", false, "Darkmode")
|
||||
rootCmd.Flags().BoolP("browser", "b", true, "Open new browser tab")
|
||||
rootCmd.Flags().IntP("port", "p", 6419, "Port to use")
|
||||
}
|
||||
|
||||
|
||||
|
||||
3
go.mod
3
go.mod
@@ -3,6 +3,9 @@ module github.com/chrishrb/go-grip
|
||||
go 1.22.7
|
||||
|
||||
require (
|
||||
github.com/alecthomas/chroma/v2 v2.14.0 // indirect
|
||||
github.com/dlclark/regexp2 v1.11.4 // indirect
|
||||
github.com/gomarkdown/markdown v0.0.0-20240930133441-72d49d9543d8 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/spf13/cobra v1.8.1 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
|
||||
6
go.sum
6
go.sum
@@ -1,4 +1,10 @@
|
||||
github.com/alecthomas/chroma/v2 v2.14.0 h1:R3+wzpnUArGcQz7fCETQBzO5n9IMNi13iIs46aU4V9E=
|
||||
github.com/alecthomas/chroma/v2 v2.14.0/go.mod h1:QolEbTfmUHIMVpBqxeDnNBj2uoeI4EbYP4i6n68SG4I=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/dlclark/regexp2 v1.11.4 h1:rPYF9/LECdNymJufQKmri9gV604RvvABwgOA8un7yAo=
|
||||
github.com/dlclark/regexp2 v1.11.4/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
||||
github.com/gomarkdown/markdown v0.0.0-20240930133441-72d49d9543d8 h1:4txT5G2kqVAKMjzidIabL/8KqjIK71yj30YOeuxLn10=
|
||||
github.com/gomarkdown/markdown v0.0.0-20240930133441-72d49d9543d8/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA=
|
||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
|
||||
7
pkg/client.go
Normal file
7
pkg/client.go
Normal file
@@ -0,0 +1,7 @@
|
||||
package pkg
|
||||
|
||||
type Client struct {
|
||||
Dark bool
|
||||
OpenBrowser bool
|
||||
Port int
|
||||
}
|
||||
23
pkg/open.go
Normal file
23
pkg/open.go
Normal file
@@ -0,0 +1,23 @@
|
||||
package pkg
|
||||
|
||||
import (
|
||||
"os/exec"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
func Open(url string) error {
|
||||
var cmd string
|
||||
var args []string
|
||||
|
||||
switch runtime.GOOS {
|
||||
case "windows":
|
||||
cmd = "cmd"
|
||||
args = []string{"/c", "start"}
|
||||
case "darwin":
|
||||
cmd = "open"
|
||||
default: // "linux", "freebsd", "openbsd", "netbsd"
|
||||
cmd = "xdg-open"
|
||||
}
|
||||
args = append(args, url)
|
||||
return exec.Command(cmd, args...).Start()
|
||||
}
|
||||
48
pkg/parser.go
Normal file
48
pkg/parser.go
Normal file
@@ -0,0 +1,48 @@
|
||||
package pkg
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/alecthomas/chroma/v2/quick"
|
||||
"github.com/gomarkdown/markdown"
|
||||
"github.com/gomarkdown/markdown/ast"
|
||||
"github.com/gomarkdown/markdown/html"
|
||||
"github.com/gomarkdown/markdown/parser"
|
||||
)
|
||||
|
||||
func (client *Client) MdToHTML(filename string) ([]byte, error) {
|
||||
bytes, err := os.ReadFile(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
extensions := parser.CommonExtensions | parser.AutoHeadingIDs
|
||||
p := parser.NewWithExtensions(extensions)
|
||||
doc := p.Parse(bytes)
|
||||
|
||||
htmlFlags := html.CommonFlags
|
||||
opts := html.RendererOptions{Flags: htmlFlags, RenderNodeHook: client.renderHookCodeBlock}
|
||||
renderer := html.NewRenderer(opts)
|
||||
|
||||
return markdown.Render(doc, renderer), err
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
var style string
|
||||
switch client.Dark {
|
||||
case true:
|
||||
style = "github-dark"
|
||||
default:
|
||||
style = "github"
|
||||
}
|
||||
|
||||
quick.Highlight(w, string(block.Literal), string(block.Info), "html", style)
|
||||
|
||||
return ast.GoToNext, true
|
||||
}
|
||||
50
pkg/webserver.go
Normal file
50
pkg/webserver.go
Normal file
@@ -0,0 +1,50 @@
|
||||
package pkg
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"path/filepath"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
type htmlStruct struct {
|
||||
Content string
|
||||
Darkmode bool
|
||||
}
|
||||
|
||||
func (client *Client) Serve(htmlContent []byte) error {
|
||||
// Serve static files
|
||||
fs := http.FileServer(http.Dir("./static"))
|
||||
http.Handle("/static/", http.StripPrefix("/static/", fs))
|
||||
|
||||
// Serve website with rendered markdown
|
||||
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
err := serveTemplate(w, htmlStruct{Content: string(htmlContent), Darkmode: client.Dark})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
})
|
||||
|
||||
addr := fmt.Sprintf("http://localhost:%d", client.Port)
|
||||
fmt.Printf("Starting server: %s\n", addr)
|
||||
|
||||
if client.OpenBrowser {
|
||||
Open(addr)
|
||||
}
|
||||
|
||||
http.ListenAndServe(fmt.Sprintf(":%d", client.Port), nil)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func serveTemplate(w http.ResponseWriter, html htmlStruct) error {
|
||||
w.Header().Set("Content-Type", "text/html")
|
||||
lp := filepath.Join("templates", "layout.html")
|
||||
tmpl, err := template.ParseFiles(lp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = tmpl.Execute(w, html)
|
||||
return err
|
||||
}
|
||||
1098
static/css/github-markdown-dark.css
Normal file
1098
static/css/github-markdown-dark.css
Normal file
File diff suppressed because it is too large
Load Diff
1098
static/css/github-markdown-light.css
Normal file
1098
static/css/github-markdown-light.css
Normal file
File diff suppressed because it is too large
Load Diff
19
templates/layout.html
Normal file
19
templates/layout.html
Normal file
@@ -0,0 +1,19 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Markdown Preview</title>
|
||||
{{if .Darkmode }}
|
||||
<link rel="stylesheet" href="/static/css/github-markdown-dark.css">
|
||||
{{else}}
|
||||
<link rel="stylesheet" href="/static/css/github-markdown-light.css">
|
||||
{{end}}
|
||||
</head>
|
||||
<body class="markdown-body entry-content container-lg">
|
||||
<div style="padding: 32px;">
|
||||
<div class="">
|
||||
{{ .Content }}
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user