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?
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.
SilverBullet detects if more than one listener responds to the pageCreating event and none of them is selected in that case.
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
Hi Robert,
This code is almost there for me - but the “|^|” is not being handled properly - it’s getting printed, and doesn’t move the caret. Any clues?
Just playing with this today myself, and here’s my solution. It’s a little hacky in that I’m chaining together the editor:pageCreating event (where @roberth renders the template) with the subsequent editor:pageLoaded event that occurs when the editor loads the new page, with a little bit of global state to correlate the two.
On the pageLoaded, assuming we’re indeed loading the same page we just created, I scan the new page’s content for the cursor marker |^|, remove it, and place the cursor at the spot.
-- 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
-- Cache the last created page
forprefix_latest_page = ""
-- 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
forprefix_latest_page = e.data.name
return {
text = returnPageFromTemplate(pt.name)
}
end
end
}
end
event.listen {
name = "editor:pageLoaded",
run = function(e)
local nav_to = e.data[1]
if nav_to == forprefix_latest_page then
forprefix_latest_page = "" -- One-time only after page creation
local page_text = editor.getText()
local cursor_idx, _ = string.find(page_text, "|^|", 1, true)
if cursor_idx then
cursor_idx = cursor_idx - 1 -- editor is 0-based
editor.replaceRange(cursor_idx, cursor_idx+3, "")
editor.moveCursor(cursor_idx, true)
end
end
end
}