diff --git a/.gitignore b/.gitignore
index adf8f72..3207fee 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,6 @@
+.DS_Store
+*.txt
+
# ---> Go
# If you prefer the allow list template instead of the deny list, see community template:
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
diff --git a/edit.html b/edit.html
new file mode 100644
index 0000000..c30e8a9
--- /dev/null
+++ b/edit.html
@@ -0,0 +1,5 @@
+
Editing {{.Title}}
+
\ No newline at end of file
diff --git a/go.mod b/go.mod
new file mode 100644
index 0000000..56ffbaf
--- /dev/null
+++ b/go.mod
@@ -0,0 +1,3 @@
+module gitea.paas.celticinfo.fr/oabrivard/gowiki
+
+go 1.20
diff --git a/gowiki.go b/gowiki.go
new file mode 100644
index 0000000..a172b5e
--- /dev/null
+++ b/gowiki.go
@@ -0,0 +1,95 @@
+package main
+
+import (
+ "html/template"
+ "log"
+ "net/http"
+ "os"
+ "regexp"
+)
+
+var templates = template.Must(template.ParseFiles("edit.html", "view.html"))
+var validPath = regexp.MustCompile("^/(edit|save|view)/([a-zA-Z0-9]+)$")
+
+type Page struct {
+ Title string
+ Body []byte
+}
+
+func (p *Page) Save() error {
+ filename := p.Title + ".txt"
+ return os.WriteFile(filename, p.Body, 0600)
+}
+
+func loadPage(title string) (*Page, error) {
+ filename := title + ".txt"
+ body, err := os.ReadFile(filename)
+ if err != nil {
+ return nil, err
+ }
+ return &Page{Title: title, Body: body}, nil
+}
+
+func renderTemplate(w http.ResponseWriter, tmpl string, p *Page) {
+ err := templates.ExecuteTemplate(w, tmpl+".html", p)
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ }
+}
+
+func viewHandler(w http.ResponseWriter, r *http.Request, title string) {
+ p, err := loadPage(title)
+ if err != nil {
+ http.Redirect(w, r, "/edit/"+title, http.StatusFound)
+ return
+ }
+ renderTemplate(w, "view", p)
+}
+
+func editHandler(w http.ResponseWriter, r *http.Request, title string) {
+ p, err := loadPage(title)
+ if err != nil {
+ p = &Page{Title: title}
+ }
+ renderTemplate(w, "edit", p)
+}
+
+func saveHandler(w http.ResponseWriter, r *http.Request, title string) {
+ body := r.FormValue("body")
+ p := &Page{Title: title, Body: []byte(body)}
+ if err := p.Save(); err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+ http.Redirect(w, r, "/view/"+title, http.StatusFound)
+}
+
+func makeHandler(fn func(http.ResponseWriter, *http.Request, string)) http.HandlerFunc {
+ return func(w http.ResponseWriter, r *http.Request) {
+ m := validPath.FindStringSubmatch(r.URL.Path)
+ if m == nil {
+ http.NotFound(w, r)
+ return
+ }
+ fn(w, r, m[2])
+ }
+}
+
+func main() {
+ http.HandleFunc("/view/", makeHandler(viewHandler))
+ http.HandleFunc("/edit/", makeHandler(editHandler))
+ http.HandleFunc("/save/", makeHandler(saveHandler))
+
+ log.Fatal((http.ListenAndServe(":8080", nil)))
+ // p1 := &Page{"oli", []byte("Abreuvoir")}
+ // if err := p1.Save(); err != nil {
+ // log.Fatal(err)
+ // }
+
+ // p2, err := loadPage("oli")
+ // if err != nil {
+ // log.Fatal(err)
+ // }
+
+ // fmt.Println(string(p2.Body))
+}
diff --git a/view.html b/view.html
new file mode 100644
index 0000000..98a63e8
--- /dev/null
+++ b/view.html
@@ -0,0 +1,3 @@
+{{.Title}}
+[edit]
+{{printf "%s" .Body}}