Hugo Template Formatting Using Prettier, Zed

Zed users coming from more mature 👴🏼 editors may balk at the lack of a Hugo template formatter. The default language server even fails to treat .gohtml files as Go templates, and your double-curly-bracket-bearing files will therefore soon become unkempt, if not downright ugg-o.

Here’s the few steps you can take to configure the editor to format your Hugo templates, using Prettier and the Go template plugin.

  1. npm i prettier prettier-plugin-go-template I don’t like making this an npm repo any more than you do, but it must be done. Attempts to locate the formatter’s plugin globally have been met with lengthy error messages.
  2. touch .zed/settings.json
// settings.json

{
  "languages": {
    "HTML": {
      "formatter": {
        "external": {
          "command": "prettier",
          "arguments": ["--stdin-filepath", "{buffer_path}"],
        }
      }
    }
  }
}

Additionally, I’ve added .gohtml to my file extensions that count as HTML.

// settings.json

{
  "file_types": {
    "HTML": ["html", "gohtml"]
  }
}

I had to confgiure Hugo to recognize .gohtml, unfortunately.

# hugo.toml

[outputformats]
[outputformats.gohtml]
mediaType = "text/html"
isHTML = true

This way, Prettier will use the HTML formatter for vanilla HTML, and the Go Template formatter with template files. 3. touch .prettierrc

{
  "plugins": [
    "prettier-plugin-go-template"
  ],
  "overrides": [
    {
      "files": [
        "*.gohtml"
      ],
      "options": {
        "parser": "go-template",
        "goTemplateBracketSpacing": true,
        "bracketSameLine": false
      }
    },
  ]
}

Your options may differ.

Bonus: Emmet Snippets for Hugo Templating

One of the nice things about Zed is the built-in snippet support. From the Command Palette, enter snippets: configure, then choose HTML. Here you can define your own snippets, to be available from .thml files. I let the AI write mine, and it came up with

// html.json

{
  "block": {
    "prefix": "block",
    "body": ["{{ block \"$1\" . }}", "  $2", "{{ end }}"],
    "description": "Create a Hugo template block",
  },
  "define": {
    "prefix": "define",
    "body": ["{{ define \"$1\" }}", "  $2", "{{ end }}"],
    "description": "Create a Hugo template definition",
  },
  "partial": {
    "prefix": "partial",
    "body": ["{{ partial \"$1\" . }}"],
    "description": "Include a Hugo template partial",
  },
  "range": {
    "prefix": "range",
    "body": ["{{ range .Items }}", "  {{ .Title }}", "{{ end }}"],
    "description": "Hugo range loop",
  },
  "if": {
    "prefix": "if",
    "body": ["{{ if $1 }}", "  $2", "{{ end }}"],
    "description": "Hugo if statement",
  },
  "with": {
    "prefix": "with",
    "body": ["{{ with .Variable }}", "  $1", "{{ end }}"],
    "description": "Hugo with statement",
  },
}

Finally, the Emmet extension is available for common html snippets.