Recreate the forPrefix hook in page templates

In v1 Page Templates we could define a prefix hook which would automatically apply a template to any page with matching prefix. Is there a simple way to recreate this in V2?

This was answered before! I made a simple solution that fixes my issue

templates = templates or {}

templates.person_template = template.new(
[==[
---
birthday:
address:
tags: person
---
]==]
)

event.listen {
  name = "editor:pageCreating",
  run = function(e)
    if e.data.name:startsWith("person/") then
      return {
        text = templates.person_template({})
      }
    end
  end
}

but I wonder if the new expectation will be to always create a new event handler for a new template?

1 Like

I thought about that too - this would have a set of implications (e.g. what happens if two if statements match for a page?). My approach hence is the following:

templates = templates or {}

templates.person_template = template.new(
[==[
---
birthday:
address:
tags: person
---
]==]
)
templates.second_template = template.new(
[==[
Hello world! This is my other template!
]==]
)

event.listen {
  name = "editor:pageCreating",
  run = function(e)
    if e.data.name:startsWith("person/") then
      return {
        text = templates.person_template({})
      }
    elseif e.data.name:startswith("second_directory/") then
      return {
        text = templates.second_template({})
      }
    end
  end
}

You can have as many elseif blocks as you want.

1 Like

SilverBullet detects if more than one listener responds to the pageCreating event and none of them is selected in that case.

1 Like

might be useful to flash a warning in that case, but the behavior seems reasonable

I’ve tried this solution before, and I cannot figure out how to make the template evaluate. In other words, any ${} block or the caret positioner |^| prints literally. I have this whole duct-taped solution that works now–it even has a single handler for multiple paths so I don’t have to write a new event handler, but this would be so much more efficient if I could just get the dynamic bits to be dynamic.

I also liked the original method of having metadata in the template file.
So following on from how command is implemented for a template I used a query to create the event listeners. I did have the same issue that others had where the page isn’t templated quite the same and the cursor isn’t moved (compare to using the command or shortcut key).
The below will add the handler from any meta/template/page tagged file with the forPrefix field present.

-- based on createPageFromTemplate but return the string
local function returnPageFromTemplate(templatePage)
  local tpl, fm = template.fromPage(templatePage)
  local initialText = ""
  if fm.frontmatter then
    initialText = "---\n"
      .. string.trim(template.new(fm.frontmatter)())
      .. "\n---\n"
  end
  return initialText .. tpl()
end

-- Create event handler for all page templates with a forPrefix key in frontmatter
for pt in query[[
    from index.tag "meta/template/page"
    where _.tag == "page" and _.forPrefix
    order by _.priority desc
  ]] do
  event.listen {
    name = "editor:pageCreating",
    run = function(e)
      if e.data.name:startsWith(pt.forPrefix) then
        return {
          text = returnPageFromTemplate(pt.name)
        }
      end
    end
  }
end
1 Like