GitRoot

Craft your forge, Build your project, Grow your community freely
  1// SPDX-FileCopyrightText: 2025 Romain Maneschi <romain@gitroot.dev>
  2//
  3// SPDX-License-Identifier: EUPL-1.2
  4
  5package main
  6
  7import (
  8	"fmt"
  9
 10	"github.com/tidwall/gjson"
 11	"gitroot.dev/libs/golang/glob"
 12	gitroot "gitroot.dev/libs/golang/plugin/model"
 13)
 14
 15type conf struct {
 16	defaultBranch       string
 17	style               string
 18	favicon             string
 19	header              string
 20	menu                []link
 21	footer              string
 22	generateGitWorktree bool
 23	branchesDir         string
 24	meta                map[string]string
 25	layout              []layout
 26}
 27
 28var defaultRun = []gitroot.PluginRun{{
 29	Path:   "**/*",
 30	Branch: []string{"main"},
 31	When:   gitroot.PluginRunWhenAll,
 32	Func:   []gitroot.PluginFunc{},
 33	Write: gitroot.PluginWrite{
 34		Git: []gitroot.PluginWriteRight{{
 35			Path: "index.md",
 36			Can:  []gitroot.PluginWriteRightCan{gitroot.PluginWriteRightCanAdd},
 37		}},
 38		Web: []gitroot.PluginWriteRight{{
 39			Path: "**/*",
 40			Can:  gitroot.PluginWriteRightCanAll,
 41		}},
 42		Exec: []gitroot.PluginExecRight{},
 43		CallFunc: []gitroot.PluginCallFuncRight{
 44			{PluginName: PLUGIN_MARKDOWN, FuncName: PLUGIN_MARKDOWN_FUNC},
 45			{PluginName: PLUGIN_CODE, FuncName: PLUGIN_CODE_FUNC},
 46			{PluginName: "apex_mermaid", FuncName: "renderCode"}, //TODO it's transitive how to not do this? It's needed because runtime check that plugin can call that other l.785 runtime.go::CallBuilder()
 47		},
 48	},
 49	Configuration: map[string]any{
 50		"defaultBranch": "main",
 51		"style":         "simple.min.css",
 52		"favicon":       "icon.png",
 53		"header":        "<h1>{{repo.name}}</h1>",
 54		"menu": []link{
 55			{Display: "🏠 Home", Link: "/"},
 56			{Display: "📖 Readme", Link: "/README.html"},
 57			{Display: "🐞 Issues", Link: "/boards/issues.html"},
 58			{Display: "⚖ Licence", Link: "/LICENCE.html"},
 59		},
 60		"footer":              "<p>Clone with <code>git clone {{repo.cloneUrl}}</code></p><small>Hosted with ❤️ by <a href=\"https://gitroot.dev\">GitRoot</a></small>",
 61		"generateGitWorktree": true,
 62		"branchesDir":         "branches",
 63		"meta": map[string]string{
 64			"description":       "a short description",
 65			"og:title":          "title displayed in social",
 66			"og:description":    "description displayed in social",
 67			"og:type":           "article",
 68			"fediverse:creator": "@forge@gitroot.dev",
 69		},
 70		"layout": []layout{},
 71	},
 72}, {
 73	Path:   "**/*",
 74	Branch: []string{"*", "!main"},
 75	When:   gitroot.PluginRunWhenAll,
 76	Func:   []gitroot.PluginFunc{},
 77	Write: gitroot.PluginWrite{
 78		Git: []gitroot.PluginWriteRight{},
 79		Web: []gitroot.PluginWriteRight{{
 80			Path: "branches/**/*",
 81			Can:  gitroot.PluginWriteRightCanAll,
 82		}},
 83		Exec: []gitroot.PluginExecRight{},
 84		CallFunc: []gitroot.PluginCallFuncRight{
 85			{PluginName: PLUGIN_MARKDOWN, FuncName: PLUGIN_MARKDOWN_FUNC},
 86			{PluginName: PLUGIN_CODE, FuncName: PLUGIN_CODE_FUNC},
 87			{PluginName: "apex_mermaid", FuncName: "renderCode"}, //TODO it's transitive how to not do this? It's needed because runtime check that plugin can call that other l.785 runtime.go::CallBuilder()
 88		},
 89	},
 90	Configuration: map[string]any{
 91		"defaultBranch": "main",
 92		"style":         "simple.min.css",
 93		"favicon":       "icon.png",
 94		"header":        "<h1>{{repo.name}}</h1>",
 95		"menu": []link{
 96			{Display: "🏠 Home", Link: "/"},
 97			{Display: "📖 Readme", Link: "/README.html"},
 98			{Display: "🐞 Issues", Link: "/boards/issues.html"},
 99			{Display: "⚖ Licence", Link: "/LICENCE.html"},
100		},
101		"footer":              "<p>Clone with <code>git clone {{repo.cloneUrl}}</code></p><small>Hosted with ❤️ by <a href=\"https://gitroot.dev\">GitRoot</a></small>",
102		"generateGitWorktree": false,
103		"branchesDir":         "branches",
104		"meta": map[string]string{
105			"description":       "a short description",
106			"og:title":          "title displayed in social",
107			"og:description":    "description displayed in social",
108			"og:type":           "article",
109			"fediverse:creator": "@forge@gitroot.dev",
110		},
111		"layout": []layout{},
112	},
113}}
114
115type link struct {
116	Link    string `json:"link"`
117	Display string `json:"display"`
118}
119
120type layout struct {
121	Glob *glob.Glob `json:"glob"`
122	Path string     `json:"path"`
123}
124
125func (p *Plugin) newConf(serializedConf string) *conf {
126	jsonConf := gjson.Parse(serializedConf)
127	menus := []link{}
128	for _, l := range jsonConf.Get("menu").Array() {
129		menus = append(menus, link{
130			Link:    l.Get("link").String(),
131			Display: l.Get("display").String(),
132		})
133	}
134	layouts := []layout{}
135	for _, ljson := range jsonConf.Get("layout").Array() {
136		l := ljson.Get("glob").String()
137		if g, err := glob.NewGlob(l); err == nil {
138			layouts = append(layouts, layout{
139				Glob: g,
140				Path: ljson.Get("path").String(),
141			})
142		} else {
143			p.server.LogError(fmt.Sprintf("bad glob ignore layout %s", l), err)
144		}
145	}
146	metaJson := jsonConf.Get("meta").Map()
147	meta := make(map[string]string, len(metaJson))
148	for key, val := range metaJson {
149		meta[key] = val.String()
150	}
151	defaultBranch := jsonConf.Get("defaultBranch").String()
152	if defaultBranch == "" {
153		defaultBranch = "main"
154	}
155	style := jsonConf.Get("style").String()
156	if style == "" {
157		style = "simple.min.css"
158	}
159	return &conf{
160		defaultBranch:       defaultBranch,
161		style:               style,
162		favicon:             jsonConf.Get("favicon").String(),
163		header:              jsonConf.Get("header").String(),
164		menu:                menus,
165		footer:              jsonConf.Get("footer").String(),
166		generateGitWorktree: jsonConf.Get("generateGitWorktree").Bool(),
167		branchesDir:         jsonConf.Get("branchesDir").String(),
168		meta:                meta,
169		layout:              layouts,
170	}
171}