114 lines
3.3 KiB
Markdown
114 lines
3.3 KiB
Markdown
---
|
|
description: APIs to create and render templates
|
|
tags: meta/api
|
|
---
|
|
|
|
APIs to create templates from strings or pages, and render query collections using templates.
|
|
|
|
# API
|
|
|
|
## template.new(templateStr, stripIndent)
|
|
Creates a template function from a string. The template string can contain `${expression}` placeholders that will be interpolated when the template is called. Conventionally, template strings typically use `[==[` and `]==]` as delimiters.
|
|
|
|
If `stripIndent` is `true` or omitted, leading 4-space indentation is stripped from each line.
|
|
|
|
Example:
|
|
|
|
```lua
|
|
-- the `templates` global table is available for custom templates
|
|
templates.greet = template.new [==[Hello ${name}!]==]
|
|
```
|
|
|
|
Which elsewhere can be used, either directly:
|
|
|
|
```lua
|
|
${templates.greet {name = "Pete"}}
|
|
```
|
|
|
|
or together with `template.each` (see below):
|
|
|
|
```lua
|
|
${template.each(query[[from tags.page limit 3]], templates.greet)}
|
|
```
|
|
|
|
Resulting in something along the lines of `Hello index!Hello CONFIG!...`
|
|
|
|
|
|
## template.each(collection, fn)
|
|
Iterates over a collection and applies a template to each element, concatenating the results. Commonly used to render query results.
|
|
|
|
Example:
|
|
|
|
```lua
|
|
${template.each(query[[from index.tag "page" limit 3]], template.new [==[
|
|
* [[${name}]]
|
|
]==])}
|
|
```
|
|
|
|
# Pre-built templates
|
|
The `templates` table contains ready-made templates for common query rendering patterns. These are defined in [[^Library/Std/Infrastructure/Query Templates]].
|
|
|
|
* **`templates.pageItem`** — renders a page as `* [[name]]`
|
|
* **`templates.fullPageItem`** — renders a page as `* [[name|name]]` (full path)
|
|
* **`templates.taskItem`** — renders a task as a togglable `* [state] [[ref]] name`
|
|
* **`templates.itemItem`** — renders an item as `* [[ref]] name`
|
|
* **`templates.paragraphItem`** — renders a paragraph as `* [[ref]] text`
|
|
* **`templates.tagItem`** — renders a tag as `* [[tag:name|#name]]`
|
|
|
|
# Implementation
|
|
|
|
```space-lua
|
|
-- priority: 50
|
|
-- Template API root table
|
|
template = template or {}
|
|
-- Template storage table
|
|
templates = {}
|
|
|
|
-- Iterates over a table/array and applies a function to each element,
|
|
-- concatenating the results
|
|
function template.each(tbl, fn)
|
|
local result = {}
|
|
for _, item in ipairs(tbl) do
|
|
table.insert(result, fn(item))
|
|
end
|
|
return #result > 0 and table.concat(result) or nil
|
|
end
|
|
|
|
-- Creates a new template function from a string template
|
|
function template.new(templateStr, stripIndent)
|
|
-- Preprocess: strip indentation
|
|
if stripIndent == nil or stripIndent == true then
|
|
local lines = {}
|
|
local splitLines = string.split(templateStr, "\n")
|
|
for _, line in ipairs(splitLines) do
|
|
line = string.gsub(line, "^ ", "")
|
|
table.insert(lines, line)
|
|
end
|
|
templateStr = table.concat(lines, "\n")
|
|
end
|
|
return function(obj)
|
|
return spacelua.interpolate(templateStr, obj)
|
|
end
|
|
end
|
|
|
|
-- Reads a template from a page
|
|
-- Return value:
|
|
-- * The template itself
|
|
-- * The extracted frontmatter
|
|
function template.fromPage(name, raw)
|
|
local fm = index.extractFrontmatter(space.readPage(name), {
|
|
removeFrontMatterSection = true,
|
|
removeTagsPrefix = {"meta/template"}
|
|
})
|
|
|
|
local templateText = string.trimStart(fm.text)
|
|
if raw then
|
|
-- Don't actually parse this as a template, just pass it along
|
|
return function()
|
|
return templateText
|
|
end, fm.frontmatter
|
|
end
|
|
return template.new(templateText, false), fm.frontmatter
|
|
end
|
|
```
|