This project provides a lua filter for Pandoc along with some CSS styles which together allow curly quotes to hang into the margin. Here’s an example:
“How do you call among you the little mouse, the mouse that jumps?” Paul asked, remembering the pop-hop of motion at Tuono Basin. He illustrated with one hand. A chuckle sounded through the troop. “We call that one muad’dib,” Stilgar said.
— Frank Herbert, Dune
Note how the “
on the first line hangs into the margin.
But also, depending on the screen width, the mid-paragraph quote
starting “We ...
may also hang into the margin:
This effect is not possible with the hanging-punctuation
CSS property. Safari supports it, but only for the very first quotation
mark in a block. All other browsers do not support it.
By contrast, this filter allows quotation characters to hang into the margin even in the middle of body text, and works in all browsers.
For more, read about hanging punctuation on Wikipedia.
Usage
Download the
hanging-punctuation.lua
file:curl -sSLO https://raw.githubusercontent.com/jez/pandoc-hanging-punctuation/refs/heads/master/hanging-punctuation.lua
Download the
hanging-punctuation.css
file:curl -sSLO https://raw.githubusercontent.com/jez/pandoc-hanging-punctuation/refs/heads/master/hanging-punctuation.css
Pass these files when invoking
pandoc
:pandoc -f markdown -t html index.md \ --standalone \ --lua-filter=./hanging-punctuation.lua \ --css ./hanging-punctuation.css > index.html
The input must either use
‘
and“
quotes directly, or have thesmart
extension enabled.The
smart
extension is on by default in Pandoc’smarkdown
input format, but off by default in others, including thecommonmark
format. Enable it by passing+smart
to the format when invokingpandoc
, like-f commonmark+smart
.See the Pandoc docs for more:
Modify the
hanging-punctuation.css
file to set the two root CSS variables:/* -- hanging-punctuation.css -- */ :root { /** * These widths will vary with font-family, font-weight, etc. * TODO: Customize these values as needed */ --single-quote-width: 0.275em; --double-quote-width: 0.44em; } /* ... */
These variables declare how big
‘
and“
characters are in the chosen font. Different font settings, like the family and weight, will affect the width.To determine a value for these variables, use a document like this:
--- title: test --- Hello\ "Hello"\ Hello\ 'Hello'\ Hello
Render this markdown to HTML, then use the browser’s developer tools to vertically align all the
H
characters.As a a trick, on some operating systems you can use the system screenshot tool as a quick way to check if things are aligned and measure pixels distances on the screen.
Ensure that no other CSS in the page sets the
hanging-punctuation
property.Either edit that CSS to remove mentions of it, or write CSS to forcibly override any inherited
hanging-punctuation
settings.
Caveats
Only HTML output has been tested. Other Pandoc output formats, like LaTeX or Microsoft Word, are not supported (though it may be possible to use this tool as a starting point to support other formats).
This overrules the
--html-q-tags=true
option affecting the HTML writer. No<q>
tags will be produced in the output, even with that option passed, if this filter is used.(Why? Because this filter eliminates
Quoted
nodes in Pandoc’s internal AST in the course of working, which otherwise power the HTML writer’s<q>
tag support.)Hanging is disabled inside list items and table cells, even if there would otherwise be enough space in the margin to hang the punctuation.
To change this, edit the relevant lines in
hanging-punctuation.css
as desired.
Inspiration
This filter is heavily inspired by Typeset, “An HTML pre-processor for web typography.” Compared to Typeset, this project:
- Requires no JavaScript library (nor JavaScript build process)
- Uses Pandoc’s internal document AST, instead of the DOM, which makes certain edge cases more robust.
- Does not need to handle straight → curly quotation mark conversion nor en- and em-dash conversion, because Pandoc handles those.
Typeset includes other features which could be handled separately if desired (like auto-soft-hyphenation and certain other punctuation substitutions). The markup structure in this project is borrowed from Typeset.
It’s also inspired by Dropbox Paper, which includes support for hanging punctuation, and has inspired my other writing-focused tools. In particular, this website is uses my Pandoc Markdown CSS Theme, which draws heavy inspiration from the look of Dropbox Paper.
Testing
“Hello”
Hello
‘Hello’
Hello