// SPDX-FileCopyrightText: 2025 Romain Maneschi // // SPDX-License-Identifier: EUPL-1.2 package main // compile cmd // tinygo build -o apex-0.0.1.wasm -scheduler=none --no-debug -target=wasi ./ import ( "bytes" _ "embed" "errors" "fmt" "io/fs" "path/filepath" "strings" gitroot "gitroot.dev/libs/golang/plugin" ) const simple = ` %s
%s
%s ` //go:embed resources/styles/add.css var addStyle string //go:embed resources/styles/pico.min.css var picoStyle string //go:embed resources/styles/simple.min.css var simpleStyle string //go:embed resources/index.md var index string type Plugin struct { server gitroot.Server repoName string config *conf gitWorktree *worktree currentCommit gitroot.Commit } func (p *Plugin) Init(repoName string, confHasChanged bool, serializedConf string) error { p.config = p.NewConf(serializedConf) p.repoName = repoName if p.config.generateGitWorktree { p.LoadWorktree() } // css style if _, err := fs.Stat(p.server.Webcontent(), "styles/style.css"); errors.Is(err, fs.ErrNotExist) || confHasChanged { style := "" if p.config.style == "pico.min.css" { style = picoStyle } else if p.config.style == "simple.min.css" { style = simpleStyle } else { // TODO download if distant? Copy if local? } p.server.ModifyWebContent(p.config.style, strings.Join([]string{style, addStyle}, "\n")) } else if err != nil { p.server.LogError("can't stats styles", err) } // index.html if _, err := fs.Stat(p.server.Webcontent(), "index.html"); errors.Is(err, fs.ErrNotExist) || confHasChanged { if _, err := fs.Stat(p.server.Worktree(), "index.html"); errors.Is(err, fs.ErrNotExist) { if _, err := fs.Stat(p.server.Worktree(), "index.md"); errors.Is(err, fs.ErrNotExist) { p.server.ModifyContent("index.md", index) p.server.CommitAllIfNeeded("init web page") p.AddFile("index.md") } else if err != nil { p.server.LogError("can't stats index.md in wortree", err) } } else if err != nil { p.server.LogError("can't stats index.html in wortree", err) } } else if err != nil { p.server.LogError("can't stats index in webContent", err) } // 404.html if _, err := fs.Stat(p.server.Webcontent(), "404.html"); errors.Is(err, fs.ErrNotExist) || confHasChanged { p.buildPage("404.md", []byte("Not found")) } return nil } func (p *Plugin) StartCommit(commit gitroot.Commit) error { p.currentCommit = commit return nil } func (p *Plugin) AddFile(fp string) error { if strings.HasSuffix(fp, ".md") { content, err := fs.ReadFile(p.server.Worktree(), fp) if err != nil { p.server.LogError("AddFile ReadFile "+fp, err) return nil } p.buildPage(fp, content) } else { content, err := fs.ReadFile(p.server.Worktree(), fp) if err != nil { p.server.LogError("AddFile ReadFile "+fp, err) return nil } p.server.ModifyWebContent(fp, string(content)) } if p.config.generateGitWorktree { p.gitWorktree.addOrModFile(fp, p.currentCommit) } return nil } func (p *Plugin) buildPage(fp string, mdContent []byte) { menu := p.buildMenu(fp) stylePath := relativePath(fp, p.config.style) newContent := fmt.Sprintf(simple, p.repoName, stylePath, p.config.header, menu, string(mdToHTML(mdContent, p.readInclude)), p.config.footer) p.server.ModifyWebContent(fmt.Sprintf("%s.html", strings.TrimSuffix(fp, ".md")), newContent) } func relativePath(fromPath string, toPath string) string { absFromPath, _ := filepath.Abs(fromPath) absToPath, _ := filepath.Abs(toPath) dirFromPath, _ := filepath.Split(absFromPath) dirToPath, fileToPath := filepath.Split(absToPath) path, err := filepath.Rel(dirFromPath, dirToPath) if err != nil { return toPath } return fmt.Sprintf("%s/%s", path, fileToPath) } func (p *Plugin) buildMenu(fp string) string { menu := bytes.NewBufferString("") return menu.String() } func (p *Plugin) readInclude(from, path string, address []byte) []byte { content, _ := fs.ReadFile(p.server.Worktree(), path) return content } func (p *Plugin) DelFile(fp string) error { if p.config.generateGitWorktree { p.gitWorktree.delFile(fp) } return nil } func (p *Plugin) ModFile(fromPath string, toPath string) error { if fromPath != toPath { p.DelFile(fromPath) } return p.AddFile(toPath) } func (p *Plugin) EndCommit(commit gitroot.Commit) error { return nil } func (p *Plugin) Finish() error { if p.config.generateGitWorktree { p.StoreWorktree() p.gitWorktree.renderHtml("", "worktree", func(fp string, htmlContent string) { menu := p.buildMenu(fp) stylePath := relativePath(fp, p.config.style) newContent := fmt.Sprintf(simple, p.repoName, stylePath, p.config.header, menu, htmlContent, p.config.footer) p.server.ModifyWebContent(fp, newContent) }) } p.config = nil p.gitWorktree = nil return nil } func Build(server gitroot.Server) gitroot.Plugin { return &Plugin{ server: server, } } //go:wasmexport install func main() { loadMimeType() loadEmojis() gitroot.Register(defaultRun, Build) }