فهرست منبع

Several changes

Added live reload for markdown
Updated prettylog
Added templates
luis 7 سال پیش
والد
کامیت
8c913d7e1e
7فایلهای تغییر یافته به همراه186 افزوده شده و 110 حذف شده
  1. 5 1
      README.md
  2. 17 0
      assets/js/watcher.js
  3. 10 0
      assets/tmpl/Folder.tmpl
  4. 9 0
      assets/tmpl/MD.tmpl
  5. 11 0
      assets/tmpl/MD_testing.tmpl
  6. 27 13
      binAssets/binAssets.go
  7. 107 96
      main.go

+ 5 - 1
README.md

@@ -10,5 +10,9 @@ $ go get dev.hexasoftware.com/hxs/httpServe
 $ # with $GOPATH/bin in  $PATH
 $ httpServe
 [2017-07-07 09:38:12.199 httpServe]: Listening with port: 8080
-
 ```
+
+#### Changelog
+
+* Added support for live reload of certain files
+	* markdown

+ 17 - 0
assets/js/watcher.js

@@ -0,0 +1,17 @@
+(function (window, WsRpc) {
+  var cli = new WsRpc()
+
+  cli.export({
+    'reload': function (result) {
+      result()
+      console.log('Reload should happen')
+      window.location.reload()
+    }
+  })
+  cli.connect('ws://' + window.location.host + '/.httpServe/_reload/ws')
+  cli.onopen = function () {
+    cli.call('watch', window.location.pathname).then(function (res) {
+      console.log('Watching:', res)
+    })
+  }
+})(window, WsRpc)

+ 10 - 0
assets/tmpl/Folder.tmpl

@@ -0,0 +1,10 @@
+<html>
+	<body>
+		<ul>
+			{{range .content}}
+				<li><a href="/{{$.path}}/{{.Name}}">{{.Name}}</a>
+				{{end}}
+		</ul>
+	</body>
+</html>
+

+ 9 - 0
assets/tmpl/MD.tmpl

@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+	<head>
+		<script src="/.httpServe/_reload/wsrpc.js"></script>
+		<script src="/.httpServe/js/watcher.js"></script>
+	</head>
+	<xmp theme="paper" style="display:none;">{{.content}}</xmp>
+	<script src="/.httpServe/strapdown.js"></script>
+</html>

+ 11 - 0
assets/tmpl/MD_testing.tmpl

@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+	<head>
+		<script src="/.httpServe/_reload/wsrpc.js"></script>
+		<script src="/.httpServe/js/watcher.js"></script>
+		<link href="/.httpServe/gfm/gfm.css" rel="stylesheet">
+	</head>
+	<body>
+	{{.content}}
+	</body>
+</html>

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 27 - 13
binAssets/binAssets.go


+ 107 - 96
main.go

@@ -1,107 +1,139 @@
 // Simpliest server
 package main
 
-//go:generate folder2go assets binAssets
+//go:generate folder2go -handler assets binAssets
 
 import (
+	"errors"
 	"fmt"
-	"io"
 	"io/ioutil"
-	"mime"
 	"net"
 	"net/http"
 	"os"
 	"path/filepath"
 	"strings"
+	"text/template"
 
 	"dev.hexasoftware.com/hxs/httpServe/binAssets"
+	"dev.hexasoftware.com/stdio/wsrpc"
+	"github.com/fsnotify/fsnotify"
+	"github.com/gohxs/prettylog"
+	"github.com/gohxs/webu"
+	"github.com/gohxs/webu/chain"
 
-	"dev.hexasoftware.com/hxs/prettylog"
+	"github.com/shurcooL/github_flavored_markdown/gfmstyle"
 )
 
 var (
-	log = prettylog.New("httpServe")
+	log  = prettylog.New("httpServe")
+	tmpl = template.New("")
 )
 
-func CreateHandleFunc(prefix string) func(http.ResponseWriter, *http.Request) {
-	return func(w http.ResponseWriter, r *http.Request) {
-		var solvedPath = r.URL.Path
-		if solvedPath == prefix {
-			solvedPath = prefix + "/index.html"
-		}
-		log.Printf("%s - (embed)%s", r.Method, r.URL.Path)
-		if strings.HasPrefix(solvedPath, prefix) {
-			solvedPath = solvedPath[len(prefix):]
+func main() {
+	prettylog.Global()
+
+	mux := http.NewServeMux()
+	c := chain.New(webu.ChainLogger(prettylog.New("serve")))
+
+	mux.HandleFunc("/.httpServe/_reload/", wsrpc.New(wsrpcClient).ServeHTTP)
+	mux.Handle("/.httpServe/gfm/", http.StripPrefix("/.httpServe/gfm", http.FileServer(gfmstyle.Assets)))
+	mux.HandleFunc("/.httpServe/", binAssets.AssetHandleFunc)
+	// Only logs this
+	mux.HandleFunc("/", c.Build(fileServe))
+
+	// Load templates from binAssets
+	tmplFiles := []string{
+		"tmpl/MD.tmpl",
+		"tmpl/Folder.tmpl",
+	}
+	for _, v := range tmplFiles {
+		_, err := tmpl.New(v).Parse(string(binAssets.Data[v]))
+		if err != nil {
+			log.Fatal("Internal error, loading templates")
 		}
-		data, ok := binAssets.Data[solvedPath]
-		if !ok {
-			w.WriteHeader(404)
+	}
+
+	var port = 8080
+	for {
+		addr := fmt.Sprintf(":%d", port)
+		listener, err := net.Listen("tcp", addr)
+		if err != nil {
+			log.Println("Err opening", port, err)
+			port++
+			log.Println("Trying port", port)
+			continue
 		}
-		w.Header().Set("Content-type", mime.TypeByExtension(filepath.Ext(solvedPath)))
-		w.Write(data)
+		log.Println("Listening with port:", port)
+
+		http.Serve(listener, mux)
 	}
+	//http.ListenAndServe(":8080", http.FileServer(http.Dir('.')))
 }
 
-func HandleMarkDown(w http.ResponseWriter, r *http.Request, path string) error {
-	log.Println("Handling markdown")
-	f, err := os.Open(path)
+func wsrpcClient(ctx *wsrpc.ClientCtx) {
+	log.Println("Ws connected")
+	watcher, err := fsnotify.NewWatcher() // watcher per socket
 	if err != nil {
-		return err
+		return
 	}
-	defer f.Close()
-	/* // Server side markdown2html
-	data, err := ioutil.ReadAll(f)
-	if err != nil {
-		return err
+	defer watcher.Close()
+
+	ctx.Define("watch", func(params ...interface{}) (interface{}, error) {
+		toWatch, ok := params[0].(string)
+		if !ok {
+			return nil, errors.New("Param invalid")
+		}
+		absFile, err := filepath.Abs(toWatch[1:])
+		if err != nil {
+			return nil, err
+		}
+		err = watcher.Add(absFile) // remove root '/' prefix
+		if err != nil {
+			log.Println("Error watching", err)
+		}
+		// Request to watch something?
+		return true, nil
+	})
+
+	for {
+		select {
+		case event := <-watcher.Events:
+			if event.Op&fsnotify.Remove != 0 {
+				ctx.Call("reload")
+			}
+		case <-ctx.Done():
+			return
+		}
 	}
-	w.Write([]byte("<html><head><link rel='stylesheet' href='/.httpServe/strapdown.css'><link rel='stylesheet' href='/.httpServe/themes/united.min.css'></head><body>"))
-	mdData := blackfriday.MarkdownCommon(data)
-	w.Write(mdData)
-	w.Write([]byte("</body></html>"))
-	return nil
-	*/
-	w.Write([]byte(
-		`
-<!DOCTYPE html>
-<html>
-<xmp theme="paper" style="display:none;">
-`))
-
-	io.Copy(w, f)
-	w.Write([]byte(
-		`
-			</xmp>
-	<script src=".httpServe/strapdown.js"></script>
-</html>`))
-	return nil
-}
 
-func HandleFolder(w http.ResponseWriter, r *http.Request, path string) error {
+}
 
-	res, err := ioutil.ReadDir(path)
+func handleMarkDown(w http.ResponseWriter, r *http.Request, path string) error {
+	fileData, err := ioutil.ReadFile(path)
 	if err != nil {
 		return err
 	}
-	w.Write([]byte(
-		`<html>
- <body>
- <ul>`))
-	for _, f := range res {
-		w.Write([]byte(fmt.Sprintf(`<li><a href="/%s">%s</a>`, path+"/"+f.Name(), f.Name())))
-	}
-	w.Write([]byte(
-		`</ul>
- </body>
- </html>
- `))
 
-	return nil
+	err = tmpl.ExecuteTemplate(w, "tmpl/MD.tmpl", map[string]interface{}{
+		"path":    path,
+		"content": string(fileData),
+	})
+	return err
 }
 
-type FileServer struct {
+func handleFolder(w http.ResponseWriter, r *http.Request, path string) error {
+	res, err := ioutil.ReadDir(path)
+	if err != nil {
+		return err
+	}
+	err = tmpl.ExecuteTemplate(w, "tmpl/Folder.tmpl", map[string]interface{}{
+		"path":    path,
+		"content": res,
+	})
+	return err
 }
 
-func (FileServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+func fileServe(w http.ResponseWriter, r *http.Request) {
 	path := r.URL.Path[1:]
 	if path == "" {
 		path = "index.html"
@@ -113,49 +145,28 @@ func (FileServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 	if strings.Contains(path, "..") {
 		http.ServeFile(w, r, path)
 	}
-	log.Printf("%s - %s", r.Method, r.URL.Path)
+	//log.Printf("%s - %s", r.Method, r.URL.Path)
 
 	fstat, err := os.Stat(path)
 	if err != nil {
-		log.Println("ERR:", err)
-		http.ServeFile(w, r, path)
+		webu.WriteStatus(w, http.StatusNotFound)
 		return
 	}
+
 	if fstat.IsDir() {
-		HandleFolder(w, r, path)
+		err := handleFolder(w, r, path)
+		if err != nil {
+			webu.WriteStatus(w, http.StatusInternalServerError, err)
+		}
 		return
 	}
 
 	if filepath.Ext(path) == ".md" {
-		err := HandleMarkDown(w, r, path)
+		err := handleMarkDown(w, r, path)
 		if err != nil {
-			http.ServeFile(w, r, path)
+			webu.WriteStatus(w, http.StatusInternalServerError, err)
 		}
 		return
 	}
-
-	// Default file server
 	http.ServeFile(w, r, path)
 }
-
-func main() {
-
-	mux := http.NewServeMux()
-	mux.HandleFunc("/.httpServe/", CreateHandleFunc("/.httpServe"))
-	mux.Handle("/", FileServer{})
-	var port = 8080
-	for {
-		addr := fmt.Sprintf(":%d", port)
-		listener, err := net.Listen("tcp", addr)
-		if err != nil {
-			log.Println("Err opening", port, err)
-			port++
-			log.Println("Trying port", port)
-			continue
-		}
-		log.Println("Listening with port:", port)
-
-		http.Serve(listener, mux)
-	}
-	//http.ListenAndServe(":8080", http.FileServer(http.Dir('.')))
-}