@@ -1,9 +1,9 @@
2−title: Pandoc Lua Filters
4- Albert Krewinkel
3- Albert Krewinkel
5- John MacFarlane
4- John MacFarlane
6date: 'December 6, 2017'
5date: 'December 6, 2017'
6+title: Pandoc Lua Filters
9# Introduction
9# Introduction
@@ -37,7 +37,7 @@ JSON to stdout and reading it from stdin.
37Here is an example of a lua filter that converts strong emphasis
37Here is an example of a lua filter that converts strong emphasis
38to small caps:
38to small caps:
43 Strong = function (elem)
43 Strong = function (elem)
@@ -49,7 +49,7 @@ return {
50or equivalently,
50or equivalently,
53function Strong(elem)
53function Strong(elem)
54 return pandoc.SmallCaps(elem.c)
54 return pandoc.SmallCaps(elem.c)
@@ -88,10 +88,10 @@ then it would be applied like this:
89 pandoc --lua-filter=current-date.lua -f markdown MANUAL.txt
89 pandoc --lua-filter=current-date.lua -f markdown MANUAL.txt
91−The `--lua-filter` option may be supplied multiple times. Pandoc
91+The `--lua-filter` option may be supplied multiple times. Pandoc
92applies all filters (including JSON filters specified via
92applies all filters (including JSON filters specified via
93−`--filter` and lua filters specified via `--lua-filter`)
93+`--filter` and lua filters specified via `--lua-filter`) in the
94−in the order they appear on the command line.
94+order they appear on the command line.
96Pandoc expects each lua file to return a list of filters. The
96Pandoc expects each lua file to return a list of filters. The
97filters in that list are called sequentially, each on the result
97filters in that list are called sequentially, each on the result
@@ -132,8 +132,8 @@ function. Two fallback functions are supported, `Inline` and
133Elements without matching functions are left untouched.
133Elements without matching functions are left untouched.
135−See [module documentation](#module-pandoc) for a list of
135+See [module documentation](#module-pandoc) for a list of pandoc
136−pandoc elements.
136+elements.
138The global `FORMAT` is set to the format of the pandoc writer
138The global `FORMAT` is set to the format of the pandoc writer
139being used (`html5`, `latex`, etc.), so the behavior of a filter
139being used (`html5`, `latex`, etc.), so the behavior of a filter
@@ -165,18 +165,18 @@ those elements accessible through the filter function parameter.
166Some pandoc functions have been made available in lua:
166Some pandoc functions have been made available in lua:
168−- [`walk_block`](#walk_block) and [`walk_inline`](#walk_inline)
168+- [`walk_block`](#walk_block) and
169+ [`walk_inline`](#walk_inline) allow filters to be applied
169− allow filters to be applied inside specific block or inline
170+ inside specific block or inline elements;
171−- [`read`](#read) allows filters to parse strings into pandoc
171+- [`read`](#read) allows filters to parse strings into pandoc
172− documents;
172+ documents;
173−- [`pipe`](#pipe) runs an external command with input from and
173+- [`pipe`](#pipe) runs an external command with input from and
174− output to strings;
174+ output to strings;
175−- the [`pandoc.mediabag`](#module-pandoc.mediabag) module allows
175+- the [`pandoc.mediabag`](#module-pandoc.mediabag) module
176− access to the "mediabag," which stores binary content such as
176+ allows access to the "mediabag," which stores binary content
177− images that may be included in the final document;
177+ such as images that may be included in the final document;
178−- the [`pandoc.utils`](#module-pandoc.utils) module contains
178+- the [`pandoc.utils`](#module-pandoc.utils) module contains
179− various utility functions.
179+ various utility functions.
181# Lua interpreter initialization
181# Lua interpreter initialization
@@ -185,7 +185,7 @@ placing a file `init.lua` in pandoc's data directory. The
185default init file loads the `pandoc` and `pandoc.mediabag`
185default init file loads the `pandoc` and `pandoc.mediabag`
188−``` lua
188+``` {.lua}
189pandoc = require 'pandoc'
189pandoc = require 'pandoc'
190pandoc.mediabag = require 'pandoc.mediabag'
190pandoc.mediabag = require 'pandoc.mediabag'
@@ -196,7 +196,7 @@ adds all unicode-aware functions defined in the [`text`
196module](#module-text) to the default `string` module, prefixed
196module](#module-text) to the default `string` module, prefixed
197with the string `uc_`.
197with the string `uc_`.
200for name, fn in pairs(require 'text') do
200for name, fn in pairs(require 'text') do
201 string['uc_' .. name] = fn
201 string['uc_' .. name] = fn
@@ -205,7 +205,6 @@ end
205This makes it possible to apply these functions on strings using
205This makes it possible to apply these functions on strings using
206colon syntax (`mystring:uc_upper()`).
206colon syntax (`mystring:uc_upper()`).
209# Examples
208# Examples
211## Macro substitution.
210## Macro substitution.
@@ -213,7 +212,7 @@ colon syntax (`mystring:uc_upper()`).
213The following filter converts the string `{{helloworld}}` into
212The following filter converts the string `{{helloworld}}` into
214emphasized text "Hello, World".
213emphasized text "Hello, World".
216−``` lua
215+``` {.lua}
219 Str = function (elem)
218 Str = function (elem)
@@ -233,7 +232,7 @@ This filter causes metadata defined in an external file
233(`metadata-file.yaml`) to be used as default values in a
232(`metadata-file.yaml`) to be used as default values in a
234document's metadata:
233document's metadata:
236−``` lua
235+``` {.lua}
237-- read metadata file into string
236-- read metadata file into string
238local metafile = io.open('metadata-file.yaml', 'r')
237local metafile = io.open('metadata-file.yaml', 'r')
239local content = metafile:read("*a")
238local content = metafile:read("*a")
@@ -260,7 +259,7 @@ return {
260This filter sets the date in the document's metadata to the
259This filter sets the date in the document's metadata to the
261current date:
260current date:
263−``` lua
262+``` {.lua}
264function Meta(m)
263function Meta(m)
265 m.date = os.date("%B %e, %Y")
264 m.date = os.date("%B %e, %Y")
@@ -272,7 +271,7 @@ end
272This filter prints a table of all the URLs linked to in the
271This filter prints a table of all the URLs linked to in the
273document, together with the number of links to that URL.
272document, together with the number of links to that URL.
275−``` lua
274+``` {.lua}
276links = {}
275links = {}
278function Link (el)
277function Link (el)
@@ -313,7 +312,7 @@ Passing information from a higher level (e.g., metadata) to a
313lower level (e.g., inlines) is still possible by using two
312lower level (e.g., inlines) is still possible by using two
314filters living in the same file:
313filters living in the same file:
316−``` lua
315+``` {.lua}
317local vars = {}
316local vars = {}
319function get_vars (meta)
318function get_vars (meta)
@@ -368,13 +367,12 @@ will output:
369## Modifying pandoc's `MANUAL.txt` for man pages
368## Modifying pandoc's `MANUAL.txt` for man pages
371−This is the filter we use when converting `MANUAL.txt`
370+This is the filter we use when converting `MANUAL.txt` to man
372−to man pages. It converts level-1 headers to uppercase
371+pages. It converts level-1 headers to uppercase (using
373−(using `walk_block` to transform inline elements
372+`walk_block` to transform inline elements inside headers),
374−inside headers), removes footnotes, and replaces links
373+removes footnotes, and replaces links with regular text.
377−``` lua
375+``` {.lua}
378-- we use preloaded text to get a UTF-8 aware 'upper' function
376-- we use preloaded text to get a UTF-8 aware 'upper' function
379local text = require('text')
377local text = require('text')
@@ -398,13 +396,13 @@ end
399## Creating a handout from a paper
397## Creating a handout from a paper
401−This filter extracts all the numbered examples, section
399+This filter extracts all the numbered examples, section headers,
402−headers, block quotes, and figures from a document, in addition
400+block quotes, and figures from a document, in addition to any
403−to any divs with class `handout`. (Note that only blocks
401+divs with class `handout`. (Note that only blocks at the "outer
404−at the "outer level" are included; this ignores blocks inside
402+level" are included; this ignores blocks inside nested
405−nested constructs, like list items.)
403+constructs, like list items.)
407−``` lua
405+``` {.lua}
408-- creates a handout from an article, using its headings,
406-- creates a handout from an article, using its headings,
409-- blockquotes, numbered examples, figures, and any
407-- blockquotes, numbered examples, figures, and any
410-- Divs with class "handout"
408-- Divs with class "handout"
@@ -427,14 +425,13 @@ end
427## Counting words in a document
425## Counting words in a document
429This filter counts the words in the body of a document (omitting
427This filter counts the words in the body of a document (omitting
430−metadata like titles and abstracts), including words in code.
428+metadata like titles and abstracts), including words in code. It
431−It should be more accurate than `wc -w` run directly on a
429+should be more accurate than `wc -w` run directly on a Markdown
432−Markdown document, since the latter will count markup
430+document, since the latter will count markup characters, like
433−characters, like the `#` in front of an ATX header, or
431+the `#` in front of an ATX header, or tags in HTML documents, as
434−tags in HTML documents, as words. To run it,
435−`pandoc --lua-filter wordcount.lua myfile.md`.
432+words. To run it, `pandoc --lua-filter wordcount.lua myfile.md`.
437−``` lua
434+``` {.lua}
438-- counts words in a document
435-- counts words in a document
@@ -468,18 +465,18 @@ end
469## Converting ABC code to music notation
466## Converting ABC code to music notation
471−This filter replaces code blocks with class `abc` with
468+This filter replaces code blocks with class `abc` with images
472−images created by running their contents through `abcm2ps`
469+created by running their contents through `abcm2ps` and
473−and ImageMagick's `convert`. (For more on ABC notation, see
470+ImageMagick's `convert`. (For more on ABC notation, see
474<http://abcnotation.com>.)
471<http://abcnotation.com>.)
476−Images are added to the mediabag. For output to binary
473+Images are added to the mediabag. For output to binary formats,
477−formats, pandoc will use images in the mediabag. For textual
474+pandoc will use images in the mediabag. For textual formats, use
478−formats, use `--extract-media` to specify a directory where
475+`--extract-media` to specify a directory where the files in the
479−the files in the mediabag will be written, or (for HTML only)
476+mediabag will be written, or (for HTML only) use
480−use `--self-contained`.
477+`--self-contained`.
482−``` lua
479+``` {.lua}
483-- Pandoc filter to process code blocks with class "abc" containing
480-- Pandoc filter to process code blocks with class "abc" containing
484-- ABC notation into images.
481-- ABC notation into images.
@@ -511,18 +508,17 @@ end
512## Building images with tikz
509## Building images with tikz
514−This filter converts raw LaTeX tikz environments into images.
511+This filter converts raw LaTeX tikz environments into images. It
515−It works with both PDF and HTML output. The tikz code is
512+works with both PDF and HTML output. The tikz code is compiled
516−compiled to an image using `pdflatex`, and the image is
513+to an image using `pdflatex`, and the image is converted (if
517−converted (if necessary) from pdf to png format using
514+necessary) from pdf to png format using ImageMagick's `convert`,
518−ImageMagick's `convert`, so both of these must be in the system
515+so both of these must be in the system path. Converted images
519−path. Converted images are cached in the working directory
516+are cached in the working directory and given filenames based on
520−and given filenames based on a hash of the source, so that
521−they need not be regenerated each time the document is built.
517+a hash of the source, so that they need not be regenerated each
518+time the document is built. (A more sophisticated version of
522−(A more sophisticated version of this might put these in a special
519+this might put these in a special cache directory.)
523−cache directory.)
520+
526local function tikz2image(src, filetype, outfile)
522local function tikz2image(src, filetype, outfile)
527 local tmp = os.tmpname()
523 local tmp = os.tmpname()
528 local tmpdir = string.match(tmp, "^(.*[\\/])") or "."
524 local tmpdir = string.match(tmp, "^(.*[\\/])") or "."
@@ -572,33 +568,31 @@ end
573Example of use:
569Example of use:
576−pandoc --lua-filter tikz.lua -s -o cycle.html <<EOF
571+ pandoc --lua-filter tikz.lua -s -o cycle.html <<EOF
577−Here is a diagram of the cycle:
572+ Here is a diagram of the cycle:
579−\begin{tikzpicture}
574+ \begin{tikzpicture}
581−\def \n {5}
576+ \def \n {5}
582−\def \radius {3cm}
577+ \def \radius {3cm}
583−\def \margin {8} % margin in angles, depends on the radius
578+ \def \margin {8} % margin in angles, depends on the radius
585−\foreach \s in {1,...,\n}
580+ \foreach \s in {1,...,\n}
587− \node[draw, circle] at ({360/\n * (\s - 1)}:\radius) {$\s$};
582+ \node[draw, circle] at ({360/\n * (\s - 1)}:\radius) {$\s$};
588− \draw[->, >=latex] ({360/\n * (\s - 1)+\margin}:\radius)
583+ \draw[->, >=latex] ({360/\n * (\s - 1)+\margin}:\radius)
589− arc ({360/\n * (\s - 1)+\margin}:{360/\n * (\s)-\margin}:\radius);
584+ arc ({360/\n * (\s - 1)+\margin}:{360/\n * (\s)-\margin}:\radius);
591−\end{tikzpicture}
586+ \end{tikzpicture}
595# Module text
589# Module text
597UTF-8 aware text manipulation functions, implemented in Haskell.
591UTF-8 aware text manipulation functions, implemented in Haskell.
598−These are available to any lua filter. However, the module must
592+These are available to any lua filter. However, the module must
599be explicitly loaded:
593be explicitly loaded:
602-- uppercase all regular text in a document:
596-- uppercase all regular text in a document:
603text = require 'text'
597text = require 'text'
604function Str (s)
598function Str (s)
@@ -628,7 +622,6 @@ end
628: Returns a substring of a UTF-8 string, using lua's string
622: Returns a substring of a UTF-8 string, using lua's string
629 indexing rules.
623 indexing rules.
632# Module pandoc
625# Module pandoc
634Lua functions for pandoc scripts.
627Lua functions for pandoc scripts.
@@ -740,7 +733,7 @@ Lua functions for pandoc scripts.
740 `content`:
733 `content`:
741 : list of items
734 : list of items
743− Returns: block quote element
736+ Returns: bullet list element
745[`CodeBlock (text[, attr])`]{#CodeBlock}
738[`CodeBlock (text[, attr])`]{#CodeBlock}
@@ -766,7 +759,7 @@ Lua functions for pandoc scripts.
766 `content`:
759 `content`:
767 : list of items
760 : list of items
769− Returns: block quote element
762+ Returns: definition list element
771[`Div (content[, attr])`]{#Div}
764[`Div (content[, attr])`]{#Div}
@@ -780,11 +773,11 @@ Lua functions for pandoc scripts.
781 : element attributes
774 : element attributes
783− Returns: code block element
776+ Returns: div element
785[`Header (level, content[, attr])`]{#Header}
778[`Header (level, content[, attr])`]{#Header}
787−: Creates a block quote element.
780+: Creates a header element.
789 Parameters:
782 Parameters:
@@ -814,7 +807,7 @@ Lua functions for pandoc scripts.
814 `content`:
807 `content`:
815 : inline content
808 : inline content
817− Returns: block quote element
810+ Returns: line block element
819[`Null ()`]{#Null}
812[`Null ()`]{#Null}
@@ -834,7 +827,7 @@ Lua functions for pandoc scripts.
834 `listAttributes`:
827 `listAttributes`:
835 : list parameters
828 : list parameters
837− Returns:
830+ Returns: ordered list element
839[`Para (content)`]{#Para}
832[`Para (content)`]{#Para}
@@ -845,7 +838,7 @@ Lua functions for pandoc scripts.
845 `content`:
838 `content`:
846 : inline content
839 : inline content
848− Returns: block quote element
841+ Returns: paragraph element
850[`Plain (content)`]{#Plain}
843[`Plain (content)`]{#Plain}
@@ -856,7 +849,7 @@ Lua functions for pandoc scripts.
856 `content`:
849 `content`:
857 : inline content
850 : inline content
859− Returns: block quote element
852+ Returns: plain element
861[`RawBlock (format, text)`]{#RawBlock}
854[`RawBlock (format, text)`]{#RawBlock}
@@ -870,7 +863,7 @@ Lua functions for pandoc scripts.
871 : string content
864 : string content
873− Returns: block quote element
866+ Returns: raw block element
875[`Table (caption, aligns, widths, headers, rows)`]{#Table}
868[`Table (caption, aligns, widths, headers, rows)`]{#Table}
@@ -893,7 +886,7 @@ Lua functions for pandoc scripts.
894 : table rows
887 : table rows
896− Returns: block quote element
889+ Returns: table element
@@ -1181,6 +1174,16 @@ Lua functions for pandoc scripts.
1182## Helpers
1175## Helpers
1177+[`apairs (value)`]{#apairs}
1179+: Return an iterator which returns key-value pairs of an
1185+ : },\...} alist associative list
1184[`Attr ([identifier[, classes[, attributes]]])`]{#Attr}
1187[`Attr ([identifier[, classes[, attributes]]])`]{#Attr}
1186: Create a new set of attributes (Attr).
1189: Create a new set of attributes (Attr).
@@ -1334,61 +1337,6 @@ Lua functions for pandoc scripts.
1335## Helper Functions
1338## Helper Functions
1337−[`walk_block (element, filter)`]{#walk_block}
1339−: Apply a filter inside a block element, walking its
1345− : the block element
1348− : a lua filter (table of functions) to be applied
1349− within the block element
1351− Returns: the transformed block element
1353−[`walk_inline (element, filter)`]{#walk_inline}
1355−: Apply a filter inside an inline element, walking its
1361− : the inline element
1364− : a lua filter (table of functions) to be applied
1365− within the inline element
1367− Returns: the transformed inline element
1369−[`read (markup[, format])`]{#read}
1371−: Parse the given string into a Pandoc document.
1376− : the markup to be parsed
1379− : format specification, defaults to \"markdown\".
1381− Returns: pandoc document
1385− local org_markup = "/emphasis/" -- Input to be read
1386− local document = pandoc.read(org_markup, "org")
1387− -- Get the first block of the document
1388− local block = document.blocks[1]
1389− -- The inline element in that block is an `Emph`
1390− assert(block.content[1].t == "Emph")
1392[`global_filter ()`]{#global_filter}
1340[`global_filter ()`]{#global_filter}
1394: Use functions defined in the global namespace to create a
1342: Use functions defined in the global namespace to create a
@@ -1399,35 +1347,14 @@ Lua functions for pandoc scripts.
1401 -- within a file defining a pandoc filter:
1349 -- within a file defining a pandoc filter:
1402− local text = require('text')
1403 function Str(text)
1350 function Str(text)
1404− return pandoc.Str(text.upper(text))
1351+ return pandoc.Str(utf8.upper(text))
1407 return {pandoc.global_filter()}
1354 return {pandoc.global_filter()}
1408− -- the above is equivalent to
1355+ -- the above is equivallent to
1409 -- return {{Str = Str}}
1356 -- return {{Str = Str}}
1411−[`pipe (command, args, input)`]{#pipe}
1413−: Runs command with arguments, passing it some input,
1414− and returns the output.
1418− - Output of command.
1422− - A table containing the keys `command`, `error_code`, and
1423− `output` is thrown if the command exits with a non-zero
1428− local output = pandoc.pipe("sed", {"-e","s/a/b/"}, "abc")
1431# Module pandoc.utils
1358# Module pandoc.utils
1433This module exposes internal pandoc functions and utility
1360This module exposes internal pandoc functions and utility
@@ -1501,7 +1428,7 @@ functions.
1502[`to_roman_numeral (integer)`]{#utils-to_roman_numeral}
1429[`to_roman_numeral (integer)`]{#utils-to_roman_numeral}
1504−: Converts an integer < 4000 to uppercase roman numeral.
1431+: Converts an integer \< 4000 to uppercase roman numeral.
1506 Returns:
1433 Returns:
@@ -1513,7 +1440,6 @@ functions.
1513 local pandoc_birth_year = to_roman_numeral(2006)
1440 local pandoc_birth_year = to_roman_numeral(2006)
1514 -- pandoc_birth_year == 'MMVI'
1441 -- pandoc_birth_year == 'MMVI'
1517# Module pandoc.mediabag
1443# Module pandoc.mediabag
1519The `pandoc.mediabag` module allows accessing pandoc's media
1445The `pandoc.mediabag` module allows accessing pandoc's media
@@ -1583,9 +1509,9 @@ storage. The "media bag" is used when pandoc is called with the
1584[`fetch (source, base_url)`]{#mediabag-fetch}
1510[`fetch (source, base_url)`]{#mediabag-fetch}
1586−: Fetches the given source from a URL or local file.
1512+: Fetches the given source from a URL or local file. Returns
1587− Returns two values: the contents of the file and the mime
1513+ two values: the contents of the file and the mime type (or
1588− type (or an empty string).
1514+ an empty string).
1590 Returns:
1516 Returns: