From 83d175b7b069bc3bbc0d600c2fab4d082e04b521 Mon Sep 17 00:00:00 2001 From: Eddy Pedroni Date: Tue, 8 Apr 2025 17:01:55 +0200 Subject: Python implementation with better multi-entry page support --- Makefile | 15 ++++ README.md | 6 +- config.toml | 17 ---- entry.go | 78 ---------------- go.mod | 15 ---- go.sum | 12 --- godocs | Bin 5396957 -> 0 bytes godocs.py | 122 +++++++++++++++++++++++++ main.go | 63 ------------- markdown.go | 17 ---- nav.go | 24 ----- page.go | 64 ------------- requirements.txt | 4 + site.go | 56 ------------ style.css | 204 ------------------------------------------ template.go | 49 ---------- template.html | 28 ------ test/generation/config.toml | 10 +-- test/generation/template.html | 18 ++-- utils.go | 42 --------- 20 files changed, 157 insertions(+), 687 deletions(-) create mode 100644 Makefile delete mode 100644 config.toml delete mode 100644 entry.go delete mode 100644 go.mod delete mode 100644 go.sum delete mode 100755 godocs create mode 100644 godocs.py delete mode 100644 main.go delete mode 100644 markdown.go delete mode 100644 nav.go delete mode 100644 page.go create mode 100644 requirements.txt delete mode 100644 site.go delete mode 100644 style.css delete mode 100644 template.go delete mode 100644 template.html delete mode 100644 utils.go 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 diff --git a/README.md b/README.md index 125bdc4..2ab914b 100644 --- a/README.md +++ b/README.md @@ -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 -} diff --git a/go.mod b/go.mod deleted file mode 100644 index 5dc5777..0000000 --- a/go.mod +++ /dev/null @@ -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 -) diff --git a/go.sum b/go.sum deleted file mode 100644 index a8fd691..0000000 --- a/go.sum +++ /dev/null @@ -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= diff --git a/godocs b/godocs deleted file mode 100755 index 234d353..0000000 Binary files a/godocs and /dev/null differ diff --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 ") - 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 -} diff --git a/nav.go b/nav.go deleted file mode 100644 index c03c90a..0000000 --- a/nav.go +++ /dev/null @@ -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
, 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 
*/ -::-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::-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 @@ - - - - {{.SiteTitle}} - Docs - - - - - -
{{.SiteTitle}}
- -
- {{range .Content}} -
- {{.}} -
- {{end}} -
- - 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 @@ - {{.SiteTitle}} - Docs - + {{site_title}} - Docs + -
{{.SiteTitle}}
+
{{site_title}}
- {{range .Content}} + {% for entry in entries %}
- {{.}} + {% markdown %}{{ entry }}{% endmarkdown %}
- {{end}} + {% endfor %}
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 -} -- cgit v1.2.3