diff options
author | Eddy Pedroni <epedroni@pm.me> | 2025-04-08 17:01:55 +0200 |
---|---|---|
committer | Eddy Pedroni <epedroni@pm.me> | 2025-04-08 17:02:46 +0200 |
commit | 83d175b7b069bc3bbc0d600c2fab4d082e04b521 (patch) | |
tree | 9d1b7975ad16f7d5433285d3fab0a7cc38d24564 | |
parent | 38b40d8c5a8915716b3aa46aac4a0a84d0113b25 (diff) |
Python implementation with better multi-entry page support
-rw-r--r-- | Makefile | 15 | ||||
-rw-r--r-- | README.md | 6 | ||||
-rw-r--r-- | config.toml | 17 | ||||
-rw-r--r-- | entry.go | 78 | ||||
-rw-r--r-- | go.mod | 15 | ||||
-rw-r--r-- | go.sum | 12 | ||||
-rwxr-xr-x | godocs | bin | 5396957 -> 0 bytes | |||
-rw-r--r-- | godocs.py | 122 | ||||
-rw-r--r-- | main.go | 63 | ||||
-rw-r--r-- | markdown.go | 17 | ||||
-rw-r--r-- | nav.go | 24 | ||||
-rw-r--r-- | page.go | 64 | ||||
-rw-r--r-- | requirements.txt | 4 | ||||
-rw-r--r-- | site.go | 56 | ||||
-rw-r--r-- | style.css | 204 | ||||
-rw-r--r-- | template.go | 49 | ||||
-rw-r--r-- | template.html | 28 | ||||
-rw-r--r-- | test/generation/config.toml | 10 | ||||
-rw-r--r-- | test/generation/template.html | 18 | ||||
-rw-r--r-- | utils.go | 42 |
20 files changed, 157 insertions, 687 deletions
diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..1413295 --- /dev/null +++ b/Makefile @@ -0,0 +1,15 @@ +all: .venv test + +test: + rm -r /tmp/godocs-test + cp -r test /tmp/godocs-test + +clean: + rm -rf .venv + +.venv: requirements.txt + rm -rf .venv + uv venv + uv pip install -r requirements.txt + +.PHONY: all test clean @@ -1,10 +1,8 @@ # godocs HTML generator for the docs site. -## Build +## Build venv ``` -go build -o godocs +make ``` - -The `-o` is important, otherwise the binary ends up being called `godocs.git`. diff --git a/config.toml b/config.toml deleted file mode 100644 index bae7ca2..0000000 --- a/config.toml +++ /dev/null @@ -1,17 +0,0 @@ -# Test golog config -# These values are intended to generate a temporary, test version of the website that is navigable with a web browser - -# This is where the logbook entries are actually stored -docsRoot = "/home/eddy/projects/logbook" - -# All pages are generated from this template -templateFile = "/home/eddy/projects/godocs/template.html" - -# This is the location where the final product is located (the directory specified here is deleted and re-created with the new files) -targetDir = "/tmp/godocs_out" - -# This CSS file is copied to the root of the generated site -cssFile = "/home/eddy/projects/godocs/style.css" - -# This is the base URL for all generated links -baseUrl = "file:///tmp/godocs_out" diff --git a/entry.go b/entry.go deleted file mode 100644 index ddb3bd8..0000000 --- a/entry.go +++ /dev/null @@ -1,78 +0,0 @@ -package main - -import ( - "os" - "path/filepath" - "regexp" - "sort" - "strconv" -) - -/* - * This file contains all the code related to reading and processing entries - */ -type entry struct { - name string - rawName string - fullPath string -} - -type logEntry struct { - baseEntry entry - day int - month int - year int -} - -func findEntries(root string) (entries []Renderer) { - baseEntryRegex := regexp.MustCompile("([A-z\\-]+)\\.md") - logEntryRegex := regexp.MustCompile("(20[0-9]{2})-([0-9]{2})-([0-9]{2})-([A-z\\-]+)\\.md") - - logEntries := make([]logEntry, 0) - - err := filepath.Walk(root, func(p string, f os.FileInfo, e error) error { - if !f.IsDir() && baseEntryRegex.MatchString(f.Name()) { - baseCaptures := baseEntryRegex.FindStringSubmatch(f.Name()) - newBaseEntry := entry{name: nameify(baseCaptures[1]), - rawName: baseCaptures[1], - fullPath: p} - - if logEntryRegex.MatchString(f.Name()) { - logCaptures := logEntryRegex.FindStringSubmatch(f.Name()) - y, _ := strconv.Atoi(logCaptures[1]) - m, _ := strconv.Atoi(logCaptures[2]) - d, _ := strconv.Atoi(logCaptures[3]) - - newLogEntry := logEntry{ - baseEntry: newBaseEntry, - day: d, - month: m, - year: y} - logEntries = append(logEntries, newLogEntry) - } else { - entries = append(entries, newBaseEntry) - } - } - return nil - }) - if err != nil { - panic(err) - } - - sort.Slice(logEntries, func(i, j int) bool { - if logEntries[i].year != logEntries[j].year { - return logEntries[i].year > logEntries[j].year - } else if logEntries[i].month != logEntries[j].month { - return logEntries[i].month > logEntries[j].month - } else { - return logEntries[i].day > logEntries[j].day - } - }) - - // must append each manually: https://golang.org/doc/faq#convert_slice_of_interface - for _, e := range logEntries { - entries = append(entries, e) - } - - return -} @@ -1,15 +0,0 @@ -module git.0xf7.com/godocs.git - -go 1.23.4 - -require ( - github.com/BurntSushi/toml v1.4.0 - github.com/otiai10/copy v1.14.1 - github.com/russross/blackfriday/v2 v2.1.0 -) - -require ( - github.com/otiai10/mint v1.6.3 // indirect - golang.org/x/sync v0.8.0 // indirect - golang.org/x/sys v0.24.0 // indirect -) @@ -1,12 +0,0 @@ -github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= -github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= -github.com/otiai10/copy v1.14.1 h1:5/7E6qsUMBaH5AnQ0sSLzzTg1oTECmcCmT6lvF45Na8= -github.com/otiai10/copy v1.14.1/go.mod h1:oQwrEDDOci3IM8dJF0d8+jnbfPDllW6vUjNc3DoZm9I= -github.com/otiai10/mint v1.6.3 h1:87qsV/aw1F5as1eH1zS/yqHY85ANKVMgkDrf9rcxbQs= -github.com/otiai10/mint v1.6.3/go.mod h1:MJm72SBthJjz8qhefc4z1PYEieWmy8Bku7CjcAqyUSM= -github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= -github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= -golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= -golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= Binary files differdiff --git a/godocs.py b/godocs.py new file mode 100644 index 0000000..554fae9 --- /dev/null +++ b/godocs.py @@ -0,0 +1,122 @@ +from collections.abc import Iterator, Callable +from pathlib import Path +from dataclasses import dataclass +import click +import os +from urllib.parse import quote +from string import capwords +import shutil +import tempfile + +DRY = False + +@dataclass +class Page: + title: str + url: str + entries: list[Path] + output: Path + + @staticmethod + def create(source: Path, entries: list[Path], site_url: str, output_dir: Path): + title = capwords(source.stem.replace("-", " ")) + url = f"{site_url}/{quote(source.stem)}" + output = output_dir / source.stem / "index.html" + return Page(title, url, entries, output) + +def renderPageCallback(template_file: Path, stylesheet_url: str) -> Callable[[Page, str], None]: + """ Callback to process the provided page metadata and output the final page to the filesystem """ + from jinja2 import Environment, FileSystemLoader, select_autoescape + + env = Environment( + loader=FileSystemLoader(template_file.parent), + autoescape=select_autoescape(), + extensions=["jinja_markdown.MarkdownExtension"] + ) + template = env.get_template(template_file.name) + + def entries(page: Page) -> Iterator[str]: + for entry in page.entries: + with open(entry, "r") as f: + yield f.read() + + def render(page: Page, site_title: str, navigation: list[dict[str, str]]) -> None: + print(f"Rendering {page.output}") + args = {"site_title": site_title, "stylesheet_url": stylesheet_url, "navigation": navigation, "entries": entries(page)} + content = template.render(args) + if DRY: + print(content) + else: + os.makedirs(page.output.parent, exist_ok=True) + with open(page.output, "w") as f: + f.write(content) + + return render + +def collectPages(site_root: Path, site_url: str, output_dir: Path) -> Iterator[Page]: + """ Walk the site root collecting all the entries and organizing them into pages """ + for f in os.listdir(site_root): + page_path = site_root / f + + # Directories are rendered as one page with multiple entries + if os.path.isdir(page_path): + yield Page.create(page_path, list(page_path.glob("**/*.md")), site_url, output_dir) + + # Single .md files are rendered as single-entry pages + elif page_path.suffix == ".md": + yield Page.create(page_path, [page_path], site_url, output_dir) + +def generateSite(site_root: Path, base_url: str, output_dir: Path, render_page: Callable[[Page, str], None]) -> None: + """ Generate the site located at the specified root """ + print(f"Generating site rooted at {site_root}") + + site_url = f"{base_url}/{quote(site_root.stem)}" + site_dir = output_dir / site_root.stem + site_title = capwords(site_root.stem.replace("-", " ")) + + pages = [p for p in collectPages(site_root, site_url, site_dir)] + navigation = [{"text": p.title, "url": p.url} for p in pages] + for page in pages: + render_page(page, site_title, navigation) + + home = Page("Home", site_url, [], site_dir / "index.html") + render_page(home, site_title, navigation) + +def generateSites(config: dict[str, str]) -> None: + """ Generate all sites according to the specified config """ + docs_root = Path(config["docs_root"]) + output_dir = Path(config["output_dir"]) + template_file = Path(config["template_file"]) + css_file = Path(config["css_file"]) + base_url = config["base_url"] + stylesheet_url = f"{base_url}/{css_file.name}" + + render_page = renderPageCallback(template_file, stylesheet_url) + + with tempfile.TemporaryDirectory() as tmpdir: + for f in os.listdir(docs_root): + site = docs_root / f + if os.path.isdir(site): + generateSite(site, base_url, Path(tmpdir), render_page) + + shutil.copyfile(css_file, Path(tmpdir) / css_file.name) + + if output_dir.exists(): + shutil.rmtree(output_dir) + shutil.move(tmpdir, output_dir) + +@click.command() +@click.argument("config_file", nargs=1, type=click.Path()) +@click.option("--dry/--no-dry", default=False, help="Instead of generating the sites, print every step to stdout") +def main(config_file, dry): + global DRY + DRY = dry + + with open(config_file, "rb") as f: + import tomllib + config = tomllib.load(f) + + generateSites(config) + +if __name__ == '__main__': + main() diff --git a/main.go b/main.go deleted file mode 100644 index 5b444a8..0000000 --- a/main.go +++ /dev/null @@ -1,63 +0,0 @@ -package main - -import ( - "fmt" - "github.com/otiai10/copy" - "os" - "path/filepath" -) - -func main() { - // show usage if config file is missing - if len(os.Args) < 2 { - fmt.Println("Usage: godocs <config>") - os.Exit(1) - } - - // read config file specified in the command line - cfg := readConfig(os.Args[1]) - - // create temporary target directory - tmp := createTempDir("godocs") - defer os.RemoveAll(tmp) - - // gather all sites in docsRoot - sites := getSites(cfg) - - for _, site := range sites { - // collect all entries - entries := findEntries(site.sourcePath) - - // render all entries - createPageMap(&site, entries) - - // create navigation item slice - createNavSlice(&site, cfg) - - // output the site - generateSite(site, cfg, tmp) - } - - // copy CSS file to generation directory - err := copy.Copy(cfg.CssFile, filepath.Join(tmp, "style.css")) - if err != nil { - panic(err) - } - - // if we are here, generation succeeded, so we move the generated content to the target directory - err = os.RemoveAll(cfg.TargetDir) - if err != nil { - panic(err) - } - - err = os.Rename(tmp, cfg.TargetDir) - if err != nil { - panic(err) - } - - // fix because for some reason the generated directory ends up with the wrong permissions - err = os.Chmod(cfg.TargetDir, 0755) - if err != nil { - panic(err) - } -} diff --git a/markdown.go b/markdown.go deleted file mode 100644 index 3a2d33c..0000000 --- a/markdown.go +++ /dev/null @@ -1,17 +0,0 @@ -package main - -import ( - "github.com/russross/blackfriday/v2" - "io/ioutil" -) - -// Takes the path to a markdown file and outputs the processed HTML in a string -func processMarkdown(path string) (md string, err error) { - data, err := ioutil.ReadFile(path) - if err != nil { - return - } - - md = string(blackfriday.Run(data)) - return -} @@ -1,24 +0,0 @@ -package main - -import ( - "sort" - "strings" -) - -type navItem struct { - AbsoluteUrl string - Text string -} - -func createNavSlice(site *siteData, cfg config) { - for k, v := range site.pages { - if k != "" { - newNavItem := navItem{AbsoluteUrl: site.baseUrl + "/" + k, Text: v.pageName} - site.nav = append(site.nav, newNavItem) - } - } - - sort.Slice(site.nav, func(i, j int) bool { - return strings.Compare(site.nav[i].Text, site.nav[j].Text) < 0 - }) -} diff --git a/page.go b/page.go deleted file mode 100644 index be52e3c..0000000 --- a/page.go +++ /dev/null @@ -1,64 +0,0 @@ -package main - -import () - -/* - * This file contains all the code related to turning entries into HTML pages - */ -type page struct { - pageName string - content []string -} - -func (p *page) appendContent(c string) { - p.content = append(p.content, c) -} - -type Renderer interface { - render(pages map[string]page) (err error) -} - -func (e entry) render(pages map[string]page) (err error) { - md, err := processMarkdown(e.fullPath) - if err != nil { - return - } - - p := page{pageName: e.name, content: []string{md}} - - pages[e.rawName] = p - return -} - -func (le logEntry) render(pages map[string]page) (err error) { - md, err := processMarkdown(le.baseEntry.fullPath) - if err != nil { - return - } - - logUrl := "log" - - if val, ok := pages[logUrl]; ok { - val.appendContent(md) - pages[logUrl] = val - } else { - p := page{pageName: "Log", content: []string{md}} - pages[logUrl] = p - } - return -} - -func createPageMap(site *siteData, entries []Renderer) { - pages := make(map[string]page) - for _, e := range entries { - err := e.render(pages) - if err != nil { - panic(err) - } - } - - // create landing page - pages[""] = page{pageName: "Home"} - - site.pages = pages -} diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..589ec47 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +click==8.1.8 +markdown==3.7 +Jinja2==3.1.6 +jinja-markdown==1.210911 diff --git a/site.go b/site.go deleted file mode 100644 index 0098fd8..0000000 --- a/site.go +++ /dev/null @@ -1,56 +0,0 @@ -package main - -import ( - "io/ioutil" - "os" - "path/filepath" -) - -type siteData struct { - name string - rawName string - baseUrl string - sourcePath string - pages map[string]page - nav []navItem -} - -func getSites(cfg config) (sites []siteData) { - files, err := ioutil.ReadDir(cfg.DocsRoot) - if err != nil { - panic(err) - } - - for _, f := range files { - if f.IsDir() && f.Name() != ".git" { - newSite := siteData{ - name: nameify(f.Name()), - rawName: f.Name(), - baseUrl: cfg.BaseUrl + "/" + f.Name(), - sourcePath: filepath.Join(cfg.DocsRoot, f.Name())} - sites = append(sites, newSite) - } - } - - return -} - -func generateSite(site siteData, cfg config, outputDir string) { - template := loadTemplate(cfg) - templData := templateData{SiteTitle: site.name, - StylesheetUrl: cfg.BaseUrl + "/style.css", - Nav: site.nav} - for k, v := range site.pages { - templData.Content = v.content - err := applyTemplate(filepath.Join(outputDir, site.rawName, k), templData, template) - if err != nil { - panic(err) - } - } - - // link assets to generation directory - err := os.Symlink(filepath.Join(site.sourcePath, "assets"), filepath.Join(outputDir, site.rawName, "assets")) - if err != nil { - panic(err) - } -} diff --git a/style.css b/style.css deleted file mode 100644 index 5f1ca6c..0000000 --- a/style.css +++ /dev/null @@ -1,204 +0,0 @@ -/* Tango colour scheme: http://tango.freedesktop.org/Tango_Icon_Theme_Guidelines#Color_Palette */ -* { - --aluminium-light: #eeeeec; - --aluminium-medium: #d3d7cf; - --aluminium-dark: #babdb6; - - --slate-light: #888a85; - --slate-medium: #555753; - --slate-dark: #2e3436; - - --butter-light: #fce94f; - --butter-medium: #edd400; - --butter-dark: #c4a000; - - --chameleon-light: #8ae234; - --chameleon-medium: #73d216; - --chameleon-dark: #4e9a06; - - --orange-light: #fcaf3e; - --orange-medium: #f57900; - --orange-dark: #ce5c00; - - --chocolate-light: #e9b96e; - --chocolate-medium: #c17d11; - --chocolate-dark: #8f5902; - - --sky-blue-light: #729fcf; - --sky-blue-medium: #3465a4; - --sky-blue-dark: #204a87; - - --plum-light: #ad7fa8; - --plum-medium: #75507b; - --plum-dark: #5c3566; - - --scarlet-red-light: #ef2929; - --scarlet-red-medium: #cc0000; - --scarlet-red-dark: #a40000; -} - -body { - margin: 0; - background: black; - font-family: monospace; -} - -header { - position: fixed; - top: 0; - width: 100%; - color: var(--slate-medium); - background: black; - padding: 10px; - font-weight: bold; - font-size: 18px; -} - -main { - margin-left: 120px; - margin-top: 42px; -} - -/* Average article stuff */ -article, section { - margin-bottom: 20px; - margin-right: 10px; - padding: 6px; - background: var(--slate-dark); - border: 1px solid var(--slate-medium); - color: var(--aluminium-light); -} - -article a, section a { - color: var(--sky-blue-light); - text-decoration: none; -} - -article a:hover, section a:hover { - color: var(--sky-blue-medium); - text-decoration: none; -} - -h1 { - margin-top: 0; -} - -h1, h2, h3, h4, h5 { - color: var(--chameleon-light); -} - -p { - font-size: 14px; -} - -article li, section li { - font-size: 14px; - line-height: 1.3em; -} - -img { - display: block; - margin: 0 auto 0; - max-width: 100%; -} - -/* Inline code and program outputs */ -code, samp { - background: var(--slate-medium); - white-space: pre; -} - -/* If wrapped in <pre>, we get block code and program outputs */ -pre > code, pre > samp { - display: block; - overflow: auto; - border: 1px dashed var(--slate-light); - padding: 10px; - - background: var(--slate-medium); - line-height: 1.4em; - margin: 0 8px 0; -} - -/* Navigation */ -nav { - width: 120px; - position: fixed; - left: 0; - top: 41px; - height: 100%; - overflow-x: hidden; - overflow-x: auto; -} - -nav ul { - list-style: none; - padding: 0; -} - -nav a { - display: block; - padding: 2px; - color: var(--slate-medium); - text-decoration: none; - font-size: 16px; -} - -nav a:hover { - display: block; - padding: 2px; - color: var(--slate-light); - text-decoration: none; -} - -nav ul, nav ul ul { - margin: 0; -} - -nav ul { - padding-left: 5px; -} - -nav ul ul { - padding-left: 10px; - padding-bottom: 10px; -} - -/* Mouse highlight style */ -::selection { - background: var(--slate-light); -} - -/* Scrollbar style for <main> */ -::-webkit-scrollbar { - width: 8px; -} - -::-webkit-scrollbar-track { - background: black; -} - -::-webkit-scrollbar-thumb { - background: var(--slate-medium); -} - -::-webkit-scrollbar-thumb:hover { - background: var(--slate-light); -} - -/* Scrollbar style for <code> */ -code::-webkit-scrollbar { - height: 8px; -} - -code::-webkit-scrollbar-track { - background: var(--slate-medium); -} - -code::-webkit-scrollbar-thumb { - background: var(--slate-light); -} - -code::-webkit-scrollbar-thumb:hover { - background: var(--slate-light); -} diff --git a/template.go b/template.go deleted file mode 100644 index 413c15f..0000000 --- a/template.go +++ /dev/null @@ -1,49 +0,0 @@ -package main - -import ( - "io/ioutil" - "os" - "path/filepath" - "strings" - "text/template" -) - -type templateData struct { - SiteTitle string - StylesheetUrl string - Nav []navItem - Content []string -} - -func loadTemplate(cfg config) (templ *template.Template) { - tmpl_raw, err := ioutil.ReadFile(cfg.TemplateFile) - if err != nil { - panic(err) - } - templ, err = template.New("template").Parse(string(tmpl_raw)) - if err != nil { - panic(err) - } - return -} - -func applyTemplate(dir string, data templateData, tmpl *template.Template) error { - // ensure directory exists - os.MkdirAll(strings.ToLower(dir), 0755) - file := filepath.Join(strings.ToLower(dir), "index.html") - - // create file, fail if it already exists - f, err := os.Create(file) - if err != nil { - return err - } - defer f.Close() - - // apply template, write to file - err = tmpl.Execute(f, data) - if err != nil { - return err - } - - return nil -} diff --git a/template.html b/template.html deleted file mode 100644 index 1e56d6f..0000000 --- a/template.html +++ /dev/null @@ -1,28 +0,0 @@ -<!DOCTYPE html> -<html> - <head> - <title>{{.SiteTitle}} - Docs</title> - <link rel="stylesheet" href="{{.StylesheetUrl}}" /> - <meta charset="UTF-8"> - <meta name="author" content="Eduardo Pedroni"> - </head> - <body> - <header>{{.SiteTitle}}</header> - <nav> - <ul> - {{range .Nav}} - <li> - <a href="{{.AbsoluteUrl}}">{{.Text}}</a> - </li> - {{end}} - </ul> - </nav> - <main> - {{range .Content}} - <article> - {{.}} - </article> - {{end}} - </main> - </body> -</html> diff --git a/test/generation/config.toml b/test/generation/config.toml index 1e83ebc..e21890f 100644 --- a/test/generation/config.toml +++ b/test/generation/config.toml @@ -1,14 +1,14 @@ # This is where the logbook entries are actually stored -docsRoot = "/tmp/godocs-test/content" +docs_root = "/tmp/godocs-test/content" # All pages are generated from this template -templateFile = "/tmp/godocs-test/generation/template.html" +template_file = "/tmp/godocs-test/generation/template.html" # This is the location where the final product is located (the directory specified here is deleted and re-created with the new files) -targetDir = "/tmp/godocs-test/output" +output_dir = "/tmp/godocs-test/output" # This CSS file is copied to the root of the generated site -cssFile = "/tmp/godocs-test/generation/style.css" +css_file = "/tmp/godocs-test/generation/style.css" # This is the base URL for all generated links -baseUrl = "file:///tmp/godocs-test/output" +base_url = "file:///tmp/godocs-test/output" diff --git a/test/generation/template.html b/test/generation/template.html index 1e56d6f..c211cd8 100644 --- a/test/generation/template.html +++ b/test/generation/template.html @@ -1,28 +1,28 @@ <!DOCTYPE html> <html> <head> - <title>{{.SiteTitle}} - Docs</title> - <link rel="stylesheet" href="{{.StylesheetUrl}}" /> + <title>{{site_title}} - Docs</title> + <link rel="stylesheet" href="{{stylesheet_url}}" /> <meta charset="UTF-8"> <meta name="author" content="Eduardo Pedroni"> </head> <body> - <header>{{.SiteTitle}}</header> + <header>{{site_title}}</header> <nav> <ul> - {{range .Nav}} + {% for item in navigation %} <li> - <a href="{{.AbsoluteUrl}}">{{.Text}}</a> + <a href="{{item.url}}">{{item.text}}</a> </li> - {{end}} + {% endfor %} </ul> </nav> <main> - {{range .Content}} + {% for entry in entries %} <article> - {{.}} + {% markdown %}{{ entry }}{% endmarkdown %} </article> - {{end}} + {% endfor %} </main> </body> </html> diff --git a/utils.go b/utils.go deleted file mode 100644 index db36745..0000000 --- a/utils.go +++ /dev/null @@ -1,42 +0,0 @@ -package main - -import ( - "github.com/BurntSushi/toml" - "io/ioutil" - "os" - "strings" -) - -type config struct { - DocsRoot string - TemplateFile string - TargetDir string - CssFile string - BaseUrl string -} - -func readConfig(file string) (cfg config) { - _, err := toml.DecodeFile(file, &cfg) - if err != nil { - panic(err) - } - cfg.BaseUrl = strings.TrimSuffix(cfg.BaseUrl, "/") - return -} - -func nameify(raw string) (clean string) { - clean = strings.ReplaceAll(raw, "-", " ") - clean = strings.TrimSpace(clean) - clean = strings.Title(clean) - return -} - -func createTempDir(name string) (path string) { - path, err := ioutil.TempDir("", "godocs") - if err != nil { - panic(err) - } - defer os.RemoveAll(path) - - return -} |