Adds Github Import and Export support
Building this in as a more sensible way to share SB libraries.
This commit is contained in:
+3
-7
@@ -31,7 +31,7 @@ event.listen {
|
||||
return {
|
||||
{
|
||||
id = "github-gist",
|
||||
name = "Gist"
|
||||
name = "Github: Gist"
|
||||
},
|
||||
}
|
||||
end
|
||||
@@ -44,11 +44,7 @@ event.listen {
|
||||
run = function(event)
|
||||
local url = event.data.url
|
||||
local gistUrl = githubGist.extractGistId(url)
|
||||
local resp = http.request("https://api.github.com/gists/" .. gistUrl, {
|
||||
headers = {
|
||||
Accept = "application/vnd.github.v3+json"
|
||||
}
|
||||
})
|
||||
local resp = http.request("https://api.github.com/gists/" .. gistUrl)
|
||||
if not resp.ok then
|
||||
editor.flashNotification("Failed, see console for error")
|
||||
js.log("Error", resp)
|
||||
@@ -121,7 +117,7 @@ event.listen {
|
||||
return {
|
||||
{
|
||||
id = "github-gist",
|
||||
name = "Gist"
|
||||
name = "Github: Gist"
|
||||
},
|
||||
}
|
||||
end
|
||||
|
||||
@@ -0,0 +1,203 @@
|
||||
#meta
|
||||
|
||||
[[^Library/Std/Import]] and [[^Library/Std/Export]] support for [Github repo files](https://github.com).
|
||||
|
||||
# Configuration
|
||||
If you only want to _import_ from Github URLs, no configuration is required.
|
||||
|
||||
To _export_ got a Github repo, you need to get a [personal Github token](https://github.com/settings/personal-access-tokens) (with repo permissions). Configure your token somewhere in Space Lua (use a `space-lua` block), ideally a `SECRETS` page. This configuration is shared with [[^Library/Std/Gist]].
|
||||
|
||||
```lua
|
||||
config.set("github.token", "your token")
|
||||
```
|
||||
|
||||
In addition, you need to configure a name and email that will be part of the commit:
|
||||
|
||||
```lua
|
||||
config.set("github.name", "John Doe")
|
||||
config.set("github.email", "john@doe.com")
|
||||
```
|
||||
|
||||
# Implementation
|
||||
|
||||
## Constants
|
||||
```space-lua
|
||||
-- priority: 50
|
||||
github = {
|
||||
fmUrlKey = "githubUrl",
|
||||
}
|
||||
```
|
||||
|
||||
## Import
|
||||
```space-lua
|
||||
-- Import discovery
|
||||
event.listen {
|
||||
name = "import:discover",
|
||||
run = function(event)
|
||||
local url = event.data.url
|
||||
if github.extractData(url) then
|
||||
return {
|
||||
{
|
||||
id = "github-file",
|
||||
name = "Github: Repo file",
|
||||
},
|
||||
}
|
||||
end
|
||||
end
|
||||
}
|
||||
|
||||
-- Import implementation
|
||||
event.listen {
|
||||
name = "import:run:github-file",
|
||||
run = function(event)
|
||||
local url = event.data.url
|
||||
local repo, branch, path = github.extractData(url)
|
||||
-- Fetch content via the Github API, unauthenticated
|
||||
local resp = http.request(github.buildUrlWithBranch(repo, branch, path), {method = "GET"})
|
||||
if not resp.ok then
|
||||
editor.flashNotification("Failed, see console for error")
|
||||
js.log("Error", resp)
|
||||
return
|
||||
end
|
||||
local content = encoding.utf8Decode(encoding.base64Decode(resp.body.content))
|
||||
local fm = index.extractFrontmatter(content)
|
||||
local suggestedPath = path:gsub("%.md$", "")
|
||||
if table.includes(fm.frontmatter.tags, "meta") then
|
||||
-- Maybe more of a library function
|
||||
suggestedPath = "Library/" .. suggestedPath
|
||||
end
|
||||
-- Ask for location to import to
|
||||
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=github.fmUrlKey, value=url}
|
||||
})
|
||||
editor.setText(updated)
|
||||
end
|
||||
}
|
||||
```
|
||||
|
||||
## Export
|
||||
```space-lua
|
||||
-- returns (something/bla, branch, path)
|
||||
function github.extractData(url)
|
||||
if url == nil then
|
||||
return nil
|
||||
end
|
||||
return url:match("github%.com/([^/]+/[^/]+)/[^/]+/([^/]+)/(.+)")
|
||||
end
|
||||
|
||||
function github.buildUrl(repo, path)
|
||||
return "https://api.github.com/repos/" .. repo .. "/contents/" .. path
|
||||
end
|
||||
|
||||
function github.buildUrlWithBranch(repo, branch, path)
|
||||
return github.buildUrl(repo, path) .. "?ref=" .. branch
|
||||
end
|
||||
|
||||
function github.checkConfig()
|
||||
if not config.get("github.token") then
|
||||
error("github.token needs to be set")
|
||||
end
|
||||
if not config.get("github.name") then
|
||||
error("github.name needs to be set")
|
||||
return
|
||||
end
|
||||
if not config.get("github.email") then
|
||||
error("github.email needs to be set")
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
-- Export discovery
|
||||
event.listen {
|
||||
name = "export:discover",
|
||||
run = function(event)
|
||||
return {
|
||||
{
|
||||
id = "github-file",
|
||||
name = "Github: Repo file"
|
||||
},
|
||||
}
|
||||
end
|
||||
}
|
||||
|
||||
-- Export implementation
|
||||
event.listen {
|
||||
name = "export:run:github-file",
|
||||
run = function(event)
|
||||
-- Check configuration
|
||||
local checkOk, err = pcall(github.checkConfig)
|
||||
if not checkOk then
|
||||
editor.flashNotification(err, "error")
|
||||
return
|
||||
end
|
||||
-- Extract the URL from frontmatter if set
|
||||
local text = event.data.text
|
||||
local fm = index.extractFrontmatter(text, {
|
||||
removeKeys = {github.fmUrlKey},
|
||||
})
|
||||
local repo, branch, path = github.extractData(fm.frontmatter[github.fmUrlKey])
|
||||
local sha = nil -- will be set for existing files
|
||||
if not repo then
|
||||
-- Not there? This will be a new file
|
||||
repo = editor.prompt "Github repo (user/repo):"
|
||||
if not repo then
|
||||
return
|
||||
end
|
||||
branch = editor.prompt("Branch:", "main")
|
||||
if not branch then
|
||||
return
|
||||
end
|
||||
path = editor.prompt("File path:", editor.getCurrentPage() .. ".md")
|
||||
if not path then
|
||||
return
|
||||
end
|
||||
else
|
||||
-- We did find an existing file, let's fetch it to get the SHA
|
||||
local oldContent = githubGist.request(github.buildUrlWithBranch(repo, branch, path), "GET")
|
||||
if not oldContent.ok then
|
||||
editor.flashNotification("Could not fetch existing file", "error")
|
||||
return
|
||||
end
|
||||
sha = oldContent.body.sha
|
||||
end
|
||||
-- Ask for a commit message
|
||||
local message = editor.prompt("Commit message:", "Commit")
|
||||
-- Push the change
|
||||
local resp = githubGist.request(github.buildUrl(repo, path), "PUT", {
|
||||
message = message,
|
||||
committer = {
|
||||
name = config.get("github.name"),
|
||||
email = config.get("github.email"),
|
||||
},
|
||||
branch = branch,
|
||||
sha = sha,
|
||||
content = encoding.base64Encode(fm.text)
|
||||
})
|
||||
if resp.ok then
|
||||
editor.flashNotification "Published file successfully"
|
||||
local url = "https://github.com/" .. repo .. "/blob/" .. branch .. "/" .. path
|
||||
local updated = index.patchFrontmatter(editor.getText(),
|
||||
{
|
||||
{op="set-key", path=github.fmUrlKey, value=url}
|
||||
})
|
||||
editor.setText(updated)
|
||||
editor.flashNotification "Done!"
|
||||
else
|
||||
editor.flashNotification("Error, check console")
|
||||
js.log("Error", resp)
|
||||
end
|
||||
end
|
||||
}
|
||||
```
|
||||
Reference in New Issue
Block a user