commit 89870243554569fb99fa0cdf59ed8d923214217a
parent 921013e4a47a87afebb7a9af7e85a88d5fbfa056
Author: weetat <wtenison@protonmail.com>
Date: Thu, 27 Feb 2025 23:51:01 +0000
Add preview page for rendering editor input
The edit form posts to /preview, which renders the submitted fmd. The
interpreter also drops any word containing a <script> tag.
Diffstat:
6 files changed, 138 insertions(+), 20 deletions(-)
diff --git a/src/fmd/fmd.go b/src/fmd/fmd.go
@@ -7,6 +7,19 @@ import (
"path/filepath"
)
+func ReadFMDStreamtoHTMLString(inputStreamFMD []byte) string {
+
+ _l := MakeLexer(inputStreamFMD)
+
+ _tokens := _l.Exec()
+
+ _p := MakeParser(_tokens)
+
+ _ast := _p.Exec()
+
+ return interpret(_ast)
+}
+
func WriteFMDToHTMLFile(inputFilePath string, outputFilePath string) {
_fileName := filepath.Base(inputFilePath)
if filepath.Ext(_fileName) != ".fmd" {
diff --git a/src/fmd/interpreter.go b/src/fmd/interpreter.go
@@ -55,6 +55,10 @@ func interpret(n node) string {
case nodeSpace:
return n.value
case nodeLiteral:
+ if strings.Contains(n.value, "<script>") || strings.Contains(n.value, "</script>") {
+ return ""
+ }
+
return n.value
}
return _res.String()
diff --git a/src/network/routes.go b/src/network/routes.go
@@ -1,6 +1,7 @@
package network
import (
+ "bytes"
"log"
"net/http"
"net/url"
@@ -11,6 +12,8 @@ import (
"miki/src/fmd"
)
+// TODO: There is a lot of duplicate functionality here. Simplify/consolidate.
+
var mux *http.ServeMux
func makeServerRoutes() {
@@ -26,6 +29,7 @@ func makeServerRoutes() {
mux.HandleFunc("/home", handlePageHome)
mux.HandleFunc("/subject", handlePageSubject)
mux.HandleFunc("/edit", handlePageEdit)
+ mux.HandleFunc("/preview", handlePagePreview)
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/" {
@@ -42,7 +46,7 @@ func handlePageHome(w http.ResponseWriter, r *http.Request) {
// Collect HTML template files from directory.
_rPkg, _err := mfs.MakeDirectoryPkg(filepath.Join(mfs.Dirs["web"], r.URL.String()), mfs.SEARCH_DEPTH_ZERO, "*.html")
if _err != nil {
- log.Printf("_ERROR:network:handlePage(\"/subject\"):%s", _err)
+ log.Printf("_ERROR:network:handlePage(\"/home\"):%s", _err)
http.NotFound(w, r)
return
}
@@ -65,12 +69,12 @@ func handlePageHome(w http.ResponseWriter, r *http.Request) {
// Render template.
if _err = _tmpl.ExecuteTemplate(w, "index.html", _templateDataContainer); _err != nil {
- log.Printf("_ERROR:network:handlePageDefault(\"/\"):%s", _err)
- http.Error(w, "_ERROR:network:handlePageDefault(\"/\"):template.ExecuteTemplate", http.StatusInternalServerError)
+ log.Printf("_ERROR:network:handlePage(\"/home\"):%s", _err)
+ http.Error(w, "_ERROR:network:handlePage(\"/home\"):template.ExecuteTemplate", http.StatusInternalServerError)
return
}
- log.Printf("DONE\thandlePageDefault:%s", r.URL)
+ log.Printf("DONE\thandlePage:%s", r.URL)
}
func handlePageSubject(w http.ResponseWriter, r *http.Request) {
@@ -122,12 +126,12 @@ func handlePageSubject(w http.ResponseWriter, r *http.Request) {
// Render template.
if _err = _tmpl.ExecuteTemplate(w, "index.html", _templateDataContainer); _err != nil {
- log.Printf("_ERROR:network:handlePageDefault(\"/\"):%s", _err)
- http.Error(w, "_ERROR:network:handlePageDefault(\"/\"):template.ExecuteTemplate", http.StatusInternalServerError)
+ log.Printf("_ERROR:network:handlePage(\"/subject\"):%s", _err)
+ http.Error(w, "_ERROR:network:handlePage(\"/subject\"):template.ExecuteTemplate", http.StatusInternalServerError)
return
}
- log.Printf("DONE\thandlePageDefault:%s", r.URL)
+ log.Printf("DONE\thandlePage:%s", r.URL)
}
func handlePageEdit(w http.ResponseWriter, r *http.Request) {
@@ -135,7 +139,7 @@ func handlePageEdit(w http.ResponseWriter, r *http.Request) {
// Collect HTML template files from directory.
_rPkg, _err := mfs.MakeDirectoryPkg(filepath.Join(mfs.Dirs["web"], r.URL.Path), mfs.SEARCH_DEPTH_ZERO, "*.html")
if _err != nil {
- log.Printf("_ERROR:network:handlePageDefault(\"/\"):%s", _err)
+ log.Printf("_ERROR:network:handlePage(\"/edit\"):%s", _err)
http.NotFound(w, r)
return
}
@@ -146,15 +150,15 @@ func handlePageEdit(w http.ResponseWriter, r *http.Request) {
// Get file name from URL
_urlContent, _err := url.Parse(r.URL.String())
if _err != nil {
- log.Printf("_ERROR:network:handlePage(\"/subject\"):%s", _err)
- http.Error(w, "_ERROR:network:handlePage(\"/subject\"):url.Parse", http.StatusInternalServerError)
+ log.Printf("_ERROR:network:handle(\"/edit\"):%s", _err)
+ http.Error(w, "_ERROR:network:handlePage(\"/edit\"):url.Parse", http.StatusInternalServerError)
}
// Parse URL for query parameters.
_urlQuerySubject, _err := url.ParseQuery(_urlContent.RawQuery)
if _err != nil {
- log.Printf("_ERROR:network:handlePage(\"/subject\"):%s", _err)
- http.Error(w, "_ERROR:network:handlePage(\"/subject\"):url.ParseQuery", http.StatusInternalServerError)
+ log.Printf("_ERROR:network:handlePage(\"/edit\"):%s", _err)
+ http.Error(w, "_ERROR:network:handlePage(\"/edit\"):url.ParseQuery", http.StatusInternalServerError)
}
_fileName := _urlQuerySubject.Get("s")
@@ -170,17 +174,67 @@ func handlePageEdit(w http.ResponseWriter, r *http.Request) {
// Create template from package.
_tmpl, _err := template.ParseFiles(_rPkg.DependencyFiles...)
if _err != nil {
- log.Printf("_ERROR:network:handlePageDefault(\"/\"):%s", _err)
- http.Error(w, "_ERROR:network:handlePageDefault(\"/\"):template.ParseFiles", http.StatusInternalServerError)
+ log.Printf("_ERROR:network:handlePage(\"/edit\"):%s", _err)
+ http.Error(w, "_ERROR:network:handlePage(\"/edit\"):template.ParseFiles", http.StatusInternalServerError)
+ return
+ }
+
+ // Render template.
+ if _err = _tmpl.ExecuteTemplate(w, "index.html", _templateDataContainer); _err != nil {
+ log.Printf("_ERROR:network:handlePage(\"/edit\"):%s", _err)
+ http.Error(w, "_ERROR:network:handlePage(\"/edit\"):template.ExecuteTemplate", http.StatusInternalServerError)
return
}
+ log.Printf("DONE\thandlePage:%s", r.URL)
+}
+
+func handlePagePreview(w http.ResponseWriter, r *http.Request) {
+
+ // Collect HTML template files from directory.
+ _rPkg, _err := mfs.MakeDirectoryPkg(filepath.Join(mfs.Dirs["web"], r.URL.Path), mfs.SEARCH_DEPTH_ZERO, "*.html")
+ if _err != nil {
+ log.Printf("_ERROR:network:handlePage(\"/preview\"):%s", _err)
+ http.NotFound(w, r)
+ return
+ }
+
+ // Add 'global' file dependencies.
+ _rPkg.DependencyFiles = append(_rPkg.DependencyFiles, mfs.WebGlobalPkg.DependencyFiles...)
+
+ // Create template from package.
+ _tmpl, _err := template.ParseFiles(_rPkg.DependencyFiles...)
+ if _err != nil {
+ log.Printf("_ERROR:network:handlePage(\"/preview\"):%s", _err)
+ http.Error(w, "_ERROR:network:handlePage(\"/preview\"):template.ParseFiles", http.StatusInternalServerError)
+ return
+ }
+
+ // Get FMD content from form post.
+ // if _err = r.ParseForm(); _err != nil {
+ // log.Printf("_ERROR:network:handlePage(\"/preview\"):%s", _err)
+ // http.Error(w, "_ERROR:network:handlePage(\"/preview\"):r.ParseForm", http.StatusInternalServerError)
+ // return
+ // }
+
+ _inputFMDStream := bytes.NewBufferString(r.FormValue("editor"))
+
+ // Assign rendered FMD file to buffer.
+ var _templateDataContainer struct {
+ FileText string
+ }
+ _templateDataContainer.FileText = fmd.ReadFMDStreamtoHTMLString(_inputFMDStream.Bytes())
+ // _templateDataContainer.FileText = r.FormValue("editor")
+ if _templateDataContainer.FileText == "" {
+ _templateDataContainer.FileText = "No File Found"
+ }
+
// Render template.
if _err = _tmpl.ExecuteTemplate(w, "index.html", _templateDataContainer); _err != nil {
- log.Printf("_ERROR:network:handlePageDefault(\"/\"):%s", _err)
- http.Error(w, "_ERROR:network:handlePageDefault(\"/\"):template.ExecuteTemplate", http.StatusInternalServerError)
+ log.Printf("_ERROR:network:handlePage(\"/preview\"):%s", _err)
+ http.Error(w, "_ERROR:network:handlePage(\"/preview\"):template.ExecuteTemplate", http.StatusInternalServerError)
return
}
- log.Printf("DONE\thandlePageDefault:%s", r.URL)
+ log.Printf("DONE\thandlePage:%s", r.URL)
}
diff --git a/web/edit/index.html b/web/edit/index.html
@@ -20,7 +20,10 @@
<section id="main" class="__container">
- <textarea name="editor" id="0">{{.FileText}}</textarea>
+ <form class="mform" action="/preview" method="post" target="_blank">
+ <button type="submit">PREVIEW HTML OUTPUT</button>
+ <textarea name="editor" id="0">{{.FileText}}</textarea>
+ </form>
</section>
diff --git a/web/edit/styles.css b/web/edit/styles.css
@@ -1,5 +1,17 @@
@layer entity {
- textarea {
- height: 75vh;
+ .mform {
+ display: grid;
+
+ > button {
+ width: fit-content;
+ padding: var(--miki_padding--half);
+ margin: var(--miki_margin);
+ }
+
+ > textarea {
+ height: 76vh;
+ padding: var(--miki_padding);
+ }
}
+
}
\ No newline at end of file
diff --git a/web/preview/index.html b/web/preview/index.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+
+ <title>Miki/Preview</title>
+ <meta name="viewport" charset="utf-8" content="width=device-width, initial-scale=1.0" />
+ {{template "meta"}}
+
+</head>
+
+<body>
+
+ {{template "header" "Preview"}}
+
+ <section class="_content">
+
+ <section id="left"></section>
+
+ <section id="subject_">
+
+ {{.FileText}}
+
+ </section>
+
+ <section id="right"></section>
+
+ </section>
+</body>
+
+</html>
+\ No newline at end of file