From 7052724c130ac620236a099496340733f717db9c Mon Sep 17 00:00:00 2001 From: surdeus Date: Sun, 9 Jun 2024 17:23:33 +0500 Subject: [PATCH] feat: move tht to sep rep. --- build.sh | 2 +- htmlx/element.go | 97 ------------------------ htmlx/html.go | 86 --------------------- install.sh | 2 +- mdx/main.go | 83 -------------------- mod/post.tengo | 26 ------- mod/pre.tengo | 40 ---------- paths/main.go | 51 ------------- run-tht.sh | 4 - server/handler.go | 189 ---------------------------------------------- server/tool.go | 53 ------------- 11 files changed, 2 insertions(+), 631 deletions(-) delete mode 100644 htmlx/element.go delete mode 100644 htmlx/html.go delete mode 100644 mdx/main.go delete mode 100644 mod/post.tengo delete mode 100644 mod/pre.tengo delete mode 100644 paths/main.go delete mode 100755 run-tht.sh delete mode 100644 server/handler.go delete mode 100644 server/tool.go diff --git a/build.sh b/build.sh index 02eb76a..98acd9b 100755 --- a/build.sh +++ b/build.sh @@ -1,4 +1,4 @@ #!/bin/sh # -go build -o ./exe/ ./cmd/tpp ./cmd/tht +go build -o ./exe/ ./cmd/tpp diff --git a/htmlx/element.go b/htmlx/element.go deleted file mode 100644 index 8f437ae..0000000 --- a/htmlx/element.go +++ /dev/null @@ -1,97 +0,0 @@ -package htmlx - -import ( - "github.com/d5/tengo/v2" - "strings" - "html" - "fmt" -) - -const RawTag = "raw" - -// The type implements basic -// way to structrize HTML elements. -type Element struct { - tengo.ObjectImpl - Tag string - Attr map[string] string - Children []*Element - // The value makes sense only if - // the tag is the "raw" - Content string -} - -func (el *Element) TypeName() string { - return "*HTMLElement" -} - -// The method renders the element to it's -// HTML representation. -func (el *Element) String() string { - if el.Tag == RawTag { - return html.EscapeString(el.Content) - } - - var b strings.Builder - - fmt.Fprintf(&b, "<%s", el.Tag) - for k, v := range el.Attr { - fmt.Fprintf(&b, " %s=%q", k, v) - } - fmt.Fprint(&b, ">") - - for _, child := range el.Children { - if child == nil { - continue - } - fmt.Fprint(&b, child.String()) - } - - fmt.Fprintf(&b, "", el.Tag) - return b.String() -} - -func (el *Element) Body(els ...*Element) *Element { - el.Children = els - return el -} - -func (el *Element) IndexGet( - index tengo.Object, -) (tengo.Object, error) { - arg, ok := tengo.ToString(index) - if !ok { - return nil, tengo.ErrInvalidIndexValueType - } - - switch arg { - case "body" : - return &tengo.UserFunction{ - Name: "Element.Body", - Value: func( - args ...tengo.Object, - ) (tengo.Object, error) { - s := []*Element{} - for _, arg := range args { - el, ok := arg.(*Element) - if !ok { - str, ok := tengo.ToString(arg) - if ok { - s = append(s, &Element{ - Tag: RawTag, - Content: str, - }) - } - continue - } - s = append(s, el) - } - return el.Body(s...), nil - }, - }, nil - } - return nil, nil -} - - - diff --git a/htmlx/html.go b/htmlx/html.go deleted file mode 100644 index 00219a3..0000000 --- a/htmlx/html.go +++ /dev/null @@ -1,86 +0,0 @@ -package htmlx - -import "github.com/d5/tengo/v2" - -type HTML struct{ - tengo.ObjectImpl -} - -/* - -html.div({ - id: "some-el-id", - value: "shit value" -}).body( - html.raw("cock "), - html.strong("something") -) - -*/ - -func (html *HTML) IndexGet( - index tengo.Object, -) (tengo.Object, error) { - str, ok := tengo.ToString(index) - if !ok { - return nil, tengo.ErrInvalidIndexValueType - } - - fn := func(args ...tengo.Object) (tengo.Object, error) { - if len(args) > 1 { - return nil, tengo.ErrWrongNumArguments - } - var arg tengo.Object - if len(args) == 1 { - arg = args[0] - } - - if arg == nil { - return &Element{ - Tag: str, - }, nil - } - - if can := arg.CanIterate() ; !can { - return nil, tengo.ErrInvalidArgumentType{ - Name: "first", - Expected: "iterable", - Found: arg.TypeName(), - } - } - attr := map[string] string{} - iter := arg.Iterate() - for iter.Next() { - key, val := iter.Key(), iter.Value() - skey, ok := tengo.ToString(key) - if !ok { - return nil, tengo.ErrInvalidArgumentType{ - Name: "attribute(key)", - Expected: "stringer", - Found: key.TypeName(), - } - } - sval, ok := tengo.ToString(val) - if !ok { - return nil, tengo.ErrInvalidArgumentType{ - Name: "attribute(value)", - Expected: "stringer", - Found: val.TypeName(), - } - } - attr[skey] = sval - } - return &Element{ - Tag: str, - Attr: attr, - }, nil - } - - return &tengo.UserFunction{ - Name: str, - Value: fn, - }, nil -} - - - diff --git a/install.sh b/install.sh index dc0cd6e..11bfb74 100755 --- a/install.sh +++ b/install.sh @@ -1,3 +1,3 @@ #!/bin/sh -go install ./cmd/tpp/ ./cmd/tht/ +go install ./cmd/tpp/ diff --git a/mdx/main.go b/mdx/main.go deleted file mode 100644 index a5bcd63..0000000 --- a/mdx/main.go +++ /dev/null @@ -1,83 +0,0 @@ -package mdx -import "github.com/gomarkdown/markdown" -import "github.com/gomarkdown/markdown/html" -import "github.com/gomarkdown/markdown/parser" -import "github.com/d5/tengo/v2" -import "bytes" - -type Markdown struct { - tengo.ObjectImpl - MakeParser func() *parser.Parser - MakeRenderer func() *html.Renderer -} - -func MakeDefaultMarkdown() *Markdown { - return &Markdown{ - MakeParser: MakeDefaultParser, - MakeRenderer: MakeDefaultRenderer, - } -} - -func (md *Markdown) TypeName() string { - return "*Markdown" -} - -func (md *Markdown) String() string { - if md == nil { - return "" - } - return "&Markdown{...}" -} - -func (md *Markdown) Render( - data []byte, -) ([]byte, error) { - doc := md.MakeParser().Parse(data) - rendered := markdown.Render(doc, md.MakeRenderer()) - return rendered, nil -} - -func (md *Markdown) CanCall() bool { - return md != nil -} - -func (md *Markdown) Call( - args ...tengo.Object, -) (tengo.Object, error) { - var b bytes.Buffer - for _, arg := range args { - str, ok := tengo.ToString(arg) - if !ok { - return nil, tengo.ErrInvalidArgumentType{ - Name: "v", - Expected: "stringer", - Found: arg.TypeName(), - } - } - b.Write([]byte(str)) - } - - rendered, err := md.Render(b.Bytes()) - if err != nil { - return nil, err - } - - return tengo.FromInterface(rendered) -} - -func MakeDefaultParser() *parser.Parser { - return parser.NewWithExtensions( - parser.CommonExtensions | parser.AutoHeadingIDs | - parser.NoEmptyLineBeforeBlock | parser.Attributes | - parser.Tables, - ) -} - -func MakeDefaultRenderer() *html.Renderer { - return html.NewRenderer( - html.RendererOptions{ - Flags: html.CommonFlags | html.HrefTargetBlank, - }, - ) -} - diff --git a/mod/post.tengo b/mod/post.tengo deleted file mode 100644 index c4a439e..0000000 --- a/mod/post.tengo +++ /dev/null @@ -1,26 +0,0 @@ -fmt := import("fmt") -paths := import("paths") -htmExt := func(c){ - if c.is_compo { - return - } - - c.pp.print(``) -} - -exts := { - ".htm": htmExt, - ".html": htmExt -} - -export func(c){ - ext := paths.ext(c.pp.filepath) - ext = paths.ext( - c.pp.filepath[:len(c.pp.filepath) - len(ext)] - ) - - cl := exts[ext] - if !is_undefined(cl) { - cl(c) - } -} diff --git a/mod/pre.tengo b/mod/pre.tengo deleted file mode 100644 index b550388..0000000 --- a/mod/pre.tengo +++ /dev/null @@ -1,40 +0,0 @@ -fmt := import("fmt") -paths := import("paths") -html := import("html").new_render() - -htmExt := func(c){ - if c.is_compo { - return - } - c.pp.print(``) - - c.pp.print(html.head().body( - func(){ - if c.title { - return html.title().body(c.title) - } - }(), - html.script({ - src: `https://unpkg.com/htmx.org@1.9.2` - }) - )) - - c.pp.print(``) -} - -exts := { - ".htm": htmExt, - ".html": htmExt -} - -export func(c){ - ext := paths.ext(c.pp.filepath) - ext = paths.ext( - c.pp.filepath[:len(c.pp.filepath) - len(ext)] - ) - - cl := exts[ext] - if cl { - cl(c) - } -} diff --git a/paths/main.go b/paths/main.go deleted file mode 100644 index 6c54566..0000000 --- a/paths/main.go +++ /dev/null @@ -1,51 +0,0 @@ -package paths - -import ( - "github.com/d5/tengo/v2" - "path" -) - -var Module = &tengo.BuiltinModule { - Attrs: moduleMap, -} - -var moduleMap = map[string] tengo.Object { - "base" : &tengo.UserFunction{ - Name: "base", - Value: wrapOneArg(path.Base), - }, - "ext" : &tengo.UserFunction{ - Name: "ext", - Value: wrapOneArg(path.Ext), - }, - "dir" : &tengo.UserFunction{ - Name: "dir", - Value: wrapOneArg(path.Dir), - }, - "clean" : &tengo.UserFunction{ - Name: "clean", - Value: wrapOneArg(path.Clean), - }, -} - -func wrapOneArg( - fn func(string) string, -) func(...tengo.Object) (tengo.Object, error) { - return func(args ...tengo.Object) (tengo.Object, error) { - if len(args) != 1 { - return nil, tengo.ErrWrongNumArguments - } - str, ok := tengo.ToString(args[0]) - if !ok { - return nil, tengo.ErrInvalidArgumentType{ - Name: "first", - Expected: "string(compatible)", - Found: args[0].TypeName(), - } - } - return &tengo.String{ - Value: fn(str), - }, nil - } -} - diff --git a/run-tht.sh b/run-tht.sh deleted file mode 100755 index 646c7c1..0000000 --- a/run-tht.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh -# -go build -o ./exe/ ./cmd/tht/ && \ - ./exe/tht diff --git a/server/handler.go b/server/handler.go deleted file mode 100644 index daa2408..0000000 --- a/server/handler.go +++ /dev/null @@ -1,189 +0,0 @@ -package server - -import ( - //"github.com/d5/tengo/v2" - "surdeus.su/util/tpp/mdx" - //"surdeus.su/core/xgo/xmodules/htmlx" - "surdeus.su/core/xgo/xmodules/httpx" - "surdeus.su/core/xgo/xmodules" - "surdeus.su/util/tpp" - "path/filepath" - "net/http" - "context" - "path" - "mime" - "log" - "os" - "io" -) - -var _ = http.Handler(&Handler{}) - -// The type describes behaviour -// of handling stuff like in PHP. -type Handler struct { - // THe field represents - // where we store site's - // source files and request handlers. - sourcePath string - // Preprocessor must be set by user - // to be able to bring custom features in. - pp *tpp.Preprocessor - // Aditional extension. ".tpp" by default. - // For example "file.html.tpp" will be - // first preprocessed TPP and sent back as simple HTML. - ext string - - // The global map accessable from all the - // request so you can keep the states - // between requests. - global any - md *mdx.Markdown - indexSuffix string -} - -// Returns the new Handler with -// specified preprocessor, source path, -// preprocessor extension and the global value. -func NewHandler( - pp *tpp.Preprocessor, - src, ext, index string, - global any, -) *Handler { - ret := &Handler{} - ret.sourcePath = src - ret.ext = ext - ret.pp = pp - ret.global = global - ret.indexSuffix = index - return ret -} - -// Returns the default tpp.Preprocessor suitable for -// the most needs. -func DefaultPP(mod string) *tpp.Preprocessor { - t := tpp.NewTengo().SetPreCompile(func( - ctx context.Context, - s *tpp.Script, - ) { - s.SetImportDir(mod) - s.SetImports(xmodules.Modules) - s.EnableFileImport(true) - - s.Add("__http_request__", ctx.Value(KeyRequest)) - s.Add("__global__", ctx.Value(KeyGlobal)) - s.Add("__markdown__", ctx.Value(KeyMarkdown)) - }).SetPreCode(func(ctx context.Context) []byte { - return []byte(` - markdown := func(...args) { - pp.write_raw(__markdown__(args...)) - } - __http__ := immutable({ - request : __http_request__ - }) - context.http = __http__ - context.pp = pp - context.global = __global__ - import("./pre")(context) - `) - }).SetPostCode(func(ctx context.Context) []byte { - return []byte(` - import("./post")(context) - `) - }) - - return tpp.New(t) -} - -func (h *Handler) SetMD(md *mdx.Markdown) *Handler { - h.md = md - return h -} - -func (h *Handler) ServeHTTP( - w http.ResponseWriter, - r *http.Request, -) { - shouldProcess := true - urlPath := r.URL.Path - // Cleaning URL path to prevent injections. - urlPath = path.Clean(urlPath) - urlExt := path.Ext(urlPath) - - filePath := filepath.Join( - filepath.FromSlash(h.sourcePath), - filepath.FromSlash(urlPath), - ) - fileStat, err := os.Stat(filePath) - if err == nil { - if fileStat.IsDir() { - filePath = filepath.Join( - filePath, - h.indexSuffix, - ) - } - } - - filePathTpp := filePath + h.ext - //log.Println("pth:", urlPath, filePathTpp) - file, err := os.Open(filePathTpp) - if err != nil { - shouldProcess = false - file, err = os.Open(filePath) - if err != nil { - http.NotFound(w, r) - return - } - } - - //process := true - fileData, err := io.ReadAll(file) - if err != nil { - http.NotFound(w, r) - return - } - - ctx := context.WithValue( - r.Context(), - KeyRequest, - &httpx.Request{ - Request: r, - }, - ) - - ctx = context.WithValue( - ctx, - KeyGlobal, - h.global, - ) - - ctx = context.WithValue( - ctx, - KeyMarkdown, - h.md, - ) - - // Setting before the code to let it change own - // content type? - contentType := mime.TypeByExtension(urlExt) - w.Header().Set("Content-Type", contentType) - processedData := fileData - if shouldProcess { - processedData, err = h.pp.Process( - ctx, - true, - filePathTpp, - fileData, - ) - if err != nil { - http.NotFound(w, r) - log.Printf( - "Error: pp.Process(...): %s\n", - err, - ) - return - } - } - - w.Write(processedData) -} diff --git a/server/tool.go b/server/tool.go deleted file mode 100644 index 24cebfc..0000000 --- a/server/tool.go +++ /dev/null @@ -1,53 +0,0 @@ -package server - -import ( - - "github.com/d5/tengo/v2" - //"github.com/d5/tengo/v2/stdlib" - "surdeus.su/util/tpp/mdx" - "surdeus.su/core/cli/mtool" - "net/http" - "log" - //"context" -) - -// Context key type for internal usage. -type CKey string - -const ( - KeyRequest CKey = "http-request" - KeyGlobal = "global" - KeyMarkdown = "markdown" - KeyHTML = "html" -) - -// Simple PHP-like server implementation. -var Tool = mtool.T("tht").Func(func(flags *mtool.Flags) { - var ( - addr, ext, src, mod, index string - ) - - flags.StringVar(&addr, "addr", ":3000", "address to serve at") - flags.StringVar(&mod, "mod", "./mod", "path to store Tengo modules") - flags.StringVar(&src, "src", "./src", "directory with source files") - flags.StringVar(&ext, "ext", ".tpp", "extension for TPP files") - flags.StringVar(&index, "index", "index.htm", "index file name") - - flags.Parse() - - - srv := &http.Server{ - Addr: addr, - Handler: NewHandler( - DefaultPP(mod), - src, ext, index, - map[string] tengo.Object{}, - ).SetMD(mdx.MakeDefaultMarkdown()), - } - - log.Printf("Listening on %q\n", addr) - err := srv.ListenAndServe() - if err != nil { - log.Printf("Error: srv.ListenAndServe(...): %s\n", err) - } -})