Skip to content

Latest commit

 

History

History
327 lines (271 loc) · 10 KB

File metadata and controls

327 lines (271 loc) · 10 KB

Template Guide

gohan themes are built with Go's standard html/template package.

日本語版: templates.ja.md


Template files

All .html files inside the theme directory (themes/default/templates/ by default) are loaded automatically.

Available page templates

File URL pattern Description
index.html / Site top page (full article list)
article.html /posts/<slug>/ Individual article page
tag.html /tags/<name>/ Tag article list page
category.html /categories/<name>/ Category article list page
archive.html /archive/<year>/ Year-based archive page

All template files are optional. If a template does not exist, that page is simply not generated (no error is raised).


Template data

Every template receives a value of type model.Site.

Site

type Site struct {
    Config          Config              // Settings from config.yaml
    Articles        []*ProcessedArticle // Articles for the current page (filtered)
    Tags            []Taxonomy          // All tags across the site
    Categories      []Taxonomy          // All categories across the site
    ArchiveYears    []int               // Unique years that have articles, sorted newest-first
    Pagination      *Pagination         // Paging metadata; nil when pagination is disabled or for non-listing pages
    CurrentLocale   string              // Locale for the current page (e.g. "en", "ja"); empty when i18n is not configured
    RelatedArticles    []*ProcessedArticle // Articles sharing at least one category with the current article (article pages only; nil on all other pages)
    CurrentTaxonomy    *Taxonomy           // The tag or category being listed; nil on all other pages
    CurrentArchivePath   string              // Set on archive pages; locale-aware path, e.g. "/archives/2024/01/" (EN) or "/ja/archives/2024/01/" (JA); empty on all other pages
    CurrentArchiveIsMonth bool                // true on month archive pages (e.g. /archives/2024/01/); false on year archive pages (e.g. /archives/2024/)
}

Pagination

type Pagination struct {
    CurrentPage int
    TotalPages  int
    PerPage     int
    TotalItems  int
    PrevURL     string // empty string if no previous page
    NextURL     string // empty string if no next page
    BaseURL     string // URL path prefix used to construct PrevURL/NextURL
}

See docs/features/pagination.md for the full pagination guide.

Config

type Config struct {
    Site  SiteConfig
    Theme ThemeConfig
    Build BuildConfig
}

type SiteConfig struct {
    Title       string // .Config.Site.Title
    Description string // .Config.Site.Description
    BaseURL     string // .Config.Site.BaseURL
    Language    string // .Config.Site.Language
}

type ThemeConfig struct {
    Name   string
    Dir    string
    Params map[string]string // .Config.Theme.Params
}

ProcessedArticle

type ProcessedArticle struct {
    FrontMatter  FrontMatter    // Parsed YAML Front Matter
    HTMLContent  template.HTML  // Rendered HTML
    Summary      string         // First ~200 characters
    OutputPath   string         // Output file path
    FilePath     string         // Source Markdown file path
    LastModified time.Time      // Last modified time
    ContentPath  string         // Content-dir-relative Markdown path (e.g. "posts/hello.md"); used for GitHub edit links
    Locale       string         // Locale code (e.g. "en", "ja"); empty when i18n is not configured
    URL          string         // Canonical URL path (e.g. "/posts/hello/" or "/ja/posts/hello/")
    Translations []LocaleRef    // Translated variants; populated by BuildTranslationMap; empty when not i18n
    PluginData   map[string]interface{} // Per-article data injected by enabled plugins; access via {{index .PluginData "plugin_name"}}
}

// LocaleRef holds the locale code and canonical URL for a translated variant.
type LocaleRef struct {
    Locale string
    URL    string
}

type FrontMatter struct {
    Title          string
    Date           time.Time
    Draft          bool
    Tags           []string
    Categories     []string
    Description    string
    Author         string
    Slug           string
    Template       string
    TranslationKey string                 // Links this article to its translations in other locales
    Extra          map[string]interface{} // Any front-matter keys not listed above; used by plugins
}

Taxonomy

type Taxonomy struct {
    Name        string // Tag or category name
    Description string // Optional description
    URL         string // Locale-aware canonical URL path set at render time, e.g. "/ja/tags/go/"; empty outside paginatedJobs
}

.Articles contents per template

Template .Articles contains Extra fields available
index.html All articles on the site .Pagination, .ArchiveYears, .Tags, .Categories
article.html The single article being rendered .RelatedArticles, .CurrentLocale
tag.html Articles that have this tag .Pagination, .CurrentTaxonomy (.CurrentTaxonomy.URL set)
category.html Articles that belong to this category .Pagination, .CurrentTaxonomy (.CurrentTaxonomy.URL set)
archive.html Articles published in this year/month .CurrentLocale, .CurrentArchivePath

Note on article.html: inside a {{range .Articles}} loop, use $ to access root-level fields — e.g. $.RelatedArticles, $.CurrentLocale, $.Config.


Built-in functions

Function Example Description
formatDate {{formatDate "2006-01-02" .FrontMatter.Date}} Format a time.Time value
tagURL {{tagURL .CurrentLocale "go"}}/tags/go/ (EN) or /ja/tags/go/ (JA) Generate a locale-aware tag page URL
categoryURL {{categoryURL .CurrentLocale "tech"}}/categories/tech/ (EN) Generate a locale-aware category page URL
markdownify {{markdownify "**bold**"}} Convert a Markdown string to HTML

formatDate uses Go's reference time layout:

  • "2006-01-02"2024-01-15
  • "January 2, 2006"January 15, 2024

Template examples

index.html — Top page

<!DOCTYPE html>
<html lang="{{.Config.Site.Language}}">
<head>
  <meta charset="UTF-8">
  <meta name="description" content="{{.Config.Site.Description}}">
  <title>{{.Config.Site.Title}}</title>
  <link rel="stylesheet" href="/assets/style.css">
  <link rel="alternate" type="application/atom+xml" title="{{.Config.Site.Title}}" href="/atom.xml">
</head>
<body>
  <header>
    <h1><a href="/">{{.Config.Site.Title}}</a></h1>
    <p>{{.Config.Site.Description}}</p>
  </header>
  <main>
    <ul>
      {{range .Articles}}
      <li>
        <time>{{formatDate "2006-01-02" .FrontMatter.Date}}</time>
        <a href="/posts/{{.FrontMatter.Slug}}/">{{.FrontMatter.Title}}</a>
        {{if .FrontMatter.Tags}}
        <span>
          {{range .FrontMatter.Tags}}<a href="{{tagURL $.CurrentLocale .}}">#{{.}}</a> {{end}}
        </span>
        {{end}}
      </li>
      {{end}}
    </ul>
  </main>
  <footer>
    <a href="/sitemap.xml">Sitemap</a> · <a href="/atom.xml">Feed</a>
    {{if .Config.Theme.Params.footer_text}}
    <p>{{.Config.Theme.Params.footer_text}}</p>
    {{end}}
  </footer>
</body>
</html>

article.html — Article page

<!DOCTYPE html>
<html lang="{{.Config.Site.Language}}">
<head>
  <meta charset="UTF-8">
  {{with (index .Articles 0)}}
  <meta name="description" content="{{.FrontMatter.Description}}">
  <title>{{.FrontMatter.Title}} — {{$.Config.Site.Title}}</title>
  {{end}}
  <link rel="stylesheet" href="/assets/style.css">
</head>
<body>
  <header><nav><a href="/">← {{.Config.Site.Title}}</a></nav></header>
  <main>
    {{with (index .Articles 0)}}
    <article>
      <h1>{{.FrontMatter.Title}}</h1>
      <time>{{formatDate "January 2, 2006" .FrontMatter.Date}}</time>
      {{if .FrontMatter.Author}}<span> · {{.FrontMatter.Author}}</span>{{end}}
      {{if .FrontMatter.Tags}}
      <ul class="tags">
        {{range .FrontMatter.Tags}}<li><a href="{{tagURL $.CurrentLocale .}}">{{.}}</a></li>{{end}}
      </ul>
      {{end}}
      <div class="content">{{.HTMLContent}}</div>
    </article>
    {{end}}
  </main>
</body>
</html>

tag.html — Tag page

<!DOCTYPE html>
<html lang="{{.Config.Site.Language}}">
<head>
  <meta charset="UTF-8">
  <title>Tag: {{(index .Articles 0).FrontMatter.Tags}} — {{.Config.Site.Title}}</title>
  <link rel="stylesheet" href="/assets/style.css">
</head>
<body>
  <header><nav><a href="/">← {{.Config.Site.Title}}</a></nav></header>
  <main>
    <h2>Articles ({{len .Articles}})</h2>
    <ul>
      {{range .Articles}}
      <li>
        <time>{{formatDate "2006-01-02" .FrontMatter.Date}}</time>
        <a href="/posts/{{.FrontMatter.Slug}}/">{{.FrontMatter.Title}}</a>
      </li>
      {{end}}
    </ul>
  </main>
</body>
</html>

Advanced features

Mermaid diagrams

Write a fenced code block with the mermaid language identifier:

```mermaid
graph TD
    A[Write article] --> B[gohan build]
    B --> C[HTML in public/]
    C --> D[Deploy]
```

gohan automatically injects the Mermaid runtime script when it detects a mermaid block.

Syntax highlighting

Fenced code blocks are highlighted automatically using chroma. Styles are applied via inline CSS — no external stylesheet is required.

Template partials

Create reusable partial templates using {{define}} and {{template}}:

themes/default/templates/
├── index.html
├── article.html
└── _partials/
    ├── header.html   ← defines "header"
    └── footer.html   ← defines "footer"
<!-- _partials/header.html -->
{{define "header"}}
<header>
  <h1><a href="/">{{.Config.Site.Title}}</a></h1>
</header>
{{end}}
<!-- index.html -->
<!DOCTYPE html>
<html>
<body>
  {{template "header" .}}
  <main>...</main>
</body>
</html>