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	language            string
 18	style               string
 19	favicon             string
 20	header              string
 21	menu                []link
 22	footer              string
 23	generateGitWorktree bool
 24	branchesDir         string
 25	meta                map[string]string
 26	layout              []layout
 27}
 28
 29var defaultRun = []gitroot.PluginRun{{
 30	Path:   "**/*",
 31	Branch: []string{"main"},
 32	When:   gitroot.PluginRunWhenAll,
 33	Func:   []gitroot.PluginFunc{{FuncName: "renderHtml", Args: []string{"fp", "html", "extraMedata"}, Res: []string{"html"}}},
 34	Write: gitroot.PluginWrite{
 35		Git: []gitroot.PluginWriteRight{{
 36			Path: "index.md",
 37			Can:  []gitroot.PluginWriteRightCan{gitroot.PluginWriteRightCanAdd},
 38		}},
 39		Web: []gitroot.PluginWriteRight{{
 40			Path: "**/*",
 41			Can:  gitroot.PluginWriteRightCanAll,
 42		}},
 43		Exec: []gitroot.PluginExecRight{},
 44		CallFunc: []gitroot.PluginCallFuncRight{
 45			{PluginPURL: PLUGIN_MARKDOWN, FuncName: PLUGIN_MARKDOWN_FUNC, Configuration: map[string]any{}},
 46			{PluginPURL: PLUGIN_CODE, FuncName: PLUGIN_CODE_FUNC, Configuration: map[string]any{}},
 47			{PluginPURL: PLUGIN_MERMAID, FuncName: PLUGIN_MERMAID_FUNC, Configuration: map[string]any{}}, //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()
 48		},
 49	},
 50	Configuration: map[string]any{
 51		"defaultBranch": "main",
 52		"language":      "en",
 53		"style":         "simple.min.css",
 54		"favicon":       "icon.png",
 55		"header":        "<h1>{{repo.name}}</h1>",
 56		"menu": []link{
 57			{Display: "🏠 Home", Link: "/"},
 58			{Display: "📖 Readme", Link: "/README.html"},
 59			{Display: "🐞 Issues", Link: "/boards/issues.html"},
 60			{Display: "⚖ Licence", Link: "/LICENCE.html"},
 61		},
 62		"footer":              "<p>Clone with <code>git clone {{repo.cloneUrl}}</code></p><small>Hosted with ❤️ by <a href=\"https://gitroot.dev\">GitRoot</a></small>",
 63		"generateGitWorktree": true,
 64		"branchesDir":         "branches",
 65		"meta": map[string]string{
 66			"description":       "a short description",
 67			"og:title":          "title displayed in social",
 68			"og:description":    "description displayed in social",
 69			"og:type":           "article",
 70			"fediverse:creator": "@forge@gitroot.dev",
 71		},
 72		"layout": []layout{},
 73	},
 74}, {
 75	Path:   "**/*",
 76	Branch: []string{"*", "!main"},
 77	When:   gitroot.PluginRunWhenAll,
 78	Func:   []gitroot.PluginFunc{},
 79	Write: gitroot.PluginWrite{
 80		Git: []gitroot.PluginWriteRight{},
 81		Web: []gitroot.PluginWriteRight{{
 82			Path: "branches/**/*",
 83			Can:  gitroot.PluginWriteRightCanAll,
 84		}},
 85		Exec: []gitroot.PluginExecRight{},
 86		CallFunc: []gitroot.PluginCallFuncRight{
 87			{PluginPURL: PLUGIN_MARKDOWN, FuncName: PLUGIN_MARKDOWN_FUNC, Configuration: map[string]any{}},
 88			{PluginPURL: PLUGIN_CODE, FuncName: PLUGIN_CODE_FUNC, Configuration: map[string]any{}},
 89			{PluginPURL: PLUGIN_MERMAID, FuncName: PLUGIN_MERMAID_FUNC, Configuration: map[string]any{}}, //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()
 90		},
 91	},
 92	Configuration: map[string]any{
 93		"defaultBranch": "main",
 94		"language":      "en",
 95		"style":         "simple.min.css",
 96		"favicon":       "icon.png",
 97		"header":        "<h1>{{repo.name}}</h1>",
 98		"menu": []link{
 99			{Display: "🏠 Home", Link: "/"},
100			{Display: "📖 Readme", Link: "/README.html"},
101			{Display: "🐞 Issues", Link: "/boards/issues.html"},
102			{Display: "⚖ Licence", Link: "/LICENCE.html"},
103		},
104		"footer":              "<p>Clone with <code>git clone {{repo.cloneUrl}}</code></p><small>Hosted with ❤️ by <a href=\"https://gitroot.dev\">GitRoot</a></small>",
105		"generateGitWorktree": false,
106		"branchesDir":         "branches",
107		"meta": map[string]string{
108			"description":       "a short description",
109			"og:title":          "title displayed in social",
110			"og:description":    "description displayed in social",
111			"og:type":           "article",
112			"fediverse:creator": "@forge@gitroot.dev",
113		},
114		"layout": []layout{},
115	},
116}}
117
118type link struct {
119	Link    string `json:"link"`
120	Display string `json:"display"`
121}
122
123type layout struct {
124	Glob *glob.Glob `json:"glob"`
125	Path string     `json:"path"`
126}
127
128func (p *Plugin) newConf(serializedConf string) *conf {
129	jsonConf := gjson.Parse(serializedConf)
130	menus := []link{}
131	for _, l := range jsonConf.Get("menu").Array() {
132		menus = append(menus, link{
133			Link:    l.Get("link").String(),
134			Display: l.Get("display").String(),
135		})
136	}
137	layouts := []layout{}
138	for _, ljson := range jsonConf.Get("layout").Array() {
139		l := ljson.Get("glob").String()
140		if g, err := glob.NewGlob(l); err == nil {
141			layouts = append(layouts, layout{
142				Glob: g,
143				Path: ljson.Get("path").String(),
144			})
145		} else {
146			p.server.LogError(fmt.Sprintf("bad glob ignore layout %s", l), err)
147		}
148	}
149	metaJson := jsonConf.Get("meta").Map()
150	meta := make(map[string]string, len(metaJson))
151	for key, val := range metaJson {
152		meta[key] = val.String()
153	}
154	defaultBranch := jsonConf.Get("defaultBranch").String()
155	if defaultBranch == "" {
156		defaultBranch = "main"
157	}
158	style := jsonConf.Get("style").String()
159	if style == "" {
160		style = "simple.min.css"
161	}
162	lang := jsonConf.Get("language").String()
163	if lang == "" {
164		lang = "en"
165	}
166	return &conf{
167		defaultBranch:       defaultBranch,
168		language:            lang,
169		style:               style,
170		favicon:             jsonConf.Get("favicon").String(),
171		header:              jsonConf.Get("header").String(),
172		menu:                menus,
173		footer:              jsonConf.Get("footer").String(),
174		generateGitWorktree: jsonConf.Get("generateGitWorktree").Bool(),
175		branchesDir:         jsonConf.Get("branchesDir").String(),
176		meta:                meta,
177		layout:              layouts,
178	}
179}