summaryrefslogtreecommitdiff
path: root/_extensions/dragonstyle/unsplash
diff options
context:
space:
mode:
authorJonas Smedegaard <dr@jones.dk>2024-01-19 13:43:55 +0100
committerJonas Smedegaard <dr@jones.dk>2024-01-19 13:43:55 +0100
commit6ffdf8759dbce8b7ade464a7f171fe1efcd73555 (patch)
treec5970ff4a9fef725c46f29ed791b9acc3823f949 /_extensions/dragonstyle/unsplash
initial draft
Diffstat (limited to '_extensions/dragonstyle/unsplash')
-rw-r--r--_extensions/dragonstyle/unsplash/_extension.yml8
-rw-r--r--_extensions/dragonstyle/unsplash/style.css25
-rw-r--r--_extensions/dragonstyle/unsplash/unsplash.lua193
3 files changed, 226 insertions, 0 deletions
diff --git a/_extensions/dragonstyle/unsplash/_extension.yml b/_extensions/dragonstyle/unsplash/_extension.yml
new file mode 100644
index 0000000..f22a6d2
--- /dev/null
+++ b/_extensions/dragonstyle/unsplash/_extension.yml
@@ -0,0 +1,8 @@
+title: Unsplash
+author: Charles Teague
+version: 1.0.3
+quarto-required: ">=1.3.0"
+contributes:
+ shortcodes:
+ - unsplash.lua
+
diff --git a/_extensions/dragonstyle/unsplash/style.css b/_extensions/dragonstyle/unsplash/style.css
new file mode 100644
index 0000000..42f9620
--- /dev/null
+++ b/_extensions/dragonstyle/unsplash/style.css
@@ -0,0 +1,25 @@
+.unsplash-container {
+ overflow: hidden;
+ margin-bottom: 1em;
+}
+
+.unsplash-container img {
+ object-fit: cover;
+ width: 100%;
+}
+
+.unsplash-container.float-right {
+ float: right;
+ padding-left: 0.75em;
+}
+
+.unsplash-container.float-left {
+ float: left;
+ padding-right: 0.75em;
+}
+
+.unsplash-container.float-center {
+ float: center;
+ padding-left: 0.75em;
+ padding-right: 0.75em;
+} \ No newline at end of file
diff --git a/_extensions/dragonstyle/unsplash/unsplash.lua b/_extensions/dragonstyle/unsplash/unsplash.lua
new file mode 100644
index 0000000..fd87ab2
--- /dev/null
+++ b/_extensions/dragonstyle/unsplash/unsplash.lua
@@ -0,0 +1,193 @@
+
+local mimeImgExts = {
+ ["image/jpeg"]="jpg",
+ ["image/gif"]="gif",
+ ["image/vnd.microsoft.icon"]="ico",
+ ["image/avif"]="avif",
+ ["image/bmp"]="bmp",
+ ["image/png"]="png",
+ ["image/svg+xml"]="svg",
+ ["image/tiff"]="tif",
+ ["image/webp"]="webp",
+}
+
+local function file_exists(name)
+ local f = io.open(name, 'r')
+ if f ~= nil then
+ io.close(f)
+ return true
+ else
+ return false
+ end
+end
+
+local function write_file(path, contents, mode)
+ pandoc.system.make_directory(pandoc.path.directory(path), true)
+ mode = mode or "a"
+ local file = io.open(path, mode)
+ if file then
+ file:write(contents)
+ file:close()
+ return true
+ else
+ return false
+ end
+end
+
+
+
+
+return {
+ ['unsplash'] = function(args, kwargs, meta)
+
+
+ -- positional == keywords
+ -- {{< unsplash cat >}}
+ -- {{< unsplash keywords="cats" height="300" width="300"}}
+
+ -- TODO: use the real api to download a copy of the image using rest
+ -- TODO: ping the download url
+ -- TODO: Generate a stable name for the image
+ -- TODO: Make this a format resource instead of media bag, so images become stable
+ -- TODO: generate more complete information from REST endpoint to credit author
+
+ local height = nil
+ local width = nil
+ local keywords = nil
+ local classes = nil
+ local float = nil
+
+ -- the filename
+ local filename
+ if args[1] ~= nil then
+ filename = pandoc.utils.stringify(args[1])
+ local stem = pandoc.path.split_extension(pandoc.path.filename(filename))
+ keywords = stem
+ end
+
+ -- height
+ if kwargs['height'] ~= nil and #kwargs['height'] > 0 then
+ height = pandoc.utils.stringify(kwargs['height'])
+ end
+
+ -- width
+ if kwargs['width'] ~= nil and #kwargs['width'] > 0 then
+ width = pandoc.utils.stringify(kwargs['width'])
+ end
+
+ -- keywords
+ if kwargs['keywords'] ~= nil and #kwargs['keywords'] > 0 then
+ keywords = pandoc.utils.stringify(kwargs['keywords'])
+ end
+
+ -- classes
+ if kwargs['class'] ~= nil and #kwargs['class'] > 0 then
+ classes = pandoc.utils.stringify(kwargs['class'])
+ end
+
+ -- classes
+ if kwargs['float'] ~= nil and #kwargs['float'] > 0 then
+ float = pandoc.utils.stringify(kwargs['float'])
+ end
+
+
+ -- form the unsplash URL that will be used
+ local url = "https://source.unsplash.com/random"
+ if width and height then
+ url = url .. "/" .. tostring(width) .. '×' .. tostring(height)
+ end
+ if keywords ~= nil then
+ url = url .. '/?' .. keywords
+ end
+
+ -- deal with the height and width
+
+ local imgContainer = function (imgEl)
+
+ -- HTML formats use a container to implement sizing, so
+ -- apply classes and so on to that container
+ if quarto.doc.is_format("html") then
+
+
+ quarto.doc.add_html_dependency({
+ name = "unsplash-styles",
+ version = "1.0.0",
+ stylesheets = {"style.css"}
+ })
+
+ local style = ""
+ if height then
+ style = style .. 'height: ' .. height .. '; '
+ end
+ if width then
+ style = style .. 'width: ' .. width .. '; '
+ end
+
+ local divAttrRaw = {}
+ if style ~= "" then
+ divAttrRaw['style'] = style
+ end
+
+ local clz = pandoc.List({'unsplash-container'})
+ if float then
+ clz:insert('float-' .. float)
+ end
+
+ if classes ~= nil then
+ for token in string.gmatch(classes, "[^%s]+") do
+ clz:insert(token)
+ end
+ end
+
+ local divAttr = pandoc.Attr("", clz, divAttrRaw)
+ local div = pandoc.Div(imgEl, divAttr)
+
+ return div
+
+ else
+
+ -- Non-HTML formats just return the raw image with
+ -- any options set on that
+
+ if height then
+ imgEl.attr.attributes['height'] = height
+ end
+ if width then
+ imgEl.attr.attributes['width'] = width
+ end
+
+ if classes ~= nil then
+ for clz in string.gmatch(classes, "[^%s]+") do
+ imgEl.attr.classes:insert(clz)
+ end
+ end
+
+ return imgEl
+
+ end
+ end
+
+ if filename ~= nil and file_exists(filename) then
+ return imgContainer(pandoc.Image("", filename))
+ elseif filename ~= nil then
+ -- read the image
+ local _imgMt, imgContents = pandoc.mediabag.fetch(url)
+ write_file(filename, imgContents, "wb")
+ return imgContainer(pandoc.Image("", filename))
+ else
+ -- read the image
+ local imgMt, imgContents = pandoc.mediabag.fetch(url)
+
+ -- place it in media bag and link to it
+ if imgContents ~= nil then
+ local tmpFileName = pandoc.path.filename(os.tmpname()) ..'.' .. mimeImgExts[imgMt]
+ pandoc.mediabag.insert(tmpFileName, imgMt, imgContents)
+ return imgContainer(pandoc.Image("", tmpFileName))
+ end
+ end
+
+
+ end
+}
+
+