Sam Walpole
Sam Walpole

Reputation: 1194

How to use LaTeX section numbers in Pandoc cross-reference

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'.

Upvotes: 10

Views: 6508

Answers (4)

Alexey Gavrilov
Alexey Gavrilov

Reputation: 10853

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}
}

Upvotes: 4

tjd
tjd

Reputation: 780

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.

Upvotes: 4

tarleb
tarleb

Reputation: 22709

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.

Upvotes: 3

Sam Walpole
Sam Walpole

Reputation: 1194

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.

Upvotes: 9

Related Questions