Files
plainleaf/libraries/Library/Std/APIs/Template.md
T

114 lines
3.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
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 directly in a query’s `select` clause:
```lua
${query[[from p = index.contentPages() limit 3 select templates.greet(p)]]}
```
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. While this API still works, but for queries the recommended approach is to call the template in the `select` clause directly (as shown above).
Example:
```lua
${query[[from p = index.contentPages() limit 3 select template.new[==[
* [[${name}]]
]==](p)]]}
```
# 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
```