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