summaryrefslogtreecommitdiff
path: root/_extensions/dragonstyle/unsplash/unsplash.lua
blob: fd87ab22bb45fa9052ffaf3ae4c06668db9d03db (plain)
  1. local mimeImgExts = {
  2. ["image/jpeg"]="jpg",
  3. ["image/gif"]="gif",
  4. ["image/vnd.microsoft.icon"]="ico",
  5. ["image/avif"]="avif",
  6. ["image/bmp"]="bmp",
  7. ["image/png"]="png",
  8. ["image/svg+xml"]="svg",
  9. ["image/tiff"]="tif",
  10. ["image/webp"]="webp",
  11. }
  12. local function file_exists(name)
  13. local f = io.open(name, 'r')
  14. if f ~= nil then
  15. io.close(f)
  16. return true
  17. else
  18. return false
  19. end
  20. end
  21. local function write_file(path, contents, mode)
  22. pandoc.system.make_directory(pandoc.path.directory(path), true)
  23. mode = mode or "a"
  24. local file = io.open(path, mode)
  25. if file then
  26. file:write(contents)
  27. file:close()
  28. return true
  29. else
  30. return false
  31. end
  32. end
  33. return {
  34. ['unsplash'] = function(args, kwargs, meta)
  35. -- positional == keywords
  36. -- {{< unsplash cat >}}
  37. -- {{< unsplash keywords="cats" height="300" width="300"}}
  38. -- TODO: use the real api to download a copy of the image using rest
  39. -- TODO: ping the download url
  40. -- TODO: Generate a stable name for the image
  41. -- TODO: Make this a format resource instead of media bag, so images become stable
  42. -- TODO: generate more complete information from REST endpoint to credit author
  43. local height = nil
  44. local width = nil
  45. local keywords = nil
  46. local classes = nil
  47. local float = nil
  48. -- the filename
  49. local filename
  50. if args[1] ~= nil then
  51. filename = pandoc.utils.stringify(args[1])
  52. local stem = pandoc.path.split_extension(pandoc.path.filename(filename))
  53. keywords = stem
  54. end
  55. -- height
  56. if kwargs['height'] ~= nil and #kwargs['height'] > 0 then
  57. height = pandoc.utils.stringify(kwargs['height'])
  58. end
  59. -- width
  60. if kwargs['width'] ~= nil and #kwargs['width'] > 0 then
  61. width = pandoc.utils.stringify(kwargs['width'])
  62. end
  63. -- keywords
  64. if kwargs['keywords'] ~= nil and #kwargs['keywords'] > 0 then
  65. keywords = pandoc.utils.stringify(kwargs['keywords'])
  66. end
  67. -- classes
  68. if kwargs['class'] ~= nil and #kwargs['class'] > 0 then
  69. classes = pandoc.utils.stringify(kwargs['class'])
  70. end
  71. -- classes
  72. if kwargs['float'] ~= nil and #kwargs['float'] > 0 then
  73. float = pandoc.utils.stringify(kwargs['float'])
  74. end
  75. -- form the unsplash URL that will be used
  76. local url = "https://source.unsplash.com/random"
  77. if width and height then
  78. url = url .. "/" .. tostring(width) .. '×' .. tostring(height)
  79. end
  80. if keywords ~= nil then
  81. url = url .. '/?' .. keywords
  82. end
  83. -- deal with the height and width
  84. local imgContainer = function (imgEl)
  85. -- HTML formats use a container to implement sizing, so
  86. -- apply classes and so on to that container
  87. if quarto.doc.is_format("html") then
  88. quarto.doc.add_html_dependency({
  89. name = "unsplash-styles",
  90. version = "1.0.0",
  91. stylesheets = {"style.css"}
  92. })
  93. local style = ""
  94. if height then
  95. style = style .. 'height: ' .. height .. '; '
  96. end
  97. if width then
  98. style = style .. 'width: ' .. width .. '; '
  99. end
  100. local divAttrRaw = {}
  101. if style ~= "" then
  102. divAttrRaw['style'] = style
  103. end
  104. local clz = pandoc.List({'unsplash-container'})
  105. if float then
  106. clz:insert('float-' .. float)
  107. end
  108. if classes ~= nil then
  109. for token in string.gmatch(classes, "[^%s]+") do
  110. clz:insert(token)
  111. end
  112. end
  113. local divAttr = pandoc.Attr("", clz, divAttrRaw)
  114. local div = pandoc.Div(imgEl, divAttr)
  115. return div
  116. else
  117. -- Non-HTML formats just return the raw image with
  118. -- any options set on that
  119. if height then
  120. imgEl.attr.attributes['height'] = height
  121. end
  122. if width then
  123. imgEl.attr.attributes['width'] = width
  124. end
  125. if classes ~= nil then
  126. for clz in string.gmatch(classes, "[^%s]+") do
  127. imgEl.attr.classes:insert(clz)
  128. end
  129. end
  130. return imgEl
  131. end
  132. end
  133. if filename ~= nil and file_exists(filename) then
  134. return imgContainer(pandoc.Image("", filename))
  135. elseif filename ~= nil then
  136. -- read the image
  137. local _imgMt, imgContents = pandoc.mediabag.fetch(url)
  138. write_file(filename, imgContents, "wb")
  139. return imgContainer(pandoc.Image("", filename))
  140. else
  141. -- read the image
  142. local imgMt, imgContents = pandoc.mediabag.fetch(url)
  143. -- place it in media bag and link to it
  144. if imgContents ~= nil then
  145. local tmpFileName = pandoc.path.filename(os.tmpname()) ..'.' .. mimeImgExts[imgMt]
  146. pandoc.mediabag.insert(tmpFileName, imgMt, imgContents)
  147. return imgContainer(pandoc.Image("", tmpFileName))
  148. end
  149. end
  150. end
  151. }