diff options
| author | Himanshu Sardana <himanshusardana2005@gmail.com> | 2026-03-26 21:26:35 +0000 |
|---|---|---|
| committer | Himanshu Sardana <himanshusardana2005@gmail.com> | 2026-03-26 21:26:35 +0000 |
| commit | 103e84d847262830bbaa550b37218e9ca8b317d3 (patch) | |
| tree | e19d3bfd6594600fb28be1ccac1a3869207bc49c /internal/build/parser.go | |
| parent | 5c631f0cdb8ee3238ff054d171dd8babd158047b (diff) | |
refactor: split into cmd, pkg
Diffstat (limited to 'internal/build/parser.go')
| -rw-r--r-- | internal/build/parser.go | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/internal/build/parser.go b/internal/build/parser.go new file mode 100644 index 0000000..e1ef3b0 --- /dev/null +++ b/internal/build/parser.go @@ -0,0 +1,82 @@ +package build + +import ( + "fmt" + "os" + "strings" + + "github.com/adrg/frontmatter" + "github.com/gomarkdown/markdown" + "github.com/gomarkdown/markdown/ast" + "github.com/gomarkdown/markdown/html" + "github.com/gomarkdown/markdown/parser" + + "github.com/HimanshuSardana/kite/pkg/content" +) + +type TOCItem struct { + Level int + Text string + ID string +} + +type ParsedPage struct { + Frontmatter content.Frontmatter + Content []byte + TOC []TOCItem +} + +func ParseMarkdown(path string) (*ParsedPage, error) { + md, err := os.ReadFile(path) + if err != nil { + return nil, fmt.Errorf("reading %s: %w", path, err) + } + + var matter content.Frontmatter + rest, err := frontmatter.Parse(strings.NewReader(string(md)), &matter) + if err != nil { + return nil, fmt.Errorf("parsing frontmatter: %w", err) + } + + extensions := parser.CommonExtensions | parser.AutoHeadingIDs + p := parser.NewWithExtensions(extensions) + doc := p.Parse(rest) + + var toc []TOCItem + ast.WalkFunc(doc, func(node ast.Node, entering bool) ast.WalkStatus { + if heading, ok := node.(*ast.Heading); ok && entering { + text := extractText(heading) + id := string(heading.HeadingID) + + toc = append(toc, TOCItem{ + Level: heading.Level, + Text: text, + ID: id, + }) + } + return ast.GoToNext + }) + + renderer := html.NewRenderer(html.RendererOptions{ + Flags: html.CommonFlags, + }) + + output := markdown.Render(doc, renderer) + + return &ParsedPage{ + Frontmatter: matter, + Content: output, + TOC: toc, + }, nil +} + +func extractText(h *ast.Heading) string { + var text string + ast.WalkFunc(h, func(node ast.Node, entering bool) ast.WalkStatus { + if leaf, ok := node.(*ast.Text); ok && entering { + text += string(leaf.Literal) + } + return ast.GoToNext + }) + return text +} |
