summaryrefslogtreecommitdiff
path: root/_extensions/pandoc-ext/abstract-section/abstract-section.lua
blob: 4badeb4793ef9e35d2b2577f3a8986991757c6cf (plain)
  1. --[[
  2. abstract-section – move an "abstract" section into document metadata
  3. Copyright: © 2017–2023 Albert Krewinkel
  4. License: MIT – see LICENSE file for details
  5. ]]
  6. local stringify = (require 'pandoc.utils').stringify
  7. local section_identifiers = {
  8. abstract = true,
  9. }
  10. local collected = {}
  11. --- The level of the highest heading that was seen so far. Abstracts
  12. --- must be at or above this level to prevent nested sections from being
  13. --- treated as metadata. Only top-level sections should become metadata.
  14. local toplevel = 6
  15. --- Extract abstract from a list of blocks.
  16. local function abstract_from_blocklist (blocks)
  17. local body_blocks = {}
  18. local looking_at_section = false
  19. for _, block in ipairs(blocks) do
  20. if block.t == 'Header' and block.level <= toplevel then
  21. toplevel = block.level
  22. if section_identifiers[block.identifier] then
  23. looking_at_section = block.identifier
  24. collected[looking_at_section] = {}
  25. else
  26. looking_at_section = false
  27. body_blocks[#body_blocks + 1] = block
  28. end
  29. elseif looking_at_section then
  30. if block.t == 'HorizontalRule' then
  31. looking_at_section = false
  32. else
  33. local collect = collected[looking_at_section]
  34. collect[#collect + 1] = block
  35. end
  36. else
  37. body_blocks[#body_blocks + 1] = block
  38. end
  39. end
  40. return body_blocks
  41. end
  42. Pandoc = function (doc)
  43. local meta = doc.meta
  44. -- configure
  45. section_identifiers_list =
  46. (doc.meta['abstract-section'] or {})['section-identifiers']
  47. if section_identifiers_list and #section_identifiers_list > 0 then
  48. section_identifiers = {}
  49. for i, ident in ipairs(section_identifiers_list) do
  50. section_identifiers[stringify(ident)] = true
  51. end
  52. end
  53. -- unset config in meta
  54. doc.meta['abstract-section'] = nil
  55. local blocks = {}
  56. if PANDOC_VERSION >= {2,17} then
  57. -- Walk all block lists by default
  58. blocks = doc.blocks:walk{Blocks = abstract_from_blocklist}
  59. elseif PANDOC_VERSION >= {2,9,2} then
  60. -- Do the same with pandoc versions that don't have walk methods but the
  61. -- `walk_block` function.
  62. blocks = pandoc.utils.walk_block(
  63. pandoc.Div(doc.blocks),
  64. {Blocks = abstract_from_blocklist}
  65. ).content
  66. else
  67. -- otherwise, just check the top-level block-list
  68. blocks = abstract_from_blocklist(doc.blocks)
  69. end
  70. for metakey in pairs(section_identifiers) do
  71. metakey = stringify(metakey)
  72. local abstract = collected[metakey]
  73. if not meta[metakey] and abstract and #abstract > 0 then
  74. meta[metakey] = pandoc.MetaBlocks(abstract)
  75. end
  76. end
  77. return pandoc.Pandoc(blocks, meta)
  78. end