|
| 1 | +local images = {} |
| 2 | + |
| 3 | +-- Extract images from the document |
| 4 | +function Image(el) |
| 5 | + local caption_text = "" |
| 6 | + |
| 7 | + -- Extract caption correctly (works with  syntax) |
| 8 | + if el.caption and type(el.caption) == "table" then |
| 9 | + for _, inline in ipairs(el.caption) do |
| 10 | + if inline.t == "Str" then |
| 11 | + caption_text = caption_text .. inline.text .. " " |
| 12 | + elseif inline.t == "Space" then |
| 13 | + caption_text = caption_text .. " " |
| 14 | + end |
| 15 | + end |
| 16 | + caption_text = caption_text:gsub("%s+$", "") |
| 17 | + end |
| 18 | + |
| 19 | + table.insert(images, { |
| 20 | + url = el.src, |
| 21 | + caption = caption_text, |
| 22 | + width = el.attributes.width or nil, |
| 23 | + height = el.attributes.height or nil |
| 24 | + }) |
| 25 | + |
| 26 | + return el |
| 27 | +end |
| 28 | + |
| 29 | +-- Function to inject JSON-LD before the first heading or at the end |
| 30 | +function Pandoc(doc) |
| 31 | + if #images == 0 then |
| 32 | + return doc |
| 33 | + end |
| 34 | + |
| 35 | + -- Ensure `site_url` exists; otherwise, use empty string |
| 36 | + local site_url = doc.meta.site_url or "" |
| 37 | + if site_url ~= "" and not site_url:match("/$") then |
| 38 | + site_url = site_url .. "/" |
| 39 | + end |
| 40 | + |
| 41 | + local jsonld_images = { |
| 42 | + ["@context"] = "https://schema.org", |
| 43 | + ["@type"] = "ItemList", |
| 44 | + itemListElement = {} |
| 45 | + } |
| 46 | + |
| 47 | + for _, img in ipairs(images) do |
| 48 | + local absolute_url = img.url |
| 49 | + if not absolute_url:match("^https?://") then |
| 50 | + absolute_url = site_url .. img.url:gsub("^%./", "") |
| 51 | + end |
| 52 | + |
| 53 | + table.insert(jsonld_images.itemListElement, { |
| 54 | + ["@type"] = "ImageObject", |
| 55 | + url = absolute_url, |
| 56 | + caption = img.caption, |
| 57 | + width = img.width, |
| 58 | + height = img.height |
| 59 | + }) |
| 60 | + end |
| 61 | + |
| 62 | + -- Convert JSON-LD to a script tag |
| 63 | + local jsonld_script = pandoc.RawBlock("html", "<script type=\"application/ld+json\">\n" |
| 64 | + .. quarto.json.encode(jsonld_images, { pretty = true }) .. "\n</script>") |
| 65 | + |
| 66 | + -- Inject JSON-LD **before the first <h1> or at the end** |
| 67 | + local inserted = false |
| 68 | + for i, block in ipairs(doc.blocks) do |
| 69 | + if block.t == "Header" and block.level == 1 then |
| 70 | + table.insert(doc.blocks, i, jsonld_script) |
| 71 | + inserted = true |
| 72 | + break |
| 73 | + end |
| 74 | + end |
| 75 | + |
| 76 | + -- If no <h1> was found, append JSON-LD at the end |
| 77 | + if not inserted then |
| 78 | + table.insert(doc.blocks, jsonld_script) |
| 79 | + end |
| 80 | + |
| 81 | + return doc |
| 82 | +end |
0 commit comments