Jay
Jay

Reputation: 9656

How do I include meta tags in Pandoc-generated HTML?

I am using Pandoc to write the contents of a site. How do I include meta tags (specifically, description and keywords tags) on a document, without changing the command line arguments passed to Pandoc?

I mean, can I include meta tags somehow in the document text? I don't want to pass command line options, because there are several different pages, with different keywords, that I'd like to send to Pandoc from within Emacs, and customizing each of them would be a problem.

Upvotes: 16

Views: 8925

Answers (3)

Warbo
Warbo

Reputation: 2736

I've found that adding the --self-contained or -s option to the pandoc command allows header contents to be defined per-file in YAML at the top.

For example:

    $ cat foo.md
    ---
    title: Foo
    header-includes:
        <meta name="keywords" content="Foo,Bar" />
        <meta name="description" content="My description" />
    ---
    
    # Bar #
    
    Baz
    $ pandoc -s -o foo.html foo.md
    $ cat foo.html
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
      <meta http-equiv="Content-Style-Type" content="text/css" />
      <meta name="generator" content="pandoc" />
      <title>Foo</title>
      <style type="text/css">code{white-space: pre;}</style>
      <meta name="keywords" content="Foo,Bar" /> <meta name="description" content="My description" />
    </head>
    <body>
    <div id="header">
    <h1 class="title">Foo</h1>
    </div>
    <h1 id="bar">Bar</h1>
    <p>Baz</p>
    </body>
    </html>

Upvotes: 24

Jay
Jay

Reputation: 9656

Ok -- so option 1 suggested by David Cain seems like a reasonably easy solution. My implementation of it is a bit ugly, but works:

First, use YAML headers with a field name ending in underscore to add a header line. The Pandoc manual says that these identifiers will be ignored.

---
head_: <meta name="description" content="x is super cool">
head_: <meta name="keywords"    content="cool,cold,temperature,super things">
---

Make Emacs search for it in the current buffer and save the line to a file.

(defvar my-markdown-header-file "head.html")

(defun my-markdown-add-headers ()
  (if (file-exists-p my-markdown-header-file)
      (delete-file   my-markdown-header-file))
  (append-to-file "" nil my-markdown-header-file)
  (save-excursion
    (goto-char 1)
    (while (re-search-forward "head_:" nil t)
      ;; get the first and last positions:
      (let ((start (point))
            (end   (progn (end-of-line) (point))))
      ;; include this line, and a newline after it:
      (append-to-file start end my-markdown-header-file)
      (append-to-file "\n"  nil my-markdown-header-file)))))

(add-hook 'markdown-before-export-hook 'my-markdown-add-headers)

(My elisp ability is not that great, so there probably are better ways of writing this)

Finally -- use pandoc -s -H head.html as markdown command in Emacs markdown-mode.

Thanks to David Cain for suggesting the -H option!

edit: as a bonus, we get to include anything in the headers, including favicons!

head_: <link rel="icon" type="image/x-icon" href="favicon.ico" />

Upvotes: 4

David Cain
David Cain

Reputation: 17353

The standard way to insert meta-tags with Pandoc would be to use the -H option.

Using -H/--include-in-header:

  1. input.md:

    ### Header
    Body text
    
  2. header.html:

    <meta name="description" content="My dummy HTML page">
    
  3. Create file:

    pandoc -s input.md -o out.html -H header.html
    

Templates

However, if you're averse to using command-line arguments, you can make use of Templates. Pandoc builds your document by inserting parsed data into a pre-defined template:

$ pandoc -D html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"$if(lang)$ lang="$lang$" xml:lang="$lang$"$endif$>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <meta http-equiv="Content-Style-Type" content="text/css" />
  <meta name="generator" content="pandoc" />
$for(author-meta)$
  <meta name="author" content="$author-meta$" />
 ... (and so on)

There's no reason why you couldn't modify the template to suit your needs. Pandoc already extracts some useful meta-data (such as the author) from the body of your document. You could modify it to do the same with some custom meta-tags. This would obviously involve modifying the source of Pandoc.

An alternate solution (that wouldn't involve any Haskell coding) would be to make Emacs parse out meta-data from each file, before passing the remainder to Pandoc for rendering. This leaves two reasonable approaches:

  1. Allow a section for an HTML header in each document, extract this section and automatically insert it with -H
  2. Define your own format for meta-data: Write a template to place meta-data accordingly, extract this meta-data, then pass variable values with -V.

I'd go with option 1, as it's far simpler.

Conclusion

To my knowledge, there's no easy way to do this without some degree of modification (whether it be a custom Emacs routine, modifying the Pandoc source, or other scripting). The easiest way I can think of would be to automatically extract some section of raw HTML and insert it into the final document with -H.

Upvotes: 3

Related Questions