Pandoc generation of pdf from markdown 4th header is rendered differently
Asked Answered
T

5

26

I am using pandoc to generate a pdf from some markdown. I am using h1 through h4 via hash symbols. Example h1=#, h4=####. When I generate my document like this:

pandoc input.md -o output.pdf

I get a document where h1, h2 and h3 have a newline after them but h4 does not have a new line. The text starts on the same line as the header (it isn't formatted the same way, but there isn't a newline character between).

I've tried adding spaces after the #### and adding manual line returns using my editor but nothing seems to work.

Any ideas?

Typographer answered 17/1, 2014 at 23:43 Comment(1)
Maybe you can some code which illustrates the problem.Damiendamietta
A
18

While the mentioned solutions work fine, pandoc offers a build-in variable to enable block-headings for \paragraph.

pandoc -s -o out.pdf some.md -V block-headings

Pandoc Manual

Alysaalyse answered 14/5, 2020 at 18:58 Comment(2)
Thanks, this should be the accepted answer. Simple, efficient and in the scope of the question.Emersonemery
I added the following code to the yaml block and it worked: block-headings: trueMarlie
F
13

pandoc generates PDFs via LaTeX. In LaTeX, "headers" are generated using the following commands:

  1. \section
  2. \subsection
  3. \subsubsection
  4. \paragraph
  5. \subparagraph

As you can see, a "level four heading" corresponds to the \paragraph command, which is rendered as you describe. There simply isn't a \subsubsubsection command to use.

The only way to get what you want is to redefine the \paragraph command, which is quite tricky. I haven't been able to make it work with Pandoc.

Fauver answered 18/1, 2014 at 13:33 Comment(0)
G
5

While @tarleb’s answer is surely the best (except that it specifies a wrong amount of vertical space), here is a “simpler” (by some measure) but more hacky (in LaTeX terms at least) solution which optionally uses a Pandoc Lua filter or a LaTeX hack but avoids loading another LaTeX package.

We want the LaTeX source to look something like this:

\hypertarget{level-4-heading}{%
\paragraph{Level 4 heading}\label{level-4-heading}}

\hfill

Lorem ipsum dolor sit amet.

This LaTeX looks awful, but if you don’t need to keep or share the LaTeX source it does what you probably want: a space between the level 4 heading and the paragraph after it equal to the space between a level 3 heading and the paragraph after it.

Level 4 heading with paragraph break

Here is how it works: since a \hfill on a line on its own is about as close as you can get to an empty paragraph in LaTeX you get a first paragraph — the one running in with the heading — containing only horizontal white space until the end of the line, and then immediately after a new paragraph — the actual first paragraph after the heading — with just a normal paragraph space between it and the heading. This probably also upsets LaTeX’s idea about what a \paragraph should be like as little as possible.

The “manual” way to do this is as follows:

    #### Level 4 heading

    ````{=latex}
    \hfill
    ````

    Lorem ipsum dolor sit amet.

This uses Pandoc’s relatively new raw markup syntax — the “code block” is actually a raw LaTeX block — but it looks even more awful than the resulting LaTeX source! It is also a tedious chore to have to insert this after every level 4 heading. In other words you want to insert that raw LaTeX automatically, and that can be done with a Lua filter:

    --[======================================================================[

    latex-h4-break.lua - Pandoc filter to get break after a level 4 heading.

    Usage:

        $ pandoc --lua-filter latex-h4-break.lua input.md -o output.pdf

    --]======================================================================]

    -- create it once, use it many times!
    local hfill_block = pandoc.RawBlock('latex', '\\hfill')

    function Header (elem)
        if 4 == elem.level then 
            return { elem, hfill_block }
        else -- ignore headings at other levels!
            return nil 
        end
    end

However you can also do a simple LaTeX hack in a header-includes metadata block to get the same effect:

    ---
    header-includes: 
      - |
        ``` {=latex}
        \let\originAlParaGraph\paragraph
        \renewcommand{\paragraph}[1]{\originAlParaGraph{#1} \hfill}
        ```
    ---

    #### Level 4 heading

    Lorem ipsum dolor sit amet.

This works by first creating an “alias” of the \paragraph command and then redefining the \paragraph command itself, using the alias in the new definition so that now wherever the LaTeX source created by Pandoc contains \paragraph{Foo} it is if it instead had contained \paragraph{Foo} \hfill which does what we want with zero extra dependencies! (In case you wonder the wacky spelling of the “aliased” command is to minimize the risk that it collides with anything which already exists, since the TeX \let command doesn’t check for that. We certainly don’t want to overwrite any existing command!)

NOTE: If you really should want more or less space than a normal paragraph break after the heading just add an appropriate \vspace command after the \hfill: \hfill \vspace{-0.5\parskip}.

Gar answered 16/8, 2019 at 13:26 Comment(0)
S
3

Shifting Headers

Arguably the best way to solve this would be to avoid the problem altogether by shifting what a level 4 header corresponds to. The default for pandoc is to use \section commands for 1st level and \paragraph for 4th level headers. This can be altered via the --top-level-division parameter:

--top-level-division=[default|section|chapter|part]

Treat top-level headers as the given division type in LaTeX [...] output. The hierarchy order is part, chapter, then section; all headers are shifted such that the top-level header becomes the specified type. The default behavior is to determine the best division type via heuristics [...]

So with --top-level-division=chapter, a 4th-level header would be generated via the \subsubsection command.

Styling via LaTeX

If this is not an option, the next best way is to configure the layout of the corresponding LaTeX command: for level-four headers, this is \paragraph by default. The following methods are taken from TeX StackExchange answers.

Please also check the answer by bpj, which is much simpler than what's proposed below.

Default document-classes

The default way would be to configure \paragraph via the titlesec package. We can use the header-includes metadata field for this, which pandoc will include in the intermediate LaTeX document.

---
header-includes: |
  ``` {=latex}
  \usepackage{titlesec}
  \titlespacing*{\paragraph}{0pt}{1ex}{-\parskip}
  \titleformat{\paragraph}[hang]
      {\normalfont\bfseries}
      {}
      {0pt}
      {}
  ```
---

KOMA document-classes

Using titlesec won't work properly for documents using KOMA classes (like scrartcl), as KOMA has it's own ways of doing things. For these, use this alternative snippet:

---
documentclass: scrartcl
header-includes: |
  ``` {=latex}
  \makeatletter
  \renewcommand\paragraph{\@startsection{paragraph}{4}{\z@}%
    {-3.25ex \@plus -1ex \@minus -0.2ex}%
    {0.01pt}%
    {\raggedsection\normalfont\sectfont\nobreak\size@paragraph}%
  }
  \makeatother
  ```
---
Stork answered 13/8, 2019 at 15:35 Comment(3)
It's not clear where the latex code should be pasted? Is this in the document itself? Does it have to be in a specific location or surrounded by some tokens?Yesima
If I use --top-level-division=chapter on the command line, I get Undefined control sequence. <argument> \chapter {Overview}\label {overview} l.128 \chapter{Overview}\label{overview}}?Were
@Were you are probably not using a document class which supports chapters. Try calling pandoc with --metadata=documentclass=report.Stork
B
0

I am not sure, why, but this works for me:

Put $\ \\ $ in the first line after your #### headline

Blackett answered 6/2, 2014 at 18:8 Comment(1)
That "works" because you're manually inserting a line break with inline LaTeX after your heading. It's not really a solution, as it must be done every time you insert a new one.Fauver

© 2022 - 2024 — McMap. All rights reserved.