diff --git a/editor.go b/editor.go
new file mode 100644
index 0000000..830171b
--- /dev/null
+++ b/editor.go
@@ -0,0 +1,32 @@
+package main
+
+import (
+ "bytes"
+ "html/template"
+)
+
+type editorJsJson struct {
+ Page string
+ ContentType string
+ Data template.JS
+}
+
+func renderEditor(pageName, inputText, contentType string) (template.HTML, error) {
+ if contentType == "json" {
+ t, err := template.ParseFiles("templates/editorjs.html")
+ if err != nil {
+ return "", err
+ }
+ if inputText == "" {
+ inputText = "null"
+ }
+ data := editorJsJson{Page: pageName, Data: template.JS(inputText), ContentType: contentType}
+ var buf bytes.Buffer
+ err = t.Execute(&buf, data)
+ if err != nil {
+ return "", err
+ }
+ return template.HTML(buf.String()), nil
+ }
+ return "", nil
+}
diff --git a/file.go b/file.go
index fb37752..a66bfd0 100644
--- a/file.go
+++ b/file.go
@@ -3,8 +3,8 @@ package main
import (
"bufio"
"bytes"
+ "encoding/json"
"fmt"
- "github.com/sergi/go-diff/diffmatchpatch"
"html"
"html/template"
"io/ioutil"
@@ -14,6 +14,8 @@ import (
"path/filepath"
"strings"
"time"
+
+ "github.com/sergi/go-diff/diffmatchpatch"
)
type FilePages struct {
@@ -44,7 +46,20 @@ func (fp *FilePages) Save(p string, page Page, summary, author string) error {
return err
}
defer f.Close()
- f.WriteString(strings.Replace(page.Content, "\r\n", "\n", -1))
+ if page.Content[0] == '{' {
+ var buf bytes.Buffer
+ err = json.Indent(&buf, []byte(page.Content), "", " ")
+ if err != nil {
+ return err
+ }
+
+ _, err = buf.WriteTo(f)
+ if err != nil {
+ return err
+ }
+ } else {
+ f.WriteString(strings.Replace(page.Content, "\r\n", "\n", -1))
+ }
return saveWithGit(fp, p, summary, author)
}
diff --git a/main.go b/main.go
index 8da69c1..c10ce17 100644
--- a/main.go
+++ b/main.go
@@ -1,18 +1,20 @@
package main
import (
+ "encoding/json"
"flag"
"fmt"
- "gitlab.com/golang-commonmark/markdown"
"html/template"
"log"
"net/http"
"net/url"
- "p83.nl/go/ekster/pkg/util"
- "p83.nl/go/indieauth"
"regexp"
"strings"
"time"
+
+ "gitlab.com/golang-commonmark/markdown"
+ "p83.nl/go/ekster/pkg/util"
+ "p83.nl/go/indieauth"
)
var (
@@ -71,6 +73,7 @@ type editPage struct {
Title string
Content string
Name string
+ Editor template.HTML
}
type historyPage struct {
@@ -280,7 +283,12 @@ func (h *saveHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
return
}
- r.ParseForm()
+ err = r.ParseForm()
+ if err != nil {
+ http.Error(w, err.Error(), 500)
+ return
+ }
+ isJson := r.PostForm.Get("json") == "1"
page := r.PostForm.Get("p")
summary := r.PostForm.Get("summary")
@@ -289,7 +297,12 @@ func (h *saveHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if err != nil {
log.Println(err)
}
- http.Redirect(w, r, "/"+page, http.StatusFound)
+
+ if isJson {
+ fmt.Print(w, "{}")
+ } else {
+ http.Redirect(w, r, "/"+page, http.StatusFound)
+ }
}
func (h *editHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
@@ -318,10 +331,35 @@ func (h *editHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
pageText := mp.Get(page).Content
+ jsonEditor := pageText[0] == '{'
+
+ var editor template.HTML
+ if jsonEditor {
+ editor, err = renderEditor(page, pageText, "json")
+ if err != nil {
+ http.Error(w, err.Error(), 500)
+ return
+ }
+ } else {
+ editor = `
+
+
+
+
+
+`
+ }
+
data := editPage{
Session: sess,
Title: strings.Replace(page, "_", " ", -1),
Content: pageText,
+ Editor: editor,
Name: page,
}
@@ -362,24 +400,36 @@ func (h *indexHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
return
}
- hrefRE := regexp.MustCompile(`\[\[\s*([\w- ]+)\s*\]\]`)
+ jsonPage := pageText[0] == '{'
+ if jsonPage {
+ pageText, err = renderJSON(pageText)
- pageText = hrefRE.ReplaceAllStringFunc(pageText, func(s string) string {
- s = strings.TrimPrefix(s, "[[")
- s = strings.TrimSuffix(s, "]]")
- s = strings.TrimSpace(s)
- if !mp.Exist(s) {
- // return fmt.Sprintf("%s", s, "edit", s)
- return fmt.Sprintf("%s[?](/%s)", s, strings.Replace(s, " ", "_", -1))
+ if err != nil {
+ http.Error(w, err.Error(), 500)
+ return
}
- return fmt.Sprintf("[%s](/%s)", s, strings.Replace(s, " ", "_", -1))
- })
+ }
- md := markdown.New(
- markdown.HTML(true),
- markdown.XHTMLOutput(true),
- )
- pageText = md.RenderToString([]byte(pageText))
+ if !jsonPage {
+ hrefRE := regexp.MustCompile(`\[\[\s*([\w.\- ]+)\s*\]\]`)
+
+ pageText = hrefRE.ReplaceAllStringFunc(pageText, func(s string) string {
+ s = strings.TrimPrefix(s, "[[")
+ s = strings.TrimSuffix(s, "]]")
+ s = strings.TrimSpace(s)
+ if !mp.Exist(s) {
+ // return fmt.Sprintf("%s", s, "edit", s)
+ return fmt.Sprintf("%s[?](/%s)", s, strings.Replace(s, " ", "_", -1))
+ }
+ return fmt.Sprintf("[%s](/%s)", s, strings.Replace(s, " ", "_", -1))
+ })
+
+ md := markdown.New(
+ markdown.HTML(true),
+ markdown.XHTMLOutput(true),
+ )
+ pageText = md.RenderToString([]byte(pageText))
+ }
data := indexPage{
Session: sess,
@@ -462,6 +512,22 @@ func (h *recentHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
}
}
+type LinkResponseMetaImage struct {
+ Url string `json:"url"`
+}
+
+type LinkResponseMeta struct {
+ Title string `json:"title"`
+ Description string `json:"description"`
+ Image LinkResponseMetaImage `json:"image"`
+}
+
+type LinkResponse struct {
+ Success int `json:"success"`
+ Link string `json:"link"`
+ Meta LinkResponseMeta `json:"meta"`
+}
+
func main() {
var port int
flag.IntVar(&port, "port", 8080, "http port")
@@ -470,7 +536,20 @@ func main() {
mp = NewFilePages("data")
http.Handle("/auth/", &authHandler{})
- http.Handle("/public/", http.StripPrefix("/public/", http.FileServer(http.Dir("ui/node_modules/trix/dist/"))))
+ http.HandleFunc("/fetchLink", func(w http.ResponseWriter, r *http.Request) {
+ link := r.URL.Query().Get("url")
+ u, err := url.Parse(link)
+ if err != nil {
+ http.Error(w, err.Error(), 400)
+ return
+ }
+ var response LinkResponse
+ response.Success = 1
+ response.Link = u.String()
+ response.Meta.Title = "Test"
+ json.NewEncoder(w).Encode(response)
+ })
+ http.Handle("/public/", http.StripPrefix("/public/", http.FileServer(http.Dir("/home/peter/work/editorjs/dist/"))))
http.Handle("/save/", &saveHandler{})
http.Handle("/edit/", &editHandler{})
http.Handle("/history/", &historyHandler{})
diff --git a/render.go b/render.go
new file mode 100644
index 0000000..2f9f185
--- /dev/null
+++ b/render.go
@@ -0,0 +1,171 @@
+package main
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+)
+
+type Block struct {
+ Type string
+ Data json.RawMessage
+}
+
+type Paragraph struct {
+ Text string
+}
+
+type Code struct {
+ Code string
+}
+
+type List struct {
+ Style string
+ Items []string
+}
+
+type Header struct {
+ Level int
+ Text string
+}
+
+type ChecklistItem struct {
+ Text string
+ Checked bool
+}
+
+type Checklist struct {
+ Style string
+ Items []ChecklistItem
+}
+
+type Link struct {
+ Link string
+ Meta LinkResponseMeta
+}
+
+type Table struct {
+ Content [][]string
+}
+
+type Document struct {
+ Time int64
+ Version string
+ Blocks []Block
+}
+
+func renderJSON(text string) (string, error) {
+ var data Document
+ err := json.Unmarshal([]byte(text), &data)
+ if err != nil {
+ return "", err
+ }
+
+ var buf bytes.Buffer
+
+ for _, block := range data.Blocks {
+ switch block.Type {
+ case "table":
+ var table Table
+ err = json.Unmarshal(block.Data, &table)
+ if err != nil {
+ return "", fmt.Errorf("error while parsing %s: %s", block.Type, err.Error())
+ }
+
+ buf.WriteString("")
+ for _, row := range table.Content {
+ buf.WriteString("")
+ for _, col := range row {
+ buf.WriteString("")
+ buf.WriteString(col)
+ buf.WriteString(" | ")
+ }
+ buf.WriteString("
")
+ }
+ buf.WriteString("
")
+ break
+ case "link":
+ // TODO(peter): improve link rendering
+ var link Link
+ err = json.Unmarshal(block.Data, &link)
+ if err != nil {
+ return "", fmt.Errorf("error while parsing %s: %s", block.Type, err.Error())
+ }
+ fmt.Fprintf(&buf, `%s`, link.Link, link.Meta.Title)
+ case "list":
+ var list List
+ err = json.Unmarshal(block.Data, &list)
+ if err != nil {
+ return "", fmt.Errorf("error while parsing %s: %s", block.Type, err.Error())
+ }
+ var tag string
+ if list.Style == "ordered" {
+ tag = "ol"
+ } else {
+ tag = "ul"
+ }
+ buf.WriteString("<")
+ buf.WriteString(tag)
+ buf.WriteString(">")
+ for _, item := range list.Items {
+ buf.WriteString("")
+ buf.WriteString(item)
+ buf.WriteString("")
+ }
+ buf.WriteString("")
+ buf.WriteString(tag)
+ buf.WriteString(">")
+ case "header":
+ var header Header
+ err = json.Unmarshal(block.Data, &header)
+ if err != nil {
+ return "", fmt.Errorf("error while parsing %s: %s", block.Type, err.Error())
+ }
+ fmt.Fprintf(&buf, "%s", header.Level, header.Text, header.Level)
+ case "paragraph":
+ var para Paragraph
+ err = json.Unmarshal(block.Data, ¶)
+ if err != nil {
+ return "", fmt.Errorf("error while parsing %s: %s", block.Type, err.Error())
+ }
+ buf.WriteString("")
+ buf.WriteString(para.Text)
+ buf.WriteString("
")
+ case "code":
+ var code Code
+ err = json.Unmarshal(block.Data, &code)
+ if err != nil {
+ return "", fmt.Errorf("error while parsing %s: %s", block.Type, err.Error())
+ }
+ buf.WriteString("")
+ buf.WriteString(code.Code)
+ buf.WriteString("
")
+ case "checklist":
+ var checklist Checklist
+ err = json.Unmarshal(block.Data, &checklist)
+ if err != nil {
+ return "", fmt.Errorf("error while parsing %s: %s", block.Type, err.Error())
+ }
+ for _, item := range checklist.Items {
+ buf.WriteString("")
+
+ buf.WriteString(``)
+ if item.Checked {
+ buf.WriteString(` `)
+ buf.WriteString(` `)
+ buf.WriteString(` `)
+ buf.WriteString(` `)
+ }
+ buf.WriteString(``)
+ buf.WriteString(item.Text)
+ buf.WriteString("
")
+ }
+ default:
+ return "", fmt.Errorf("unknown type: %s", block.Type)
+ }
+
+ fmt.Fprintln(&buf)
+ }
+
+ return buf.String(), nil
+}
diff --git a/templates/edit.html b/templates/edit.html
index 7aea027..877e7b1 100644
--- a/templates/edit.html
+++ b/templates/edit.html
@@ -2,18 +2,12 @@
{{ .Title }}
{{ end }}
{{ define "content_head" }}
{{ end }}
+
+{{ define "footer_scripts" }}
+{{ end }}
diff --git a/templates/editorjs.html b/templates/editorjs.html
new file mode 100644
index 0000000..39f1a01
--- /dev/null
+++ b/templates/editorjs.html
@@ -0,0 +1,2 @@
+
+
diff --git a/templates/layout.html b/templates/layout.html
index f7dd4dd..01344b6 100644
--- a/templates/layout.html
+++ b/templates/layout.html
@@ -6,6 +6,7 @@
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
+
{{ .Title }} - Wiki
{{ block "content_head" . }} {{ end }}