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

3.5 KiB
Raw Blame History

description, tags
description tags
APIs to create and render templates 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:

-- the `templates` global table is available for custom templates
templates.greet = template.new [==[Hello ${name}!]==]

Which elsewhere can be used, either directly:

${templates.greet {name = "Pete"}}

or directly in a query’s select clause:

${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:

${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

-- 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