How to use LaTeX section numbers in Pandoc cross-reference
Asked Answered
S

4

10

The Pandoc documentation says that cross references can be made to section headers in a number of ways. For example, you can create your own ID and reference that ID. For example:

# This is my header {#header}

Will create an ID with value '#header' that can be refenced in the text, as such:

[Link to header](#header)

Which will display the text 'Link to header' with a link to the header.

I couldn't find anywhere how to make the text of the link be the section number when compiled as a LaTeX document.

For example, if my header is compiled to '1.2.3 Section Header', I want my cross-reference to text to display as '1.2.3'.

Sign answered 10/1, 2019 at 12:12 Comment(0)
S
9

This can be achieved by defining the ID as done previously. eg:

# This is my header {#header}

Then in the text, the cross reference can be written as:

\ref{header}

When this compiles to LaTeX, the cross-reference text will be the section number of the referenced heading.

Sign answered 10/1, 2019 at 12:12 Comment(0)
C
4

You can use the pandoc-secnos filter, which is part of the pandoc-xnos filter suite.

The header

# This is my header {#sec:header}

is referenced using @sec:header. Alternatively, you can reference

# This is my header

using @sec:this-is-my-header.

Markdown documents coded in this way can be processed by adding --filter pandoc-secnos to the pandoc call. The --number-sections option should be used as well. The output uses LaTeX's native commands (i.e., \label and \ref or \cref).

The benefit to this approach is that output in other formats (html, epub, docx, ...) is also possible.

Caddric answered 18/9, 2019 at 3:22 Comment(0)
M
4

Since pandoc version 2.8 the function pandoc.utils.hierarchicalize has been replaced with make_sections. Here is an updated version of the @tarleb's answer which works with newer ´pandoc´ versions.

local make_sections = (require 'pandoc.utils').make_sections
local section_numbers = {}

function populate_section_numbers (doc)
  function populate (elements)
    for _, el in pairs(elements) do
      if el.t == 'Div' and el.attributes.number then
        section_numbers['#' .. el.attr.identifier] = el.attributes.number
        populate(el.content)
      end
    end
  end

  populate(make_sections(true, nil, doc.blocks))
end

function resolve_section_ref (link)
  if #link.content > 0 or link.target:sub(1, 1) ~= '#' then
    return nil
  end
  local section_number = pandoc.Str(section_numbers[link.target])
  return pandoc.Link({section_number}, link.target, link.title, link.attr)
end

return {
  {Pandoc = populate_section_numbers},
  {Link = resolve_section_ref}
}
Metonymy answered 3/5, 2020 at 15:48 Comment(0)
B
3

A general solution which works with all supported output formats can be build by leveraging pandoc Lua filters: The function pandoc.utils.hierarchicalize can be used to get the document hierarchy. We can use this to associate section IDs with section numbers, which can later be used to add these numbers to links with no link description (e.g., [](#myheader)).

local hierarchicalize = (require 'pandoc.utils').hierarchicalize

local section_numbers = {}

function populate_section_numbers (doc)
  function populate (elements)
    for _, el in pairs(elements) do
      if el.t == 'Sec' then
        section_numbers['#' .. el.attr.identifier] = table.concat(el.numbering, '.')
        populate(el.contents)
      end
    end
  end

  populate(hierarchicalize(doc.blocks))
end

function resolve_section_ref (link)
  if #link.content > 0 or link.target:sub(1, 1) ~= '#' then
    return nil
  end
  local section_number = pandoc.Str(section_numbers[link.target])
  return pandoc.Link({section_number}, link.target, link.title, link.attr)
end

return {
  {Pandoc = populate_section_numbers},
  {Link = resolve_section_ref}
}

The above should be saved to a file and then passed to pandoc via the --lua-filter option.

Example

Using the example from the question

# This is my header {#header}

## Some subsection

See section [](#header), especially [](#some-subsection)

Using the above filter, the last line will render as "See section 1, especially 1.1".

Don't forget to call pandoc with option --number-sections, or headers will not be numbered.

Benildas answered 10/1, 2019 at 14:8 Comment(2)
Finally I have enough karma to upvote you. Thank you for this nice filter! For future reference, it should be included in pandoc's lua-filters repository. Cheers!Aquilar
Thanks @A.M.! So great to hear that this is useful :)Benildas

© 2022 - 2024 — McMap. All rights reserved.