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
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"github.com/chrishrb/go-grip/pkg"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// rootCmd represents the base command when called without any subcommands
|
|
||||||
var rootCmd = &cobra.Command{
|
var rootCmd = &cobra.Command{
|
||||||
Use: "go-grip",
|
Use: "go-grip [file]",
|
||||||
Short: "A brief description of your application",
|
Short: "Render markdown document as html",
|
||||||
Long: `A longer description that spans multiple lines and likely contains
|
Args: cobra.MatchAll(cobra.MinimumNArgs(1), cobra.OnlyValidArgs),
|
||||||
examples and usage of using your application. For example:
|
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.
|
client := pkg.Client{Dark: dark, OpenBrowser: browser, Port: port}
|
||||||
This application is a tool to generate the needed files
|
|
||||||
to quickly create a Cobra application.`,
|
bytes, err := client.MdToHTML(args[0])
|
||||||
// Uncomment the following line if your bare application
|
cobra.CheckErr(err)
|
||||||
// has an action associated with it:
|
|
||||||
// Run: func(cmd *cobra.Command, args []string) { },
|
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() {
|
func Execute() {
|
||||||
err := rootCmd.Execute()
|
err := rootCmd.Execute()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -37,15 +34,7 @@ func Execute() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
// Here you will define your flags and configuration settings.
|
rootCmd.Flags().BoolP("dark", "d", false, "Darkmode")
|
||||||
// Cobra supports persistent flags, which, if defined here,
|
rootCmd.Flags().BoolP("browser", "b", true, "Open new browser tab")
|
||||||
// will be global for your application.
|
rootCmd.Flags().IntP("port", "p", 6419, "Port to use")
|
||||||
|
|
||||||
// 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")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
3
go.mod
3
go.mod
@@ -3,6 +3,9 @@ module github.com/chrishrb/go-grip
|
|||||||
go 1.22.7
|
go 1.22.7
|
||||||
|
|
||||||
require (
|
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/inconshreveable/mousetrap v1.1.0 // indirect
|
||||||
github.com/spf13/cobra v1.8.1 // indirect
|
github.com/spf13/cobra v1.8.1 // indirect
|
||||||
github.com/spf13/pflag v1.0.5 // 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/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 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
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