commit 7e97bdd091170ba3906d1b1f5cf0c781b8466f3a
parent 71227694331584f2d0958b1c251512438859db14
Author: gearsix <gearsix@tuta.io>
Date: Tue, 6 Jul 2021 16:57:27 +0100
finished comment doc; renamed content.go HTML conversion functions
txt2html -> convertTextToHTML and getMarkdown -> convertMarkdownToHTML.
Note markdown -> HTML conversion was moved to convertMarkdownToHTML for
tidyness.
Diffstat:
3 files changed, 54 insertions(+), 19 deletions(-)
diff --git a/config.go b/config.go
@@ -6,12 +6,15 @@ import (
"path/filepath"
)
+// Config is the data structure containing all key/values to be loaded
+// in pagr configuration files
type Config struct {
Contents string
Templates string
Output string
}
+// relPaths sets all filepath values in `cfg` relative to `dir`
func (cfg *Config) relPaths(dir string) {
var paths = []string{cfg.Contents, cfg.Templates, cfg.Output}
for i, path := range paths {
diff --git a/content.go b/content.go
@@ -3,6 +3,7 @@ package main
import (
"bufio"
"bytes"
+ "fmt"
"github.com/yuin/goldmark"
goldmarkext "github.com/yuin/goldmark/extension"
goldmarkparse "github.com/yuin/goldmark/parser"
@@ -15,10 +16,13 @@ import (
"strings"
)
+// SupportedContent provides a list of supported file extensions for Content files.
+// Any file in the Content directory not matching one of these will be ignored unless
+// it's a Meta file.
var SupportedContent = [5]string{
".txt", // plain-text
".html", // HTML
- ".md", // commonmark with non-intrusive extensions: linkify, auto heading id, unsafe HTML
+ ".md", // commonmark + extensions (linkify, auto-heading id, unsafe HTML)
".gfm", // github-flavoured markdown
".cm", // commonmark
}
@@ -79,7 +83,7 @@ func LoadContentDir(dir string) (c Content, e error) {
} else if strings.Contains(fpath, ".defaults") {
defaults[path] = m
}
- } else if isContentContentsExt(filepath.Ext(fpath)) > -1 {
+ } else if isSupportedContentExt(filepath.Ext(fpath)) > -1 {
page.NewContentsFromFile(fpath)
} else {
page.Assets = append(page.Assets, strings.TrimPrefix(fpath, path))
@@ -96,7 +100,7 @@ func LoadContentDir(dir string) (c Content, e error) {
return c, e
}
-func isContentContentsExt(ext string) int {
+func isSupportedContentExt(ext string) int {
for i, supported := range SupportedContent {
if ext == supported {
return i
@@ -105,8 +109,11 @@ func isContentContentsExt(ext string) int {
return -1
}
+// Meta is the structure any metadata is parsed into (_.toml_, _.json_, etc)
type Meta map[string]interface{}
+// MergeMeta merges `meta` into `m`. When there are matching keys in both,
+// `overwrite` determines whether the existing value in `m` is overwritten.
func (m Meta) MergeMeta(meta Meta, overwrite bool) {
for k, v := range meta {
if _, ok := m[k]; ok && overwrite {
@@ -117,6 +124,9 @@ func (m Meta) MergeMeta(meta Meta, overwrite bool) {
}
}
+// Page is the data structure loaded from Content files/folders that
+// gets passed to templates for execution after Content has been loaded.
+// This is the data structure to reference when writing a template!
type Page struct {
Path string
Meta Meta
@@ -124,6 +134,8 @@ type Page struct {
Assets []string
}
+// NewPage returns a Page with init values.
+// `.Path` will be set to `path`.
func NewPage(path string) Page {
return Page{
Path: path,
@@ -147,6 +159,12 @@ func (p *Page) GetTemplate() string {
}
}
+// NewContentsFromFile loads the file from `fpath` and converts it to HTML
+// from the language matching it's file extension (see below).
+// - ".txt" = plain-text
+// - ".md", ".gfm", ".cm" = various flavours of markdown
+// - ".html" = parsed as-is
+// Successful conversions are appended to `p.Contents`
func (p *Page) NewContentsFromFile(fpath string) (err error) {
var buf []byte
if f, err := os.Open(fpath); err == nil {
@@ -162,41 +180,37 @@ func (p *Page) NewContentsFromFile(fpath string) (err error) {
if filepath.Ext(fpath) == lang {
switch lang {
case ".txt":
- body = txt2html(bytes.NewReader(buf))
+ body = convertTextToHTML(bytes.NewReader(buf))
case ".md":
fallthrough
case ".gfm":
fallthrough
case ".cm":
- markdown := getMarkdown(lang)
- var out bytes.Buffer
- if err = markdown.Convert(buf, &out); err == nil {
- body = out.String()
- } else {
- return err
- }
+ body, err = convertMarkdownToHTML(lang, buf)
case ".html":
body = string(buf)
default:
- continue
+ break
}
}
}
-
if len(body) == 0 {
- panic("invalid filetype (" + filepath.Ext(fpath) + ") passed to NewContentsFromFile")
+ err = fmt.Errorf("invalid filetype (%s) passed to NewContentsFromFile",
+ filepath.Ext(fpath))
+ }
+ if err == nil {
+ p.Contents = append(p.Contents, body)
}
- p.Contents = append(p.Contents, body)
return err
}
-// txt2html parses textual data from `in` and line-by-line converts
+// convertTextToHTML parses textual data from `in` and line-by-line converts
// it to HTML. Conversion rules are as follows:
// - Blank lines (with escape characters trimmed) will close any opon tags
// - If a text line is prefixed with a tab and no tag is open, it will open a <pre> tag
// - Otherwise any line of text will open a <p> tag
-func txt2html(in io.Reader) (html string) {
+func convertTextToHTML(in io.Reader) (html string) {
var tag int
const p = 1
const pre = 2
@@ -236,7 +250,14 @@ func txt2html(in io.Reader) (html string) {
return html
}
-func getMarkdown(lang string) (markdown goldmark.Markdown) {
+// convertMarkdownToHTML initialises a `goldmark.Markdown` based on `lang` and
+// returns values from calling it's `Convert` function on `in`.
+// Markdown `lang` options, see the code for specfics:
+// - ".gfm" = github-flavoured markdown
+// - ".cm" = standard commonmark
+// - ".md" (and anything else) = commonmark + extensions (linkify, auto-heading id, unsafe HTML)
+func convertMarkdownToHTML(lang string, buf []byte) (string, error) {
+ var markdown goldmark.Markdown
switch lang {
case ".gfm":
markdown = goldmark.New(
@@ -272,5 +293,8 @@ func getMarkdown(lang string) (markdown goldmark.Markdown) {
),
)
}
- return
+
+ var out bytes.Buffer
+ err := markdown.Convert(buf, &out)
+ return out.String(), err
}
diff --git a/template.go b/template.go
@@ -8,8 +8,12 @@ import (
"notabug.org/gearsix/suti"
)
+// DefaultTemplate provides the default name for the template used
+// when one isn't specified in a `Page.Meta`.
const DefaultTemplate = "root"
+// loadPaths calls `filepath.Walk` on dir and loads all
+// non-directory filepaths in `dir`
func loadPaths(dir string) ([]string, error) {
var r []string
err := filepath.Walk(dir,
@@ -25,6 +29,10 @@ func loadPaths(dir string) ([]string, error) {
return r, err
}
+// LoadTemplateDir loads all files in `dir` that are not directories as a `suti.Template`
+// by calling `suti.LoadTemplateFile`. Partials for each template will be parsed from all
+// files in a directory matching the base filename of the template (not including
+// extension) if it exists.
func LoadTemplateDir(dir string) ([]suti.Template, error) {
paths := make(map[string][]string) // [template][]partials