Skip to content

Commit

Permalink
add serve command
Browse files Browse the repository at this point in the history
  • Loading branch information
ihadeed committed Nov 15, 2019
1 parent 4d966d2 commit b9ad68c
Show file tree
Hide file tree
Showing 48 changed files with 6,292 additions and 24 deletions.
32 changes: 32 additions & 0 deletions cmd/docs/actions/generate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package actions

import (
"fmt"
"github.com/urfave/cli"
"github.com/zyra/zmdocs"
"os"
"path/filepath"
)

func Generate(ctx *cli.Context) error {
configPath := ctx.String("config")

if !filepath.IsAbs(configPath) {
if pwd, err := os.Getwd(); err != nil {
return err
} else {
configPath = filepath.Join(pwd, configPath)
}
}

if p, e := zmdocs.NewParserFromConfigFile(configPath); e != nil {
return fmt.Errorf("unable to parse config: %s", e)
} else if e := p.LoadSourceFiles(); e != nil {
return fmt.Errorf("unable to load files: %s", e)
} else if rnd, e := p.Renderer(); e != nil {
return fmt.Errorf("unable to create renderer: %s", e)
} else if e := rnd.Render(); e != nil {
return fmt.Errorf("unable to render files: %s", e)
}
return nil
}
225 changes: 225 additions & 0 deletions cmd/docs/actions/serve.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
package actions

import (
"context"
"fmt"
"github.com/fsnotify/fsnotify"
"github.com/gorilla/websocket"
"github.com/urfave/cli"
"github.com/zyra/zmdocs"
"io/ioutil"
"log"
"net/http"
"os"
"os/signal"
"path/filepath"
"strconv"
"strings"
"sync"
)

var upgrader = websocket.Upgrader{
ReadBufferSize: 1024,
WriteBufferSize: 1024,
}

var chansMtx = sync.RWMutex{}
var reloadChans = make(map[string]chan<- struct{})
var chanId = 1

func serveWs(w http.ResponseWriter, r *http.Request) {
ws, err := upgrader.Upgrade(w, r, nil)
if err != nil {
if _, ok := err.(websocket.HandshakeError); !ok {
log.Println(err)
}
return
}

ch := make(chan struct{})
chId := strconv.Itoa(chanId)
chanId++
chansMtx.Lock()
reloadChans[chId] = ch
chansMtx.Unlock()

ws.SetCloseHandler(func(code int, text string) error {
chansMtx.Lock()
defer chansMtx.RUnlock()
close(ch)
delete(reloadChans, chId)
return nil
})

for {
<-ch
_ = ws.WriteMessage(1, []byte{})
}
}

func Serve(ctx *cli.Context) error {
c, cancelFn := context.WithCancel(context.Background())

configPath := ctx.String("config")

if !filepath.IsAbs(configPath) {
if pwd, err := os.Getwd(); err != nil {
return err
} else {
configPath = filepath.Join(pwd, configPath)
}
}

var config *zmdocs.ParserConfig
var p *zmdocs.Parser
var e error
var rnd *zmdocs.Renderer

setupParser := func() {
if config, e = zmdocs.NewConfigFromFile(configPath); e != nil {
e = fmt.Errorf("unable to parse config: %s", e.Error())
}

config.BaseURL = "http://localhost:3500"

p = zmdocs.NewParser(config)

if e = p.LoadSourceFiles(); e != nil {
e = fmt.Errorf("unable to load files: %s", e)
} else if rnd, e = p.Renderer(); e != nil {
e = fmt.Errorf("unable to create renderer: %s", e)
}
}

render := func() {
if e = rnd.Render(); e != nil {
e = fmt.Errorf("unable to render files: %s", e)
}
}

setupParser()

if e != nil {
return e
}

render()

if e != nil {
return e
}

watcher, err := fsnotify.NewWatcher()

if err != nil {
return fmt.Errorf("unable to start watcher: %s", err.Error())
}

defer watcher.Close()

if err := watcher.Add(configPath); err != nil {
return fmt.Errorf("unable to add config to watcher: %s", err.Error())
}

setupFileWatchers := func() {
for _, f := range p.Files {
_ = watcher.Add(f.SourceFile)
}

for _, t := range p.Config.Templates {
_ = watcher.Add(t.SourceFile)
}
}

setupFileWatchers()

reload := func() {
chansMtx.RLock()
defer chansMtx.RUnlock()
for _, ch := range reloadChans {
ch <- struct{}{}
}
}

go func() {
for {
select {
case <-c.Done():
return

case ev, ok := <-watcher.Events:
if ! ok {
return
}

if ev.Op&fsnotify.Remove == fsnotify.Remove {
_ = watcher.Remove(ev.Name)
} else if ev.Op&fsnotify.Write == fsnotify.Write {
setupParser()

if e != nil {
fmt.Println(e)
continue
}

render()

if e != nil {
fmt.Println(e)
continue
}

setupFileWatchers()

if e != nil {
fmt.Println(e)
e = nil
}

reload()
}
}
}
}()

go func() {
http.HandleFunc("/reload", serveWs)
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
p := filepath.Join(p.Config.OutDir, strings.TrimSuffix(strings.TrimPrefix(r.URL.Path, "/"), "index.html"), "index.html")
if fc, e := ioutil.ReadFile(p); e != nil {
http.NotFound(w, r)
return
} else {
html := strings.Replace(string(fc), "</body>", `
<script>(() => {
const ws = new WebSocket("ws://localhost:3500/reload");
ws.onopen = e => console.log("Livereload WS is open");
ws.onmessage = () => location.reload();
ws.onclose = () => console.log("Livereload WS is closed");
})()</script></body>
`, 1)
w.WriteHeader(http.StatusOK)
w.Write([]byte(html))
}
})
if err := http.ListenAndServe(":3500", nil); err != nil {
if context.Canceled != nil {
return
}

fmt.Printf("unable to serve: %s", err.Error())
cancelFn()
}
}()

ch := make(chan os.Signal, 1)
signal.Notify(ch, os.Interrupt)

select {
case <-ch:
cancelFn()
case <-c.Done():
}

return nil
}
39 changes: 15 additions & 24 deletions cmd/docs/main.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
package main

import (
"fmt"
"github.com/urfave/cli"
"github.com/zyra/zmdocs"
"github.com/zyra/zmdocs/cmd/docs/actions"
"log"
"os"
"path/filepath"
)

var AppVersion = "0.0.1"
Expand Down Expand Up @@ -37,28 +35,21 @@ func main() {
Name: "generate",
Aliases: []string{"g"},
Usage: "Generate documentation",
Action: func(ctx *cli.Context) error {
configPath := ctx.String("config")

if !filepath.IsAbs(configPath) {
if pwd, err := os.Getwd(); err != nil {
return err
} else {
configPath = filepath.Join(pwd, configPath)
}
}

if p, e := zmdocs.NewParserFromConfigFile(configPath); e != nil {
return fmt.Errorf("unable to parse config: %s", e)
} else if e := p.LoadSourceFiles(); e != nil {
return fmt.Errorf("unable to load files: %s", e)
} else if rnd, e := p.Renderer(); e != nil {
return fmt.Errorf("unable to create renderer: %s", e)
} else if e := rnd.Render(); e != nil {
return fmt.Errorf("unable to render files: %s", e)
}
return nil
Action: actions.Generate,
Flags: []cli.Flag{
cli.StringFlag{
Name: "config, c",
Usage: "Config file",
EnvVar: "ZMDOC_CONFIG",
Value: "./.docs.yaml",
},
},
},
{
Name: "serve",
Aliases: []string{"s"},
Usage: "Run a webserver with livereload",
Action: actions.Serve,
Flags: []cli.Flag{
cli.StringFlag{
Name: "config, c",
Expand Down
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ module github.com/zyra/zmdocs
go 1.12

require (
github.com/fsnotify/fsnotify v1.4.7
github.com/gorilla/websocket v1.4.1
github.com/russross/blackfriday v2.0.0+incompatible
github.com/sirupsen/logrus v1.4.2
github.com/urfave/cli v1.22.1
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSY
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM=
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
Expand Down
1 change: 1 addition & 0 deletions parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ func (p *Parser) Renderer() (*Renderer, error) {
rnd := &Renderer{
MenuItems: p.Config.MenuItems,
Contexts: rndCtxs,
Templates: p.Config.Templates,
}

return rnd, nil
Expand Down
5 changes: 5 additions & 0 deletions vendor/github.com/fsnotify/fsnotify/.editorconfig

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions vendor/github.com/fsnotify/fsnotify/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 30 additions & 0 deletions vendor/github.com/fsnotify/fsnotify/.travis.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit b9ad68c

Please sign in to comment.