From 243bd2b9e9843d212307823c85ff3a51805439c6 Mon Sep 17 00:00:00 2001 From: surdeus Date: Sun, 3 Mar 2024 04:25:25 +0500 Subject: [PATCH] feat: added automatic document navigation generation. --- server/main.go | 126 ++++++++++++++++++++++++++++++++++++++-- tool.go | 3 +- wiki/some-file-name.pmd | 9 +++ 3 files changed, 132 insertions(+), 6 deletions(-) diff --git a/server/main.go b/server/main.go index c5c88d6..13c3dd1 100644 --- a/server/main.go +++ b/server/main.go @@ -3,6 +3,7 @@ package server import ( "github.com/gomarkdown/markdown" "github.com/gomarkdown/markdown/html" + "github.com/gomarkdown/markdown/ast" "github.com/gomarkdown/markdown/parser" "vultras.su/core/bond" "vultras.su/core/bond/contents" @@ -11,7 +12,7 @@ import ( "path" "os" "fmt" - //"strings" + "strings" "bytes" ) @@ -32,6 +33,7 @@ type ServerOptions struct { WikiExt string WebPath string AddFileNavigation bool + AddDocNavigation bool } type Server struct { @@ -88,6 +90,113 @@ func (srv *Server) pageFooter() string { return htmlFooter } +type Heading struct { + Id string + Level int + Text string +} + +func getDocumentHeadings(doc ast.Node) []Heading { + ret := []Heading{} + ast.WalkFunc(doc, func(node ast.Node, entering bool) ast.WalkStatus { + heading, ok := node.(*ast.Heading) + if !ok { + return ast.GoToNext + } + children := node.GetChildren() + if len(children) > 0 && !entering { + leaf := children[0].AsLeaf() + if leaf == nil { + return ast.GoToNext + } + ret = append(ret, Heading{ + Id: heading.HeadingID, + Level: heading.Level, + Text: string(leaf.Literal), + }) + return ast.SkipChildren + } + + return ast.GoToNext + }) + return ret +} + +type HeadingTree struct { + Heading Heading + Children HeadingTrees +} + +type HeadingTrees []*HeadingTree + +func makeHeadingTrees(hs []Heading) HeadingTrees { + fmt.Println("fooooooooooooooouuuuuuuuund", len(hs), hs) + if len(hs) == 0 { + return nil + } + + if len(hs) == 1 { + return HeadingTrees{ + &HeadingTree{ + Heading: hs[0], + }, + } + } + + var ( + lasti int + found bool + ) + + first := hs[0] + rest := hs[1:] + for i, h := range rest { + if first.Level >= h.Level { + fmt.Println("thefound: ", first, h) + lasti = i+1 + found = true + break + } + } + + if !found { + fmt.Println("in not found") + return HeadingTrees{ + &HeadingTree{ + Heading: first, + Children: makeHeadingTrees(rest), + }, + } + } + + fmt.Println("through", lasti) + return append( + makeHeadingTrees(hs[:lasti]), + makeHeadingTrees(hs[lasti:])... , + ) +} + +func RenderHeadingTrees(trees HeadingTrees, first bool) string { + var b strings.Builder + fmt.Fprint(&b, "") + + for _, tree := range trees { + fmt.Fprintf( + &b, "%s", + tree.Heading.Id, tree.Heading.Text, + ) + if len(tree.Children) > 0 { + fmt.Fprint(&b, RenderHeadingTrees(tree.Children, false)) + } + } + fmt.Fprint(&b, "") + return b.String() +} + func (srv *Server) ProcessToHtml(urlPath, filePath string, bts []byte) ([]byte, error) { var b bytes.Buffer doc := srv.makeMdParser().Parse(bts) @@ -133,14 +242,21 @@ func (srv *Server) ProcessToHtml(urlPath, filePath string, bts []byte) ([]byte, fmt.Fprint(&b, "") } - fmt.Fprint(&b, "
", string(main_section), "
") + fmt.Fprint(&b, "
") + if srv.options.AddDocNavigation { + headings := getDocumentHeadings(doc) + trees := makeHeadingTrees(headings) + docNav := RenderHeadingTrees(trees, true) + fmt.Fprint(&b, docNav) + } + fmt.Fprint(&b, "
") + fmt.Fprintf(&b, string(main_section)) + fmt.Fprintf(&b, "
") + fmt.Fprintf(&b, "
") fmt.Fprint(&b, srv.pageFooter()) return b.Bytes(), nil } - - - var makeRootHandler = func(opts ServerOptions) bond.Handler { return bond.Root(bond.Path(). Case( diff --git a/tool.go b/tool.go index e3f2a42..6ebaf67 100644 --- a/tool.go +++ b/tool.go @@ -16,7 +16,8 @@ var Tool = mtool.T("rwiki").Func(func(flags *mtool.Flags){ flags.StringVar(&opts.WikiPath, "wiki", "wiki", "path to wiki files") flags.StringVar(&opts.WebPath, "web", "web", "path to static web files") flags.StringVar(&opts.WikiExt, "ext", ".pmd", "wiki file exitension") - flags.BoolVar(&opts.AddFileNavigation, "nav", true, "generate navigation") + flags.BoolVar(&opts.AddFileNavigation, "filenav", true, "generate file navigation") + flags.BoolVar(&opts.AddDocNavigation, "docnav", true, "generate document navigation") flags.Parse() srv := bond.Server{ diff --git a/wiki/some-file-name.pmd b/wiki/some-file-name.pmd index 73f102f..ac3582b 100644 --- a/wiki/some-file-name.pmd +++ b/wiki/some-file-name.pmd @@ -6,7 +6,16 @@ teahuste| ehtua | shit --------|-------------|-------------- cock| dick|die +* [X] check + ```go func main() { } ``` + +## Second header shit + + +## another dick + +### third level header