package notes import ( "bytes" "encoding/base64" "errors" "fmt" "io" "io/ioutil" "local/notes-server/filetree" "path" "regexp" "strings" "github.com/gomarkdown/markdown" "github.com/gomarkdown/markdown/ast" "github.com/gomarkdown/markdown/html" "github.com/gomarkdown/markdown/parser" ) func (n *Notes) File(urlPath string) (string, error) { p := filetree.NewPathFromURL(urlPath) if p.IsDir() { return "", errors.New("path is dir") } b, _ := ioutil.ReadFile(p.Local) renderer := html.NewRenderer(html.RendererOptions{ Flags: html.CommonFlags | html.TOC, RenderNodeHook: n.commentFormer(urlPath, b), }) parser := parser.NewWithExtensions(parser.CommonExtensions | parser.HeadingIDs | parser.AutoHeadingIDs | parser.Titleblock) content := markdown.ToHTML(b, parser, renderer) return string(content) + "\n", nil } func (n *Notes) commentFormer(urlPath string, md []byte) html.RenderNodeFunc { urlPath = strings.TrimPrefix(urlPath, "/") urlPath = strings.TrimPrefix(urlPath, strings.Split(urlPath, "/")[0]) lines := bytes.Split(md, []byte("\n")) cur := -1 nextHeader := func() { cur++ for cur < len(lines) { if bytes.Contains(lines[cur], []byte("```")) { cur++ for cur < len(lines) && !bytes.Contains(lines[cur], []byte("```")) { cur++ } cur++ } if cur >= len(lines) { break } line := lines[cur] if ok, err := regexp.Match(`^\s*#+\s*[^\s]+\s*$`, line); err != nil { panic(err) } else if ok { return } cur++ } } return func(w io.Writer, node ast.Node, entering bool) (ast.WalkStatus, bool) { if heading, ok := node.(*ast.Heading); ok && !entering { nextHeader() fmt.Fprintf(w, `
`, path.Join("/comment", urlPath)+"#"+heading.HeadingID, cur) } return ast.GoToNext, false } } func (n *Notes) commentFormerOld() html.RenderNodeFunc { return func(w io.Writer, node ast.Node, entering bool) (ast.WalkStatus, bool) { if heading, ok := node.(*ast.Heading); ok { if !entering { literal := "" ast.WalkFunc(heading, func(n ast.Node, e bool) ast.WalkStatus { if leaf := n.AsLeaf(); e && leaf != nil { if literal != "" { literal += ".*" } literal += string(leaf.Literal) } return ast.GoToNext }) level := heading.Level id := base64.URLEncoding.EncodeToString([]byte(fmt.Sprintf(`^[ \t]*%s\s*%s(].*)?\s*$`, strings.Repeat("#", level), literal))) fmt.Fprintf(w, ` `, id) } } return ast.GoToNext, false } }