Top nav works
parent
a8ee907a0f
commit
a6325abca3
|
|
@ -4,29 +4,23 @@ import (
|
|||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
)
|
||||
|
||||
func isDir(path string) bool {
|
||||
stat, err := os.Stat(path)
|
||||
return err == nil && stat.IsDir()
|
||||
}
|
||||
|
||||
func notesDir(path string, w http.ResponseWriter, r *http.Request) {
|
||||
func notesDir(path Path, w http.ResponseWriter, r *http.Request) {
|
||||
dirs, files := lsDir(path)
|
||||
content := dirs.List()
|
||||
block(content, w)
|
||||
fmt.Fprintln(w, files.List())
|
||||
}
|
||||
|
||||
func lsDir(p string) (Paths, Paths) {
|
||||
func lsDir(path Path) (Paths, Paths) {
|
||||
dirs := newDirs()
|
||||
files := newFiles()
|
||||
|
||||
found, _ := ioutil.ReadDir(p)
|
||||
found, _ := ioutil.ReadDir(path.Local)
|
||||
for _, f := range found {
|
||||
dirs.Push(p, f)
|
||||
files.Push(p, f)
|
||||
dirs.Push(path, f)
|
||||
files.Push(path, f)
|
||||
}
|
||||
return Paths(*dirs), Paths(*files)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,20 +5,9 @@ import (
|
|||
"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) {
|
||||
dirs, files := lsDir("/usr/local")
|
||||
p := Path{Local: "/usr/local"}
|
||||
dirs, files := lsDir(p)
|
||||
if len(dirs) == 0 {
|
||||
t.Fatal(len(dirs))
|
||||
}
|
||||
|
|
@ -30,7 +19,7 @@ func TestLsDir(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestNotesDir(t *testing.T) {
|
||||
path := "/usr/local"
|
||||
path := Path{Local: "/usr/local"}
|
||||
w := httptest.NewRecorder()
|
||||
notesDir(path, w, nil)
|
||||
t.Logf("%s", w.Body.Bytes())
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package server
|
|||
|
||||
import (
|
||||
"os"
|
||||
"path"
|
||||
)
|
||||
|
||||
type Dirs []Path
|
||||
|
|
@ -11,11 +12,8 @@ func newDirs() *Dirs {
|
|||
return &d
|
||||
}
|
||||
|
||||
func (d *Dirs) Push(p string, f os.FileInfo) {
|
||||
func (d *Dirs) Push(p Path, f os.FileInfo) {
|
||||
if f.IsDir() {
|
||||
*d = append(*d, Path{
|
||||
dir: p,
|
||||
base: f.Name(),
|
||||
})
|
||||
*d = append(*d, NewPathFromLocal(path.Join(p.Local, f.Name())))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,20 +4,12 @@ import (
|
|||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
"github.com/gomarkdown/markdown"
|
||||
)
|
||||
|
||||
func isFile(path string) bool {
|
||||
stat, err := os.Stat(path)
|
||||
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)
|
||||
func notesFile(path Path, w http.ResponseWriter, r *http.Request) {
|
||||
b, _ := ioutil.ReadFile(path.Local)
|
||||
content := markdown.ToHTML(b, nil, nil)
|
||||
fmt.Fprintf(w, "%s\n", content)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,18 +9,6 @@ import (
|
|||
"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) {
|
||||
f, err := ioutil.TempFile(os.TempDir(), "until*")
|
||||
if err != nil {
|
||||
|
|
@ -41,7 +29,8 @@ func TestNotesFile(t *testing.T) {
|
|||
`)
|
||||
f.Close()
|
||||
w := httptest.NewRecorder()
|
||||
notesFile(f.Name(), w, nil)
|
||||
p := Path{Local: f.Name()}
|
||||
notesFile(p, w, nil)
|
||||
s := string(w.Body.Bytes())
|
||||
shouldContain := []string{
|
||||
"tbody",
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package server
|
|||
|
||||
import (
|
||||
"os"
|
||||
"path"
|
||||
)
|
||||
|
||||
type Files []Path
|
||||
|
|
@ -11,11 +12,8 @@ func newFiles() *Files {
|
|||
return &d
|
||||
}
|
||||
|
||||
func (d *Files) Push(p string, f os.FileInfo) {
|
||||
func (d *Files) Push(p Path, f os.FileInfo) {
|
||||
if !f.IsDir() {
|
||||
*d = append(*d, Path{
|
||||
dir: p,
|
||||
base: f.Name(),
|
||||
})
|
||||
*d = append(*d, NewPathFromLocal(path.Join(p.Local, f.Name())))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,20 +2,17 @@ package server
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"local/notes-server/config"
|
||||
"net/http"
|
||||
"path"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func (s *Server) notes(w http.ResponseWriter, r *http.Request) {
|
||||
p := resolvePath(r.URL.Path)
|
||||
if isDir(p) {
|
||||
p := NewPath(r.URL.Path)
|
||||
if p.IsDir() {
|
||||
head(w, r)
|
||||
notesHead(w, p)
|
||||
notesDir(p, w, r)
|
||||
foot(w, r)
|
||||
} else if isFile(p) {
|
||||
} else if p.IsFile() {
|
||||
head(w, r)
|
||||
notesHead(w, p)
|
||||
notesFile(p, w, r)
|
||||
|
|
@ -25,18 +22,6 @@ func (s *Server) notes(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
}
|
||||
|
||||
func resolvePath(p string) string {
|
||||
p = strings.TrimPrefix(p, "/")
|
||||
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()))
|
||||
func notesHead(w http.ResponseWriter, p Path) {
|
||||
fmt.Fprintln(w, h2(p.MultiLink()))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1 @@
|
|||
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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package server
|
|||
import (
|
||||
"fmt"
|
||||
"local/notes-server/config"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
)
|
||||
|
|
@ -13,12 +14,23 @@ type Path struct {
|
|||
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 {
|
||||
base := path.Base(p)
|
||||
href := path.Join("/notes", p)
|
||||
local := strings.TrimPrefix(p, "/")
|
||||
local = strings.TrimPrefix(p, "notes")
|
||||
local = strings.TrimPrefix(p, "/")
|
||||
href := p
|
||||
local := strings.TrimPrefix(p, "/notes")
|
||||
if len(local) != len(p) {
|
||||
local = strings.TrimPrefix(local, "/")
|
||||
}
|
||||
local = path.Join(config.Root, local)
|
||||
return Path{
|
||||
Base: base,
|
||||
|
|
@ -28,31 +40,36 @@ func NewPath(p string) Path {
|
|||
}
|
||||
|
||||
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 := ""
|
||||
for pa != "/" {
|
||||
base := path.Base(pa)
|
||||
full = fmt.Sprintf(`/<a href=%q>%s</a>`, pa, base) + full
|
||||
pa = path.Dir(pa)
|
||||
for i := range segments {
|
||||
href := "/" + strings.Join(segments[:i], "/") + "/"
|
||||
href += segments[i]
|
||||
href = path.Clean(href)
|
||||
base := segments[i]
|
||||
add := fmt.Sprintf(`/<a href=%q>%s</a>`, href, base)
|
||||
full += add
|
||||
}
|
||||
return full
|
||||
}
|
||||
|
||||
func (p Path) String() string {
|
||||
root := path.Base(config.Root)
|
||||
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 {
|
||||
return fmt.Sprintf(`<li><a href=%q>%s</a></li>`, p.HREF, p.Base)
|
||||
}
|
||||
|
||||
func (p Path) LI() string {
|
||||
content := fmt.Sprintf(`<li><a href="%s">`, path.Join("/notes", p.String()))
|
||||
content += p.base
|
||||
content += "</li>"
|
||||
return content
|
||||
func (p Path) IsDir() bool {
|
||||
stat, err := os.Stat(p.Local)
|
||||
return err == nil && stat.IsDir()
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,23 +1,23 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"testing"
|
||||
)
|
||||
import "testing"
|
||||
|
||||
func TestPathLI(t *testing.T) {
|
||||
p := Path{
|
||||
dir: "a/b/c",
|
||||
base: "d",
|
||||
}
|
||||
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)
|
||||
func TestPathIs(t *testing.T) {
|
||||
p := Path{Local: "/dev/null"}
|
||||
if ok := p.IsDir(); ok {
|
||||
t.Fatal(ok, p)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue