GitRoot
Craft your forge, Build your project, Grow your community freely
1// SPDX-FileCopyrightText: 2026 Romain Maneschi <romain@gitroot.dev>
2//
3// SPDX-License-Identifier: EUPL-1.2
4
5package main
6
7import (
8 "bytes"
9 "fmt"
10 "io/fs"
11 "regexp"
12 "strings"
13
14 "gitroot.dev/libs/golang/plugin/model"
15)
16
17type rendererEmbed struct {
18 conf Conf
19 server model.Server
20}
21
22func NewRendererEmbed(conf Conf, server model.Server) rendererEmbed {
23 return rendererEmbed{conf: conf, server: server}
24}
25
26func (r rendererEmbed) renderPage(pageBuilder *strings.Builder, lines []CacheLineRelativeLink) {
27 for i, line := range lines {
28 pageBuilder.WriteString(r.makeLink(line.line, line.relativePath))
29 if i < len(lines)-1 {
30 pageBuilder.WriteString("\n")
31 }
32 }
33}
34
35func (r rendererEmbed) makeLink(cacheLine CacheLine, path string) string {
36 t := cacheLine.selects
37 append := "\n\n"
38 for i, a := range t {
39 if i == 0 {
40 append = fmt.Sprintf("%s%s", append, a)
41 }
42 }
43 append = fmt.Sprintf("%s\n%s\n", append, r.findEmbed(cacheLine.fp))
44 return fmt.Sprintf("### [%s](%s)%s", cacheLine.title, path, append)
45}
46
47func (r rendererEmbed) findEmbed(path string) string {
48 content, err := fs.ReadFile(r.server.Worktree(), path)
49 if err != nil {
50 r.server.LogError("can't find file", err)
51 return ""
52 }
53 if strings.HasSuffix(path, ".md") { //special case, search first description
54 re := regexp.MustCompile(`(?m)^#\s(.*)$`)
55 t := re.FindSubmatch(content)
56 hasTitle := len(t) > 1
57 hasMeta := bytes.Contains(content, []byte("---"))
58 contents := bytes.Split(content, []byte("\n"))
59 for i, l := range contents {
60 titleCase := hasTitle && bytes.HasPrefix(l, []byte("# "))
61 metaCase := !hasTitle && hasMeta && i > 0 && bytes.HasPrefix(l, []byte("---"))
62 bodyCase := !hasTitle && !hasMeta
63 if titleCase || metaCase || bodyCase {
64 res := ""
65 if i+1 < len(contents) && len(contents[i+1]) > 0 {
66 res = fmt.Sprintf("%s\n%s", res, string(contents[i+1]))
67 }
68 if i+2 < len(contents) && len(contents[i+2]) > 0 {
69 res = fmt.Sprintf("%s\n%s", res, string(contents[i+2]))
70 }
71 if i+3 < len(contents) && len(contents[i+3]) > 0 {
72 res = fmt.Sprintf("%s\n%s", res, string(contents[i+3]))
73 }
74 return res
75 }
76 }
77 } else {
78 contents := bytes.Split(content, []byte("\n"))
79 for i, l := range contents {
80 if bytes.Contains(l, []byte(r.conf.Where)) {
81 var buffer bytes.Buffer
82 buffer.Write([]byte("```\n"))
83 if i > 0 {
84 buffer.Write(contents[i-1])
85 buffer.Write([]byte("\n"))
86 }
87 buffer.Write(l)
88 if i < len(contents) {
89 buffer.Write([]byte("\n"))
90 buffer.Write(contents[i+1])
91 }
92 buffer.Write([]byte("\n```"))
93 return buffer.String()
94 }
95 }
96 }
97
98 return "-"
99}