Pandoc Filter to add footnotes to links

2019-06-22 08:18发布

问题:

I just wanted to ask if anyone knows a short filter for Pandoc to automatically add footnotes to any links. I just want to have readable link source in my printed documents. So to specify, I'd like to go from

[link](url)

To something like

[link](url)[^link: url] 

So in the printed PDF the URL of the links I am referring to, should be visible at the bottom of the page.

回答1:

Try

pandoc -o myfile.pdf -V links-as-notes=true myfile.md

This only works in PDF output, but it's simple and doesn't require a filter. See the User's Guide/README under "Variables for LaTeX."

Edit: with this approach, you no longer have a hyperlink in the main text, just a note with the URL. So it's not exactly what you were asking for, but maybe it's enough.

Edit: here's how you could do it with a pandoc filter, retaining the link (untested, but should be close):

import Text.Pandoc.JSON

main = toJSONFilter go
  where go (Link attr lab (src, tit)) = Span ("",[],[]) [Link attr lab (src, tit), Note [Plain [Str src]]]
        go x = x


回答2:

An alternative to doing it with Pandoc filters, as in John MacFarlane answer would be to use LaTeX for that, creating a *.tex file and including it for example via -H / --include-in-header option to pandoc.

The LaTeX code could look like this (as of yet untested), based on Heiko Oberdiek answer to Auto generate list of \url usages within document question on TeX & LaTeX StackExchange:

\let\saved@hyper@linkurl\hyper@linkurl
\renewcommand*{\hyper@linkurl}[2]{%
  \saved@hyper@linkurl{#1}{#2}%
  \footnote{\url{#1}}%
}

I think the url package is automatically included by Pandoc; if not, you would need to add \usepackage{url} at the top of above code.


Note that the link in footnote in above solution uses \url{<link-target>} instead of bare <link-target> as footnote contents. I think it looks better, and there would certainly be no problems with _ in the URL (I don't know if Pandoc escapes that for LaTeX or not), and no problems with URL-friendly line break handling for very long URLs.

The John MacFarlane answer can be quite simply modified to do that:

import Text.Pandoc.JSON

main = toJSONFilter go
  where go (Link alt desc (url, title)) = Span ("",[],[]) [Link alt desc (url, title), Note [Plain [Link alt [Str url] (url, "")]]]
        go x = x


回答3:

The following solution provides exactly what the OP requested (and what I need) with no filter. Wherever you have a link in your document, it preserves the link, adds a footnote, and in the footnote there's a full URL.

This solution does require you to modify the LaTeX template, though.

Step 1 (Optional, if you already have a custom LaTeX template)

If you haven't already copied the default template somewhere, do that now using pandoc -D latex and saving that output to a file, perhaps template.latex, which I'll use as an example name for the rest of this.

Step 2

Find the following section your template (which is present in the default template):

$if(links-as-notes)$
% Make links footnotes instead of hotlinks:
\renewcommand{\href}[2]{#2\footnote{\url{#1}}}
$endif$

and replace it with

$if(links-as-notes)$
\usepackage{letltxmacro}
% Alias href to originalHref to avoid an infinite loop
\LetLtxMacro{\originalHref}{\href}
% Make links footnotes in addition to hotlinks:
\renewcommand{\href}[2]{\originalHref{#1}{#2}\footnote{\url{#1}}}
$endif$

Then run pandoc like pandoc -V links-as-notes --template=template.latex document.md -o document.pdf. You're done!

Step 3 (Optional)

There are a couple tweaks you can make. If you're tired of writing -V links-as-notes, you can either:

  • Add links-as-notes: true to your document's YAML metadata, or
  • Simply remove the $if(links-as-notes)$ and corresponding $endif$ from your template.

References

  • Similar solution, but for LaTeX, not pandoc
  • How to best rewrite a macro in terms of itself without causing an infinite loop