HTML Templates
Standard HTML content can be included in the HTML section of a page. The application server uses Go's HTML Template library to dynamically generate the HTML content using available data from the SQL commands.
See https://pkg.go.dev/text/template for more details on the HTML template library.
Template Data
Data values are applied to the template using the {{.field}} syntax.
The rows and fields returned by SQL commands are available as template data under .<alias>.
Aliases are always lowercase in template data, even if defined with uppercase characters.
Field names must match the casing of the database column name exactly.
By default, every alias returns an array of rows, which must be accessed via {{ range .<alias> }}.
The range must have a matching {{end}}.
Everything inside the range will be repeated for each SQL record.
Inside the range, each field is available as {{ .<fieldname> }}
For example:
{{range .select}}
<tr>
<td>{{.id}}</td>
<td>{{.name}}</td>
</tr>
{{end}}
Single Record Results
Aliases can be defined as singular by prefixing the alias with a $, which eliminates the need to use {{ range }} when accessing the command results.
This is ideal for a query that you know will always return a single row, such as on a page that returns the data for a single item.
If multiple rows are returned by a command marked as singular, only the first row is available in the template.
For example:
<h1>{{.select.name}}</h1>
Metadata
Metadata about the alias SQL command is available as template data under .<alias>_data. The following fields are available:
commandis the SQL command that was passed to the database engineexecreturns a boolean indicating if the alias was executed on the database engine (e.g. will be false if didn't run due to missing parameter, or if previous critical command failed and stopped execution before this alias was executed)errorreturns the text of any error messages returned by the commands in the alias. If the text is blank, either no error occurred or it did not execute. If the length is greater than 0 then the command executed and failed.countreturns the # of rows returned
For example:
<ul>
<li>SQL Command: {{.select_data.command}}</li>
<li>Was Executed? {{.select_data.exec}}</li>
<li>SQL Errors: {{.select_data.error}}</li>
<li>SQL Records Returned: {{.select_data.count}}</li>
</ul>
Template Control Structure
The following control structures are available in the HTML template:
{{if <condition>}}- Uses the<condition>to decide if the block should be rendered.{{range .<alias>}}- Renders the block for each row returned by the SQL command with the name<alias>.{{define "<name>"}}- Defines a reusable block that can be referenced in other parts of the file.{{else}}- Renders as the alternative block if theifcondition was false or no rows were found in therange.{{end}}- Ends aniforrangeordefineblock.{{/* <comment> */}}- Adds a comment to the template.{{break}}- Breaks out of the currentrangeblock.{{continue}}- Stops iterating the currentrangeblock and continues to the next record.{{template "<name>" [.data]}}- See the Reusable HTML Templates section below.
Conditions
Conditions can be a data value (e.g. .alias.field) or a function described below.
Conditions evaluate to either true or false.
Empty and missing values are considered false.
Template Functions
All functions follow the format of <function name> [parameter n...] .
Parameters can be wrapped in parentheses to allow stacking of functions, e.g. {{if and (eq method "GET") (eq username .field1)}}.
Logic Functions
and <x> <y>- Returns the boolean AND of its arguments by returning the first empty argument or the last argument. That is, "and x y" behaves as "if x then y else x". Evaluation proceeds left to right and returns when the result is determined.len <x>- Returns the integer length of the string or arrayx.js <x>- Returns the JavaScript-escaped stringx.not <x>- Returns the boolean NOT of its argument.or <x> <y>- Returns the boolean OR of its arguments by returning the first non-empty argument or the last argument. That is, "or x y" behaves as "if x then x else y". Evaluation proceeds left to right and returns when the result is determined.
Comparison Functions
eq <x> <y>- Returns true ifxis equal toy.ne <x> <y>- Returns true ifxis not equal toy.lt <x> <y>- Returns true ifxis less thany.le <x> <y>- Returns true ifxis less than or equal toy.gt <x> <y>- Returns true ifxis greater thany.ge <x> <y>- Returns true ifxis greater than or equal toy.
Application Functions
method- returns the current HTTP method:GET,POST,PUT,PATCH, orDELETEroute- returns the URL path of the current page (e.g. for generating links back to this page)slugname- returns the name of the slug variable in the routeslug- returns the value of the slug; returns a blank string if no slug is usedparam <name>- returns a query parameter value as a string. Use string comparison operators (e.g.eq) when comparing in templates.pathescape <url path>- escapes a single URL path segment (e.g.%Test Page→%25Test%20Page)queryescape <url>- escapes a value for use in a URL query stringusername- returns the authenticated user's username, orANONYMOUSif not authenticateddisplayname- returns the authenticated user's display name, orANONYMOUSif not authenticatedrole <name>- returnstrueif the authenticated user literally has the specified rolenotrole <name>- returnstrueif the authenticated user does not have the specified roleauth <name...>- returnstrueif the user is authorized for any of the given roles (mirrors page-policy allow semantics: honorsauth.adminRole, the reservedpublic/authroles, and accepts multiple comma-separated or separate-argument roles)notauth <name...>- the negation ofauth
String Formatting Functions
date <value>- returns the value formatted asYYYY-MM-DDisodate <value>- returns the value formatted asYYYY-MM-DDsdate <value>- returns the value formatted with the configured short date format (defaultYYYY-MM-DD)ldate <value>- returns the value formatted with the configured long date format (defaultDDD MMM D YYYY)isotime <value>- returns the value formatted asHH:MM:SStime <value>- returns the value formatted with the configured time format (defaultH:MMTT)isodtime <value>- returns the value formatted asYYYY-MM-DD HH:MM:SSsdtime <value>- returns the value formatted with the configured short date and time format (defaultYYYY-MM-DD H:MMTT)ldtime <value>- returns the value formatted with the configured long date and time format (defaultDDD MMM D YYYY H:MMTT)num <value>- returns the value formatted with the configured number format (default0,000)dec <value>- returns the value formatted with the configured decimal format (default0,000.0)ldec <value>- returns the value formatted with the configured long decimal format (default0,000.0000)money <value>- returns the value formatted with the configured money format (default$0,000.00)fmt <value> <format>- returns the value formatted with the defined formatformat <value> <format>- same asfmtabovefdate <value> <format>- returns the date value formatted with the defined formatfnum <value> <format>- returns the numeric value formatted with the defined formatbr <value>- converts CR, LF, and CRLF line breaks into HTML<br/>tagsstr <value>- converts any value to a stringmarkdown <value>- renders a Markdown string as sanitized HTML (GitHub Flavored Markdown).mdis an alias. See Markdown editor and rendering.
The default formats can be overridden using the following settings underneath the formatting section of the configuration file:
shortDate- the format for short dateslongDate- the format for long datestime- the format for timesshortDateTime- the format for short date and timelongDateTime- the format for long date and timenumbers- the format for numbersdecimals- the format for decimalslongDecimals- the format for long decimalsmoney- the format for money
Reusable HTML Templates
You can make re-usable "components" by creating .html files in the templates folder.
These HTML files will be available in pages using {{ template "<filename.html>" }}.
These template files are not parsed for SQL commands.
You can make data from the page available to the sub-template, e.g. {{ template "filename.html" .select }}
Slugs are not available in templates, only in pages.
Markdown Editor and Rendering
HTMQL supports authoring rich text as Markdown while keeping Markdown as the single source of truth in the database. Markdown is stored in a plain column; HTML is generated on demand and never stored. There are two halves:
1. WYSIWYG editing (client-side). The bundled Toast UI Editor
(MIT) provides a what-you-see-is-what-you-get editor that reads and writes Markdown. It is
wired to a hidden <textarea> by the reusable md-editor.html template, so the Markdown
submits as an ordinary form field - no special server handling is needed.
{{/*
@id=0
GET:$record:SELECT id, notes FROM article WHERE id=@id;
POST:!!save:UPDATE article SET notes=@notes WHERE id=@id;
*/}}
<form hx-post="{{route}}">
<input type="hidden" name="id" value="{{.record.id}}" />
<textarea name="notes" data-md-editor>{{.record.notes}}</textarea>
{{template "md-editor.html" .}}
<button type="submit">Save</button>
</form>
The textarea's content seeds the editor (Markdown), and the editor writes Markdown back
into the textarea on every change. Include the md-editor.html snippet once per page.
Per-editor options are set with data-* attributes on the textarea:
data-md-height- editor height (default400px)data-md-mode- initial tab,wysiwyg(default) ormarkdown
2. Rendering Markdown → HTML (server-side). The markdown template function (alias
md) converts a stored Markdown string into sanitized HTML using
goldmark (GitHub Flavored Markdown) with output run
through bluemonday so authored content cannot
inject unsafe markup:
<article>{{markdown .record.notes}}</article>
The same renderer powers the email body_format=markdown option, so Markdown authored in
the editor can be emailed as a proper HTML body without duplicating any conversion logic.