From bdde3f53e1717d24ee974bf405ba8d8a943b8137 Mon Sep 17 00:00:00 2001 From: "Kirill Che." Date: Sat, 24 Feb 2024 00:46:47 +0400 Subject: [PATCH] refactor: render templates refactoring Add `helpers.tmpl` to render common parts. Add renderConfig to configure some static render behavior across different templates. --- _examples/complex-fields.md | 1 + _examples/complex.env | 3 +- _examples/complex.md | 1 + _examples/complex.txt | 1 + _examples/config.env | 5 ++- _examples/config.go | 3 ++ _examples/config.html | 1 + _examples/config.md | 2 + _examples/config.txt | 2 + _examples/envprefix.env | 3 +- _examples/envprefix.md | 1 + _examples/envprefix.txt | 1 + _examples/x_complex.md | 1 + generator.go | 24 ++++++---- render.go | 90 ++++++++++++++++++++++++++----------- render_test.go | 30 ++++++++----- templ/dotenv.tmpl | 65 +++++++-------------------- templ/helpers.tmpl | 55 +++++++++++++++++++++++ templ/html.tmpl | 53 ++++++---------------- templ/markdown.tmpl | 63 ++++++++------------------ templ/plaintext.tmpl | 61 +++++++------------------ templates.go | 47 +++++++++++++++++++ 22 files changed, 288 insertions(+), 225 deletions(-) create mode 100644 templ/helpers.tmpl create mode 100644 templates.go diff --git a/_examples/complex-fields.md b/_examples/complex-fields.md index 3ba3779..3f6a4d4 100644 --- a/_examples/complex-fields.md +++ b/_examples/complex-fields.md @@ -10,3 +10,4 @@ FieldNames uses field names as env names. - `QUUX` - Quux is a field with a tag. - `FOO_BAR` (default: `quuux`) - FooBar is a field with a default value. - `REQUIRED` (**required**) - Required is a required field. + diff --git a/_examples/complex.env b/_examples/complex.env index e1b633c..5804cb5 100644 --- a/_examples/complex.env +++ b/_examples/complex.env @@ -50,4 +50,5 @@ ## FieldNames uses field names as env names. # ## Quux is a field with a tag. -# QUUX="" \ No newline at end of file +# QUUX="" + diff --git a/_examples/complex.md b/_examples/complex.md index e6d895a..4c41e7b 100644 --- a/_examples/complex.md +++ b/_examples/complex.md @@ -27,3 +27,4 @@ It is trying to cover all the possible cases. FieldNames uses field names as env names. - `QUUX` - Quux is a field with a tag. + diff --git a/_examples/complex.txt b/_examples/complex.txt index 4cc5afa..1f2a398 100644 --- a/_examples/complex.txt +++ b/_examples/complex.txt @@ -27,3 +27,4 @@ It is trying to cover all the possible cases. FieldNames uses field names as env names. * `QUUX` - Quux is a field with a tag. + diff --git a/_examples/config.env b/_examples/config.env index 87cfefc..4d32876 100644 --- a/_examples/config.env +++ b/_examples/config.env @@ -14,4 +14,7 @@ # PORT="" ## Debug mode enabled. ## (default: 'false') -# DEBUG="false" \ No newline at end of file +# DEBUG="false" +## Prefix for something. +# PREFIX="" + diff --git a/_examples/config.go b/_examples/config.go index 6db8c4d..e62a0a3 100644 --- a/_examples/config.go +++ b/_examples/config.go @@ -16,4 +16,7 @@ type Config struct { // Debug mode enabled. Debug bool `env:"DEBUG" envDefault:"false"` + + // Prefix for something. + Prefix string `env:"PREFIX"` } diff --git a/_examples/config.html b/_examples/config.html index b2b8da7..b16feb0 100644 --- a/_examples/config.html +++ b/_examples/config.html @@ -84,6 +84,7 @@

Config

  • HOST (separated by ";", required) - Hosts name of hosts to listen on.
  • PORT (required, non-empty) - Port to listen on.
  • DEBUG (default: false) - Debug mode enabled.
  • +
  • PREFIX - Prefix for something.
  • diff --git a/_examples/config.md b/_examples/config.md index b29ceb4..7a8f82f 100644 --- a/_examples/config.md +++ b/_examples/config.md @@ -9,3 +9,5 @@ using the commands below. - `HOST` (separated by `;`, **required**) - Hosts name of hosts to listen on. - `PORT` (**required**, non-empty) - Port to listen on. - `DEBUG` (default: `false`) - Debug mode enabled. + - `PREFIX` - Prefix for something. + diff --git a/_examples/config.txt b/_examples/config.txt index cb6e4cf..5eb7ebe 100644 --- a/_examples/config.txt +++ b/_examples/config.txt @@ -9,3 +9,5 @@ using the commands below. * `HOST` (separated by `;`, required) - Hosts name of hosts to listen on. * `PORT` (required, non-empty) - Port to listen on. * `DEBUG` (default: `false`) - Debug mode enabled. + * `PREFIX` - Prefix for something. + diff --git a/_examples/envprefix.env b/_examples/envprefix.env index 3939fa4..52550c1 100644 --- a/_examples/envprefix.env +++ b/_examples/envprefix.env @@ -38,4 +38,5 @@ ## (default: '30') # SERVER_TIMEOUT_WRITE="30" ## Debug is the debug flag -# DEBUG="" \ No newline at end of file +# DEBUG="" + diff --git a/_examples/envprefix.md b/_examples/envprefix.md index 195a427..7a492fd 100644 --- a/_examples/envprefix.md +++ b/_examples/envprefix.md @@ -17,3 +17,4 @@ Settings is the application settings. - `SERVER_TIMEOUT_READ` (default: `30`) - Read is the read timeout - `SERVER_TIMEOUT_WRITE` (default: `30`) - Write is the write timeout - `DEBUG` - Debug is the debug flag + diff --git a/_examples/envprefix.txt b/_examples/envprefix.txt index 7b36901..0d6df14 100644 --- a/_examples/envprefix.txt +++ b/_examples/envprefix.txt @@ -17,3 +17,4 @@ Settings is the application settings. * `SERVER_TIMEOUT_READ` (default: `30`) - Read is the read timeout * `SERVER_TIMEOUT_WRITE` (default: `30`) - Write is the write timeout * `DEBUG` - Debug is the debug flag + diff --git a/_examples/x_complex.md b/_examples/x_complex.md index 84152b5..9f62d97 100644 --- a/_examples/x_complex.md +++ b/_examples/x_complex.md @@ -27,3 +27,4 @@ It is trying to cover all the possible cases. FieldNames uses field names as env names. - `X_QUUX` - Quux is a field with a tag. + diff --git a/generator.go b/generator.go index d70c9f3..9b6e7f4 100644 --- a/generator.go +++ b/generator.go @@ -6,14 +6,15 @@ import ( ) type generator struct { - fileName string - execLine int - targetType string - all bool // generate documentation for all types in the file - tmpl template - prefix string - noStyles bool - fieldNames bool + fileName string + execLine int + targetType string + all bool // generate documentation for all types in the file + tmpl template + renderConfig renderConfig + prefix string + noStyles bool + fieldNames bool } type generatorOption func(*generator) error @@ -41,12 +42,16 @@ func withFormat(formatName string) generatorOption { fallthrough case "markdown": g.tmpl = tmplMarkdown + g.renderConfig = renderMarkdown case "plaintext": g.tmpl = tmplPlaintext + g.renderConfig = renderPlaintext case "html": g.tmpl = tmplHTML + g.renderConfig = renderHTML case "dotenv": g.tmpl = tmplDotEnv + g.renderConfig = renderDotenv default: return fmt.Errorf("unknown format: %s", formatName) } @@ -84,6 +89,7 @@ func newGenerator(fileName string, execLine int, opts ...generatorOption) (*gene } if g.tmpl == nil { g.tmpl = tmplMarkdown + g.renderConfig = renderMarkdown } return g, nil } @@ -95,7 +101,7 @@ func (g *generator) generate(out io.Writer) error { return fmt.Errorf("inspect file: %w", err) } renderer := templateRenderer(g.tmpl) - rctx := newRenderContext(data, g.prefix, g.noStyles) + rctx := newRenderContext(data, g.renderConfig, g.prefix, g.noStyles) if err := renderer(rctx, out); err != nil { return err } diff --git a/render.go b/render.go index 4f274ac..9c03014 100644 --- a/render.go +++ b/render.go @@ -1,13 +1,8 @@ package main import ( - "embed" "fmt" "io" - "strings" - - htmltmpl "html/template" - texttmpl "text/template" ) type renderSection struct { @@ -41,16 +36,31 @@ func (i renderItem) Children(indentInc int) []renderItem { return res } +type renderItemConfigt struct { + SeparatorFormat string + SeparatorDefault string + OptRequired string + OptExpand string + OptNonEmpty string + OptFromFile string + EnvDefaultFormat string +} +type renderConfig struct { + Item renderItemConfigt +} + type renderContext struct { Title string Sections []renderSection Styles bool + Config renderConfig } -func newRenderContext(scopes []*EnvScope, envPrefix string, noStyles bool) renderContext { +func newRenderContext(scopes []*EnvScope, cfg renderConfig, envPrefix string, noStyles bool) renderContext { res := renderContext{ Sections: make([]renderSection, len(scopes)), Styles: !noStyles, + Config: cfg, } res.Title = "Environment Variables" for i, scope := range scopes { @@ -90,26 +100,56 @@ func newRenderItem(item *EnvDocItem, envPrefix string) renderItem { } } -//go:embed templ -var templates embed.FS - -var tplFuncs = map[string]any{ - "repeat": strings.Repeat, - "split": strings.Split, - "strAppend": func(arr []string, item string) []string { - return append(arr, item) - }, - "join": strings.Join, - "strSlice": func() []string { - return make([]string, 0) - }, -} - var ( - tmplMarkdown = texttmpl.Must(texttmpl.New("markdown.tmpl").Funcs(tplFuncs).ParseFS(templates, "templ/markdown.tmpl")) - tmplHTML = htmltmpl.Must(htmltmpl.New("html.tmpl").Funcs(tplFuncs).ParseFS(templates, "templ/html.tmpl")) - tmplPlaintext = texttmpl.Must(texttmpl.New("plaintext.tmpl").Funcs(tplFuncs).ParseFS(templates, "templ/plaintext.tmpl")) - tmplDotEnv = texttmpl.Must(texttmpl.New("dotenv.tmpl").Funcs(tplFuncs).ParseFS(templates, "templ/dotenv.tmpl")) + tmplMarkdown = newTmplText("markdown.tmpl") + tmplHTML = newTmplText("html.tmpl") + tmplPlaintext = newTmplText("plaintext.tmpl") + tmplDotEnv = newTmplText("dotenv.tmpl") + + renderMarkdown = renderConfig{ + Item: renderItemConfigt{ + SeparatorFormat: "separated by `%s`", + SeparatorDefault: "comma-separated", + OptRequired: "**required**", + OptExpand: "expand", + OptFromFile: "from-file", + OptNonEmpty: "non-empty", + EnvDefaultFormat: "default: `%s`", + }, + } + renderPlaintext = renderConfig{ + Item: renderItemConfigt{ + SeparatorFormat: "separated by `%s`", + SeparatorDefault: "comma-separated", + OptRequired: "required", + OptExpand: "expand", + OptFromFile: "from-file", + OptNonEmpty: "non-empty", + EnvDefaultFormat: "default: `%s`", + }, + } + renderDotenv = renderConfig{ + Item: renderItemConfigt{ + SeparatorFormat: "separated by '%s'", + SeparatorDefault: "comma-separated", + OptRequired: "required", + OptExpand: "expand", + OptFromFile: "from-file", + OptNonEmpty: "non-empty", + EnvDefaultFormat: "default: '%s'", + }, + } + renderHTML = renderConfig{ + Item: renderItemConfigt{ + SeparatorFormat: `separated by "%s"`, + SeparatorDefault: "comma-separated", + OptRequired: "required", + OptExpand: "expand", + OptFromFile: "from-file", + OptNonEmpty: "non-empty", + EnvDefaultFormat: "default: %s", + }, + } ) type template interface { diff --git a/render_test.go b/render_test.go index 7797518..78d1fcc 100644 --- a/render_test.go +++ b/render_test.go @@ -77,7 +77,7 @@ var testRenderSections = []renderSection{ func TestRender(t *testing.T) { t.Run("simple", func(t *testing.T) { rc := renderContext{Title: "Simple", Sections: []renderSection{{Items: testRenderItems}}} - t.Run("markdown", testRenderer(tmplMarkdown, rc, + t.Run("markdown", testRenderer(tmplMarkdown, rc, renderMarkdown, "# Simple", "- `TEST_ENV` - This is a test environment variable.", "- `TEST_ENV2` (comma-separated, default: `default value`) - This is another test environment variable.", @@ -87,8 +87,9 @@ func TestRender(t *testing.T) { " - `NESTED_ENV2` - This is a second nested environment variable.", " - Nested item level two", " - `NESTED_ENV3` - This is a third nested environment variable.", + "", )) - t.Run("plaintext", testRenderer(tmplPlaintext, rc, + t.Run("plaintext", testRenderer(tmplPlaintext, rc, renderPlaintext, "Simple", " * `TEST_ENV` - This is a test environment variable.", " * `TEST_ENV2` (comma-separated, default: `default value`) - This is another test environment variable.", @@ -98,8 +99,9 @@ func TestRender(t *testing.T) { " * `NESTED_ENV2` - This is a second nested environment variable.", " * Nested item level two", " * `NESTED_ENV3` - This is a third nested environment variable.", + "", )) - t.Run("html", testRenderer(tmplHTML, rc, + t.Run("html", testRenderer(tmplHTML, rc, renderHTML, ``, ``, ``, @@ -132,21 +134,25 @@ func TestRender(t *testing.T) { }) t.Run("sections", func(t *testing.T) { rc := renderContext{Title: "Sections", Sections: testRenderSections, Styles: true} - t.Run("markdown", testRenderer(tmplMarkdown, rc, + t.Run("markdown", testRenderer(tmplMarkdown, rc, renderMarkdown, "# Sections", "## First", " - `ONE` - First one", " - `TWO` - First two", "## Second", - " - `THREE` - Second three")) - t.Run("plaintext", testRenderer(tmplPlaintext, rc, + " - `THREE` - Second three", + "", + )) + t.Run("plaintext", testRenderer(tmplPlaintext, rc, renderPlaintext, "Sections", "## First", " * `ONE` - First one", " * `TWO` - First two", "## Second", - " * `THREE` - Second three")) - t.Run("html", testRenderer(tmplHTML, rc, + " * `THREE` - Second three", + "", + )) + t.Run("html", testRenderer(tmplHTML, rc, renderHTML, ``, ``, ``, @@ -169,7 +175,8 @@ func TestRender(t *testing.T) { ``, ``, ``, - ``)) + ``, + )) }) } @@ -194,7 +201,7 @@ func TestNewRenderContext(t *testing.T) { }, }, } - rc := newRenderContext(src, "PREFIX_", false) + rc := newRenderContext(src, renderPlaintext, "PREFIX_", false) const title = "Environment Variables" if rc.Title != title { t.Errorf("expected title %q, got %q", title, rc.Title) @@ -235,8 +242,9 @@ func TestNewRenderContext(t *testing.T) { } } -func testRenderer(tmpl template, c renderContext, expectLines ...string) func(*testing.T) { +func testRenderer(tmpl template, c renderContext, cfg renderConfig, expectLines ...string) func(*testing.T) { return func(t *testing.T) { + c.Config = cfg var buf bytes.Buffer r := templateRenderer(tmpl) err := r(c, &buf) diff --git a/templ/dotenv.tmpl b/templ/dotenv.tmpl index 5477754..86ac7cb 100644 --- a/templ/dotenv.tmpl +++ b/templ/dotenv.tmpl @@ -1,72 +1,41 @@ -{{/* -Render doc lines: split doc by newline and prefix with `##` each line. -*/}} -{{- define "doc.lines" }} - {{- if . }} - {{- $docLines := split . "\n" }} - {{- range $line := $docLines }} -## {{ $line }} - {{- end }} - {{- end }} -{{- end -}} - {{- define "item" }} - {{- if eq .EnvName "" }} + {{- $ := index . 0 }} + {{- $cfg := index . 1 }} + {{- if eq $.EnvName "" }} # {{- end }} - {{- template "doc.lines" .Doc }} - {{- if .EnvName }} - {{- if .Doc }} + {{- template "doc.lines" (list $.Doc "##") }} + {{- if $.EnvName }} + {{- if $.Doc }} {{- printf "\n" }} {{- end }} - {{- $opts := strSlice }} - {{- if eq .EnvSeparator "," }} - {{- $opts = (strAppend $opts "comma-separated") }} - {{- else if ne .EnvSeparator "" }} - {{- $opts = (printf "separated by '%s'" .EnvSeparator | strAppend $opts) }} - {{- end }} - {{- if .Required }} - {{- $opts = (strAppend $opts "required") }} - {{- end }} - {{- if .Expand }} - {{- $opts = (strAppend $opts "expand") }} - {{- end }} - {{- if .NonEmpty }} - {{- $opts = (strAppend $opts "non-empty") }} - {{- end }} - {{- if .FromFile }} - {{- $opts = (strAppend $opts "from-file") }} - {{- end }} - {{- if ne .EnvDefault "" }} - {{- $opts = (printf "default: '%s'" .EnvDefault | strAppend $opts) }} - {{- end }} - {{- if $opts }} - {{- join $opts ", " | printf "## (%s)\n" }} - {{- end }} - {{- if .EnvDefault }} - {{- printf `# %s="%s"` .EnvName .EnvDefault }} + {{- template "item.options" (list $ $cfg "## (%s)\n") }} + {{- if $.EnvDefault }} + {{- printf `# %s="%s"` $.EnvName $.EnvDefault }} {{- else }} - {{- printf `# %s=""` .EnvName }} + {{- printf `# %s=""` $.EnvName }} {{- end }} {{- end }} - {{- $children := .Children 0 }} + {{- $children := $.Children 0 }} {{- if $children }} # {{- range $child := $children }} - {{- template "item" $child }} + {{- template "item" (list $child $cfg) }} {{- end }} {{- end }} {{- end -}} +{{- $cfg := $.Config -}} # {{ .Title }} {{ range .Sections }} {{- print "\n" }} {{- if .Name }} ## {{ .Name }} {{- end }} - {{- template "doc.lines" .Doc }} + {{- template "doc.lines" (list .Doc "##") }} # {{- range $item := .Items }} - {{- template "item" $item }} + {{- template "item" (list $item $cfg.Item) }} {{- end }} -{{- end -}} +{{- end }} + diff --git a/templ/helpers.tmpl b/templ/helpers.tmpl new file mode 100644 index 0000000..626dcaa --- /dev/null +++ b/templ/helpers.tmpl @@ -0,0 +1,55 @@ +{{/* +Render doc lines: split doc by newline and prefix with `##` each line. +*/}} +{{- define "doc.lines" }} + {{- $ := index . 0 }} + {{- $prefix := index . 1 }} + {{- if $ }} + {{- $docLines := split $ "\n" }} + {{- range $line := $docLines }} +{{ $prefix }} {{ $line }} + {{- end }} + {{- end }} +{{- end -}} + +{{/* +Render item options using items config (inline rendering). +*/}} +{{- define "item.options" -}} + {{- $ := index . 0 -}} + {{- $cfg := index . 1 -}} + {{- $format := index . 2 -}} + {{/* + SeparatorFormat string + SeparatorDefault string + OptRequired string + OptExpand string + OptNonEmpty string + OptFromFile string + EnvDefaultFormat string + */}} + {{- $opts := strSlice -}} + {{- if eq $.EnvSeparator "," -}} + {{- $opts = (strAppend $opts $cfg.SeparatorDefault) -}} + {{- else if $.EnvSeparator -}} + {{- $opts = (printf $cfg.SeparatorFormat $.EnvSeparator | strAppend $opts) -}} + {{- end }} + {{- if $.Required -}} + {{- $opts = (strAppend $opts $cfg.OptRequired) -}} + {{- end -}} + {{- if $.Expand -}} + {{- $opts = (strAppend $opts $cfg.OptExpand) -}} + {{- end -}} + {{- if $.NonEmpty -}} + {{- $opts = (strAppend $opts $cfg.OptNonEmpty) -}} + {{- end -}} + {{- if $.FromFile -}} + {{- $opts = (strAppend $opts $cfg.OptFromFile) -}} + {{- end -}} + {{- if $.EnvDefault -}} + {{- $opts = (printf $cfg.EnvDefaultFormat $.EnvDefault | strAppend $opts) -}} + {{- end -}} + {{- if $opts -}} + {{- join $opts ", " | printf $format -}} + {{- end -}} +{{- end -}} diff --git a/templ/html.tmpl b/templ/html.tmpl index 6799714..2507a1b 100644 --- a/templ/html.tmpl +++ b/templ/html.tmpl @@ -1,54 +1,27 @@ {{- define "item" }} + {{- $ := index . 0 }} + {{- $cfg := index . 1 }}
  • {{- $comma := false -}} - {{- if .EnvName -}} - {{ .EnvName }} - {{- if eq .EnvSeparator "," -}} - {{- $comma = true }} (comma-separated - {{- else if ne .EnvSeparator "" -}} - {{- $comma = true }} (separated by "{{.EnvSeparator}}" - {{- end -}} - {{- if .Required -}} - {{- if $comma }}, {{ else }} ({{ end -}} - {{- $comma = true -}} - required - {{- end -}} - {{- if .Expand -}} - {{- if $comma }}, {{ else }} ({{ end -}} - {{- $comma = true -}} - expand - {{- end -}} - {{- if .NonEmpty -}} - {{- if $comma }}, {{ else }} ({{ end -}} - {{- $comma = true -}} - non-empty - {{- end -}} - {{if .FromFile -}} - {{- if $comma }}, {{ else }} ({{ end -}} - {{- $comma = true -}} - from-file - {{- end -}} - {{- if ne .EnvDefault "" -}} - {{- if $comma }}, {{ else }} ({{ end -}} - {{- $comma = true -}} - default: {{ .EnvDefault }} - {{- end -}} - {{- if $comma }}){{ end -}} - {{- .Doc | printf " - %s" -}} + {{- if $.EnvName -}} + {{ $.EnvName }} + {{- template "item.options" (list $ $cfg " (%s)") }} + {{- $.Doc | printf " - %s" -}} {{- else -}} - {{- .Doc | printf "%s" -}} + {{- $.Doc | printf "%s" -}} {{- end}} - {{- $children := .Children 0 -}} + {{- $children := $.Children 0 -}} {{- if $children }} {{ end -}}
  • {{- end -}} +{{- $cfg := $.Config -}} @@ -134,8 +107,8 @@ p {

    {{ .Doc }}

    {{- end }} {{ end }} diff --git a/templ/markdown.tmpl b/templ/markdown.tmpl index 3e7c140..70a1af7 100644 --- a/templ/markdown.tmpl +++ b/templ/markdown.tmpl @@ -1,60 +1,33 @@ {{- define "item" }} - {{- $comma := false -}} - {{- repeat " " .Indent -}} - {{- if .EnvName }} - {{- .EnvName | printf "- `%s`" -}} - {{- if eq .EnvSeparator "," -}} - {{- $comma = true }} (comma-separated - {{- else if ne .EnvSeparator "" -}} - {{- $comma = true }} (separated by `{{.EnvSeparator}}` - {{- end -}} - {{- if .Required -}} - {{- if $comma }}, {{ else }} ({{ end -}} - {{- $comma = true -}} - **required** - {{- end -}} - {{- if .Expand -}} - {{- if $comma }}, {{ else }} ({{ end -}} - {{- $comma = true -}} - expand - {{- end -}} - {{- if .NonEmpty -}} - {{- if $comma }}, {{ else }} ({{ end -}} - {{- $comma = true -}} - non-empty - {{- end -}} - {{if .FromFile -}} - {{- if $comma }}, {{ else }} ({{ end -}} - {{- $comma = true -}} - from-file - {{- end -}} - {{- if ne .EnvDefault "" -}} - {{- if $comma }}, {{ else }} ({{ end -}} - {{- $comma = true -}} - {{- .EnvDefault | printf "default: `%s`" -}} - {{- end -}} - {{- if $comma }}){{ end -}} - {{- .Doc | printf " - %s"}} + {{- $ := index . 0 }} + {{- $cfg := index . 1 }} + {{- $indent := index . 2 }} + {{- repeat " " $indent }} + {{- if $.EnvName }} + {{- $.EnvName | printf "- `%s`" }} + {{- template "item.options" (list $ $cfg " (%s)") }} + {{- $.Doc | printf " - %s" }} {{- else }} - {{- .Doc | printf "- %s" }} + {{- $.Doc | printf "- %s" }} {{- end }} - {{- $children := .Children 2 }} + {{- $children := $.Children 0 }} {{- if $children }} - {{- range $children }} -{{ template "item" . }} + {{- range $child := $children }} +{{ template "item" (list $child $cfg (sum $indent 2)) }} {{- end }} {{- end -}} {{ end -}} +{{- $cfg := $.Config -}} # {{ .Title }} {{ range .Sections -}} -{{ if ne .Name "" }} +{{ if .Name }} ## {{ .Name }} {{ end }} -{{- if ne .Doc "" }} +{{- if .Doc }} {{ .Doc }} {{ end }} -{{ range .Items }} -{{- template "item" . }} -{{ end -}} +{{ range $item := .Items }} +{{- template "item" (list $item $cfg.Item 1) }} {{ end -}} +{{ end }} diff --git a/templ/plaintext.tmpl b/templ/plaintext.tmpl index 5f9250b..54e232b 100644 --- a/templ/plaintext.tmpl +++ b/templ/plaintext.tmpl @@ -1,58 +1,31 @@ {{- define "item" }} - {{- $comma := false -}} - {{- repeat " " .Indent -}} - {{- if .EnvName }} - {{- .EnvName | printf "* `%s`" -}} - {{- if eq .EnvSeparator "," -}} - {{- $comma = true }} (comma-separated - {{- else if ne .EnvSeparator "" -}} - {{- $comma = true }} (separated by `{{.EnvSeparator}}` - {{- end -}} - {{- if .Required -}} - {{- if $comma }}, {{ else }} ({{ end -}} - {{- $comma = true -}} - required - {{- end -}} - {{- if .Expand -}} - {{- if $comma }}, {{ else }} ({{ end -}} - {{- $comma = true -}} - expand - {{- end -}} - {{- if .NonEmpty -}} - {{- if $comma }}, {{ else }} ({{ end -}} - {{- $comma = true -}} - non-empty - {{- end -}} - {{if .FromFile -}} - {{- if $comma }}, {{ else }} ({{ end -}} - {{- $comma = true -}} - from-file - {{- end -}} - {{- if ne .EnvDefault "" -}} - {{- if $comma }}, {{ else }} ({{ end -}} - {{- $comma = true -}} - {{- .EnvDefault | printf "default: `%s`" -}} - {{- end -}} - {{- if $comma }}){{ end -}} - {{- .Doc | printf " - %s" }} + {{- $ := index . 0 }} + {{- $cfg := index . 1 }} + {{- $indent := index . 2 }} + {{- repeat " " $indent }} + {{- if $.EnvName }} + {{- $.EnvName | printf "* `%s`" -}} + {{- template "item.options" (list $ $cfg " (%s)") }} + {{- $.Doc | printf " - %s" }} {{- else }} - {{- .Doc | printf "* %s" }} + {{- $.Doc | printf "* %s" }} {{- end }} - {{- $children := .Children 2 }} + {{- $children := $.Children 0 }} {{- if $children }} - {{- range $children }} -{{ template "item" . }} + {{- range $child := $children }} +{{ template "item" (list $child $cfg (sum $indent 2)) }} {{- end }} {{- end -}} {{ end -}} +{{- $cfg := $.Config -}} {{ .Title }} {{ range .Sections }} ## {{ .Name }} -{{ if ne .Doc "" }} +{{ if .Doc }} {{ .Doc }} {{ end }} -{{ range .Items }} -{{- template "item" . }} -{{ end -}} +{{ range $item := .Items }} +{{- template "item" (list $item $cfg.Item 1) }} {{ end -}} +{{ end }} diff --git a/templates.go b/templates.go new file mode 100644 index 0000000..3be6e12 --- /dev/null +++ b/templates.go @@ -0,0 +1,47 @@ +package main + +import ( + "embed" + "path" + "strings" + + texttmpl "text/template" +) + +//go:embed templ +var templatesFS embed.FS + +var tplFuncs = map[string]any{ + "repeat": strings.Repeat, + "split": strings.Split, + "strAppend": func(arr []string, item string) []string { + return append(arr, item) + }, + "join": strings.Join, + "strSlice": func() []string { + return make([]string, 0) + }, + "list": func(args ...any) []any { + return args + }, + "sum": func(args ...int) int { + var sum int + for _, v := range args { + sum += v + } + return sum + }, +} + +const ( + tmplDir = "templ" + tmplHelpers = "helpers.tmpl" +) + +func newTmplText(name string) *texttmpl.Template { + return texttmpl.Must(texttmpl.New(name). + Funcs(tplFuncs). + ParseFS(templatesFS, + path.Join(tmplDir, name), + path.Join(tmplDir, tmplHelpers))) +}