Search code examples
luapandocquarto

How can you take Quarto YAML metadata and use it as a value in Lua filter?


I am currently trying to write an extension for Quarto, and I've been asked to make it customizable using options in the YAML rather than having users edit the Lua script directly

Here is the lua filter I have so far, but I cannot for the life of me get working code to have metadata inputs to replace the fixed values for color and style. I've tried a variety of ways I found online of including meta, but cannot get any to work. I'm sure it's simple enough, but if someone could point me in the right direction it would be greatly appreciated.

function HorizontalRule (elem)
    if FORMAT == 'docx' then
    
    local color = "0000FF"
    local style = "double"

    local horizontallinerule = string.format([[<w:p>
      <w:pPr>
        <w:pStyle w:val="HorizontalRule"/>
          <w:ind w:firstLine="0"/>
          <w:jc w:val="center"/>
        <w:pBdr>
          <w:bottom w:val="%s" w:color="%s"/>
        </w:pBdr>
      </w:pPr>
      <w:r>
        <w:t></w:t>
      </w:r>
    </w:p>]], style, color)

      return pandoc.RawBlock('openxml', horizontallinerule)
    end
end

If a full repex is useful, see my test branch of the project on GitHub here


Solution

  • The easiest way is probably to filter the main Pandoc document. That element contains both the metadata and the actual document. Here's an example:

    local function make_hr_handler (remove_hr)
      return function (el)
        if remove_hr then
          return {}
        end
      end
    end
    
    function Pandoc (doc)
      local remove_horizontal_rules = doc.meta['remove-horizontal-rules']
      return doc:walk {
        HorizontalRule = make_hr_handler(remove_horizontal_rules),
      }
    end
    

    Note that make_hr_handler returns a function, so the filter function is generated dynamically. The doc:walk method takes a table of filter functions; it basically works the same as defining global (top-level) filter functions.

    The same effect could be achieved with variables shared by both functions, but I find the above easier.