#metaProvides infrastructure for importing pages outside of your space. It standardizes the ${widgets.commandButton("Import: URL")} to export the current page or selection in various ways. Technical architecture
Steps:- The user is asked to supply a URL
- An import:discover event is triggered with:
- url the URL the user supplied
- Listeners can respond with:
- id: Call identifier
- name: Presented name for the importer
- Ask user to select option, then invoke import:run:${id} with the same data as step 2
- Importer listens to this event and handles it as it sees fit.
General best practices for importers:- Set the source key in the imported frontmatter to the type importer used (to allow for later automated updating of content)
- Set another key in frontmatter that points to the origin URL somehow (also for later updating use)
Implementation
command.define {
name = "Import: URL",
key = "Ctrl-Shift-i",
mac = "Cmd-Shift-i",
run = function()
local url = editor.prompt("URL to import:")
if not url then
return
end
local importObj = { url = url }
local handlers = event.dispatch("import:discover", importObj)
if #handlers == 0 then
editor.flashNotification("No importers available for URL", "error")
return
end
local selectionOptions = {}
for _, handler in ipairs(handlers) do
for _, option in ipairs(handler) do
table.insert(selectionOptions, option)
end
end
local selectedOption = editor.filterBox("Select importer",
selectionOptions, "Pick your desired importer from the list")
if not selectedOption then
return
end
event.dispatch("import:run:" .. selectedOption.id, importObj)
end
}
Implementation for .md URLs
event.listen {
name = "import:discover",
run = function(event)
local url = event.data.url
if url:endsWith(".md") then
return {
{
id = "markdown-import",
name = "Markdown"
},
}
end
end
}
event.listen {
name = "import:run:markdown-import",
run = function(e)
local url = e.data.url
local req = http.request(url)
if not req.ok then
editor.flashNotification("Failed to import, see console for error")
js.log("Error", req)
return
end
local content = req.body
local fm = index.extractFrontmatter(content)
-- Extract the last part of the path, without the .md
local suggestedPath = url:match("^.*/([^/?#]+)%.md{{CONTENT}}quot;)
if table.includes(fm.frontmatter.tags, "meta") then
-- Maybe more of a library function
suggestedPath = "Library/" .. suggestedPath
end
local localPath = editor.prompt("Save to", suggestedPath)
if not localPath then
return
end
if space.fileExists(localPath .. ".md") then
editor.flashNotification("Page already exists, won't do that", "error")
return
end
space.writePage(localPath, content)
editor.flashNotification("Imported to " .. localPath)
editor.navigate({kind="page", page=localPath})
local updated = index.patchFrontmatter(editor.getText(),
{
{op="set-key", path="source", value="markdown-import"},
{op="set-key", path="sourceUrl", value=url},
})
editor.setText(updated)
end
}