2019-12-13 08:57:01 +01:00
|
|
|
|
package main
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"bufio"
|
|
|
|
|
"encoding/json"
|
|
|
|
|
"fmt"
|
|
|
|
|
"html/template"
|
|
|
|
|
"io/ioutil"
|
|
|
|
|
"log"
|
|
|
|
|
"net/http"
|
|
|
|
|
"os"
|
|
|
|
|
"path"
|
|
|
|
|
"path/filepath"
|
|
|
|
|
"strings"
|
2019-12-13 12:30:55 +01:00
|
|
|
|
"time"
|
2019-12-13 08:57:01 +01:00
|
|
|
|
|
2019-12-17 16:52:54 +01:00
|
|
|
|
"github.com/blevesearch/bleve"
|
2019-12-24 13:37:28 +01:00
|
|
|
|
"github.com/blevesearch/bleve/search/highlight/highlighter/html"
|
2019-12-13 08:57:01 +01:00
|
|
|
|
"github.com/gorilla/mux"
|
2019-12-13 17:19:13 +01:00
|
|
|
|
"github.com/mandolyte/mdtopdf"
|
2019-12-13 12:30:55 +01:00
|
|
|
|
"gopkg.in/src-d/go-git.v4"
|
|
|
|
|
"gopkg.in/src-d/go-git.v4/plumbing/object"
|
2019-12-13 08:57:01 +01:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
var config = readConfig("")
|
|
|
|
|
|
|
|
|
|
type Configuration struct {
|
2019-12-17 16:52:54 +01:00
|
|
|
|
Host string
|
|
|
|
|
Port string
|
|
|
|
|
DataPath string
|
|
|
|
|
DataPathFTS string
|
2019-12-13 08:57:01 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// our main function
|
|
|
|
|
func main() {
|
|
|
|
|
|
|
|
|
|
// Ausgeben der Config-Optionen
|
|
|
|
|
fmt.Println("Host: " + config.Host)
|
|
|
|
|
fmt.Println("Post: " + config.Port)
|
|
|
|
|
fmt.Println("DataPath: " + config.DataPath)
|
2019-12-17 16:52:54 +01:00
|
|
|
|
fmt.Println("DataPathFTS: " + config.DataPathFTS)
|
2019-12-13 08:57:01 +01:00
|
|
|
|
|
|
|
|
|
// DataPath-Verzeichnis anlegen, wenn es noch nicht existiert
|
|
|
|
|
if !directoryExists(config.DataPath) {
|
|
|
|
|
os.MkdirAll(config.DataPath, os.ModePerm)
|
|
|
|
|
|
|
|
|
|
// Default Seiten anlegen
|
|
|
|
|
bStartmd, _ := Asset("web/pages/start.md")
|
|
|
|
|
bHilfemd, _ := Asset("web/pages/hilfe.md")
|
|
|
|
|
bPlaygroundmd, _ := Asset("web/pages/playground.md")
|
|
|
|
|
bSidebarmd, _ := Asset("web/pages/sidebar.md")
|
|
|
|
|
|
|
|
|
|
err := ioutil.WriteFile(path.Join(config.DataPath, "start.md"), bStartmd, 0644)
|
|
|
|
|
check(err)
|
|
|
|
|
err = ioutil.WriteFile(path.Join(config.DataPath, "sidebar.md"), bSidebarmd, 0644)
|
|
|
|
|
check(err)
|
|
|
|
|
err = ioutil.WriteFile(path.Join(config.DataPath, "hilfe.md"), bHilfemd, 0644)
|
|
|
|
|
check(err)
|
|
|
|
|
err = ioutil.WriteFile(path.Join(config.DataPath, "playground.md"), bPlaygroundmd, 0644)
|
|
|
|
|
check(err)
|
|
|
|
|
}
|
|
|
|
|
|
2019-12-13 12:30:55 +01:00
|
|
|
|
// Git Repository Init
|
|
|
|
|
if !directoryExists(path.Join(config.DataPath, ".git")) {
|
|
|
|
|
|
|
|
|
|
_, err := git.PlainInit(config.DataPath, false)
|
|
|
|
|
check(err)
|
|
|
|
|
GitCommit("Initial Wiki Commit")
|
|
|
|
|
}
|
|
|
|
|
|
2019-12-17 16:52:54 +01:00
|
|
|
|
// Volltextsuche
|
|
|
|
|
if config.DataPathFTS != "" {
|
|
|
|
|
if strings.HasPrefix(config.DataPathFTS, config.DataPath) {
|
|
|
|
|
fmt.Println("FTS disabled (Please don´t put the DataPathFTS inside the DataPath)")
|
|
|
|
|
} else {
|
|
|
|
|
fmt.Println("FTS enabled")
|
|
|
|
|
if !directoryExists(config.DataPathFTS) {
|
|
|
|
|
fmt.Println("Create new FTS Data in " + config.DataPathFTS)
|
|
|
|
|
mapping := bleve.NewIndexMapping()
|
|
|
|
|
|
|
|
|
|
index, err := bleve.New(config.DataPathFTS, mapping)
|
|
|
|
|
check(err)
|
|
|
|
|
|
|
|
|
|
filepath.Walk(config.DataPath, func(filepath string, info os.FileInfo, err error) error {
|
|
|
|
|
tmpPath := strings.Replace(filepath, "\\", "/", -1)
|
|
|
|
|
tmpPath = strings.Replace(tmpPath, "data/", "", -1)
|
|
|
|
|
|
|
|
|
|
if !info.IsDir() && !strings.HasPrefix(tmpPath, ".git") {
|
|
|
|
|
b, err := ioutil.ReadFile(path.Join(config.DataPath, tmpPath))
|
|
|
|
|
check(err)
|
2019-12-24 13:37:28 +01:00
|
|
|
|
|
|
|
|
|
indexData := struct {
|
|
|
|
|
Text string
|
|
|
|
|
}{
|
|
|
|
|
string(b),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
err = index.Index(tmpPath, indexData)
|
2019-12-17 16:52:54 +01:00
|
|
|
|
check(err)
|
|
|
|
|
fmt.Println("Indexed: " + info.Name())
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
index.Close()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-12-24 13:37:28 +01:00
|
|
|
|
/*
|
|
|
|
|
repo, err := git.PlainOpen(config.DataPath)
|
|
|
|
|
check(err)
|
|
|
|
|
|
|
|
|
|
ref, err := repo.Head()
|
|
|
|
|
check(err)
|
|
|
|
|
|
|
|
|
|
// ... retrieves the commit history
|
|
|
|
|
//since := time.Date(2019, 1, 1, 0, 0, 0, 0, time.UTC)
|
|
|
|
|
//until := time.Date(2019, 7, 30, 0, 0, 0, 0, time.UTC)
|
|
|
|
|
var filename = "playground.md"
|
|
|
|
|
cIter, err := repo.Log(&git.LogOptions{From: ref.Hash(), FileName: &filename}) //, Since: &since, Until: &until})
|
|
|
|
|
check(err)
|
|
|
|
|
|
|
|
|
|
// ... just iterates over the commits, printing it
|
|
|
|
|
err = cIter.ForEach(func(c *object.Commit) error {
|
|
|
|
|
fmt.Println(c.Files())
|
|
|
|
|
fmt.Println(c.Committer.When)
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
})
|
|
|
|
|
*/
|
|
|
|
|
|
2019-12-13 08:57:01 +01:00
|
|
|
|
router := mux.NewRouter()
|
2019-12-13 17:19:13 +01:00
|
|
|
|
router.HandleFunc("/_api/md/{pagename:.*}", getRawPage).Methods("GET")
|
|
|
|
|
router.HandleFunc("/_api/pdf/{pagename:.*}", getPDFPage).Methods("GET")
|
2019-12-20 12:55:43 +01:00
|
|
|
|
router.HandleFunc("/_api/pinfo/{pagename:.*}", getPageInfo).Methods("GET")
|
2019-12-17 16:52:54 +01:00
|
|
|
|
router.HandleFunc("/_api/fts/{searchterm:.*}", getFTS).Methods("GET")
|
2019-12-13 08:57:01 +01:00
|
|
|
|
router.HandleFunc("/{pagename:.*}", getHTMLPage).Methods("GET")
|
|
|
|
|
router.HandleFunc("/{pagename:.*}", postHTMLPage).Methods("POST")
|
|
|
|
|
|
|
|
|
|
log.Fatal(http.ListenAndServe(":"+config.Port, router))
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2019-12-13 17:19:13 +01:00
|
|
|
|
func getPDFPage(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
|
|
|
|
|
params := mux.Vars(r)
|
|
|
|
|
pPageName := params["pagename"] + ".md"
|
|
|
|
|
// Hack für anzeige der start.md wenn / aufgerufen wird
|
|
|
|
|
if pPageName == ".md" {
|
|
|
|
|
pPageName = "start.md"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
content, err := ioutil.ReadFile(path.Join(config.DataPath, pPageName))
|
|
|
|
|
check(err)
|
|
|
|
|
pdfRender := mdtopdf.NewPdfRenderer("", "", "./tmp.pdf", "")
|
|
|
|
|
// get the unicode translator
|
|
|
|
|
tr := pdfRender.Pdf.UnicodeTranslatorFromDescriptor("cp1252")
|
|
|
|
|
|
|
|
|
|
pdfRender.Normal = mdtopdf.Styler{Font: "Arial", Style: "",
|
|
|
|
|
Size: 8, Spacing: 1,
|
|
|
|
|
TextColor: mdtopdf.Color{0, 0, 0},
|
|
|
|
|
FillColor: mdtopdf.Color{255, 255, 255}}
|
|
|
|
|
|
|
|
|
|
err = pdfRender.Process([]byte(tr(string(content))))
|
|
|
|
|
check(err)
|
|
|
|
|
|
|
|
|
|
pdfcontent, err := ioutil.ReadFile("./tmp.pdf")
|
|
|
|
|
check(err)
|
|
|
|
|
w.Header().Set("Content-Type", "application/pdf")
|
|
|
|
|
w.Write(pdfcontent)
|
|
|
|
|
}
|
|
|
|
|
|
2019-12-13 08:57:01 +01:00
|
|
|
|
func getHTMLPage(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
|
|
|
|
|
params := mux.Vars(r)
|
|
|
|
|
|
|
|
|
|
if strings.HasSuffix(params["pagename"], ".css") {
|
|
|
|
|
//fmt.Println("CSS: " + params["pagename"])
|
|
|
|
|
b, _ := Asset("web/" + params["pagename"])
|
|
|
|
|
w.Header().Set("Content-Type", "text/css")
|
|
|
|
|
w.Write(b)
|
|
|
|
|
} else if strings.HasSuffix(params["pagename"], ".js") {
|
|
|
|
|
//fmt.Println("JS: " + params["pagename"])
|
|
|
|
|
b, _ := Asset("web/" + params["pagename"])
|
|
|
|
|
w.Header().Set("Content-Type", "application/javascript")
|
|
|
|
|
w.Write(b)
|
|
|
|
|
} else {
|
|
|
|
|
// Directory Listing für die Sidebar
|
|
|
|
|
sidebarAusgabe := " \r\n \r\n**Inhaltsverzeichnis** \r\n\r\n"
|
|
|
|
|
filepath.Walk(config.DataPath, func(path string, info os.FileInfo, err error) error {
|
|
|
|
|
|
|
|
|
|
tmpPath := strings.Replace(path, "\\", "/", -1)
|
|
|
|
|
tmpPath = strings.Replace(tmpPath, "data", "", -1)
|
|
|
|
|
tmpPathSplit := strings.Split(tmpPath, "/")
|
|
|
|
|
|
|
|
|
|
sidebarTABs := ""
|
|
|
|
|
for i, _ := range tmpPathSplit {
|
|
|
|
|
//fmt.Println(i, " => ", string(c))
|
|
|
|
|
if i > 1 {
|
|
|
|
|
sidebarTABs = sidebarTABs + " "
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-12-13 12:30:55 +01:00
|
|
|
|
if info.Name() != "data" && !strings.HasPrefix(tmpPath, "/.git") && info.Name() != "start.md" && info.Name() != "sidebar.md" && info.Name() != "hilfe.md" {
|
2019-12-13 08:57:01 +01:00
|
|
|
|
if !strings.HasSuffix(info.Name(), ".md") {
|
|
|
|
|
sidebarAusgabe = sidebarAusgabe + sidebarTABs + "* [" + strings.TrimSuffix(info.Name(), ".md") + "](" + strings.TrimSuffix(tmpPath, ".md") + "/start) \r\n"
|
|
|
|
|
} else {
|
|
|
|
|
sidebarAusgabe = sidebarAusgabe + sidebarTABs + "* [" + strings.TrimSuffix(info.Name(), ".md") + "](" + strings.TrimSuffix(tmpPath, ".md") + ") \r\n"
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
//tmpl := template.Must(template.ParseFiles("./web/index.html"))
|
|
|
|
|
bTmpl, _ := Asset("web/index.html")
|
|
|
|
|
tmpl := template.Must(template.New("tml").Parse(string(bTmpl)))
|
|
|
|
|
data := MarkDownData{
|
|
|
|
|
PageTitle: " ",
|
|
|
|
|
MDText: "",
|
|
|
|
|
SideBar: sidebarAusgabe,
|
|
|
|
|
}
|
|
|
|
|
tmpl.Execute(w, data)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func getRawPage(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
|
|
|
|
|
params := mux.Vars(r)
|
|
|
|
|
pPageName := params["pagename"] + ".md"
|
|
|
|
|
// Hack für anzeige der start.md wenn / aufgerufen wird
|
|
|
|
|
if pPageName == ".md" {
|
|
|
|
|
pPageName = "start.md"
|
|
|
|
|
}
|
|
|
|
|
pageContent := "Empty"
|
|
|
|
|
|
|
|
|
|
//fmt.Println(path.Join(config.DataPath, pPageName))
|
|
|
|
|
b, err := ioutil.ReadFile(path.Join(config.DataPath, pPageName))
|
|
|
|
|
check(err)
|
|
|
|
|
|
|
|
|
|
pageContent = string(b)
|
|
|
|
|
|
|
|
|
|
json.NewEncoder(w).Encode(pageContent)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func postHTMLPage(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
|
|
|
|
|
params := mux.Vars(r)
|
|
|
|
|
pPageName := params["pagename"] + ".md"
|
|
|
|
|
|
|
|
|
|
// Verzeichnis erstellen
|
|
|
|
|
dir := path.Dir(pPageName)
|
|
|
|
|
if !directoryExists(path.Join(config.DataPath, dir)) {
|
|
|
|
|
os.MkdirAll(path.Join(config.DataPath, dir), os.ModePerm)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//{ "MDText":"**test3**" }
|
|
|
|
|
var oBody TPostBody
|
|
|
|
|
json.NewDecoder(r.Body).Decode(&oBody)
|
|
|
|
|
//fmt.Println(oBody)
|
|
|
|
|
|
|
|
|
|
f, err := os.Create(path.Join(config.DataPath, pPageName))
|
|
|
|
|
check(err)
|
|
|
|
|
defer f.Close()
|
|
|
|
|
fw := bufio.NewWriter(f)
|
|
|
|
|
_, err = fw.WriteString(oBody.MDText)
|
|
|
|
|
check(err)
|
|
|
|
|
fw.Flush()
|
|
|
|
|
|
2019-12-13 12:30:55 +01:00
|
|
|
|
// Git Commit
|
|
|
|
|
GitCommit("Auto-Commit Page: " + pPageName)
|
2019-12-17 16:52:54 +01:00
|
|
|
|
// FTS Index
|
|
|
|
|
BleveIndex(pPageName)
|
2019-12-13 12:30:55 +01:00
|
|
|
|
|
2019-12-13 08:57:01 +01:00
|
|
|
|
json.NewEncoder(w).Encode("OK")
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2019-12-17 16:52:54 +01:00
|
|
|
|
func getFTS(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
|
|
|
|
|
params := mux.Vars(r)
|
|
|
|
|
pSearchterm := params["searchterm"]
|
|
|
|
|
|
|
|
|
|
if config.DataPathFTS != "" {
|
|
|
|
|
if directoryExists(config.DataPathFTS) {
|
|
|
|
|
|
|
|
|
|
index, err := bleve.Open(config.DataPathFTS)
|
|
|
|
|
check(err)
|
|
|
|
|
|
|
|
|
|
query := bleve.NewQueryStringQuery(pSearchterm)
|
|
|
|
|
search := bleve.NewSearchRequest(query)
|
2019-12-24 13:37:28 +01:00
|
|
|
|
search.Highlight = bleve.NewHighlightWithStyle(html.Name)
|
2019-12-17 16:52:54 +01:00
|
|
|
|
search.Size = 30
|
|
|
|
|
searchResults, err := index.Search(search)
|
|
|
|
|
index.Close()
|
|
|
|
|
|
|
|
|
|
//fmt.Println("SR: " + searchResults.String())
|
|
|
|
|
json.NewEncoder(w).Encode(searchResults.Hits)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-12-20 12:55:43 +01:00
|
|
|
|
func getPageInfo(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
|
|
|
|
|
params := mux.Vars(r)
|
|
|
|
|
pPageName := params["pagename"] + ".md"
|
|
|
|
|
|
|
|
|
|
f, err := os.Open(path.Join(config.DataPath, pPageName))
|
|
|
|
|
check(err)
|
|
|
|
|
statinfo, err := f.Stat()
|
|
|
|
|
check(err)
|
|
|
|
|
|
|
|
|
|
data := struct {
|
|
|
|
|
PageName string
|
|
|
|
|
ModTime time.Time
|
|
|
|
|
}{
|
|
|
|
|
pPageName,
|
|
|
|
|
statinfo.ModTime(),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
json.NewEncoder(w).Encode(data)
|
|
|
|
|
}
|
|
|
|
|
|
2019-12-13 08:57:01 +01:00
|
|
|
|
//--------------------------------------------------------------------------
|
|
|
|
|
// Typen
|
|
|
|
|
//--------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
type MarkDownData struct {
|
|
|
|
|
PageTitle string
|
|
|
|
|
MDText string
|
|
|
|
|
SideBar string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type TPostBody struct {
|
|
|
|
|
MDText string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------
|
|
|
|
|
// Hilfsfunktionen
|
|
|
|
|
//--------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
func check(e error) {
|
|
|
|
|
if e != nil {
|
|
|
|
|
fmt.Println(e)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func fileExists(filename string) bool {
|
|
|
|
|
info, err := os.Stat(filename)
|
|
|
|
|
if os.IsNotExist(err) {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
return !info.IsDir()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func directoryExists(filename string) bool {
|
|
|
|
|
info, err := os.Stat(filename)
|
|
|
|
|
if os.IsNotExist(err) {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
return info.IsDir()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func readConfig(filename string) *Configuration {
|
|
|
|
|
// initialize conf with default values.
|
2019-12-17 16:52:54 +01:00
|
|
|
|
conf := &Configuration{Host: "http://127.0.0.1", Port: "8000", DataPath: "./data", DataPathFTS: ""}
|
2019-12-13 08:57:01 +01:00
|
|
|
|
|
|
|
|
|
b, err := ioutil.ReadFile("./config.json")
|
|
|
|
|
if err != nil {
|
|
|
|
|
return conf
|
|
|
|
|
}
|
|
|
|
|
if err = json.Unmarshal(b, conf); err != nil {
|
|
|
|
|
return conf
|
|
|
|
|
}
|
|
|
|
|
return conf
|
|
|
|
|
}
|
2019-12-13 12:30:55 +01:00
|
|
|
|
|
|
|
|
|
func GitCommit(CommitText string) {
|
|
|
|
|
|
|
|
|
|
// Git Repo öffnen
|
|
|
|
|
repo, err := git.PlainOpen(config.DataPath)
|
|
|
|
|
check(err)
|
|
|
|
|
|
|
|
|
|
// Working Tree setzen
|
|
|
|
|
wt, err := repo.Worktree()
|
|
|
|
|
check(err)
|
|
|
|
|
|
|
|
|
|
// Alle Dateien zum Working Tree hinzufügen
|
|
|
|
|
_, err = wt.Add(".")
|
|
|
|
|
check(err)
|
|
|
|
|
|
|
|
|
|
// Status ausgeben
|
|
|
|
|
//status, err := wt.Status()
|
|
|
|
|
//check(err)
|
|
|
|
|
//fmt.Println(status)
|
|
|
|
|
|
|
|
|
|
// Neuen Commit Erstellen
|
|
|
|
|
_, err = wt.Commit(CommitText, &git.CommitOptions{
|
|
|
|
|
Author: &object.Signature{
|
|
|
|
|
Name: "GoWiki",
|
|
|
|
|
Email: "gowiki@local.org",
|
|
|
|
|
When: time.Now(),
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
check(err)
|
|
|
|
|
|
|
|
|
|
// Commit infos anzeigen
|
|
|
|
|
//obj, err := repo.CommitObject(commit)
|
|
|
|
|
//check(err)
|
|
|
|
|
//fmt.Println(obj)
|
|
|
|
|
}
|
2019-12-17 16:52:54 +01:00
|
|
|
|
|
|
|
|
|
func BleveIndex(PageName string) {
|
|
|
|
|
if config.DataPathFTS != "" {
|
|
|
|
|
if directoryExists(config.DataPathFTS) {
|
|
|
|
|
|
|
|
|
|
index, err := bleve.Open(config.DataPathFTS)
|
|
|
|
|
check(err)
|
|
|
|
|
|
|
|
|
|
b, err := ioutil.ReadFile(path.Join(config.DataPath, PageName))
|
|
|
|
|
check(err)
|
2019-12-24 13:37:28 +01:00
|
|
|
|
|
|
|
|
|
indexData := struct {
|
|
|
|
|
Text string
|
|
|
|
|
}{
|
|
|
|
|
string(b),
|
|
|
|
|
}
|
|
|
|
|
err = index.Index(PageName, indexData)
|
2019-12-17 16:52:54 +01:00
|
|
|
|
check(err)
|
|
|
|
|
index.Close()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|