|
1 | | --- Lua filter that behaves like `--citeproc` |
| 1 | +-- Check if a citekey looks like a crossref |
| 2 | +function is_crossref(id, meta) |
| 3 | + -- These are all of Quarto's built-in crossref prefixes: |
| 4 | + -- https://quarto.org/docs/authoring/cross-references.html#reserved-prefixes |
| 5 | + -- |
| 6 | + -- This checks to see if it's one of those |
| 7 | + local known_prefixes = { |
| 8 | + "fig", "tbl", "lst", "tip", "nte", "wrn", "imp", "cau", "thm", "lem", "cor", |
| 9 | + "prp", "cnj", "def", "exm", "exr", "sol", "rem", "alg", "eq", "sec" |
| 10 | + } |
| 11 | + for _, prefix in ipairs(known_prefixes) do |
| 12 | + if id:match("^" .. prefix .. "%-") then |
| 13 | + return true |
| 14 | + end |
| 15 | + end |
| 16 | + |
| 17 | + -- Users can specify their own custom crossref types: |
| 18 | + -- https://quarto.org/docs/authoring/cross-references-custom.html |
| 19 | + -- |
| 20 | + -- This checks the document metadata and to see if there's a crossref entry |
| 21 | + -- and then extracts the key prefix if present |
| 22 | + if meta.crossref and meta.crossref.custom then |
| 23 | + local custom = meta.crossref.custom |
| 24 | + -- custom could be a list of tables |
| 25 | + for i = 1, #custom do |
| 26 | + local item = custom[i] |
| 27 | + if item.key then |
| 28 | + local key = pandoc.utils.stringify(item.key) |
| 29 | + if id:match("^" .. key .. "%-") then |
| 30 | + return true |
| 31 | + end |
| 32 | + end |
| 33 | + end |
| 34 | + end |
| 35 | + |
| 36 | + return false |
| 37 | +end |
| 38 | + |
| 39 | +-- Run citeproc, but first protect/preserve all the cross references |
2 | 40 | function Pandoc (doc) |
3 | | - return pandoc.utils.citeproc(doc) |
| 41 | + -- Remove crossref keys before running citeproc |
| 42 | + local crossrefs = {} |
| 43 | + doc = doc:walk({ |
| 44 | + Cite = function(el) |
| 45 | + if is_crossref(el.citations[1].id, doc.meta) then |
| 46 | + -- Store the cite element with a unique placeholder |
| 47 | + local placeholder = "CROSSREF" .. #crossrefs .. "PLACEHOLDER" |
| 48 | + table.insert(crossrefs, el) |
| 49 | + return pandoc.Str(placeholder) |
| 50 | + end |
| 51 | + end |
| 52 | + }) |
| 53 | + |
| 54 | + -- Run citeproc |
| 55 | + doc = pandoc.utils.citeproc(doc) |
| 56 | + |
| 57 | + -- Put crossref keys back now that citations have been handled |
| 58 | + doc = doc:walk({ |
| 59 | + Str = function(el) |
| 60 | + local match = el.text:match("CROSSREF(%d+)PLACEHOLDER") |
| 61 | + if match then |
| 62 | + return crossrefs[tonumber(match) + 1] |
| 63 | + end |
| 64 | + end |
| 65 | + }) |
| 66 | + |
| 67 | + return doc |
4 | 68 | end |
0 commit comments