Top nav works

master
scratch 2019-10-19 05:46:55 +00:00
parent a8ee907a0f
commit a6325abca3
10 changed files with 81 additions and 131 deletions

View File

@ -4,29 +4,23 @@ import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"os"
) )
func isDir(path string) bool { func notesDir(path Path, w http.ResponseWriter, r *http.Request) {
stat, err := os.Stat(path)
return err == nil && stat.IsDir()
}
func notesDir(path string, w http.ResponseWriter, r *http.Request) {
dirs, files := lsDir(path) dirs, files := lsDir(path)
content := dirs.List() content := dirs.List()
block(content, w) block(content, w)
fmt.Fprintln(w, files.List()) fmt.Fprintln(w, files.List())
} }
func lsDir(p string) (Paths, Paths) { func lsDir(path Path) (Paths, Paths) {
dirs := newDirs() dirs := newDirs()
files := newFiles() files := newFiles()
found, _ := ioutil.ReadDir(p) found, _ := ioutil.ReadDir(path.Local)
for _, f := range found { for _, f := range found {
dirs.Push(p, f) dirs.Push(path, f)
files.Push(p, f) files.Push(path, f)
} }
return Paths(*dirs), Paths(*files) return Paths(*dirs), Paths(*files)
} }

View File

@ -5,20 +5,9 @@ import (
"testing" "testing"
) )
func TestIsDir(t *testing.T) {
if ok := isDir("/tmp"); !ok {
t.Fatal(ok)
}
if ok := isDir("/dev/null"); ok {
t.Fatal(ok)
}
if ok := isDir("/proc/not/real/tho"); ok {
t.Fatal(ok)
}
}
func TestLsDir(t *testing.T) { func TestLsDir(t *testing.T) {
dirs, files := lsDir("/usr/local") p := Path{Local: "/usr/local"}
dirs, files := lsDir(p)
if len(dirs) == 0 { if len(dirs) == 0 {
t.Fatal(len(dirs)) t.Fatal(len(dirs))
} }
@ -30,7 +19,7 @@ func TestLsDir(t *testing.T) {
} }
func TestNotesDir(t *testing.T) { func TestNotesDir(t *testing.T) {
path := "/usr/local" path := Path{Local: "/usr/local"}
w := httptest.NewRecorder() w := httptest.NewRecorder()
notesDir(path, w, nil) notesDir(path, w, nil)
t.Logf("%s", w.Body.Bytes()) t.Logf("%s", w.Body.Bytes())

View File

@ -2,6 +2,7 @@ package server
import ( import (
"os" "os"
"path"
) )
type Dirs []Path type Dirs []Path
@ -11,11 +12,8 @@ func newDirs() *Dirs {
return &d return &d
} }
func (d *Dirs) Push(p string, f os.FileInfo) { func (d *Dirs) Push(p Path, f os.FileInfo) {
if f.IsDir() { if f.IsDir() {
*d = append(*d, Path{ *d = append(*d, NewPathFromLocal(path.Join(p.Local, f.Name())))
dir: p,
base: f.Name(),
})
} }
} }

View File

@ -4,20 +4,12 @@ import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"os"
"github.com/gomarkdown/markdown" "github.com/gomarkdown/markdown"
) )
func isFile(path string) bool { func notesFile(path Path, w http.ResponseWriter, r *http.Request) {
stat, err := os.Stat(path) b, _ := ioutil.ReadFile(path.Local)
return err == nil && !stat.IsDir()
}
func notesFile(path string, w http.ResponseWriter, r *http.Request) {
title := h1(path)
block(title, w)
b, _ := ioutil.ReadFile(path)
content := markdown.ToHTML(b, nil, nil) content := markdown.ToHTML(b, nil, nil)
fmt.Fprintf(w, "%s\n", content) fmt.Fprintf(w, "%s\n", content)
} }

View File

@ -9,18 +9,6 @@ import (
"testing" "testing"
) )
func TestIsFile(t *testing.T) {
if ok := isFile("/tmp"); ok {
t.Fatal(ok)
}
if ok := isFile("/dev/null"); !ok {
t.Fatal(ok)
}
if ok := isFile("/proc/not/real/tho"); ok {
t.Fatal(ok)
}
}
func TestNotesFile(t *testing.T) { func TestNotesFile(t *testing.T) {
f, err := ioutil.TempFile(os.TempDir(), "until*") f, err := ioutil.TempFile(os.TempDir(), "until*")
if err != nil { if err != nil {
@ -41,7 +29,8 @@ func TestNotesFile(t *testing.T) {
`) `)
f.Close() f.Close()
w := httptest.NewRecorder() w := httptest.NewRecorder()
notesFile(f.Name(), w, nil) p := Path{Local: f.Name()}
notesFile(p, w, nil)
s := string(w.Body.Bytes()) s := string(w.Body.Bytes())
shouldContain := []string{ shouldContain := []string{
"tbody", "tbody",

View File

@ -2,6 +2,7 @@ package server
import ( import (
"os" "os"
"path"
) )
type Files []Path type Files []Path
@ -11,11 +12,8 @@ func newFiles() *Files {
return &d return &d
} }
func (d *Files) Push(p string, f os.FileInfo) { func (d *Files) Push(p Path, f os.FileInfo) {
if !f.IsDir() { if !f.IsDir() {
*d = append(*d, Path{ *d = append(*d, NewPathFromLocal(path.Join(p.Local, f.Name())))
dir: p,
base: f.Name(),
})
} }
} }

View File

@ -2,20 +2,17 @@ package server
import ( import (
"fmt" "fmt"
"local/notes-server/config"
"net/http" "net/http"
"path"
"strings"
) )
func (s *Server) notes(w http.ResponseWriter, r *http.Request) { func (s *Server) notes(w http.ResponseWriter, r *http.Request) {
p := resolvePath(r.URL.Path) p := NewPath(r.URL.Path)
if isDir(p) { if p.IsDir() {
head(w, r) head(w, r)
notesHead(w, p) notesHead(w, p)
notesDir(p, w, r) notesDir(p, w, r)
foot(w, r) foot(w, r)
} else if isFile(p) { } else if p.IsFile() {
head(w, r) head(w, r)
notesHead(w, p) notesHead(w, p)
notesFile(p, w, r) notesFile(p, w, r)
@ -25,18 +22,6 @@ func (s *Server) notes(w http.ResponseWriter, r *http.Request) {
} }
} }
func resolvePath(p string) string { func notesHead(w http.ResponseWriter, p Path) {
p = strings.TrimPrefix(p, "/") fmt.Fprintln(w, h2(p.MultiLink()))
p = strings.TrimPrefix(p, "notes")
p = strings.TrimPrefix(p, "/")
p = path.Join(config.Root, p)
return p
}
func notesHead(w http.ResponseWriter, p string) {
path := Path{
dir: path.Dir(p),
base: path.Base(p),
}
fmt.Fprintln(w, h2(path.MultiLink()))
} }

View File

@ -1,13 +1 @@
package server package server
import (
"local/notes-server/config"
"testing"
)
func TestResolvePath(t *testing.T) {
config.Root = "ROOT"
if p := resolvePath("/notes/a/b/c"); p != "ROOT/a/b/c" {
t.Fatal(p)
}
}

View File

@ -3,6 +3,7 @@ package server
import ( import (
"fmt" "fmt"
"local/notes-server/config" "local/notes-server/config"
"os"
"path" "path"
"strings" "strings"
) )
@ -13,12 +14,23 @@ type Path struct {
Base string Base string
} }
func NewPathFromLocal(p string) Path {
splits := strings.SplitN(p, path.Base(config.Root), 2)
href := splits[0]
if len(splits) > 1 {
href = splits[1]
}
href = path.Join("/notes", href)
return NewPath(href)
}
func NewPath(p string) Path { func NewPath(p string) Path {
base := path.Base(p) base := path.Base(p)
href := path.Join("/notes", p) href := p
local := strings.TrimPrefix(p, "/") local := strings.TrimPrefix(p, "/notes")
local = strings.TrimPrefix(p, "notes") if len(local) != len(p) {
local = strings.TrimPrefix(p, "/") local = strings.TrimPrefix(local, "/")
}
local = path.Join(config.Root, local) local = path.Join(config.Root, local)
return Path{ return Path{
Base: base, Base: base,
@ -28,31 +40,36 @@ func NewPath(p string) Path {
} }
func (p Path) MultiLink() string { func (p Path) MultiLink() string {
pa := path.Join("/notes", p.String()) href := p.HREF
href = strings.TrimPrefix(href, "/")
href = strings.TrimSuffix(href, "/")
segments := strings.Split(href, "/")
full := "" full := ""
for pa != "/" { for i := range segments {
base := path.Base(pa) href := "/" + strings.Join(segments[:i], "/") + "/"
full = fmt.Sprintf(`/<a href=%q>%s</a>`, pa, base) + full href += segments[i]
pa = path.Dir(pa) href = path.Clean(href)
base := segments[i]
add := fmt.Sprintf(`/<a href=%q>%s</a>`, href, base)
full += add
} }
return full return full
} }
func (p Path) String() string { func (p Path) LI() string {
root := path.Base(config.Root) return fmt.Sprintf(`<li><a href=%q>%s</a></li>`, p.HREF, p.Base)
dir := p.dir
dirs := strings.SplitN(dir, root, 2)
dir = dirs[0]
if len(dirs) > 1 {
dir = dirs[1]
}
base := p.base
return path.Join(dir, base)
} }
func (p Path) LI() string { func (p Path) IsDir() bool {
content := fmt.Sprintf(`<li><a href="%s">`, path.Join("/notes", p.String())) stat, err := os.Stat(p.Local)
content += p.base return err == nil && stat.IsDir()
content += "</li>" }
return content
func (p Path) IsFile() bool {
stat, err := os.Stat(p.Local)
return err == nil && !stat.IsDir()
}
func (p Path) String() string {
return fmt.Sprintf(`[Local:%s HREF:%s Base:%s]`, p.Local, p.HREF, p.Base)
} }

View File

@ -1,23 +1,23 @@
package server package server
import ( import "testing"
"regexp"
"testing"
)
func TestPathLI(t *testing.T) { func TestPathIs(t *testing.T) {
p := Path{ p := Path{Local: "/dev/null"}
dir: "a/b/c", if ok := p.IsDir(); ok {
base: "d", t.Fatal(ok, p)
}
link := p.LI()
ok, err := regexp.MatchString(`li.*a.*href="a/b/c/d".d..li`, link)
if err != nil {
t.Fatal(err, link)
}
if !ok {
t.Fatal(ok, link)
} }
t.Log(p, link) if ok := p.IsFile(); !ok {
t.Fatal(ok, p)
}
p = Path{Local: "/tmp"}
if ok := p.IsDir(); !ok {
t.Fatal(ok, p)
}
if ok := p.IsFile(); ok {
t.Fatal(ok, p)
}
} }