packages feed

pandoc 2.15 → 2.16

raw patch · 52 files changed

+1849/−1551 lines, 52 filesdep +yamldep −HsYAMLdep ~skylightingdep ~skylighting-coredep ~timePVP ok

version bump matches the API change (PVP)

Dependencies added: yaml

Dependencies removed: HsYAML

Dependency ranges changed: skylighting, skylighting-core, time

API changes (from Hackage documentation)

- Text.Pandoc.Filter: instance Data.YAML.FromYAML Text.Pandoc.Filter.Filter
- Text.Pandoc.Logging: instance Data.YAML.FromYAML Text.Pandoc.Logging.Verbosity
- Text.Pandoc.Options: instance Data.YAML.FromYAML Text.Pandoc.Options.CiteMethod
- Text.Pandoc.Options: instance Data.YAML.FromYAML Text.Pandoc.Options.HTMLMathMethod
- Text.Pandoc.Options: instance Data.YAML.FromYAML Text.Pandoc.Options.ObfuscationMethod
- Text.Pandoc.Options: instance Data.YAML.FromYAML Text.Pandoc.Options.ReferenceLocation
- Text.Pandoc.Options: instance Data.YAML.FromYAML Text.Pandoc.Options.TopLevelDivision
- Text.Pandoc.Options: instance Data.YAML.FromYAML Text.Pandoc.Options.TrackChanges
- Text.Pandoc.Options: instance Data.YAML.FromYAML Text.Pandoc.Options.WrapOption

Files

AUTHORS.md view
@@ -1,10 +1,7 @@ # Contributors -- Anabra-- Aner Lucero-- Arata Mizuki-- Arfon Smith - Aaron Wolen+- Agustín Martín Barbero - Albert Krewinkel - Alex Ivkin - Alex Toldaiev@@ -16,18 +13,21 @@ - Alexandre Franke - Alfred Wechselberger - Amogh Rathore+- Anabra - Anders Waldenborg - Andreas Lööw - Andrew Dunning - Andy Morris+- Aner Lucero - Anti-Distinctlyminty - Antoine Latter - Antonio Terceiro - Arata Mizuki+- Arata Mizuki - Arfon Smith+- Arfon Smith - Arlo O'Keeffe - Artyom Kazak-- Agustín Martín Barbero - B. Scott Michel - Ben Firshman - Ben Gamari@@ -54,6 +54,7 @@ - Christian Despres - Christoffer Ackelman - Christoffer Sawicki+- Christophe Dervieux - Clare Macrae - Clint Adams - Conal Elliott@@ -82,17 +83,19 @@ - Emily Bourke - Emily Eisenberg - Eric Kow-- Erik Rask-- Eric Seidel - Eric Schrijver+- Eric Seidel+- Erik Rask - Ethan Riley - Étienne Bersac-- Felix Yan+- Ezwal - Félix Baylac-Jacqué+- Felix Yan - Florian Beeres - Florian Eitel - Florian Klink - Florian Kohrt+- Francesco Mazzoli - Francesco Occhipinti - François Gannaz - Frederik Elwert@@ -112,6 +115,7 @@ - Heiko Schlittermann - Henrik Tramberend - Henry de Valence+- Herwig Stuetz - Hubert Plociniczak - Ian Max Andolina - Igor Khorlo@@ -119,7 +123,6 @@ - Ilya V. Portnov - Ivan Trubach - Ivo Clarysse-- Jared Lander - J. B. Rainsberger - J. Lewis Muir - Jaime Marquínez Ferrándiz@@ -131,22 +134,24 @@ - Jan Schulz - Jan Tojnar - Jan-Otto Kröpke+- Jared Lander - Jason Ronallo - Jeff Arnold - Jeff Runningen - Jens Getreu - Jens Petersen+- Jérémy Bobbio - Jeroen de Haas - Jerry Sky - Jesse Rosenthal - Joe Hermaszewski - Joe Hillenbrand - John KetzerX+- John Luke Bentley - John MacFarlane - John Muccigrosso-- John Luke Bentley-- Jonas Smedegaard - Jonas Scholl+- Jonas Smedegaard - Jonathan Daugherty - Jose Luis Duran - José de Mattos Neto@@ -157,7 +162,6 @@ - Juliette Fourcot - Juliusz Gonera - Justin Bogner-- Jérémy Bobbio - Karl Pettersson - Keiichiro Shikano - Kelsey Hightower@@ -165,7 +169,6 @@ - Konstantin Zudov - Kristof Bastiaensen - Krystof Beuermann-- Herwig Stuetz - Lars-Dominik Braun - Laurent P. René de Cotret - Leif Metcalf@@ -201,6 +204,7 @@ - Michael Snoyman - Michael Thompson - Mike Tzou+- Milan Bracke - MinRK - Morton Fox - Nathan Gass@@ -222,8 +226,8 @@ - Owen McGrath - Pablo Rodríguez - Pascal Wagler-- Paul Tilley - Paul Rivier+- Paul Tilley - Paulo Tanimoto - Pete Ryland - Peter Fabinksi@@ -233,6 +237,7 @@ - Phillip Alday - Prayag Verma - Puneeth Chaganti+- Quinn - Ralf Stephan - Raniere Silva - Raymond Ehlers@@ -241,6 +246,7 @@ - Roman Beránek - RyanGlScott - Salim B+- Samuel Tardieu - Sascha Wilde - Scott Morrison - Sebastian Talmon@@ -253,8 +259,10 @@ - Sidarth Kapur - Sidharth Kapur - Simon Hengel+- Simon Schuster - Stefan Dresselhaus - Sumit Sahrawat+- TEC - Tarik Graba - Tatiana Porras - Thenaesh Elango@@ -266,12 +274,12 @@ - Tiziano Müller - Todd Sifleet - Tom Leese-- Tristan de Cacqueray - Tristan Stenner+- Tristan de Cacqueray - Uli Köhler - Urs Liska-- Václav Zeman - Václav Haisman+- Václav Zeman - Vaibhav Sagar - Vanessa McHale - Vasily Alferov@@ -279,8 +287,8 @@ - Viktor Kronvall - Vincent - Vlad Hanciuta-- Wandmalfarbe - Waldir Pimenta+- Wandmalfarbe - Wikiwide - William Lupton - Winnie Hellmann@@ -299,10 +307,11 @@ - chinapedia - cholonam - csforste-- dbecher-ito - d-dorazio+- dbecher-ito - ebiim - favonia+- hseg - infinity0x - jeongminkim-islab - kaizshang91@@ -310,14 +319,14 @@ - lwolfsonkin - mbrackeantidot - mt_caret-- nkalvi - niszet+- nkalvi - nuew - obcat - oltolm - oquechy-- quasicomputational - qerub+- quasicomputational - robabla - roblabla - rodja.trappe@@ -326,11 +335,10 @@ - takahashim - taotieren - tecosaur-- TEC - tgkokk - the-solipsist-- timo-a - thsutton+- timo-a - vijayphoenix - wiefling - wuffi
MANUAL.txt view
@@ -1,7 +1,7 @@ --- title: Pandoc User's Guide author: John MacFarlane-date: October 22, 2021+date: October 30, 2021 ---  # Synopsis
changelog.md view
@@ -1,13 +1,104 @@ # Revision history for pandoc -## pandoc 2.15 (NODATE)+## pandoc 2.16 (2021-10-31) +  * Switch back from HsYAML to yaml for parsing YAML metadata (#6084).+    HsYAML is around 20 times slower in parsing large YAML bibliographies.+    In addition, HsYAML is not being actively maintained.  This sets us back+    in our attempts to free ourselves from C dependencies (#4535).  But I+    don't see a good alternative until a faster pure Haskell parser is available.+    Notes:++    + We've removed the FromYAML instances for all types that had them, since+      this is a HsYAML-specific typeclass [API change].  (The yaml package just+      uses From/ToJSON instead of having a dedicated From/ToYAML class.)+    + Unlike HsYAML (in the configuration we were using), yaml parses 'Y', 'N',+      'Yes', 'No', 'On', 'Off' as boolean values.  Users may need to quote these+      when they are meant to be interpreted as strings.  Similarly, 'null' is+      parsed as a YAML null value (and will be treated as an empty string by+      pandoc rather than the string 'null').  Quoting it will force it to be+      interpreted as a string.+    + Some tests had to be adjusted accordingly.+    + Pandoc now behaves in a more useful way when the YAML metadata contains+      escaping errors: instead of just failng silently and falling back to+      some other interpretation of the section, it raises a YAML parsing error.++  * Markdown writer: Ensure that special values are quoted in YAML metadata.+    These include "Y", "yes", "on", and "off", which are now (with yaml library)+    considered boolean values, as well as "null".++  * Change JSON encodings of some types.++    + For LineEnding use lowercase constructors, e.g. `crlf`, `native`.+    + For HTMLSlideVariant use lowercase constructors.+    + For ReaderOptions use e.g. `default-image-extension`+      instead of `readerDefaultImageExtension` for field names.+    + For Extension, use e.g. `tex_math_dollars` instead of+      `Ext_tex_math_dollars` as constructor.+    + For Extensions, use an array of Extensions, instead of+      an object wrapping the tag `Extensions` and an integer.+      (The integer representation is not supposed to be part of the+      public API.)+    + For Opt, use field names like `tab-stop` instead of `optTabStop`.++  * Docx writer:++    + Add IDs to native_numbering test (Tristan Stenner).+    + Move ": " out of the caption bookmark (Tristan Stenner).+      This is needed so that native references to the figure are included as+      "As seen in Figure X, it is..." instead of "As seen in [Figure: X, it is..."++  * Lua (Albert Krewinkel, except as noted):++    + Use hslua module abstraction where possible.+    + Fix placement of tests for Block elements in pandoc module tests+    + Increase strictness when getting attribute keys+    + Re-add `t` and `tag` property to Attr values.+      Removal of these properties from Attr values was a regression.+    + Fix `pandoc.utils.stringify` regression.  The `pandoc.utils.stringify`+      function returned empty strings when called with a string argument.+    + Fix a copy/paste bug in Lua marshalling code (John MacFarlane, #7639).+      This caused links to be changed to figures when Lua filters changed+      link properties.+    + Re-add `content` property to Link elements (#7647).+      This was a regression introduced in version 2.15.+    + Generate constants in module pandoc programmatically.+    + Marshal SimpleTable, ListAttributes, Citation, and Block values as+      userdata objects.  Properties of Block values are marshalled lazily,+      which generally improves performance considerably. Script users may also+      notice the following differences:++      - Block element properties can no longer be accessed by numerical+        indexing of the `.c` field. The `.c` property now serves as an alias+        for `.content`, so some filter that used this undocumented method+        for property access may continue to work, while others will need to+        be updated and use proper property names.+      - The marshalled Block elements now have a `show` method, and a+        `__tostring` metamethod. Both return the Haskell string+        representation of the element.+      - Block values now have the Lua type `userdata` instead of `table`.++  * Add a short guide to pandoc's sources (Albert Krewinkel).++  * Fix epub files in epub reader tests, so that they are valid+    according to epubcheck (#7586).++  * Allow time 1.13.++  * Require latest skylighting (0.12.1).++  * Fix build on GHC 9.2 (Joseph C. Sible).++  * Fix trypandoc so it builds with aeson > 2.+++## pandoc 2.15 (2021-10-23)+   * Add `--sandbox` option  (#5045). -    + Add sandbox feature for readers.  When this option is used,-      readers and writers only have access to input files (and-      other files specified directly on command line).  This restriction-      is enforced in the type system.+    + Add sandbox feature.  When this option is used, readers and writers+      only have access to input files (and other files specified directly on+      command line).  This restriction is enforced in the type system.     + Filters, PDF production, custom writers are unaffected.  This       feature only insulates the actual readers and writers, not       the pipeline around them in Text.Pandoc.App.
data/pandoc.lua view
@@ -45,125 +45,19 @@ -- @section -- @local ---- Create a new indexing function.--- @param template function template--- @param indices list of indices, starting with the most deeply nested--- @return newly created function--- @local-function make_indexing_function(template, ...)-  local indices = {...}-  local loadstring = loadstring or load-  local bracketed = {}-  for i = 1, #indices do-    local idx = indices[#indices - i + 1]-    bracketed[i] = type(idx) == 'number'-      and string.format('[%d]', idx)-      or string.format('.%s', idx)-  end-  local fnstr = string.format('return ' .. template, table.concat(bracketed))-  return assert(loadstring(fnstr))()-end----- Create accessor functions using a function template.--- @param fn_template function template in which '%s' is replacd with indices--- @param accessors list of accessors--- @return mapping from accessor names to accessor functions--- @local-local function create_accessor_functions (fn_template, accessors)-  local res = {}-  function add_accessors(acc, ...)-    if type(acc) == 'string' then-      res[acc] = make_indexing_function(fn_template, ...)-    elseif type(acc) == 'table' and #acc == 0 and next(acc) then-      -- Named substructure: the given names are accessed via the substructure,-      -- but the accessors are also added to the result table, enabling direct-      -- access from the parent element. Mainly used for `attr`.-      local name, substructure = next(acc)-      res[name] = make_indexing_function(fn_template, ...)-      for _, subname in ipairs(substructure) do-        res[subname] = make_indexing_function(fn_template, subname, ...)-      end-    else-      for i = 1, #(acc or {}) do-        add_accessors(acc[i], i, ...)-      end-    end-  end-  add_accessors(accessors)-  return res-end----- Get list of top-level fields from field descriptor table.--- E.g.: `top_level_fields{'foo', {bar='baz'}, {'qux', 'quux'}}`--- gives {'foo, 'bar', 'qux', 'quux'}--- @local-local function top_level_fields (fields)-  local result = List:new{}-  for _, v in ipairs(fields) do-    if type(v) == 'string' then-      table.insert(result, v)-    elseif type(v) == 'table' and #v == 0 and next(v) then-      table.insert(result, (next(v)))-    else-      result:extend(top_level_fields(v))-    end-  end-  return result-end----- Creates a function which behaves like next, but respects field names.--- @local-local function make_next_function (fields)-  local field_indices = {}-  for i, f in ipairs(fields) do-    field_indices[f] = i-  end--  return function (t, field)-    local raw_idx = field == nil and 0 or field_indices[field]-    local next_field = fields[raw_idx + 1]-    return next_field, t[next_field]-  end-end- --- Create a new table which allows to access numerical indices via accessor -- functions. -- @local-local function create_accessor_behavior (tag, accessors)+local function create_accessor_behavior (tag)   local behavior = {tag = tag}-  behavior.getters = create_accessor_functions(-    'function (x) return x.c%s end',-    accessors-  )-  behavior.setters = create_accessor_functions(-    'function (x, v) x.c%s = v end',-    accessors-  )   behavior.__eq = utils.equals   behavior.__index = function(t, k)-    if getmetatable(t).getters[k] then-      return getmetatable(t).getters[k](t)-    elseif k == "t" then+    if k == "t" then       return getmetatable(t)["tag"]-    else-      return getmetatable(t)[k]     end   end-  behavior.__newindex = function(t, k, v)-    if getmetatable(t).setters[k] then-      getmetatable(t).setters[k](t, v)-    else-      rawset(t, k, v)-    end-  end   behavior.__pairs = function (t)-    if accessors == nil then-      return next, t-    end-    local iterable_fields = type(accessors) == 'string'-      and {accessors}-      or top_level_fields(accessors)-    return make_next_function(iterable_fields), t+    return next, t   end   return behavior end@@ -242,8 +136,8 @@ -- @param fn Function to be called when constructing a new element -- @param accessors names to use as accessors for numerical fields -- @return function that constructs a new element-function AstElement:create_constructor(tag, fn, accessors)-  local constr = self:make_subtype(tag, create_accessor_behavior(tag, accessors))+function AstElement:create_constructor(tag, fn)+  local constr = self:make_subtype(tag, create_accessor_behavior(tag))   function constr:new(...)     return setmetatable(fn(...), self.behavior)   end@@ -273,22 +167,6 @@   end end ---- Ensure that the given object is a definition pair, convert if necessary.--- @local-local function ensureDefinitionPairs (pair)-  local inlines = ensureInlineList(pair[1] or {})-  local blocks = ensureList(pair[2] or {}):map(ensureList)-  return {inlines, blocks}-end----- Try hard to turn the arguments into an Attr object.-local function ensureAttr(attr)-  if type(attr) == 'userdata' then-    return attr-  end-  return M.Attr(attr)-end- ------------------------------------------------------------------------ -- Meta -- @section Meta@@ -363,367 +241,5 @@ function M.MetaBool(bool)   return bool end----------------------------------------------------------------------------- Blocks--- @section Block----- Block elements-M.Block = AstElement:make_subtype'Block'-M.Block.behavior.clone = M.types.clone.Block----- Creates a block quote element--- @function BlockQuote--- @tparam      {Block,...} content     block content--- @treturn     Block                   block quote element-M.BlockQuote = M.Block:create_constructor(-  "BlockQuote",-  function(content) return {c = ensureList(content)} end,-  "content"-)----- Creates a bullet (i.e. unordered) list.--- @function BulletList--- @tparam      {{Block,...},...} content     list of items--- @treturn     Block                         bullet list element-M.BulletList = M.Block:create_constructor(-  "BulletList",-  function(content) return {c = ensureList(content):map(ensureList)} end,-  "content"-)----- Creates a code block element--- @function CodeBlock--- @tparam      string      text        code string--- @tparam[opt] Attr        attr element attributes--- @treturn     Block                   code block element-M.CodeBlock = M.Block:create_constructor(-  "CodeBlock",-  function(text, attr) return {c = {ensureAttr(attr), text}} end,-  {{attr = {"identifier", "classes", "attributes"}}, "text"}-)----- Creates a definition list, containing terms and their explanation.--- @function DefinitionList--- @tparam      {{{Inline,...},{{Block,...}}},...} content     list of items--- @treturn     Block                  definition list element-M.DefinitionList = M.Block:create_constructor(-  "DefinitionList",-  function(content)-    return {c = ensureList(content):map(ensureDefinitionPairs)}-  end,-  "content"-)----- Creates a div element--- @function Div--- @tparam      {Block,...} content     block content--- @tparam[opt] Attr        attr  element attributes--- @treturn     Block                   div element-M.Div = M.Block:create_constructor(-  "Div",-  function(content, attr)-    return {c = {ensureAttr(attr), ensureList(content)}}-  end,-  {{attr = {"identifier", "classes", "attributes"}}, "content"}-)----- Creates a header element.--- @function Header--- @tparam      int          level       header level--- @tparam      {Inline,...} content     inline content--- @tparam[opt] Attr         attr element attributes--- @treturn     Block                    header element-M.Header = M.Block:create_constructor(-  "Header",-  function(level, content, attr)-    return {c = {level, ensureAttr(attr), ensureInlineList(content)}}-  end,-  {"level", {attr = {"identifier", "classes", "attributes"}}, "content"}-)----- Creates a horizontal rule.--- @function HorizontalRule--- @treturn     Block                   horizontal rule-M.HorizontalRule = M.Block:create_constructor(-  "HorizontalRule",-  function() return {} end-)----- Creates a line block element.--- @function LineBlock--- @tparam      {{Inline,...},...} content    inline content--- @treturn     Block                   line block element-M.LineBlock = M.Block:create_constructor(-  "LineBlock",-  function(content) return {c = ensureList(content):map(ensureInlineList)} end,-  "content"-)----- Creates a null element.--- @function Null--- @treturn     Block                   null element-M.Null = M.Block:create_constructor(-  "Null",-  function() return {} end-)----- Creates an ordered list.--- @function OrderedList--- @tparam      {{Block,...},...} items list items--- @param[opt]  listAttributes list parameters--- @treturn     Block  ordered list element-M.OrderedList = M.Block:create_constructor(-  "OrderedList",-  function(items, listAttributes)-    listAttributes = listAttributes or M.ListAttributes()-    return {c = {listAttributes, ensureList(items):map(ensureList)}}-  end,-  {{listAttributes = {"start", "style", "delimiter"}}, "content"}-)----- Creates a para element.--- @function Para--- @tparam      {Inline,...} content    inline content--- @treturn     Block                   paragraph element-M.Para = M.Block:create_constructor(-  "Para",-  function(content) return {c = ensureInlineList(content)} end,-  "content"-)----- Creates a plain element.--- @function Plain--- @tparam      {Inline,...} content    inline content--- @treturn     Block                   plain element-M.Plain = M.Block:create_constructor(-  "Plain",-  function(content) return {c = ensureInlineList(content)} end,-  "content"-)----- Creates a raw content block of the specified format.--- @function RawBlock--- @tparam      string      format      format of content--- @tparam      string      text        string content--- @treturn     Block                   raw block element-M.RawBlock = M.Block:create_constructor(-  "RawBlock",-  function(format, text) return {c = {format, text}} end,-  {"format", "text"}-)----- Creates a table element.--- @function Table--- @tparam      Caption      caption    table caption--- @tparam      {ColSpec,...} colspecs  column alignments and widths--- @tparam      TableHead    head       table head--- @tparam      {TableBody,..} bodies   table bodies--- @treturn     TableFoot    foot       table foot--- @tparam[opt] Attr         attr       attributes-M.Table = M.Block:create_constructor(-  "Table",-  function(caption, colspecs, head, bodies, foot, attr)-    return {-      c = {-        ensureAttr(attr),-        caption,-        List:new(colspecs),-        head,-        List:new(bodies),-        foot-      }-    }-  end,-  {"attr", "caption", "colspecs", "head", "bodies", "foot"}-)------------------------------------------------------------------------------ Element components--- @section components---- Monkey-patch setters for `attr` fields to be more forgiving in the input that--- results in a valid Attr value.-function augment_attr_setter (setters)-  if setters.attr then-    local orig = setters.attr-    setters.attr = function(k, v)-      orig(k, ensureAttr(v))-    end-  end-end-for _, blk in pairs(M.Block.constructor) do-  augment_attr_setter(blk.behavior.setters)-end---- Citation-M.Citation = AstElement:make_subtype'Citation'-M.Citation.behavior.clone = M.types.clone.Citation----- Creates a single citation.--- @function Citation--- @tparam      string       id       citation identifier (like a bibtex key)--- @tparam      AuthorInText|SuppressAuthor|NormalCitation mode citation mode--- @tparam[opt] {Inline,...} prefix   citation prefix--- @tparam[opt] {Inline,...} suffix   citation suffix--- @tparam[opt] int          note_num note number--- @tparam[opt] int          hash  hash number-function M.Citation:new (id, mode, prefix, suffix, note_num, hash)-  return {-    id = id,-    mode = mode,-    prefix = ensureList(prefix or {}),-    suffix = ensureList(suffix or {}),-    note_num = note_num or 0,-    hash = hash or 0,-  }-end---- ListAttributes-M.ListAttributes = AstElement:make_subtype 'ListAttributes'-M.ListAttributes.behavior.clone = M.types.clone.ListAttributes----- Creates a set of list attributes.--- @function ListAttributes--- @tparam[opt] integer start number of the first list item--- @tparam[opt] string  style style used for list numbering--- @tparam[opt] DefaultDelim|Period|OneParen|TwoParens delimiter delimiter of list numbers--- @treturn table list attributes table-function M.ListAttributes:new (start, style, delimiter)-  start = start or 1-  style = style or 'DefaultStyle'-  delimiter = delimiter or 'DefaultDelim'-  return {start, style, delimiter}-end-M.ListAttributes.behavior._field_names = {start = 1, style = 2, delimiter = 3}-M.ListAttributes.behavior.__eq = utils.equals-M.ListAttributes.behavior.__index = function (t, k)-  return rawget(t, getmetatable(t)._field_names[k]) or-    getmetatable(t)[k]-end-M.ListAttributes.behavior.__newindex = function (t, k, v)-  if getmetatable(t)._field_names[k] then-    rawset(t, getmetatable(t)._field_names[k], v)-  else-    rawset(t, k, v)-  end-end-M.ListAttributes.behavior.__pairs = function(t)-  local field_names = M.ListAttributes.behavior._field_names-  local fields = {}-  for name, i in pairs(field_names) do-    fields[i] = name-  end-  return make_next_function(fields), t, nil-end------- Legacy and compatibility types-------- Creates a simple (old style) table element.--- @function SimpleTable--- @tparam      {Inline,...} caption    table caption--- @tparam      {AlignDefault|AlignLeft|AlignRight|AlignCenter,...} aligns alignments--- @tparam      {int,...}    widths     column widths--- @tparam      {Block,...}  headers    header row--- @tparam      {{Block,...}} rows      table rows--- @treturn     Block                   table element-M.SimpleTable = function(caption, aligns, widths, headers, rows)-  return {-    caption = ensureInlineList(caption),-    aligns = List:new(aligns),-    widths = List:new(widths),-    headers = List:new(headers),-    rows = List:new(rows),-    tag = "SimpleTable",-    t = "SimpleTable",-  }-end------------------------------------------------------------------------------ Constants--- @section constants----- Author name is mentioned in the text.--- @see Citation--- @see Cite-M.AuthorInText = "AuthorInText"----- Author name is suppressed.--- @see Citation--- @see Cite-M.SuppressAuthor = "SuppressAuthor"----- Default citation style is used.--- @see Citation--- @see Cite-M.NormalCitation = "NormalCitation"----- Table cells aligned left.--- @see Table-M.AlignLeft = "AlignLeft"----- Table cells right-aligned.--- @see Table-M.AlignRight = "AlignRight"----- Table cell content is centered.--- @see Table-M.AlignCenter = "AlignCenter"----- Table cells are alignment is unaltered.--- @see Table-M.AlignDefault = "AlignDefault"----- Default list number delimiters are used.--- @see OrderedList-M.DefaultDelim = "DefaultDelim"----- List numbers are delimited by a period.--- @see OrderedList-M.Period = "Period"----- List numbers are delimited by a single parenthesis.--- @see OrderedList-M.OneParen = "OneParen"----- List numbers are delimited by a double parentheses.--- @see OrderedList-M.TwoParens = "TwoParens"----- List are numbered in the default style--- @see OrderedList-M.DefaultStyle = "DefaultStyle"----- List items are numbered as examples.--- @see OrderedList-M.Example = "Example"----- List are numbered using decimal integers.--- @see OrderedList-M.Decimal = "Decimal"----- List are numbered using lower-case roman numerals.--- @see OrderedList-M.LowerRoman = "LowerRoman"----- List are numbered using upper-case roman numerals--- @see OrderedList-M.UpperRoman = "UpperRoman"----- List are numbered using lower-case alphabetic characters.--- @see OrderedList-M.LowerAlpha = "LowerAlpha"----- List are numbered using upper-case alphabetic characters.--- @see OrderedList-M.UpperAlpha = "UpperAlpha"----------------------------------------------------------------------------- Functions which have moved to different modules-M.sha1 = utils.sha1  return M
man/pandoc.1 view
@@ -1,7 +1,7 @@ '\" t-.\" Automatically generated by Pandoc 2.14.2+.\" Automatically generated by Pandoc 2.16 .\"-.TH "Pandoc User\[cq]s Guide" "" "October 22, 2021" "pandoc 2.15" ""+.TH "Pandoc User\[cq]s Guide" "" "October 30, 2021" "pandoc 2.16" "" .hy .SH NAME pandoc - general markup converter@@ -554,13 +554,14 @@ pandoc uses a level-1 heading to render the document title. .TP \f[B]\f[CB]--base-header-level=\f[B]\f[R]\f[I]NUMBER\f[R]-\f[I]Deprecated. Use \f[CI]--shift-heading-level-by\f[I]=X instead,-where X = NUMBER - 1.\f[R] Specify the base level for headings (defaults-to 1).+\f[I]Deprecated.+Use \f[CI]--shift-heading-level-by\f[I]=X instead, where X = NUMBER -+1.\f[R] Specify the base level for headings (defaults to 1). .TP \f[B]\f[CB]--strip-empty-paragraphs\f[B]\f[R]-\f[I]Deprecated. Use the \f[CI]+empty_paragraphs\f[I] extension-instead.\f[R] Ignore paragraphs with no content.+\f[I]Deprecated.+Use the \f[CI]+empty_paragraphs\f[I] extension instead.\f[R] Ignore+paragraphs with no content. This option is useful for converting word processing documents where users have used empty paragraphs to create inter-paragraph space. .TP@@ -776,8 +777,8 @@ .TP \f[B]\f[CB]-D\f[B]\f[R] \f[I]FORMAT\f[R], \f[B]\f[CB]--print-default-template=\f[B]\f[R]\f[I]FORMAT\f[R] Print the system default template for an output \f[I]FORMAT\f[R].-(See \f[C]-t\f[R] for a list of possible \f[I]FORMAT\f[R]s.) Templates-in the user data directory are ignored.+(See \f[C]-t\f[R] for a list of possible \f[I]FORMAT\f[R]s.)+Templates in the user data directory are ignored. This option may be used with \f[C]-o\f[R]/\f[C]--output\f[R] to redirect output to a file, but \f[C]-o\f[R]/\f[C]--output\f[R] must come before \f[C]--print-default-template\f[R] on the command line.@@ -805,8 +806,8 @@ \f[B]\f[CB]--dpi\f[B]\f[R]=\f[I]NUMBER\f[R] Specify the default dpi (dots per inch) value for conversion from pixels to inch/centimeters and vice versa.-(Technically, the correct term would be ppi: pixels per inch.) The-default is 96dpi.+(Technically, the correct term would be ppi: pixels per inch.)+The default is 96dpi. When images contain information about dpi internally, the encoded value is used instead of the default specified by this option. .TP@@ -1012,8 +1013,8 @@ \f[B]\f[CB]--markdown-headings=setext\f[B]\f[R]|\f[B]\f[CB]atx\f[B]\f[R] Specify whether to use ATX-style (\f[C]#\f[R]-prefixed) or Setext-style (underlined) headings for level 1 and 2 headings in Markdown output.-(The default is \f[C]atx\f[R].) ATX-style headings are always used for-levels 3+.+(The default is \f[C]atx\f[R].)+ATX-style headings are always used for levels 3+. This option also affects Markdown cells in \f[C]ipynb\f[R] output. .TP \f[B]\f[CB]--atx-headers\f[B]\f[R]@@ -1433,10 +1434,11 @@ The style is controlled by a CSL stylesheet specified using the \f[C]--csl\f[R] option or the \f[C]csl\f[R] field in metadata. (If no stylesheet is specified, the \f[C]chicago-author-date\f[R] style-will be used by default.) The citation processing transformation may be-applied before or after filters or Lua filters (see \f[C]--filter\f[R],-\f[C]--lua-filter\f[R]): these transformations are applied in the order-they appear on the command line.+will be used by default.)+The citation processing transformation may be applied before or after+filters or Lua filters (see \f[C]--filter\f[R], \f[C]--lua-filter\f[R]):+these transformations are applied in the order they appear on the+command line. For more information, see the section on Citations. .TP \f[B]\f[CB]--bibliography=\f[B]\f[R]\f[I]FILE\f[R]@@ -1451,8 +1453,8 @@ \f[B]\f[CB]--csl=\f[B]\f[R]\f[I]FILE\f[R] Set the \f[C]csl\f[R] field in the document\[cq]s metadata to \f[I]FILE\f[R], overriding any value set in the metadata.-(This is equivalent to \f[C]--metadata csl=FILE\f[R].) If \f[I]FILE\f[R]-is a URL, it will be fetched via HTTP.+(This is equivalent to \f[C]--metadata csl=FILE\f[R].)+If \f[I]FILE\f[R] is a URL, it will be fetched via HTTP. If \f[I]FILE\f[R] is not found relative to the working directory, it will be sought in the resource path (see \f[C]--resource-path\f[R]) and finally in the \f[C]csl\f[R] subdirectory of the pandoc user data@@ -1462,8 +1464,8 @@ Set the \f[C]citation-abbreviations\f[R] field in the document\[cq]s metadata to \f[I]FILE\f[R], overriding any value set in the metadata. (This is equivalent to-\f[C]--metadata citation-abbreviations=FILE\f[R].) If \f[I]FILE\f[R] is-a URL, it will be fetched via HTTP.+\f[C]--metadata citation-abbreviations=FILE\f[R].)+If \f[I]FILE\f[R] is a URL, it will be fetched via HTTP. If \f[I]FILE\f[R] is not found relative to the working directory, it will be sought in the resource path (see \f[C]--resource-path\f[R]) and finally in the \f[C]csl\f[R] subdirectory of the pandoc user data@@ -2451,8 +2453,9 @@ \f[C]title-meta\f[R], \f[C]author-meta\f[R], and \f[C]date-meta\f[R] variables. (By default these are set automatically, based on \f[C]title\f[R],-\f[C]author\f[R], and \f[C]date\f[R].) The page title in HTML is set by-\f[C]pagetitle\f[R], which is equal to \f[C]title\f[R] by default.+\f[C]author\f[R], and \f[C]date\f[R].)+The page title in HTML is set by \f[C]pagetitle\f[R], which is equal to+\f[C]title\f[R] by default. .RE .TP \f[B]\f[CB]subtitle\f[B]\f[R]@@ -3148,8 +3151,9 @@ The markdown reader and writer make by far the most use of extensions. Extensions only used by them are therefore covered in the section Pandoc\[cq]s Markdown below (See Markdown variants for-\f[C]commonmark\f[R] and \f[C]gfm\f[R].) In the following, extensions-that also work for other formats are covered.+\f[C]commonmark\f[R] and \f[C]gfm\f[R].)+In the following, extensions that also work for other formats are+covered. .PP Note that markdown extensions added to the \f[C]ipynb\f[R] format affect Markdown cells in Jupyter notebooks (as do command-line options like@@ -3932,8 +3936,8 @@ If highlighting is supported for your output format and language, then the code block above will appear highlighted, with numbered lines. (To see which languages are supported, type-\f[C]pandoc --list-highlight-languages\f[R].) Otherwise, the code block-above will appear as follows:+\f[C]pandoc --list-highlight-languages\f[R].)+Otherwise, the code block above will appear as follows: .IP .nf \f[C]@@ -4365,7 +4369,8 @@ \f[R] .fi .PP-Trouble! Here pandoc (like other Markdown implementations) will treat+Trouble!+Here pandoc (like other Markdown implementations) will treat \f[C]{ my code block }\f[R] as the second paragraph of item two, and not as a code block. .PP@@ -4645,9 +4650,10 @@ widths determined by the number of dashes in the line separating the table header from the table body. (For example \f[C]---|-\f[R] would make the first column 3/4 and the-second column 1/4 of the full text width.) On the other hand, if no-lines are wider than column width, then cell contents will not be-wrapped, and the cells will be sized to their contents.+second column 1/4 of the full text width.)+On the other hand, if no lines are wider than column width, then cell+contents will not be wrapped, and the cells will be sized to their+contents. .PP Note: pandoc also recognizes pipe tables of the following form, as can be produced by Emacs\[cq] orgtbl-mode:@@ -4680,8 +4686,9 @@ .PP it will be parsed as bibliographic information, not regular text. (It will be used, for example, in the title of standalone LaTeX or HTML-output.) The block may contain just a title, a title and an author, or-all three elements.+output.)+The block may contain just a title, a title and an author, or all three+elements. If you want to include an author but no title, or a title and a date but no author, you need a blank line: .IP@@ -4804,8 +4811,8 @@ .fi .PP Just be sure that the YAML file begins with \f[C]---\f[R] and ends with-\f[C]---\f[R] or \f[C]...\f[R].) Alternatively, you can use the-\f[C]--metadata-file\f[R] option.+\f[C]---\f[R] or \f[C]...\f[R].)+Alternatively, you can use the \f[C]--metadata-file\f[R] option. Using that approach however, you cannot reference content (like footnotes) from the main markdown input document. .PP@@ -4814,10 +4821,10 @@ Metadata can contain lists and objects (nested arbitrarily), but all string scalars will be interpreted as Markdown. Fields with names ending in an underscore will be ignored by pandoc.-(They may be given a role by external processors.) Field names must not-be interpretable as YAML numbers or boolean values (so, for example,-\f[C]yes\f[R], \f[C]True\f[R], and \f[C]15\f[R] cannot be used as field-names).+(They may be given a role by external processors.)+Field names must not be interpretable as YAML numbers or boolean values+(so, for example, \f[C]yes\f[R], \f[C]True\f[R], and \f[C]15\f[R] cannot+be used as field names). .PP A document may contain multiple metadata blocks. If two metadata blocks attempt to set the same field, the value from the@@ -5077,9 +5084,9 @@ must be escaped with backslashes. (This is to prevent accidental superscripting and subscripting through the ordinary use of \f[C]\[ti]\f[R] and \f[C]\[ha]\f[R], and also bad-interactions with footnotes.) Thus, if you want the letter P with `a-cat' in subscripts, use \f[C]P\[ti]a\[rs] cat\[ti]\f[R], not-\f[C]P\[ti]a cat\[ti]\f[R].+interactions with footnotes.)+Thus, if you want the letter P with `a cat' in subscripts, use+\f[C]P\[ti]a\[rs] cat\[ti]\f[R], not \f[C]P\[ti]a cat\[ti]\f[R]. .SS Verbatim .PP To make a short span of text verbatim, put it inside backticks:@@ -5503,10 +5510,10 @@ The link consists of link text in square brackets, followed by a label in square brackets. (There cannot be space between the two unless the-\f[C]spaced_reference_links\f[R] extension is enabled.) The link-definition consists of the bracketed label, followed by a colon and a-space, followed by the URL, and optionally (after a space) a link title-either in quotes or in parentheses.+\f[C]spaced_reference_links\f[R] extension is enabled.)+The link definition consists of the bracketed label, followed by a colon+and a space, followed by the URL, and optionally (after a space) a link+title either in quotes or in parentheses. The label must not be parseable as a citation (assuming the \f[C]citations\f[R] extension is enabled): citations take precedence over link labels.@@ -6516,8 +6523,9 @@ By default, pandoc will use the Chicago Manual of Style author-date format. (You can override this default by copying a CSL style of your choice to-\f[C]default.csl\f[R] in your user data directory.) The CSL project-provides further information on finding and editing styles.+\f[C]default.csl\f[R] in your user data directory.)+The CSL project provides further information on finding and editing+styles. .PP The \f[C]--citation-abbreviations\f[R] option (or the \f[C]citation-abbreviations\f[R] metadata field) may be used to specify@@ -6564,7 +6572,8 @@ be rendered in parentheses. In-text citations (such as \f[C]\[at]foo [p. 33]\f[R]) will be rendered without parentheses.-(A comma will be added if appropriate.) Thus:+(A comma will be added if appropriate.)+Thus: .IP .nf \f[C]@@ -6677,7 +6686,8 @@ as hyperlinks. (If an entry contains a DOI, PMCID, PMID, or URL, but none of these fields are rendered by the style, then the title, or in the absence of a-title the whole entry, will be hyperlinked.) Defaults to true.+title the whole entry, will be hyperlinked.)+Defaults to true. .TP \f[B]\f[CB]lang\f[B]\f[R] The \f[C]lang\f[R] field will affect how the style is localized, for@@ -6780,9 +6790,9 @@ \f[C]w3.org\f[R] (for Slidy). (These paths can be changed by setting the \f[C]slidy-url\f[R], \f[C]slideous-url\f[R], \f[C]revealjs-url\f[R], or \f[C]s5-url\f[R]-variables; see Variables for HTML slides, above.) For DZSlides, the-(relatively short) JavaScript and CSS are included in the file by-default.+variables; see Variables for HTML slides, above.)+For DZSlides, the (relatively short) JavaScript and CSS are included in+the file by default. .PP With all HTML slide formats, the \f[C]--self-contained\f[R] option can be used to produce a single file that contains all of the data necessary@@ -7258,8 +7268,8 @@ .TP \f[B]\f[CB]date\f[B]\f[R] A string value in \f[C]YYYY-MM-DD\f[R] format.-(Only the year is necessary.) Pandoc will attempt to convert other-common date formats.+(Only the year is necessary.)+Pandoc will attempt to convert other common date formats. .TP \f[B]\f[CB]lang\f[B]\f[R] (or legacy: \f[B]\f[CB]language\f[B]\f[R]) A string value in BCP 47 format.@@ -7904,8 +7914,9 @@ Copyright 2006\[en]2021 John MacFarlane (jgm\[at]berkeley.edu). Released under the GPL, version 2 or greater. This software carries no warranty of any kind.-(See COPYRIGHT for full copyright and warranty notices.) For a full list-of contributors, see the file AUTHORS.md in the pandoc source code.+(See COPYRIGHT for full copyright and warranty notices.)+For a full list of contributors, see the file AUTHORS.md in the pandoc+source code. .PP The Pandoc source code and all documentation may be downloaded from <https://pandoc.org>.
pandoc.cabal view
@@ -1,6 +1,6 @@ cabal-version:   2.2 name:            pandoc-version:         2.15+version:         2.16 build-type:      Simple license:         GPL-2.0-or-later license-file:    COPYING.md@@ -522,7 +522,6 @@ library   import:        common-options   build-depends: Glob                  >= 0.7      && < 0.11,-                 HsYAML                >= 0.2      && < 0.3,                  JuicyPixels           >= 3.1.6.1  && < 3.4,                  SHA                   >= 1.6      && < 1.7,                  aeson                 >= 0.7      && < 2.1,@@ -567,12 +566,14 @@                  network-uri           >= 2.6      && < 2.8,                  pandoc-types          >= 1.22.1   && < 1.23,                  parsec                >= 3.1      && < 3.2,+                 pretty                >= 1.1      && < 1.2,+                 pretty-show           >= 1.10     && < 1.11,                  process               >= 1.2.3    && < 1.7,                  random                >= 1        && < 1.3,                  safe                  >= 0.3.18   && < 0.4,                  scientific            >= 0.3      && < 0.4,-                 skylighting           >= 0.12     && < 0.13,-                 skylighting-core      >= 0.12     && < 0.13,+                 skylighting           >= 0.12.1   && < 0.13,+                 skylighting-core      >= 0.12.1   && < 0.13,                  split                 >= 0.2      && < 0.3,                  syb                   >= 0.1      && < 0.8,                  tagsoup               >= 0.14.6   && < 0.15,@@ -580,15 +581,14 @@                  texmath               >= 0.12.3.2 && < 0.12.4,                  text                  >= 1.1.1.0  && < 1.3,                  text-conversions      >= 0.3      && < 0.4,-                 time                  >= 1.5      && < 1.13,+                 time                  >= 1.5      && < 1.14,+                 unicode-collation     >= 0.1.1    && < 0.2,                  unicode-transforms    >= 0.3      && < 0.4,                  xml                   >= 1.3.12   && < 1.4,                  xml-conduit           >= 1.9.1.1  && < 1.10,-                 unicode-collation     >= 0.1.1    && < 0.2,+                 yaml                  >= 0.11     && < 0.12,                  zip-archive           >= 0.2.3.4  && < 0.5,-                 zlib                  >= 0.5      && < 0.7,-                 pretty-show           >= 1.10     && < 1.11,-                 pretty                >= 1.1      && < 1.2+                 zlib                  >= 0.5      && < 0.7   if os(windows) && arch(i386)      build-depends: basement >= 0.0.10,                     foundation >= 0.0.23@@ -781,6 +781,7 @@                    Text.Pandoc.Lua.Marshaling.CommonState,                    Text.Pandoc.Lua.Marshaling.Context,                    Text.Pandoc.Lua.Marshaling.List,+                   Text.Pandoc.Lua.Marshaling.ListAttributes,                    Text.Pandoc.Lua.Marshaling.PandocError,                    Text.Pandoc.Lua.Marshaling.ReaderOptions,                    Text.Pandoc.Lua.Marshaling.SimpleTable,@@ -857,7 +858,7 @@                   tasty-lua         >= 1.0     && < 1.1,                   tasty-quickcheck  >= 0.8     && < 0.11,                   text              >= 1.1.1.0  && < 1.3,-                  time              >= 1.5     && < 1.13,+                  time              >= 1.5     && < 1.14,                   xml               >= 1.3.12  && < 1.4,                   zip-archive       >= 0.2.3.4 && < 0.5   other-modules:  Tests.Old
src/Text/Pandoc/App.hs view
@@ -217,7 +217,7 @@       case optMetadataFiles opts of         []    -> return mempty         paths -> mconcat <$>-           mapM (\path -> do raw <- readFileLazy path+           mapM (\path -> do raw <- readFileStrict path                              yamlToMeta readerOpts (Just path) raw) paths      let transforms = (case optShiftHeadingLevelBy opts of
src/Text/Pandoc/App/Opt.hs view
@@ -29,7 +29,7 @@ import Control.Monad.State.Strict (StateT, modify, gets) import System.FilePath ( addExtension, (</>), takeExtension, takeDirectory ) import System.Directory ( canonicalizePath )-import Data.Char (isLower, toLower)+import Data.Char (toLower) import Data.Maybe (fromMaybe) import GHC.Generics hiding (Meta) import Text.Pandoc.Filter (Filter (..))@@ -40,11 +40,10 @@                             ReferenceLocation (EndOfDocument),                             ObfuscationMethod (NoObfuscation),                             CiteMethod (Citeproc))-import Text.Pandoc.Class (readFileLazy, fileExists, setVerbosity, report,+import Text.Pandoc.Class (readFileStrict, fileExists, setVerbosity, report,                           PandocMonad(lookupEnv), getUserDataDir) import Text.Pandoc.Error (PandocError (PandocParseError, PandocSomeError))-import Text.Pandoc.Shared (camelCaseStrToHyphenated, defaultUserDataDir,-                           findM, ordNub)+import Text.Pandoc.Shared (defaultUserDataDir, findM, ordNub) import qualified Text.Pandoc.Parsing as P import Text.Pandoc.Readers.Metadata (yamlMap) import Text.Pandoc.Class.PandocPure@@ -54,21 +53,18 @@ import qualified Data.Text as T import qualified Data.Map as M import Text.Pandoc.Definition (Meta(..), MetaValue(..))-import Data.Aeson (defaultOptions, Options(..))+import Data.Aeson (defaultOptions, Options(..), Result(..), fromJSON, camelTo2) import Data.Aeson.TH (deriveJSON) import Control.Applicative ((<|>))-import Data.YAML+import Data.Yaml  -- | The type of line-endings to be used when writing plain-text. data LineEnding = LF | CRLF | Native deriving (Show, Generic) -instance FromYAML LineEnding where-  parseYAML = withStr "LineEnding" $ \t ->-    case T.toLower t of-      "lf"     -> return LF-      "crlf"   -> return CRLF-      "native" -> return Native-      _        -> fail $ "Unknown line ending type " ++ show t+-- see https://github.com/jgm/pandoc/pull/4083+-- using generic deriving caused long compilation times+$(deriveJSON+   defaultOptions{ constructorTagModifier = map toLower } ''LineEnding)  -- | How to handle output blocks in ipynb. data IpynbOutput =@@ -77,13 +73,8 @@   | IpynbOutputBest   deriving (Show, Generic) -instance FromYAML IpynbOutput where-  parseYAML = withStr "LineEnding" $ \t ->-    case t of-      "none"  -> return IpynbOutputNone-      "all"   -> return IpynbOutputAll-      "best"  -> return IpynbOutputBest-      _       -> fail $ "Unknown ipynb output type " ++ show t+$(deriveJSON+   defaultOptions{ fieldLabelModifier = map toLower . drop 11 } ''IpynbOutput)  -- | Data structure for command line options. data Opt = Opt@@ -163,10 +154,16 @@     , optSandbox               :: Bool     } deriving (Generic, Show) -instance FromYAML (Opt -> Opt) where-  parseYAML (Mapping _ _ m) = chain doOpt (M.toList m)-  parseYAML n = failAtNode n "Expected a mapping"+$(deriveJSON+   defaultOptions{ fieldLabelModifier = camelTo2 '-' . drop 3 } ''Opt) +instance FromJSON (Opt -> Opt) where+  parseJSON (Object m) =+    case fromJSON (Object m) of+      Error err' -> fail err'+      Success (m' :: M.Map Text Value) -> chain doOpt (M.toList m')+  parseJSON _ = fail "Expected a mapping"+ data DefaultsState = DefaultsState     {       curDefaults      :: Maybe FilePath -- currently parsed file@@ -174,22 +171,21 @@     } deriving (Show)  instance (PandocMonad m, MonadIO m)-      => FromYAML (Opt -> StateT DefaultsState m Opt) where-  parseYAML (Mapping _ _ m) = do-    let opts = M.mapKeys toText m-    dataDir <- case M.lookup "data-dir" opts of-      Nothing -> return Nothing-      Just v -> Just . unpack <$> parseYAML v-    f <- parseOptions (M.toList m)-    case M.lookup "defaults" opts of-      Just v -> do-        g <- parseDefaults v dataDir-        return  $ g >=> f >=> resolveVarsInOpt-      Nothing -> return $ f >=> resolveVarsInOpt-    where-      toText (Scalar _ (SStr s)) = s-      toText _ = ""-  parseYAML n = failAtNode n "Expected a mapping"+      => FromJSON (Opt -> StateT DefaultsState m Opt) where+  parseJSON (Object o) =+    case fromJSON (Object o) of+      Error err' -> fail err'+      Success (opts :: M.Map Text Value) -> do+        dataDir <- case M.lookup "data-dir" opts of+          Nothing -> return Nothing+          Just v -> Just . unpack <$> parseJSON v+        f <- parseOptions (M.toList opts)+        case M.lookup "defaults" opts of+          Just v -> do+            g <- parseDefaults v dataDir+            return  $ g >=> f >=> resolveVarsInOpt+          Nothing -> return $ f >=> resolveVarsInOpt+  parseJSON _ = fail "Expected a mapping"  resolveVarsInOpt :: forall m. (PandocMonad m, MonadIO m)                  => Opt -> StateT DefaultsState m Opt@@ -303,7 +299,7 @@   parseDefaults :: (PandocMonad m, MonadIO m)-              => Node Pos+              => Value               -> Maybe FilePath               -> Parser (Opt -> StateT DefaultsState m Opt) parseDefaults n dataDir = parseDefsNames n >>= \ds -> return $ \o -> do@@ -322,11 +318,11 @@         "Error: Circular defaults file reference in " ++         "'" ++ defsParent ++ "'"     else foldM applyDefaults o defsChildren-  where parseDefsNames x = (parseYAML x >>= \xs -> return $ map unpack xs)-                       <|> (parseYAML x >>= \x' -> return [unpack x'])+  where parseDefsNames x = (parseJSON x >>= \xs -> return $ map unpack xs)+                       <|> (parseJSON x >>= \x' -> return [unpack x'])  parseOptions :: Monad m-             => [(Node Pos, Node Pos)]+             => [(Text, Value)]              -> Parser (Opt -> StateT DefaultsState m Opt) parseOptions ns = do   f <- chain doOpt' ns@@ -336,269 +332,267 @@ chain f = foldM g id   where g o n = f n >>= \o' -> return $ o' . o -doOpt' :: (Node Pos, Node Pos) -> Parser (Opt -> Opt)-doOpt' (k',v) = do-  k <- parseStringKey k'+doOpt' :: (Text, Value) -> Parser (Opt -> Opt)+doOpt' (k,v) = do   case k of     "defaults" -> return id-    _ -> doOpt (k',v)+    _ -> doOpt (k,v) -doOpt :: (Node Pos, Node Pos) -> Parser (Opt -> Opt)-doOpt (k',v) = do-  k <- parseStringKey k'+doOpt :: (Text, Value) -> Parser (Opt -> Opt)+doOpt (k,v) = do   case k of     "tab-stop" ->-      parseYAML v >>= \x -> return (\o -> o{ optTabStop = x })+      parseJSON v >>= \x -> return (\o -> o{ optTabStop = x })     "preserve-tabs" ->-      parseYAML v >>= \x -> return (\o -> o{ optPreserveTabs = x })+      parseJSON v >>= \x -> return (\o -> o{ optPreserveTabs = x })     "standalone" ->-      parseYAML v >>= \x -> return (\o -> o{ optStandalone = x })+      parseJSON v >>= \x -> return (\o -> o{ optStandalone = x })     "table-of-contents" ->-      parseYAML v >>= \x -> return (\o -> o{ optTableOfContents = x })+      parseJSON v >>= \x -> return (\o -> o{ optTableOfContents = x })     "toc" ->-      parseYAML v >>= \x -> return (\o -> o{ optTableOfContents = x })+      parseJSON v >>= \x -> return (\o -> o{ optTableOfContents = x })     "from" ->-      parseYAML v >>= \x -> return (\o -> o{ optFrom = x })+      parseJSON v >>= \x -> return (\o -> o{ optFrom = x })     "reader" ->-      parseYAML v >>= \x -> return (\o -> o{ optFrom = x })+      parseJSON v >>= \x -> return (\o -> o{ optFrom = x })     "to" ->-      parseYAML v >>= \x -> return (\o -> o{ optTo = x })+      parseJSON v >>= \x -> return (\o -> o{ optTo = x })     "writer" ->-      parseYAML v >>= \x -> return (\o -> o{ optTo = x })+      parseJSON v >>= \x -> return (\o -> o{ optTo = x })     "shift-heading-level-by" ->-      parseYAML v >>= \x -> return (\o -> o{ optShiftHeadingLevelBy = x })+      parseJSON v >>= \x -> return (\o -> o{ optShiftHeadingLevelBy = x })     "template" ->-      parseYAML v >>= \x -> return (\o -> o{ optTemplate = unpack <$> x })+      parseJSON v >>= \x -> return (\o -> o{ optTemplate = unpack <$> x })     "variables" ->-      parseYAML v >>= \x -> return (\o -> o{ optVariables =+      parseJSON v >>= \x -> return (\o -> o{ optVariables =                                                x <> optVariables o })       -- Note: x comes first because <> for Context is left-biased union       -- and we want to favor later default files. See #5988.     "metadata" ->       yamlToMeta v >>= \x -> return (\o -> o{ optMetadata = optMetadata o <> x })     "metadata-files" ->-      parseYAML v >>= \x ->+      parseJSON v >>= \x ->                         return (\o -> o{ optMetadataFiles =                                            optMetadataFiles o <>                                            map unpack x })     "metadata-file" -> -- allow either a list or a single value-      (parseYAML v >>= \x -> return (\o -> o{ optMetadataFiles =+      (parseJSON v >>= \x -> return (\o -> o{ optMetadataFiles =                                                 optMetadataFiles o <>                                                 map unpack x }))       <|>-      (parseYAML v >>= \x ->+      (parseJSON v >>= \x ->                         return (\o -> o{ optMetadataFiles =                                            optMetadataFiles o <>[unpack x] }))     "output-file" ->-      parseYAML v >>= \x -> return (\o -> o{ optOutputFile = unpack <$> x })+      parseJSON v >>= \x -> return (\o -> o{ optOutputFile = unpack <$> x })     "input-files" ->-      parseYAML v >>= \x -> return (\o -> o{ optInputFiles =+      parseJSON v >>= \x -> return (\o -> o{ optInputFiles =                                               optInputFiles o <>                                                 (map unpack <$> x) })     "input-file" -> -- allow either a list or a single value-      (parseYAML v >>= \x -> return (\o -> o{ optInputFiles =+      (parseJSON v >>= \x -> return (\o -> o{ optInputFiles =                                                 optInputFiles o <>                                                   (map unpack <$> x) }))       <|>-      (parseYAML v >>= \x -> return (\o -> o{ optInputFiles =+      (parseJSON v >>= \x -> return (\o -> o{ optInputFiles =                                                 optInputFiles o <>                                                 ((\z -> [unpack z]) <$> x)                                             }))     "number-sections" ->-      parseYAML v >>= \x -> return (\o -> o{ optNumberSections = x })+      parseJSON v >>= \x -> return (\o -> o{ optNumberSections = x })     "number-offset" ->-      parseYAML v >>= \x -> return (\o -> o{ optNumberOffset = x })+      parseJSON v >>= \x -> return (\o -> o{ optNumberOffset = x })     "section-divs" ->-      parseYAML v >>= \x -> return (\o -> o{ optSectionDivs = x })+      parseJSON v >>= \x -> return (\o -> o{ optSectionDivs = x })     "incremental" ->-      parseYAML v >>= \x -> return (\o -> o{ optIncremental = x })+      parseJSON v >>= \x -> return (\o -> o{ optIncremental = x })     "self-contained" ->-      parseYAML v >>= \x -> return (\o -> o{ optSelfContained = x })+      parseJSON v >>= \x -> return (\o -> o{ optSelfContained = x })     "html-q-tags" ->-      parseYAML v >>= \x -> return (\o -> o{ optHtmlQTags = x })+      parseJSON v >>= \x -> return (\o -> o{ optHtmlQTags = x })     "highlight-style" ->-      parseYAML v >>= \x -> return (\o -> o{ optHighlightStyle = x })+      parseJSON v >>= \x -> return (\o -> o{ optHighlightStyle = x })     "syntax-definition" ->-      (parseYAML v >>= \x ->+      (parseJSON v >>= \x ->                 return (\o -> o{ optSyntaxDefinitions =                                    optSyntaxDefinitions o <> map unpack x }))       <|>-      (parseYAML v >>= \x ->+      (parseJSON v >>= \x ->              return (\o -> o{ optSyntaxDefinitions =                                  optSyntaxDefinitions o <> [unpack x] }))     "syntax-definitions" ->-      parseYAML v >>= \x ->+      parseJSON v >>= \x ->              return (\o -> o{ optSyntaxDefinitions =                                 optSyntaxDefinitions o <> map unpack x })     "top-level-division" ->-      parseYAML v >>= \x -> return (\o -> o{ optTopLevelDivision = x })+      parseJSON v >>= \x -> return (\o -> o{ optTopLevelDivision = x })     "html-math-method" ->-      parseYAML v >>= \x -> return (\o -> o{ optHTMLMathMethod = x })+      parseJSON v >>= \x -> return (\o -> o{ optHTMLMathMethod = x })     "abbreviations" ->-      parseYAML v >>= \x ->+      parseJSON v >>= \x ->              return (\o -> o{ optAbbreviations = unpack <$> x })     "reference-doc" ->-      parseYAML v >>= \x ->+      parseJSON v >>= \x ->              return (\o -> o{ optReferenceDoc = unpack <$> x })     "epub-subdirectory" ->-      parseYAML v >>= \x ->+      parseJSON v >>= \x ->              return (\o -> o{ optEpubSubdirectory = unpack x })     "epub-metadata" ->-      parseYAML v >>= \x ->+      parseJSON v >>= \x ->              return (\o -> o{ optEpubMetadata = unpack <$> x })     "epub-fonts" ->-      parseYAML v >>= \x -> return (\o -> o{ optEpubFonts = optEpubFonts o <>+      parseJSON v >>= \x -> return (\o -> o{ optEpubFonts = optEpubFonts o <>                                                map unpack x })     "epub-chapter-level" ->-      parseYAML v >>= \x -> return (\o -> o{ optEpubChapterLevel = x })+      parseJSON v >>= \x -> return (\o -> o{ optEpubChapterLevel = x })     "epub-cover-image" ->-      parseYAML v >>= \x ->+      parseJSON v >>= \x ->              return (\o -> o{ optEpubCoverImage = unpack <$> x })     "toc-depth" ->-      parseYAML v >>= \x -> return (\o -> o{ optTOCDepth = x })+      parseJSON v >>= \x -> return (\o -> o{ optTOCDepth = x })     "dump-args" ->-      parseYAML v >>= \x -> return (\o -> o{ optDumpArgs = x })+      parseJSON v >>= \x -> return (\o -> o{ optDumpArgs = x })     "ignore-args" ->-      parseYAML v >>= \x -> return (\o -> o{ optIgnoreArgs = x })+      parseJSON v >>= \x -> return (\o -> o{ optIgnoreArgs = x })     "verbosity" ->-      parseYAML v >>= \x -> return (\o -> o{ optVerbosity = x })+      parseJSON v >>= \x -> return (\o -> o{ optVerbosity = x })     "trace" ->-      parseYAML v >>= \x -> return (\o -> o{ optTrace = x })+      parseJSON v >>= \x -> return (\o -> o{ optTrace = x })     "log-file" ->-      parseYAML v >>= \x -> return (\o -> o{ optLogFile = unpack <$> x })+      parseJSON v >>= \x -> return (\o -> o{ optLogFile = unpack <$> x })     "fail-if-warnings" ->-      parseYAML v >>= \x -> return (\o -> o{ optFailIfWarnings = x })+      parseJSON v >>= \x -> return (\o -> o{ optFailIfWarnings = x })     "reference-links" ->-      parseYAML v >>= \x -> return (\o -> o{ optReferenceLinks = x })+      parseJSON v >>= \x -> return (\o -> o{ optReferenceLinks = x })     "reference-location" ->-      parseYAML v >>= \x -> return (\o -> o{ optReferenceLocation = x })+      parseJSON v >>= \x -> return (\o -> o{ optReferenceLocation = x })     "dpi" ->-      parseYAML v >>= \x -> return (\o -> o{ optDpi = x })+      parseJSON v >>= \x -> return (\o -> o{ optDpi = x })     "wrap" ->-      parseYAML v >>= \x -> return (\o -> o{ optWrap = x })+      parseJSON v >>= \x -> return (\o -> o{ optWrap = x })     "columns" ->-      parseYAML v >>= \x -> return (\o -> o{ optColumns = x })+      parseJSON v >>= \x -> return (\o -> o{ optColumns = x })     "filters" ->-      parseYAML v >>= \x -> return (\o -> o{ optFilters = optFilters o <> x })+      parseJSON v >>= \x -> return (\o -> o{ optFilters = optFilters o <> x })     "citeproc" ->-      parseYAML v >>= \x ->+      parseJSON v >>= \x ->         if x            then return (\o -> o{ optFilters = CiteprocFilter : optFilters o })            else return id     "email-obfuscation" ->-      parseYAML v >>= \x -> return (\o -> o{ optEmailObfuscation = x })+      parseJSON v >>= \x -> return (\o -> o{ optEmailObfuscation = x })     "identifier-prefix" ->-      parseYAML v >>= \x ->+      parseJSON v >>= \x ->              return (\o -> o{ optIdentifierPrefix = x })     "strip-empty-paragraphs" ->-      parseYAML v >>= \x -> return (\o -> o{ optStripEmptyParagraphs = x })+      parseJSON v >>= \x -> return (\o -> o{ optStripEmptyParagraphs = x })     "indented-code-classes" ->-      parseYAML v >>= \x ->+      parseJSON v >>= \x ->              return (\o -> o{ optIndentedCodeClasses = x })     "data-dir" ->-      parseYAML v >>= \x -> return (\o -> o{ optDataDir = unpack <$> x })+      parseJSON v >>= \x -> return (\o -> o{ optDataDir = unpack <$> x })     "cite-method" ->-      parseYAML v >>= \x -> return (\o -> o{ optCiteMethod = x })+      parseJSON v >>= \x -> return (\o -> o{ optCiteMethod = x })     "listings" ->-      parseYAML v >>= \x -> return (\o -> o{ optListings = x })+      parseJSON v >>= \x -> return (\o -> o{ optListings = x })     "pdf-engine" ->-      parseYAML v >>= \x -> return (\o -> o{ optPdfEngine = unpack <$> x })+      parseJSON v >>= \x -> return (\o -> o{ optPdfEngine = unpack <$> x })     "pdf-engine-opts" ->-      parseYAML v >>= \x ->+      parseJSON v >>= \x ->              return (\o -> o{ optPdfEngineOpts = map unpack x })     "pdf-engine-opt" ->-      (parseYAML v >>= \x ->+      (parseJSON v >>= \x ->              return (\o -> o{ optPdfEngineOpts = map unpack x }))       <|>-      (parseYAML v >>= \x ->+      (parseJSON v >>= \x ->              return (\o -> o{ optPdfEngineOpts = [unpack x] }))     "slide-level" ->-      parseYAML v >>= \x -> return (\o -> o{ optSlideLevel = x })+      parseJSON v >>= \x -> return (\o -> o{ optSlideLevel = x })     "atx-headers" ->-      parseYAML v >>= \x -> return (\o -> o{ optSetextHeaders = not x })+      parseJSON v >>= \x -> return (\o -> o{ optSetextHeaders = not x })     "markdown-headings" ->-      parseYAML v >>= \x -> return (\o ->+      parseJSON v >>= \x -> return (\o ->         case T.toLower x of           "atx"    -> o{ optSetextHeaders = False }           "setext" -> o{ optSetextHeaders = True }           _        -> o)     "ascii" ->-      parseYAML v >>= \x -> return (\o -> o{ optAscii = x })+      parseJSON v >>= \x -> return (\o -> o{ optAscii = x })     "default-image-extension" ->-      parseYAML v >>= \x ->+      parseJSON v >>= \x ->              return (\o -> o{ optDefaultImageExtension = x })     "extract-media" ->-      parseYAML v >>= \x ->+      parseJSON v >>= \x ->              return (\o -> o{ optExtractMedia = unpack <$> x })     "track-changes" ->-      parseYAML v >>= \x -> return (\o -> o{ optTrackChanges = x })+      parseJSON v >>= \x -> return (\o -> o{ optTrackChanges = x })     "file-scope" ->-      parseYAML v >>= \x -> return (\o -> o{ optFileScope = x })+      parseJSON v >>= \x -> return (\o -> o{ optFileScope = x })     "title-prefix" ->-      parseYAML v >>= \x -> return (\o -> o{ optTitlePrefix = x,+      parseJSON v >>= \x -> return (\o -> o{ optTitlePrefix = x,                                              optStandalone = True })     "css" ->-      (parseYAML v >>= \x -> return (\o -> o{ optCss = optCss o <>+      (parseJSON v >>= \x -> return (\o -> o{ optCss = optCss o <>                                                  map unpack x }))       <|>-      (parseYAML v >>= \x -> return (\o -> o{ optCss = optCss o <>+      (parseJSON v >>= \x -> return (\o -> o{ optCss = optCss o <>                                                 [unpack x] }))     "bibliography" ->-      (parseYAML v >>= \x -> return (\o ->+      (parseJSON v >>= \x -> return (\o ->                                o{ optBibliography = optBibliography o <>                                                       map unpack x }))       <|>-      (parseYAML v >>= \x -> return (\o ->+      (parseJSON v >>= \x -> return (\o ->                                o{ optBibliography = optBibliography o <>                                                        [unpack x] }))     "csl" ->-      parseYAML v >>= \x -> return (\o -> o{ optCSL = unpack <$> x })+      parseJSON v >>= \x -> return (\o -> o{ optCSL = unpack <$> x })     "citation-abbreviations" ->-      parseYAML v >>= \x -> return (\o -> o{ optCitationAbbreviations =+      parseJSON v >>= \x -> return (\o -> o{ optCitationAbbreviations =                                                   unpack <$> x })     "ipynb-output" ->-      parseYAML v >>= \x -> return (\o -> o{ optIpynbOutput = x })+      parseJSON v >>= \x -> return (\o -> o{ optIpynbOutput = x })     "include-before-body" ->-      (parseYAML v >>= \x ->+      (parseJSON v >>= \x ->              return (\o -> o{ optIncludeBeforeBody =                                 optIncludeBeforeBody o <> map unpack x }))       <|>-      (parseYAML v >>= \x ->+      (parseJSON v >>= \x ->              return (\o -> o{ optIncludeBeforeBody =                                 optIncludeBeforeBody o <> [unpack x] }))     "include-after-body" ->-      (parseYAML v >>= \x ->+      (parseJSON v >>= \x ->              return (\o -> o{ optIncludeAfterBody =                                 optIncludeAfterBody o <> map unpack x }))       <|>-      (parseYAML v >>= \x ->+      (parseJSON v >>= \x ->              return (\o -> o{ optIncludeAfterBody =                                 optIncludeAfterBody o <> [unpack x] }))     "include-in-header" ->-      (parseYAML v >>= \x ->+      (parseJSON v >>= \x ->              return (\o -> o{ optIncludeInHeader =                                 optIncludeInHeader o <> map unpack x }))       <|>-      (parseYAML v >>= \x ->+      (parseJSON v >>= \x ->              return (\o -> o{ optIncludeInHeader =                                 optIncludeInHeader o <> [unpack x] }))     "resource-path" ->-      parseYAML v >>= \x ->+      parseJSON v >>= \x ->              return (\o -> o{ optResourcePath = map unpack x <>                                  optResourcePath o })     "request-headers" ->-      parseYAML v >>= \x ->+      parseJSON v >>= \x ->              return (\o -> o{ optRequestHeaders = x })     "no-check-certificate" ->-      parseYAML v >>= \x ->+      parseJSON v >>= \x ->              return (\o -> o{ optNoCheckCertificate = x })     "eol" ->-      parseYAML v >>= \x -> return (\o -> o{ optEol = x })+      parseJSON v >>= \x -> return (\o -> o{ optEol = x })     "strip-comments" ->-      parseYAML v >>= \x -> return (\o -> o  { optStripComments = x })+      parseJSON v >>= \x -> return (\o -> o  { optStripComments = x })     "sandbox" ->-      parseYAML v >>= \x -> return (\o -> o  { optSandbox = x })-    _ -> failAtNode k' $ "Unknown option " ++ show k+      parseJSON v >>= \x -> return (\o -> o  { optSandbox = x })+    _ -> fail $ "Unknown option " ++ show k  -- | Defaults for command-line options. defaultOpts :: Opt@@ -679,18 +673,12 @@     , optSandbox               = False     } -parseStringKey ::  Node Pos -> Parser Text-parseStringKey k = case k of-  Scalar _ (SStr t) -> return t-  Scalar _ _ -> failAtNode k "Non-string key"-  _ -> failAtNode k "Non-scalar key"--yamlToMeta :: Node Pos -> Parser Meta-yamlToMeta (Mapping _ _ m) =-    either (fail . show) return $ runEverything (yamlMap pMetaString m)-  where-    pMetaString = pure . MetaString <$> P.manyChar P.anyChar-    runEverything p =+yamlToMeta :: Value -> Parser Meta+yamlToMeta (Object o) =+  either (fail . show) return $ runEverything (yamlMap pMetaString o)+ where+  pMetaString = pure . MetaString <$> P.manyChar P.anyChar+  runEverything p =       runPure (P.readWithM p (def :: P.ParserState) ("" :: Text))       >>= fmap (Meta . flip P.runF def) yamlToMeta _ = return mempty@@ -703,14 +691,12 @@ applyDefaults opt file = do   setVerbosity $ optVerbosity opt   modify $ \defsState -> defsState{ curDefaults = Just file }-  inp <- readFileLazy file-  case decode1 inp of+  inp <- readFileStrict file+  case decodeEither' inp of       Right f -> f opt-      Left (errpos, errmsg)  -> throwError $-         PandocParseError $ T.pack $-         "Error parsing " ++ file ++ " line " ++-          show (posLine errpos) ++ " column " ++-          show (posColumn errpos) ++ ":\n" ++ errmsg+      Left err'  -> throwError $+         PandocParseError+             $ T.pack $ Data.Yaml.prettyPrintParseException err'  fullDefaultsPath :: (PandocMonad m, MonadIO m)                  => Maybe FilePath@@ -738,14 +724,3 @@ cyclic = any hasDuplicate   where     hasDuplicate xs = length (ordNub xs) /= length xs---- see https://github.com/jgm/pandoc/pull/4083--- using generic deriving caused long compilation times-$(deriveJSON-   defaultOptions{ fieldLabelModifier = drop 11 . map toLower } ''IpynbOutput)-$(deriveJSON-   defaultOptions{ fieldLabelModifier = map toLower } ''LineEnding)-$(deriveJSON-   defaultOptions{ fieldLabelModifier =-                      camelCaseStrToHyphenated . dropWhile isLower-                 } ''Opt)
src/Text/Pandoc/Citeproc.hs view
@@ -268,7 +268,7 @@       rs <- yamlToRefs idpred               def{ readerExtensions = pandocExtensions }               (T.unpack <$> mbfp)-              (L.fromStrict raw)+              raw       return $ mapMaybe metaValueToReference rs  -- assumes we walk in same order as query
src/Text/Pandoc/Extensions.hs view
@@ -40,31 +40,8 @@ import GHC.Generics (Generic) import Safe (readMay) import Text.Parsec-import Data.Aeson.TH (deriveJSON, defaultOptions)--newtype Extensions = Extensions Integer-  deriving (Show, Read, Eq, Ord, Data, Typeable, Generic)--instance Semigroup Extensions where-  (Extensions a) <> (Extensions b) = Extensions (a .|. b)-instance Monoid Extensions where-  mempty = Extensions 0-  mappend = (<>)--extensionsFromList :: [Extension] -> Extensions-extensionsFromList = foldr enableExtension emptyExtensions--emptyExtensions :: Extensions-emptyExtensions = Extensions 0--extensionEnabled :: Extension -> Extensions -> Bool-extensionEnabled x (Extensions exts) = testBit exts (fromEnum x)--enableExtension :: Extension -> Extensions -> Extensions-enableExtension x (Extensions exts) = Extensions (setBit exts (fromEnum x))--disableExtension :: Extension -> Extensions -> Extensions-disableExtension x (Extensions exts) = Extensions (clearBit exts (fromEnum x))+import Data.Aeson.TH (deriveJSON)+import Data.Aeson  -- | Individually selectable syntax extensions. data Extension =@@ -162,6 +139,40 @@     | Ext_yaml_metadata_block -- ^ YAML metadata block     deriving (Show, Read, Enum, Eq, Ord, Bounded, Data, Typeable, Generic) +$(deriveJSON defaultOptions{ constructorTagModifier = drop 4 } ''Extension)++newtype Extensions = Extensions Integer+  deriving (Show, Read, Eq, Ord, Data, Typeable, Generic)++instance Semigroup Extensions where+  (Extensions a) <> (Extensions b) = Extensions (a .|. b)+instance Monoid Extensions where+  mempty = Extensions 0+  mappend = (<>)++instance FromJSON Extensions where+  parseJSON =+    return . foldr enableExtension emptyExtensions . fromJSON++instance ToJSON Extensions where+  toJSON exts = toJSON $+    [ext | ext <- [minBound..maxBound], extensionEnabled ext exts]++extensionsFromList :: [Extension] -> Extensions+extensionsFromList = foldr enableExtension emptyExtensions++emptyExtensions :: Extensions+emptyExtensions = Extensions 0++extensionEnabled :: Extension -> Extensions -> Bool+extensionEnabled x (Extensions exts) = testBit exts (fromEnum x)++enableExtension :: Extension -> Extensions -> Extensions+enableExtension x (Extensions exts) = Extensions (setBit exts (fromEnum x))++disableExtension :: Extension -> Extensions -> Extensions+disableExtension x (Extensions exts) = Extensions (clearBit exts (fromEnum x))+ -- | Extensions to be used with pandoc-flavored markdown. pandocExtensions :: Extensions pandocExtensions = extensionsFromList@@ -618,5 +629,3 @@                         '+' -> (ext : extsToEnable, extsToDisable)                         _   -> (extsToEnable, ext : extsToDisable) -$(deriveJSON defaultOptions ''Extension)-$(deriveJSON defaultOptions ''Extensions)
src/Text/Pandoc/Filter.hs view
@@ -19,7 +19,7 @@   ) where  import System.CPUTime (getCPUTime)-import Data.Aeson.TH (deriveJSON, defaultOptions)+import Data.Aeson import GHC.Generics (Generic) import Text.Pandoc.Class (report, getVerbosity, PandocMonad) import Text.Pandoc.Definition (Pandoc)@@ -29,7 +29,6 @@ import qualified Text.Pandoc.Filter.JSON as JSONFilter import qualified Text.Pandoc.Filter.Lua as LuaFilter import qualified Text.Pandoc.Filter.Path as Path-import Data.YAML import qualified Data.Text as T import System.FilePath (takeExtension) import Control.Applicative ((<|>))@@ -42,9 +41,9 @@             | CiteprocFilter -- built-in citeproc             deriving (Show, Generic) -instance FromYAML Filter where- parseYAML node =-  (withMap "Filter" $ \m -> do+instance FromJSON Filter where+ parseJSON node =+  (withObject "Filter" $ \m -> do     ty <- m .: "type"     fp <- m .:? "path"     let missingPath = fail $ "Expected 'path' for filter of type " ++ show ty@@ -55,7 +54,7 @@       "json" -> filterWithPath JSONFilter fp       _      -> fail $ "Unknown filter type " ++ show (ty :: T.Text)) node   <|>-  (withStr "Filter" $ \t -> do+  (withText "Filter" $ \t -> do     let fp = T.unpack t     if fp == "citeproc"        then return CiteprocFilter@@ -64,6 +63,13 @@            ".lua"  -> LuaFilter fp            _       -> JSONFilter fp) node +instance ToJSON Filter where+ toJSON CiteprocFilter = object [ "type" .= String "citeproc" ]+ toJSON (LuaFilter fp) = object [ "type" .= String "lua",+                                  "path" .= String (T.pack fp) ]+ toJSON (JSONFilter fp) = object [ "type" .= String "json",+                                   "path" .= String (T.pack fp) ]+ -- | Modify the given document using a filter. applyFilters :: (PandocMonad m, MonadIO m)              => ReaderOptions@@ -96,5 +102,3 @@ expandFilterPath (LuaFilter fp) = LuaFilter <$> Path.expandFilterPath fp expandFilterPath (JSONFilter fp) = JSONFilter <$> Path.expandFilterPath fp expandFilterPath CiteprocFilter = return CiteprocFilter--$(deriveJSON defaultOptions ''Filter)
src/Text/Pandoc/Logging.hs view
@@ -24,7 +24,6 @@   ) where  import Control.Monad (mzero)-import Data.YAML (withStr, FromYAML(..)) import Data.Aeson import Data.Aeson.Encode.Pretty (Config (..), defConfig, encodePretty',                                  keyOrder)@@ -52,13 +51,6 @@          "INFO"    -> return INFO          _         -> mzero   parseJSON _      =  mzero--instance FromYAML Verbosity where-  parseYAML = withStr "Verbosity" $ \case-         "ERROR"   -> return ERROR-         "WARNING" -> return WARNING-         "INFO"    -> return INFO-         _         -> mzero  data LogMessage =     SkippedContent Text SourcePos
src/Text/Pandoc/Lua/Filter.hs view
@@ -14,6 +14,7 @@ -} module Text.Pandoc.Lua.Filter ( LuaFilterFunction                               , LuaFilter+                              , peekLuaFilter                               , runFilterFile                               , walkInlines                               , walkInlineLists@@ -68,20 +69,24 @@ newtype LuaFilter = LuaFilter (Map Name LuaFilterFunction)  instance Peekable LuaFilter where-  peek idx = do-    let constrs = listOfInlinesFilterName-                : listOfBlocksFilterName-                : metaFilterName-                : pandocFilterNames-                ++ blockElementNames-                ++ inlineElementNames-    let go constr acc = do-          Lua.getfield idx constr-          filterFn <- registerFilterFunction-          return $ case filterFn of-            Nothing -> acc-            Just fn -> Map.insert constr fn acc-    LuaFilter <$!> foldrM go Map.empty constrs+  peek = Lua.forcePeek . peekLuaFilter++-- | Retrieves a LuaFilter object from the stack.+peekLuaFilter :: LuaError e => Peeker e LuaFilter+peekLuaFilter idx = do+  let constrs = listOfInlinesFilterName+              : listOfBlocksFilterName+              : metaFilterName+              : pandocFilterNames+              ++ blockElementNames+              ++ inlineElementNames+  let go constr acc = Lua.liftLua $ do+        Lua.getfield idx constr+        filterFn <- registerFilterFunction+        return $ case filterFn of+          Nothing -> acc+          Just fn -> Map.insert constr fn acc+  LuaFilter <$!> foldrM go Map.empty constrs  -- | Register the function at the top of the stack as a filter function in the -- registry.
src/Text/Pandoc/Lua/Init.hs view
@@ -83,13 +83,8 @@ -- stack. putConstructorsInRegistry :: PandocLua () putConstructorsInRegistry = liftPandocLua $ do-  constrsToReg $ Pandoc.Pandoc mempty mempty-  constrsToReg $ Pandoc.Str mempty-  constrsToReg $ Pandoc.Para mempty   constrsToReg $ Pandoc.Meta mempty   constrsToReg $ Pandoc.MetaList mempty-  constrsToReg $ Pandoc.Citation mempty mempty mempty Pandoc.AuthorInText 0 0-  putInReg "ListAttributes"  -- used for ListAttributes type alias   putInReg "List"  -- pandoc.List   putInReg "SimpleTable"  -- helper for backward-compatible table handling  where
src/Text/Pandoc/Lua/Marshaling/AST.hs view
@@ -19,33 +19,40 @@ module Text.Pandoc.Lua.Marshaling.AST   ( peekAttr   , peekBlock+  , peekBlockFuzzy   , peekBlocks+  , peekBlocksFuzzy   , peekCaption   , peekCitation+  , peekColSpec+  , peekDefinitionItem   , peekFormat   , peekInline+  , peekInlineFuzzy   , peekInlines-  , peekListAttributes+  , peekInlinesFuzzy   , peekMeta   , peekMetaValue   , peekPandoc   , peekMathType   , peekQuoteType--  , peekFuzzyInlines-  , peekFuzzyBlocks+  , peekTableBody+  , peekTableHead+  , peekTableFoot    , pushAttr   , pushBlock+  , pushCitation   , pushInline   , pushListAttributes+  , pushMeta   , pushMetaValue   , pushPandoc   ) where  import Control.Applicative ((<|>), optional) import Control.Monad.Catch (throwM)-import Control.Monad ((<$!>), (>=>))+import Control.Monad ((<$!>)) import Data.Data (showConstr, toConstr) import Data.Text (Text) import Data.Version (Version)@@ -53,9 +60,11 @@ import HsLua.Module.Version (peekVersionFuzzy) import Text.Pandoc.Definition import Text.Pandoc.Error (PandocError (PandocLuaError))-import Text.Pandoc.Lua.Util (pushViaConstr', pushViaConstructor)+import Text.Pandoc.Lua.Util (pushViaConstr') import Text.Pandoc.Lua.Marshaling.Attr (peekAttr, pushAttr) import Text.Pandoc.Lua.Marshaling.List (pushPandocList)+import Text.Pandoc.Lua.Marshaling.ListAttributes+  (peekListAttributes, pushListAttributes)  import qualified HsLua as Lua import qualified Text.Pandoc.Lua.Util as LuaUtil@@ -101,32 +110,35 @@ instance Pushable Block where   push = pushBlock --- Inline-instance Pushable Inline where-  push = pushInline---- Citation-instance Pushable Citation where-  push = pushCitation+typeCitation :: LuaError e => DocumentedType e Citation+typeCitation = deftype "Citation" []+  [ property "id" "citation ID / key"+      (pushText, citationId)+      (peekText, \citation cid -> citation{ citationId = cid })+  , property "mode" "citation mode"+      (pushString . show, citationMode)+      (peekRead, \citation mode -> citation{ citationMode = mode })+  , property "prefix" "citation prefix"+      (pushInlines, citationPrefix)+      (peekInlines, \citation prefix -> citation{ citationPrefix = prefix })+  , property "suffix" "citation suffix"+      (pushInlines, citationSuffix)+      (peekInlines, \citation suffix -> citation{ citationPrefix = suffix })+  , property "note_num" "note number"+      (pushIntegral, citationNoteNum)+      (peekIntegral, \citation noteNum -> citation{ citationNoteNum = noteNum })+  , property "hash" "hash number"+      (pushIntegral, citationHash)+      (peekIntegral, \citation hash -> citation{ citationHash = hash })+  , method $ defun "clone" ### return <#> udparam typeCitation "obj" ""+    =#> functionResult pushCitation "Citation" "copy of obj"+  ]  pushCitation :: LuaError e => Pusher e Citation-pushCitation (Citation cid prefix suffix mode noteNum hash) =-  pushViaConstr' "Citation"-  [ push cid, push mode, push prefix, push suffix, push noteNum, push hash-  ]+pushCitation = pushUD typeCitation  peekCitation :: LuaError e => Peeker e Citation-peekCitation = fmap (retrieving "Citation")-  . typeChecked "table" Lua.istable $ \idx -> do-      idx' <- liftLua $ absindex idx-      Citation-        <$!> peekFieldRaw peekText "id" idx'-        <*>  peekFieldRaw (peekList peekInline) "prefix" idx'-        <*>  peekFieldRaw (peekList peekInline) "suffix" idx'-        <*>  peekFieldRaw peekRead "mode" idx'-        <*>  peekFieldRaw peekIntegral "note_num" idx'-        <*>  peekFieldRaw peekIntegral "hash" idx'-+peekCitation = peekUD typeCitation  instance Pushable Alignment where   push = Lua.pushString . show@@ -220,75 +232,207 @@         Nothing  -> peekUntagged     _        -> failPeek "could not get meta value" +typeBlock :: LuaError e => DocumentedType e Block+typeBlock = deftype "Block"+  [ operation Eq $ lambda+    ### liftPure2 (==)+    <#> parameter peekBlockFuzzy "Block" "a" ""+    <#> parameter peekBlockFuzzy "Block" "b" ""+    =#> boolResult "whether the two values are equal"+  , operation Tostring $ lambda+    ### liftPure show+    <#> udparam typeBlock "self" ""+    =#> functionResult pushString "string" "Haskell representation"+  ]+  [ possibleProperty "attr" "element attributes"+      (pushAttr, \case+          CodeBlock attr _     -> Actual attr+          Div attr _           -> Actual attr+          Header _ attr _      -> Actual attr+          Table attr _ _ _ _ _ -> Actual attr+          _                    -> Absent)+      (peekAttr, \case+          CodeBlock _ code     -> Actual . flip CodeBlock code+          Div _ blks           -> Actual . flip Div blks+          Header lvl _ blks    -> Actual . (\attr -> Header lvl attr blks)+          Table _ c cs h bs f  -> Actual . (\attr -> Table attr c cs h bs f)+          _                    -> const Absent)+  , possibleProperty "bodies" "table bodies"+      (pushPandocList pushTableBody, \case+          Table _ _ _ _ bs _ -> Actual bs+          _                  -> Absent)+      (peekList peekTableBody, \case+          Table attr c cs h _ f -> Actual . (\bs -> Table attr c cs h bs f)+          _                     -> const Absent)+  , possibleProperty "caption" "element caption"+      (pushCaption, \case {Table _ capt _ _ _ _ -> Actual capt; _ -> Absent})+      (peekCaption, \case+          Table attr _ cs h bs f -> Actual . (\c -> Table attr c cs h bs f)+          _                      -> const Absent)+  , possibleProperty "colspecs" "column alignments and widths"+      (pushPandocList pushColSpec, \case+          Table _ _ cs _ _ _     -> Actual cs+          _                      -> Absent)+      (peekList peekColSpec, \case+          Table attr c _ h bs f  -> Actual . (\cs -> Table attr c cs h bs f)+          _                      -> const Absent)+  , possibleProperty "content" "element content"+      (pushContent, getBlockContent)+      (peekContent, setBlockContent)+  , possibleProperty "foot" "table foot"+      (pushTableFoot, \case {Table _ _ _ _ _ f -> Actual f; _ -> Absent})+      (peekTableFoot, \case+          Table attr c cs h bs _ -> Actual . (\f -> Table attr c cs h bs f)+          _                      -> const Absent)+  , possibleProperty "format" "format of raw content"+      (pushFormat, \case {RawBlock f _ -> Actual f; _ -> Absent})+      (peekFormat, \case+          RawBlock _ txt -> Actual . (`RawBlock` txt)+          _              -> const Absent)+  , possibleProperty "head" "table head"+      (pushTableHead, \case {Table _ _ _ h _ _ -> Actual h; _ -> Absent})+      (peekTableHead, \case+          Table attr c cs _ bs f  -> Actual . (\h -> Table attr c cs h bs f)+          _                       -> const Absent)+  , possibleProperty "level" "heading level"+      (pushIntegral, \case {Header lvl _ _ -> Actual lvl; _ -> Absent})+      (peekIntegral, \case+          Header _ attr inlns -> Actual . \lvl -> Header lvl attr inlns+          _                   -> const Absent)+  , possibleProperty "listAttributes" "ordered list attributes"+      (pushListAttributes, \case+          OrderedList listAttr _ -> Actual listAttr+          _                      -> Absent)+      (peekListAttributes, \case+          OrderedList _ content -> Actual . (`OrderedList` content)+          _                     -> const Absent)+  , possibleProperty "text" "text contents"+      (pushText, getBlockText)+      (peekText, setBlockText)++  , readonly "tag" "type of Block"+      (pushString, showConstr . toConstr )++  , alias "t" "tag" ["tag"]+  , alias "c" "content" ["content"]+  , alias "identifier" "element identifier"       ["attr", "identifier"]+  , alias "classes"    "element classes"          ["attr", "classes"]+  , alias "attributes" "other element attributes" ["attr", "attributes"]+  , alias "start"      "ordered list start number" ["listAttributes", "start"]+  , alias "style"      "ordered list style"       ["listAttributes", "style"]+  , alias "delimiter"  "numbering delimiter"      ["listAttributes", "delimiter"]++  , method $ defun "clone"+    ### return+    <#> parameter peekBlock "Block" "block" "self"+    =#> functionResult pushBlock "Block" "cloned Block"++  , method $ defun "show"+    ### liftPure show+    <#> parameter peekBlock "Block" "self" ""+    =#> functionResult pushString "string" "Haskell string representation"+  ]+ where+  boolResult = functionResult pushBool "boolean"++getBlockContent :: Block -> Possible Content+getBlockContent = \case+  -- inline content+  Para inlns          -> Actual $ ContentInlines inlns+  Plain inlns         -> Actual $ ContentInlines inlns+  -- inline content+  BlockQuote blks     -> Actual $ ContentBlocks blks+  Div _ blks          -> Actual $ ContentBlocks blks+  -- lines content+  LineBlock lns       -> Actual $ ContentLines lns+  -- list items content+  BulletList itms     -> Actual $ ContentListItems itms+  OrderedList _ itms  -> Actual $ ContentListItems itms+  -- definition items content+  DefinitionList itms -> Actual $ ContentDefItems itms+  _                   -> Absent++setBlockContent :: Block -> Content -> Possible Block+setBlockContent = \case+  -- inline content+  Para _           -> Actual . Para . inlineContent+  Plain _          -> Actual . Plain . inlineContent+  -- block content+  BlockQuote _     -> Actual . BlockQuote . blockContent+  Div attr _       -> Actual . Div attr . blockContent+  -- lines content+  LineBlock _      -> Actual . LineBlock . lineContent+  -- list items content+  BulletList _     -> Actual . BulletList . listItemContent+  OrderedList la _ -> Actual . OrderedList la . listItemContent+  -- definition items content+  DefinitionList _ -> Actual . DefinitionList . defItemContent+  _                -> const Absent+  where+    inlineContent = \case+      ContentInlines inlns -> inlns+      c -> throwM . PandocLuaError $ "expected Inlines, got " <>+           contentTypeDescription c+    blockContent = \case+      ContentBlocks blks   -> blks+      ContentInlines inlns -> [Plain inlns]+      c -> throwM . PandocLuaError $ "expected Blocks, got " <>+           contentTypeDescription c+    lineContent = \case+      ContentLines lns     -> lns+      c -> throwM . PandocLuaError $ "expected list of lines, got " <>+           contentTypeDescription c+    defItemContent = \case+      ContentDefItems itms -> itms+      c -> throwM . PandocLuaError $ "expected definition items, got " <>+           contentTypeDescription c+    listItemContent = \case+      ContentBlocks blks    -> [blks]+      ContentLines lns      -> map ((:[]) . Plain) lns+      ContentListItems itms -> itms+      c -> throwM . PandocLuaError $ "expected list of items, got " <>+           contentTypeDescription c++getBlockText :: Block -> Possible Text+getBlockText = \case+  CodeBlock _ lst -> Actual lst+  RawBlock _ raw  -> Actual raw+  _               -> Absent++setBlockText :: Block -> Text -> Possible Block+setBlockText = \case+  CodeBlock attr _ -> Actual . CodeBlock attr+  RawBlock f _     -> Actual . RawBlock f+  _                -> const Absent+ -- | Push a block element to the top of the Lua stack. pushBlock :: forall e. LuaError e => Block -> LuaE e ()-pushBlock = \case-  BlockQuote blcks         -> pushViaConstructor @e "BlockQuote" blcks-  BulletList items         -> pushViaConstructor @e "BulletList" items-  CodeBlock attr code      -> pushViaConstr' @e "CodeBlock"-                              [ push code, pushAttr attr ]-  DefinitionList items     -> pushViaConstructor @e "DefinitionList" items-  Div attr blcks           -> pushViaConstr' @e "Div"-                              [push blcks, pushAttr attr]-  Header lvl attr inlns    -> pushViaConstr' @e "Header"-                              [push lvl, push inlns, pushAttr attr]-  HorizontalRule           -> pushViaConstructor @e "HorizontalRule"-  LineBlock blcks          -> pushViaConstructor @e "LineBlock" blcks-  OrderedList lstAttr list -> pushViaConstr' @e "OrderedList"-                              [ push list, pushListAttributes @e lstAttr ]-  Null                     -> pushViaConstructor @e "Null"-  Para blcks               -> pushViaConstructor @e "Para" blcks-  Plain blcks              -> pushViaConstructor @e "Plain" blcks-  RawBlock f cs            -> pushViaConstructor @e "RawBlock" f cs-  Table attr blkCapt specs thead tbody tfoot ->-    pushViaConstr' @e "Table"-    [ pushCaption blkCapt, push specs, push thead, push tbody-    , push tfoot, pushAttr attr]+pushBlock = pushUD typeBlock  -- | Return the value at the given index as block if possible. peekBlock :: forall e. LuaError e => Peeker e Block-peekBlock = fmap (retrieving "Block")-  . typeChecked "table" Lua.istable-  $ \idx -> do-  -- Get the contents of an AST element.-  let mkBlock :: (a -> Block) -> Peeker e a -> Peek e Block-      mkBlock f p = f <$!> peekFieldRaw p "c" idx-  LuaUtil.getTag idx >>= \case-      "BlockQuote"     -> mkBlock BlockQuote peekBlocks-      "BulletList"     -> mkBlock BulletList (peekList peekBlocks)-      "CodeBlock"      -> mkBlock (uncurry CodeBlock)-                                  (peekPair peekAttr peekText)-      "DefinitionList" -> mkBlock DefinitionList-                          (peekList (peekPair peekInlines (peekList peekBlocks)))-      "Div"            -> mkBlock (uncurry Div) (peekPair peekAttr peekBlocks)-      "Header"         -> mkBlock (\(lvl, attr, lst) -> Header lvl attr lst)-                          (peekTriple peekIntegral peekAttr peekInlines)-      "HorizontalRule" -> return HorizontalRule-      "LineBlock"      -> mkBlock LineBlock (peekList peekInlines)-      "OrderedList"    -> mkBlock (uncurry OrderedList)-                          (peekPair peekListAttributes (peekList peekBlocks))-      "Null"           -> return Null-      "Para"           -> mkBlock Para peekInlines-      "Plain"          -> mkBlock Plain peekInlines-      "RawBlock"       -> mkBlock (uncurry RawBlock)-                                  (peekPair peekFormat peekText)-      "Table"          -> mkBlock id-        (retrieving "Table" . (liftLua . absindex >=> (\idx' -> cleanup $ do-          attr  <- liftLua (rawgeti idx' 1) *> peekAttr top-          capt  <- liftLua (rawgeti idx' 2) *> peekCaption top-          cs    <- liftLua (rawgeti idx' 3) *> peekList peekColSpec top-          thead <- liftLua (rawgeti idx' 4) *> peekTableHead top-          tbods <- liftLua (rawgeti idx' 5) *> peekList peekTableBody top-          tfoot <- liftLua (rawgeti idx' 6) *> peekTableFoot top-          return $! Table attr capt cs thead tbods tfoot)))-      Name tag -> failPeek ("Unknown block type: " <> tag)+peekBlock = retrieving "Block" . peekUD typeBlock +-- | Retrieves a list of Block elements. peekBlocks :: LuaError e => Peeker e [Block] peekBlocks = peekList peekBlock  peekInlines :: LuaError e => Peeker e [Inline] peekInlines = peekList peekInline +pushInlines :: LuaError e => Pusher e [Inline]+pushInlines = pushPandocList pushInline++-- | Retrieves a single definition item from a the stack; it is expected+-- to be a pair of a list of inlines and a list of list of blocks. Uses+-- fuzzy parsing, i.e., tries hard to convert mismatching types into the+-- expected result.+peekDefinitionItem :: LuaError e => Peeker e ([Inline], [[Block]])+peekDefinitionItem = peekPair peekInlinesFuzzy $ choice+  [ peekList peekBlocksFuzzy+  , \idx -> (:[]) <$!> peekBlocksFuzzy idx+  ]+ -- | Push Caption element pushCaption :: LuaError e => Caption -> LuaE e () pushCaption (Caption shortCaption longCaption) = do@@ -303,37 +447,48 @@   long <- peekFieldRaw peekBlocks "long" idx   return $! Caption short long -peekColWidth :: LuaError e => Peeker e ColWidth-peekColWidth = retrieving "ColWidth" . \idx -> do-  maybe ColWidthDefault ColWidth <$!> optional (peekRealFloat idx)+-- | Push a ColSpec value as a pair of Alignment and ColWidth.+pushColSpec :: LuaError e => Pusher e ColSpec+pushColSpec = pushPair (pushString . show) pushColWidth +-- | Peek a ColSpec value as a pair of Alignment and ColWidth. peekColSpec :: LuaError e => Peeker e ColSpec peekColSpec = peekPair peekRead peekColWidth -instance Pushable ColWidth where-  push = \case-    (ColWidth w)    -> Lua.push w-    ColWidthDefault -> Lua.pushnil+peekColWidth :: LuaError e => Peeker e ColWidth+peekColWidth = retrieving "ColWidth" . \idx -> do+  maybe ColWidthDefault ColWidth <$!> optional (peekRealFloat idx) -instance Pushable Row where-  push (Row attr cells) = Lua.push (attr, cells)+-- | Push a ColWidth value by pushing the width as a plain number, or+-- @nil@ for ColWidthDefault.+pushColWidth :: LuaError e => Pusher e ColWidth+pushColWidth = \case+  (ColWidth w)    -> Lua.push w+  ColWidthDefault -> Lua.pushnil -instance Peekable Row where-  peek = forcePeek . peekRow+-- | Push a table row as a pair of attr and the list of cells.+pushRow :: LuaError e => Pusher e Row+pushRow (Row attr cells) =+  pushPair pushAttr (pushPandocList pushCell) (attr, cells) +-- | Push a table row from a pair of attr and the list of cells. peekRow :: LuaError e => Peeker e Row peekRow = ((uncurry Row) <$!>)   . retrieving "Row"   . peekPair peekAttr (peekList peekCell) -instance Pushable TableBody where-  push (TableBody attr (RowHeadColumns rowHeadColumns) head' body) = do+-- | Pushes a 'TableBody' value as a Lua table with fields @attr@,+-- @row_head_columns@, @head@, and @body@.+pushTableBody :: LuaError e => Pusher e TableBody+pushTableBody (TableBody attr (RowHeadColumns rowHeadColumns) head' body) = do     Lua.newtable     LuaUtil.addField "attr" attr     LuaUtil.addField "row_head_columns" rowHeadColumns     LuaUtil.addField "head" head'     LuaUtil.addField "body" body +-- | Retrieves a 'TableBody' value from a Lua table with fields @attr@,+-- @row_head_columns@, @head@, and @body@. peekTableBody :: LuaError e => Peeker e TableBody peekTableBody = fmap (retrieving "TableBody")   . typeChecked "table" Lua.istable@@ -343,17 +498,25 @@   <*>  peekFieldRaw (peekList peekRow) "head" idx   <*>  peekFieldRaw (peekList peekRow) "body" idx -instance Pushable TableHead where-  push (TableHead attr rows) = Lua.push (attr, rows)+-- | Push a table head value as the pair of its Attr and rows.+pushTableHead :: LuaError e => Pusher e TableHead+pushTableHead (TableHead attr rows) =+  pushPair pushAttr (pushPandocList pushRow) (attr, rows) +-- | Peek a table head value from a pair of Attr and rows. peekTableHead :: LuaError e => Peeker e TableHead peekTableHead = ((uncurry TableHead) <$!>)   . retrieving "TableHead"   . peekPair peekAttr (peekList peekRow) -instance Pushable TableFoot where-  push (TableFoot attr cells) = Lua.push (attr, cells)+-- | Pushes a 'TableFoot' value as a pair of the Attr value and the list+-- of table rows.+pushTableFoot :: LuaError e => Pusher e TableFoot+pushTableFoot (TableFoot attr rows) =+  pushPair pushAttr (pushPandocList pushRow) (attr, rows) +-- | Retrieves a 'TableFoot' value from a pair containing an Attr value+-- and a list of table rows. peekTableFoot :: LuaError e => Peeker e TableFoot peekTableFoot = ((uncurry TableFoot) <$!>)   . retrieving "TableFoot"@@ -365,6 +528,8 @@ instance Peekable Cell where   peek = forcePeek . peekCell +-- | Push a table cell as a table with fields @attr@, @alignment@,+-- @row_span@, @col_span@, and @contents@. pushCell :: LuaError e => Cell -> LuaE e () pushCell (Cell attr align (RowSpan rowSpan) (ColSpan colSpan) contents) = do   Lua.newtable@@ -401,15 +566,49 @@   Str _           -> Actual . Str   _               -> const Absent +-- | Helper type to represent all the different types a `content`+-- attribute can have. data Content   = ContentBlocks [Block]   | ContentInlines [Inline]+  | ContentLines [[Inline]]+  | ContentDefItems [([Inline], [[Block]])]+  | ContentListItems [[Block]] +contentTypeDescription :: Content -> Text+contentTypeDescription = \case+  ContentBlocks {}    -> "list of Block items"+  ContentInlines {}   -> "list of Inline items"+  ContentLines {}     -> "list of Inline lists (i.e., a list of lines)"+  ContentDefItems {}  -> "list of definition items items"+  ContentListItems {} -> "list items (i.e., list of list of Block elements)"++pushContent :: LuaError e => Pusher e Content+pushContent = \case+  ContentBlocks blks -> pushPandocList pushBlock blks+  ContentInlines inlns -> pushPandocList pushInline inlns+  ContentLines lns -> pushPandocList (pushPandocList pushInline) lns+  ContentDefItems itms ->+    let pushItem = pushPair (pushPandocList pushInline)+                            (pushPandocList (pushPandocList pushBlock))+    in pushPandocList pushItem itms+  ContentListItems itms ->+    pushPandocList (pushPandocList pushBlock) itms++peekContent :: LuaError e => Peeker e Content+peekContent idx =+  (ContentInlines <$!> peekInlinesFuzzy idx) <|>+  (ContentLines  <$!> peekList (peekList peekInlineFuzzy) idx) <|>+  (ContentBlocks  <$!> peekBlocksFuzzy idx ) <|>+  (ContentListItems <$!> peekList peekBlocksFuzzy idx) <|>+  (ContentDefItems  <$!> peekList (peekDefinitionItem) idx)+ setInlineContent :: Inline -> Content -> Possible Inline setInlineContent = \case   -- inline content   Cite cs _     -> Actual . Cite cs . inlineContent   Emph _        -> Actual . Emph . inlineContent+  Link a _ tgt  -> Actual . (\inlns -> Link a inlns tgt) . inlineContent   Quoted qt _   -> Actual . Quoted qt . inlineContent   SmallCaps _   -> Actual . SmallCaps . inlineContent   Span attr _   -> Actual . Span attr . inlineContent@@ -423,18 +622,19 @@   where     inlineContent = \case       ContentInlines inlns -> inlns-      ContentBlocks _      -> throwM $-                              PandocLuaError "expected Inlines, got Blocks"+      c -> throwM . PandocLuaError $ "expected Inlines, got " <>+           contentTypeDescription c     blockContent = \case       ContentBlocks blks -> blks       ContentInlines []  -> []-      ContentInlines _   -> throwM $-                            PandocLuaError "expected Blocks, got Inlines"+      c -> throwM . PandocLuaError $ "expected Blocks, got " <>+           contentTypeDescription c  getInlineContent :: Inline -> Possible Content getInlineContent = \case   Cite _ inlns      -> Actual $ ContentInlines inlns   Emph inlns        -> Actual $ ContentInlines inlns+  Link _ inlns _    -> Actual $ ContentInlines inlns   Quoted _ inlns    -> Actual $ ContentInlines inlns   SmallCaps inlns   -> Actual $ ContentInlines inlns   Span _ inlns      -> Actual $ ContentInlines inlns@@ -481,16 +681,6 @@   <#> parameter peekInline "inline" "Inline" "Object"   =#> functionResult pushString "string" "stringified Inline" -pushContent :: LuaError e => Pusher e Content-pushContent = \case-  ContentBlocks blks -> pushPandocList pushBlock blks-  ContentInlines inlns -> pushPandocList pushInline inlns--peekContent :: LuaError e => Peeker e Content-peekContent idx =-  (ContentInlines <$!> peekList peekInline idx) <|>-  (ContentBlocks  <$!> peekList peekBlock idx)- typeInline :: LuaError e => DocumentedType e Inline typeInline = deftype "Inline"   [ operation Tostring showInline@@ -545,7 +735,7 @@           Link _ _ (tgt, _) -> Actual tgt           _                 -> Absent)       (peekText, \case-          Link attr capt (_, title) -> Actual . Image attr capt . (,title)+          Link attr capt (_, title) -> Actual . Link attr capt . (,title)           _                         -> const Absent)   , possibleProperty "title" "title text"       (pushText, getInlineTitle)@@ -576,34 +766,58 @@ peekInline :: forall e. LuaError e => Peeker e Inline peekInline = retrieving "Inline" . \idx -> peekUD typeInline idx +-- | Try extra hard to retrieve an Inline value from the stack. Treats+-- bare strings as @Str@ values.+peekInlineFuzzy :: LuaError e => Peeker e Inline+peekInlineFuzzy = retrieving "Inline" . choice+  [ peekUD typeInline+  , \idx -> Str <$!> peekText idx+  ]+ -- | Try extra-hard to return the value at the given index as a list of -- inlines.-peekFuzzyInlines :: LuaError e => Peeker e [Inline]-peekFuzzyInlines = choice-  [ peekList peekInline-  , fmap pure . peekInline-  , \idx -> pure . Str <$!> peekText idx+peekInlinesFuzzy :: LuaError e => Peeker e [Inline]+peekInlinesFuzzy = choice+  [ peekList peekInlineFuzzy+  , fmap pure . peekInlineFuzzy   ] -peekFuzzyBlocks :: LuaError e => Peeker e [Block]-peekFuzzyBlocks = choice-  [ peekList peekBlock-  , fmap pure . peekBlock-  , \idx -> pure . Plain . pure . Str <$!> peekText idx+-- | Try extra hard to retrieve a Block value from the stack. Treats bar+-- Inline elements as if they were wrapped in 'Plain'.+peekBlockFuzzy :: LuaError e => Peeker e Block+peekBlockFuzzy = choice+  [ peekBlock+  , (\idx -> Plain <$!> peekInlinesFuzzy idx)   ] +-- | Try extra-hard to return the value at the given index as a list of+-- blocks.+peekBlocksFuzzy :: LuaError e => Peeker e [Block]+peekBlocksFuzzy = choice+  [ peekList peekBlockFuzzy+  , (<$!>) pure . peekBlockFuzzy+  ] -pushListAttributes :: forall e. LuaError e => ListAttributes -> LuaE e ()-pushListAttributes (start, style, delimiter) =-    pushViaConstr' "ListAttributes"-    [ push start, push style, push delimiter ]+-- * Orphan Instances -peekListAttributes :: LuaError e => Peeker e ListAttributes-peekListAttributes = retrieving "ListAttributes" . peekTriple-  peekIntegral-  peekRead-  peekRead+instance Pushable Inline where+  push = pushInline +instance Pushable Citation where+  push = pushCitation++instance Pushable Row where+  push = pushRow++instance Pushable TableBody where+  push = pushTableBody++instance Pushable TableFoot where+  push = pushTableFoot++instance Pushable TableHead where+  push = pushTableHead+ -- These instances exist only for testing. It's a hack to avoid making -- the marshalling modules public. instance Peekable Inline where@@ -617,6 +831,9 @@  instance Peekable Pandoc where   peek = forcePeek . peekPandoc++instance Peekable Row where+  peek = forcePeek . peekRow  instance Peekable Version where   peek = forcePeek . peekVersionFuzzy
src/Text/Pandoc/Lua/Marshaling/Attr.hs view
@@ -56,6 +56,10 @@     ### return     <#> parameter peekAttr "attr" "Attr" ""     =#> functionResult pushAttr "Attr" "new Attr element"+  , readonly "tag" "element type tag (always 'Attr')"+      (pushText, const "Attr")++  , alias "t" "alias for `tag`" ["tag"]   ]  pushAttr :: LuaError e => Pusher e Attr@@ -67,7 +71,7 @@   TypeTable    -> liftLua (rawlen idx) >>= \case     0 -> peekKeyValuePairs peekText peekText idx     _ -> peekList (peekPair peekText peekText) idx-  _            -> fail "unsupported type"+  _            -> failPeek "unsupported type"  pushAttribs :: LuaError e => Pusher e [(Text, Text)] pushAttribs = pushUD typeAttributeList@@ -135,7 +139,7 @@  lookupKey :: [(Text,Text)] -> Maybe Key -> Maybe Attribute lookupKey !kvs = \case-  Just (StringKey str) -> AttributeValue <$> lookup str kvs+  Just (StringKey str) -> AttributeValue <$!> lookup str kvs   Just (IntKey n)      -> AttributePair <$!> atMay kvs (n - 1)   Nothing              -> Nothing @@ -200,26 +204,30 @@       return $ ident `seq` classes `seq` attribs `seq`         (ident, classes, attribs) -mkAttr :: LuaError e => LuaE e NumResults-mkAttr = do-  attr <- ltype (nthBottom 1) >>= \case-    TypeString -> forcePeek $ do-      mident <- optional (peekText (nthBottom 1))-      mclass <- optional (peekList peekText (nthBottom 2))-      mattribs <- optional (peekAttribs (nthBottom 3))-      return (fromMaybe "" mident, fromMaybe [] mclass, fromMaybe [] mattribs)-    TypeTable  -> forcePeek $ peekAttrTable (nthBottom 1)-    TypeUserdata -> forcePeek $ peekUD typeAttr (nthBottom 1) <|> do-      attrList <- peekUD typeAttributeList (nthBottom 1)-      return ("", [], attrList)-    TypeNil    -> pure nullAttr-    TypeNone   -> pure nullAttr-    x          -> failLua $ "Cannot create Attr from " ++ show x-  pushAttr attr-  return 1+-- | Constructor for 'Attr'.+mkAttr :: LuaError e => DocumentedFunction e+mkAttr = defun "Attr"+  ### (ltype (nthBottom 1) >>= \case+          TypeString -> forcePeek $ do+            mident <- optional (peekText (nthBottom 1))+            mclass <- optional (peekList peekText (nthBottom 2))+            mattribs <- optional (peekAttribs (nthBottom 3))+            return ( fromMaybe "" mident+                   , fromMaybe [] mclass+                   , fromMaybe [] mattribs)+          TypeTable  -> forcePeek $ peekAttrTable (nthBottom 1)+          TypeUserdata -> forcePeek $ peekUD typeAttr (nthBottom 1) <|> do+            attrList <- peekUD typeAttributeList (nthBottom 1)+            return ("", [], attrList)+          TypeNil    -> pure nullAttr+          TypeNone   -> pure nullAttr+          x          -> failLua $ "Cannot create Attr from " ++ show x)+  =#> functionResult pushAttr "Attr" "new Attr object" -mkAttributeList :: LuaError e => LuaE e NumResults-mkAttributeList = do-  attribs <- forcePeek $ peekAttribs (nthBottom 1)-  pushUD typeAttributeList attribs-  return 1+-- | Constructor for 'AttributeList'.+mkAttributeList :: LuaError e => DocumentedFunction e+mkAttributeList = defun "AttributeList"+  ### return+  <#> parameter peekAttribs "table|AttributeList" "attribs" "an attribute list"+  =#> functionResult (pushUD typeAttributeList) "AttributeList"+        "new AttributeList object"
src/Text/Pandoc/Lua/Marshaling/List.hs view
@@ -1,5 +1,6 @@ {-# LANGUAGE DeriveDataTypeable    #-} {-# LANGUAGE FlexibleInstances     #-}+{-# LANGUAGE FlexibleContexts      #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE OverloadedStrings     #-} {-# LANGUAGE UndecidableInstances  #-}
+ src/Text/Pandoc/Lua/Marshaling/ListAttributes.hs view
@@ -0,0 +1,72 @@+{-# LANGUAGE OverloadedStrings    #-}+{-# LANGUAGE TupleSections        #-}+{- |+Module      : Text.Pandoc.Lua.Marshaling.ListAttributes+Copyright   : © 2021 Albert Krewinkel+License     : GNU GPL, version 2 or above+Maintainer  : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>++Marshaling/unmarshaling functions and constructor for 'ListAttributes'+values.+-}+module Text.Pandoc.Lua.Marshaling.ListAttributes+  ( typeListAttributes+  , peekListAttributes+  , pushListAttributes+  , mkListAttributes+  ) where++import Data.Maybe (fromMaybe)+import HsLua+import Text.Pandoc.Definition ( ListAttributes, ListNumberStyle (DefaultStyle)+                              , ListNumberDelim (DefaultDelim))++typeListAttributes :: LuaError e => DocumentedType e ListAttributes+typeListAttributes = deftype "ListAttributes"+  [ operation Eq $ lambda+    ### liftPure2 (==)+    <#> parameter peekListAttributes "a" "ListAttributes" ""+    <#> parameter peekListAttributes "b" "ListAttributes" ""+    =#> functionResult pushBool "boolean" "whether the two are equal"+  ]+  [ property "start" "number of the first list item"+      (pushIntegral, \(start,_,_) -> start)+      (peekIntegral, \(_,style,delim) -> (,style,delim))+  , property "style" "style used for list numbering"+      (pushString . show, \(_,classes,_) -> classes)+      (peekRead, \(start,_,delim) -> (start,,delim))+  , property "delimiter" "delimiter of list numbers"+      (pushString . show, \(_,_,delim) -> delim)+      (peekRead, \(start,style,_) -> (start,style,))+  , method $ defun "clone"+    ### return+    <#> udparam typeListAttributes "a" ""+    =#> functionResult (pushUD typeListAttributes) "ListAttributes"+          "cloned ListAttributes value"+  ]++-- | Pushes a 'ListAttributes' value as userdata object.+pushListAttributes :: LuaError e => Pusher e ListAttributes+pushListAttributes = pushUD typeListAttributes++-- | Retrieve a 'ListAttributes' triple, either from userdata or from a+-- Lua tuple.+peekListAttributes :: LuaError e => Peeker e ListAttributes+peekListAttributes = retrieving "ListAttributes" . choice+  [ peekUD typeListAttributes+  , peekTriple peekIntegral peekRead peekRead+  ]++-- | Constructor for a new 'ListAttributes' value.+mkListAttributes :: LuaError e => DocumentedFunction e+mkListAttributes = defun "ListAttributes"+  ### liftPure3 (\mstart mstyle mdelim ->+                   ( fromMaybe 1 mstart+                   , fromMaybe DefaultStyle mstyle+                   , fromMaybe DefaultDelim mdelim+                   ))+  <#> optionalParameter peekIntegral "integer" "start" "number of first item"+  <#> optionalParameter peekRead "string" "style" "list numbering style"+  <#> optionalParameter peekRead "string" "delimiter" "list number delimiter"+  =#> functionResult pushListAttributes "ListAttributes" "new ListAttributes"+  #? "Creates a new ListAttributes object."
src/Text/Pandoc/Lua/Marshaling/SimpleTable.hs view
@@ -1,13 +1,10 @@ {-# LANGUAGE OverloadedStrings    #-} {-# LANGUAGE ScopedTypeVariables  #-}-{-# LANGUAGE TypeApplications     #-} {- |    Module      : Text.Pandoc.Lua.Marshaling.SimpleTable    Copyright   : © 2020-2021 Albert Krewinkel    License     : GNU GPL, version 2 or above-    Maintainer  : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>-   Stability   : alpha  Definition and marshaling of the 'SimpleTable' data type used as a convenience type when dealing with tables.@@ -16,14 +13,14 @@   ( SimpleTable (..)   , peekSimpleTable   , pushSimpleTable+  , mkSimpleTable   )   where -import Control.Monad ((<$!>)) import HsLua as Lua import Text.Pandoc.Definition-import Text.Pandoc.Lua.Util (pushViaConstructor) import Text.Pandoc.Lua.Marshaling.AST+import Text.Pandoc.Lua.Marshaling.List  -- | A simple (legacy-style) table. data SimpleTable = SimpleTable@@ -32,23 +29,64 @@   , simpleTableColumnWidths :: [Double]   , simpleTableHeader :: [[Block]]   , simpleTableBody :: [[[Block]]]-  }+  } deriving (Eq, Show) +typeSimpleTable :: LuaError e => DocumentedType e SimpleTable+typeSimpleTable = deftype "SimpleTable"+  [ operation Eq $ lambda+    ### liftPure2 (==)+    <#> udparam typeSimpleTable "a" ""+    <#> udparam typeSimpleTable "b" ""+    =#> functionResult pushBool "boolean" "whether the two objects are equal"+  , operation Tostring $ lambda+    ### liftPure show+    <#> udparam typeSimpleTable "self" ""+    =#> functionResult pushString "string" "Haskell string representation"+  ]+  [ property "caption" "table caption"+      (pushPandocList pushInline, simpleTableCaption)+      (peekInlinesFuzzy, \t capt -> t {simpleTableCaption = capt})+  , property "aligns" "column alignments"+      (pushPandocList (pushString . show), simpleTableAlignments)+      (peekList peekRead, \t aligns -> t{simpleTableAlignments = aligns})+  , property "widths" "relative column widths"+      (pushPandocList pushRealFloat, simpleTableColumnWidths)+      (peekList peekRealFloat, \t ws -> t{simpleTableColumnWidths = ws})+  , property "headers" "table header"+      (pushRow, simpleTableHeader)+      (peekRow, \t h -> t{simpleTableHeader = h})+  , property "rows" "table body rows"+      (pushPandocList pushRow, simpleTableBody)+      (peekList peekRow, \t bs -> t{simpleTableBody = bs})++  , readonly "t" "type tag (always 'SimpleTable')"+      (pushText, const "SimpleTable")++  , alias "header" "alias for `headers`" ["headers"]+  ]+ where+  pushRow = pushPandocList (pushPandocList pushBlock)++peekRow :: LuaError e => Peeker e [[Block]]+peekRow = peekList peekBlocksFuzzy+ -- | Push a simple table to the stack by calling the -- @pandoc.SimpleTable@ constructor. pushSimpleTable :: forall e. LuaError e => SimpleTable -> LuaE e ()-pushSimpleTable tbl = pushViaConstructor @e "SimpleTable"-  (simpleTableCaption tbl)-  (simpleTableAlignments tbl)-  (simpleTableColumnWidths tbl)-  (simpleTableHeader tbl)-  (simpleTableBody tbl)+pushSimpleTable = pushUD typeSimpleTable  -- | Retrieve a simple table from the stack. peekSimpleTable :: forall e. LuaError e => Peeker e SimpleTable-peekSimpleTable idx = retrieving "SimpleTable" $ SimpleTable-  <$!> peekFieldRaw peekInlines "caption" idx-  <*>  peekFieldRaw (peekList peekRead) "aligns" idx-  <*>  peekFieldRaw (peekList peekRealFloat) "widths" idx-  <*>  peekFieldRaw (peekList peekBlocks) "headers" idx-  <*>  peekFieldRaw (peekList (peekList peekBlocks)) "rows" idx+peekSimpleTable = retrieving "SimpleTable" . peekUD typeSimpleTable++-- | Constructor for the 'SimpleTable' type.+mkSimpleTable :: LuaError e => DocumentedFunction e+mkSimpleTable = defun "SimpleTable"+  ### liftPure5 SimpleTable+  <#> parameter peekInlinesFuzzy "Inlines" "caption" "table caption"+  <#> parameter (peekList peekRead) "{Alignment,...}" "align" "column alignments"+  <#> parameter (peekList peekRealFloat) "{number,...}" "widths"+        "relative column widths"+  <#> parameter peekRow "{Blocks,...}" "header" "table header row"+  <#> parameter (peekList peekRow) "{{Blocks,...},...}" "body" "table body rows"+  =#> functionResult pushSimpleTable "SimpleTable" "new SimpleTable object"
src/Text/Pandoc/Lua/Module/MediaBag.hs view
@@ -1,112 +1,126 @@+{-# LANGUAGE LambdaCase        #-} {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Text.Pandoc.Lua.Module.MediaBag    Copyright   : Copyright © 2017-2021 Albert Krewinkel    License     : GNU GPL, version 2 or above-    Maintainer  : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>-   Stability   : alpha -The lua module @pandoc.mediabag@.+The Lua module @pandoc.mediabag@. -} module Text.Pandoc.Lua.Module.MediaBag-  ( pushModule+  ( documentedModule   ) where  import Prelude hiding (lookup)-import Control.Monad (zipWithM_)-import HsLua (LuaE, NumResults, Optional)-import HsLua.Marshalling (pushIterator)+import Data.Maybe (fromMaybe)+import HsLua ( LuaE, DocumentedFunction, Module (..)+             , (<#>), (###), (=#>), (=?>), defun, functionResult+             , optionalParameter , parameter) import Text.Pandoc.Class.CommonState (CommonState (..)) import Text.Pandoc.Class.PandocMonad (fetchItem, getMediaBag, modifyCommonState,                                       setMediaBag) import Text.Pandoc.Error (PandocError) import Text.Pandoc.Lua.Marshaling ()-import Text.Pandoc.Lua.PandocLua (PandocLua (..), liftPandocLua, addFunction)+import Text.Pandoc.Lua.Marshaling.List (pushPandocList)+import Text.Pandoc.Lua.PandocLua (unPandocLua) import Text.Pandoc.MIME (MimeType)  import qualified Data.ByteString.Lazy as BL-import qualified Data.Text as T import qualified HsLua as Lua import qualified Text.Pandoc.MediaBag as MB  -- -- MediaBag submodule ---pushModule :: PandocLua NumResults-pushModule = do-  liftPandocLua Lua.newtable-  addFunction "delete" delete-  addFunction "empty" empty-  addFunction "insert" insert-  addFunction "items" items-  addFunction "lookup" lookup-  addFunction "list" list-  addFunction "fetch" fetch-  return 1+documentedModule :: Module PandocError+documentedModule = Module+  { moduleName = "pandoc.mediabag"+  , moduleDescription = "mediabag access"+  , moduleFields = []+  , moduleFunctions =+      [ delete+      , empty+      , fetch+      , insert+      , items+      , list+      , lookup+      ]+  , moduleOperations = []+  }  -- | Delete a single item from the media bag.-delete :: FilePath -> PandocLua NumResults-delete fp = 0 <$ modifyCommonState-  (\st -> st { stMediaBag = MB.deleteMedia fp (stMediaBag st) })+delete :: DocumentedFunction PandocError+delete = defun "delete"+  ### (\fp -> unPandocLua $ modifyCommonState+              (\st -> st { stMediaBag = MB.deleteMedia fp (stMediaBag st) }))+  <#> parameter Lua.peekString "string" "filepath" "filename of item to delete"+  =#> [] + -- | Delete all items from the media bag.-empty :: PandocLua NumResults-empty = 0 <$ modifyCommonState (\st -> st { stMediaBag = mempty })+empty :: DocumentedFunction PandocError+empty = defun "empty"+  ### unPandocLua (modifyCommonState (\st -> st { stMediaBag = mempty }))+  =#> []  -- | Insert a new item into the media bag.-insert :: FilePath-       -> Optional MimeType-       -> BL.ByteString-       -> PandocLua NumResults-insert fp optionalMime contents = do-  mb <- getMediaBag-  setMediaBag $ MB.insertMedia fp (Lua.fromOptional optionalMime) contents mb-  return (Lua.NumResults 0)+insert :: DocumentedFunction PandocError+insert = defun "insert"+  ### (\fp mmime contents -> unPandocLua $ do+          mb <- getMediaBag+          setMediaBag $ MB.insertMedia fp mmime contents mb+          return (Lua.NumResults 0))+  <#> parameter Lua.peekString "string" "filepath" "item file path"+  <#> optionalParameter Lua.peekText "string" "mimetype" "the item's MIME type"+  <#> parameter Lua.peekLazyByteString "string" "contents" "binary contents"+  =?> "Nothing"  -- | Returns iterator values to be used with a Lua @for@ loop.-items :: PandocLua NumResults-items = do-  mb <- getMediaBag-  liftPandocLua $ do-    let pushItem (fp, mimetype, contents) = do-          Lua.pushString fp-          Lua.pushText mimetype-          Lua.pushByteString $ BL.toStrict contents-          return (Lua.NumResults 3)-    pushIterator pushItem (MB.mediaItems mb)+items :: DocumentedFunction PandocError+items = defun "items"+  ### (do+          mb <-unPandocLua getMediaBag+          let pushItem (fp, mimetype, contents) = do+                Lua.pushString fp+                Lua.pushText mimetype+                Lua.pushByteString $ BL.toStrict contents+                return (Lua.NumResults 3)+          Lua.pushIterator pushItem (MB.mediaItems mb))+  =?> "Iterator triple" -lookup :: FilePath-       -> PandocLua NumResults-lookup fp = do-  res <- MB.lookupMedia fp <$> getMediaBag-  liftPandocLua $ case res of-    Nothing -> 1 <$ Lua.pushnil-    Just item -> do-      Lua.push $ MB.mediaMimeType item-      Lua.push $ MB.mediaContents item-      return 2+-- | Function to lookup a value in the mediabag.+lookup :: DocumentedFunction PandocError+lookup = defun "lookup"+  ### (\fp -> unPandocLua (MB.lookupMedia fp <$> getMediaBag) >>= \case+          Nothing   -> 1 <$ Lua.pushnil+          Just item -> 2 <$ do+            Lua.pushText $ MB.mediaMimeType item+            Lua.pushLazyByteString $ MB.mediaContents item)+  <#> parameter Lua.peekString "string" "filepath" "path of item to lookup"+  =?> "MIME type and contents" -list :: PandocLua NumResults-list = do-  dirContents <- MB.mediaDirectory <$> getMediaBag-  liftPandocLua $ do-    Lua.newtable-    zipWithM_ addEntry [1..] dirContents-  return 1+-- | Function listing all mediabag items.+list :: DocumentedFunction PandocError+list = defun "list"+  ### (unPandocLua (MB.mediaDirectory <$> getMediaBag))+  =#> functionResult (pushPandocList pushEntry) "table" "list of entry triples"  where-  addEntry :: Lua.Integer -> (FilePath, MimeType, Int) -> LuaE PandocError ()-  addEntry idx (fp, mimeType, contentLength) = do+  pushEntry :: (FilePath, MimeType, Int) -> LuaE PandocError ()+  pushEntry (fp, mimeType, contentLength) = do     Lua.newtable-    Lua.push ("path" :: T.Text) *> Lua.push fp *> Lua.rawset (-3)-    Lua.push ("type" :: T.Text) *> Lua.push mimeType *> Lua.rawset (-3)-    Lua.push ("length" :: T.Text) *> Lua.push contentLength *> Lua.rawset (-3)-    Lua.rawseti (-2) idx+    Lua.pushName "path"   *> Lua.pushString fp              *> Lua.rawset (-3)+    Lua.pushName "type"   *> Lua.pushText mimeType          *> Lua.rawset (-3)+    Lua.pushName "length" *> Lua.pushIntegral contentLength *> Lua.rawset (-3) -fetch :: T.Text-      -> PandocLua NumResults-fetch src = do-  (bs, mimeType) <- fetchItem src-  liftPandocLua . Lua.push $ maybe "" T.unpack mimeType-  liftPandocLua $ Lua.push bs-  return 2 -- returns 2 values: contents, mimetype+-- | Lua function to retrieve a new item.+fetch :: DocumentedFunction PandocError+fetch = defun "fetch"+  ### (\src -> do+          (bs, mimeType) <- unPandocLua $ fetchItem src+          Lua.pushText $ fromMaybe "" mimeType+          Lua.pushByteString bs+          return 2)+  <#> parameter Lua.peekText "string" "src" "URI to fetch"+  =?> "Returns two string values: the fetched contents and the mimetype."
src/Text/Pandoc/Lua/Module/Pandoc.hs view
@@ -1,5 +1,7 @@+{-# LANGUAGE LambdaCase        #-} {-# LANGUAGE FlexibleContexts  #-} {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeApplications  #-} {- |    Module      : Text.Pandoc.Lua.Module.Pandoc@@ -13,33 +15,43 @@ -} module Text.Pandoc.Lua.Module.Pandoc   ( pushModule+  , documentedModule   ) where  import Prelude hiding (read)-import Control.Applicative (optional)-import Control.Monad ((>=>), forM_, when)+import Control.Applicative ((<|>))+import Control.Monad ((<$!>), forM_, when) import Control.Monad.Catch (catch, throwM) import Control.Monad.Except (throwError)+import Data.Data (Data, dataTypeConstrs, dataTypeOf, showConstr) import Data.Default (Default (..)) import Data.Maybe (fromMaybe)-import HsLua as Lua hiding (pushModule)+import Data.Proxy (Proxy (Proxy))+import Data.Text (Text)+import HsLua hiding (Div, pushModule) import HsLua.Class.Peekable (PeekError) import System.Exit (ExitCode (..)) import Text.Pandoc.Class.PandocIO (runIO) import Text.Pandoc.Definition-import Text.Pandoc.Lua.Filter (SingletonsList (..), walkInlines,-                               walkInlineLists, walkBlocks, walkBlockLists)+import Text.Pandoc.Lua.Filter (SingletonsList (..), LuaFilter, peekLuaFilter,+                               walkInlines, walkInlineLists,+                               walkBlocks, walkBlockLists) import Text.Pandoc.Lua.Marshaling () import Text.Pandoc.Lua.Marshaling.AST import Text.Pandoc.Lua.Marshaling.Attr (mkAttr, mkAttributeList) import Text.Pandoc.Lua.Marshaling.List (List (..))-import Text.Pandoc.Lua.PandocLua (PandocLua, addFunction, liftPandocLua,+import Text.Pandoc.Lua.Marshaling.ListAttributes ( mkListAttributes+                                                 , peekListAttributes)+import Text.Pandoc.Lua.Marshaling.SimpleTable (mkSimpleTable)+import Text.Pandoc.Lua.Module.Utils (sha1)+import Text.Pandoc.Lua.PandocLua (PandocLua, liftPandocLua,                                   loadDefaultModule) import Text.Pandoc.Options (ReaderOptions (readerExtensions)) import Text.Pandoc.Process (pipeProcess) import Text.Pandoc.Readers (Reader (..), getReader) import Text.Pandoc.Walk (Walkable) +import qualified HsLua as Lua import qualified Data.ByteString.Lazy as BL import qualified Data.ByteString.Lazy.Char8 as BSL import qualified Data.Text as T@@ -50,42 +62,80 @@ -- module to be loadable. pushModule :: PandocLua NumResults pushModule = do+  liftPandocLua $ Lua.pushModule documentedModule   loadDefaultModule "pandoc"-  addFunction "read" read-  addFunction "pipe" pipe-  addFunction "walk_block" (walkElement peekBlock pushBlock)-  addFunction "walk_inline" (walkElement peekInline pushInline)-  -- Constructors-  addFunction "Attr" (liftPandocLua mkAttr)-  addFunction "AttributeList" (liftPandocLua mkAttributeList)-  addFunction "Pandoc" mkPandoc+  let copyNext = do+        hasNext <- next (nth 2)+        if not hasNext+          then return ()+          else do+            pushvalue (nth 2)+            insert (nth 2)+            rawset (nth 5) -- pandoc module+            copyNext   liftPandocLua $ do-    let addConstr fn = do-          pushName (functionName fn)-          pushDocumentedFunction fn-          rawset (nth 3)-    forM_ inlineConstructors addConstr-    -- add constructors to Inlines.constructor-    newtable  -- constructor-    forM_ (inlineConstructors @PandocError) $ \fn -> do-      let name = functionName fn-      pushName name-      pushName name-      rawget (nth 4)-      rawset (nth 3)-    -- set as pandoc.Inline.constructor-    pushName "Inline"-    newtable *> pushName "constructor" *> pushvalue (nth 4) *> rawset (nth 3)-    rawset (nth 4)-    pop 1 -- remaining constructor table+    pushnil  -- initial key+    copyNext+    pop 1+   return 1 +documentedModule :: Module PandocError+documentedModule = Module+  { moduleName = "pandoc"+  , moduleDescription = T.unlines+    [ "Lua functions for pandoc scripts; includes constructors for"+    , "document elements, functions to parse text in a given"+    , "format, and functions to filter and modify a subtree."+    ]+  , moduleFields = stringConstants ++ [inlineField, blockField]+  , moduleOperations = []+  , moduleFunctions = mconcat+      [ functions+      , otherConstructors+      , blockConstructors+      , inlineConstructors+      ]+  }++-- | Inline table field+inlineField :: Field PandocError+inlineField = Field+  { fieldName = "Inline"+  , fieldDescription = "Inline constructors, nested under 'constructors'."+  -- the nesting happens for historical reasons and should probably be+  -- changed.+  , fieldPushValue = pushWithConstructorsSubtable inlineConstructors+  }++-- | @Block@ module field+blockField :: Field PandocError+blockField = Field+  { fieldName = "Block"+  , fieldDescription = "Inline constructors, nested under 'constructors'."+  -- the nesting happens for historical reasons and should probably be+  -- changed.+  , fieldPushValue = pushWithConstructorsSubtable blockConstructors+  }++pushWithConstructorsSubtable :: [DocumentedFunction PandocError]+                             -> LuaE PandocError ()+pushWithConstructorsSubtable constructors = do+  newtable -- Field table+  newtable -- constructor table+  pushName "constructor" *> pushvalue (nth 2) *> rawset (nth 4)+  forM_ constructors $ \fn -> do+    pushName (functionName fn)+    pushDocumentedFunction fn+    rawset (nth 3)+  pop 1 -- pop constructor table+ inlineConstructors :: LuaError e =>  [DocumentedFunction e] inlineConstructors =   [ defun "Cite"     ### liftPure2 Cite     <#> parameter (peekList peekCitation) "citations" "list of Citations" ""-    <#> parameter peekFuzzyInlines "content" "Inline" "placeholder content"+    <#> parameter peekInlinesFuzzy "content" "Inline" "placeholder content"     =#> functionResult pushInline "Inline" "cite element"   , defun "Code"     ### liftPure2 (flip Code)@@ -98,7 +148,7 @@                      let attr = fromMaybe nullAttr mattr                          title = fromMaybe mempty mtitle                      in Image attr caption (src, title))-    <#> parameter peekFuzzyInlines "Inlines" "caption" "image caption / alt"+    <#> parameter peekInlinesFuzzy "Inlines" "caption" "image caption / alt"     <#> parameter peekText "string" "src" "path/URL of the image file"     <#> optionalParameter peekText "string" "title" "brief image description"     <#> optionalParameter peekAttr "Attr" "attr" "image attributes"@@ -111,7 +161,7 @@                      let attr = fromMaybe nullAttr mattr                          title = fromMaybe mempty mtitle                      in Link attr content (target, title))-    <#> parameter peekFuzzyInlines "Inlines" "content" "text for this link"+    <#> parameter peekInlinesFuzzy "Inlines" "content" "text for this link"     <#> parameter peekText "string" "target" "the link target"     <#> optionalParameter peekText "string" "title" "brief link description"     <#> optionalParameter peekAttr "Attr" "attr" "link attributes"@@ -123,12 +173,12 @@     =#> functionResult pushInline "Inline" "math element"   , defun "Note"     ### liftPure Note-    <#> parameter peekFuzzyBlocks "content" "Blocks" "note content"+    <#> parameter peekBlocksFuzzy "content" "Blocks" "note content"     =#> functionResult pushInline "Inline" "note"   , defun "Quoted"     ### liftPure2 Quoted     <#> parameter peekQuoteType "quotetype" "QuoteType" "type of quotes"-    <#> parameter peekFuzzyInlines "content" "Inlines" "inlines in quotes"+    <#> parameter peekInlinesFuzzy "content" "Inlines" "inlines in quotes"     =#> functionResult pushInline "Inline" "quoted element"   , defun "RawInline"     ### liftPure2 RawInline@@ -144,11 +194,11 @@     =#> functionResult pushInline "Inline" "new space"   , defun "Span"     ### liftPure2 (\inlns mattr -> Span (fromMaybe nullAttr mattr) inlns)-    <#> parameter peekFuzzyInlines "content" "Inlines" "inline content"+    <#> parameter peekInlinesFuzzy "content" "Inlines" "inline content"     <#> optionalParameter peekAttr "attr" "Attr" "additional attributes"     =#> functionResult pushInline "Inline" "span element"   , defun "Str"-    ### liftPure (\s -> s `seq` Str s)+    ### liftPure Str     <#> parameter peekText "text" "string" ""     =#> functionResult pushInline "Inline" "new Str object"   , mkInlinesConstr "Strong" Strong@@ -158,62 +208,237 @@   , mkInlinesConstr "Underline" Underline   ] +blockConstructors :: LuaError e => [DocumentedFunction e]+blockConstructors =+  [ defun "BlockQuote"+    ### liftPure BlockQuote+    <#> blocksParam+    =#> blockResult "BlockQuote element"++  , defun "BulletList"+    ### liftPure BulletList+    <#> blockItemsParam "list items"+    =#> blockResult "BulletList element"++  , defun "CodeBlock"+    ### liftPure2 (\code mattr -> CodeBlock (fromMaybe nullAttr mattr) code)+    <#> textParam "text" "code block content"+    <#> optAttrParam+    =#> blockResult "CodeBlock element"++  , defun "DefinitionList"+    ### liftPure DefinitionList+    <#> parameter (choice+                   [ peekList peekDefinitionItem+                   , \idx -> (:[]) <$!> peekDefinitionItem idx+                   ])+                  "{{Inlines, {Blocks,...}},...}"+                  "content" "definition items"+    =#> blockResult "DefinitionList element"++  , defun "Div"+    ### liftPure2 (\content mattr -> Div (fromMaybe nullAttr mattr) content)+    <#> blocksParam+    <#> optAttrParam+    =#> blockResult "Div element"++  , defun "Header"+    ### liftPure3 (\lvl content mattr ->+                     Header lvl (fromMaybe nullAttr mattr) content)+    <#> parameter peekIntegral "integer" "level" "heading level"+    <#> parameter peekInlinesFuzzy "Inlines" "content" "inline content"+    <#> optAttrParam+    =#> blockResult "Header element"++  , defun "HorizontalRule"+    ### return HorizontalRule+    =#> blockResult "HorizontalRule element"++  , defun "LineBlock"+    ### liftPure LineBlock+    <#> parameter (peekList peekInlinesFuzzy) "{Inlines,...}" "content" "lines"+    =#> blockResult "LineBlock element"++  , defun "Null"+    ### return Null+    =#> blockResult "Null element"++  , defun "OrderedList"+    ### liftPure2 (\items mListAttrib ->+                     let defListAttrib = (1, DefaultStyle, DefaultDelim)+                     in OrderedList (fromMaybe defListAttrib mListAttrib) items)+    <#> blockItemsParam "ordered list items"+    <#> optionalParameter peekListAttributes "ListAttributes" "listAttributes"+                          "specifier for the list's numbering"+    =#> blockResult "OrderedList element"++  , defun "Para"+    ### liftPure Para+    <#> parameter peekInlinesFuzzy "Inlines" "content" "paragraph content"+    =#> blockResult "Para element"++  , defun "Plain"+    ### liftPure Plain+    <#> parameter peekInlinesFuzzy "Inlines" "content" "paragraph content"+    =#> blockResult "Plain element"++  , defun "RawBlock"+    ### liftPure2 RawBlock+    <#> parameter peekFormat "Format" "format" "format of content"+    <#> parameter peekText "string" "text" "raw content"+    =#> blockResult "RawBlock element"++  , defun "Table"+    ### (\capt colspecs thead tbodies tfoot mattr ->+           let attr = fromMaybe nullAttr mattr+           in return $! attr `seq` capt `seq` colspecs `seq` thead `seq` tbodies+              `seq` tfoot `seq` Table attr capt colspecs thead tbodies tfoot)+    <#> parameter peekCaption "Caption" "caption" "table caption"+    <#> parameter (peekList peekColSpec) "{ColSpec,...}" "colspecs"+                  "column alignments and widths"+    <#> parameter peekTableHead "TableHead" "head" "table head"+    <#> parameter (peekList peekTableBody) "{TableBody,...}" "bodies"+                  "table bodies"+    <#> parameter peekTableFoot "TableFoot" "foot" "table foot"+    <#> optAttrParam+    =#> blockResult "Table element"+  ]+ where+  blockResult = functionResult pushBlock "Block"+  blocksParam = parameter peekBlocksFuzzy "Blocks" "content" "block content"+  blockItemsParam = parameter peekItemsFuzzy "List of Blocks" "content"+  peekItemsFuzzy idx = peekList peekBlocksFuzzy idx+    <|> ((:[]) <$!> peekBlocksFuzzy idx)++textParam :: LuaError e => Text -> Text -> Parameter e Text+textParam = parameter peekText "string"++optAttrParam :: LuaError e => Parameter e (Maybe Attr)+optAttrParam = optionalParameter peekAttr "attr" "Attr" "additional attributes"+ mkInlinesConstr :: LuaError e                 => Name -> ([Inline] -> Inline) -> DocumentedFunction e mkInlinesConstr name constr = defun name   ### liftPure (\x -> x `seq` constr x)-  <#> parameter peekFuzzyInlines "content" "Inlines" ""+  <#> parameter peekInlinesFuzzy "content" "Inlines" ""   =#> functionResult pushInline "Inline" "new object" +otherConstructors :: LuaError e => [DocumentedFunction e]+otherConstructors =+  [ defun "Pandoc"+    ### liftPure2 (\blocks mMeta -> Pandoc (fromMaybe nullMeta mMeta) blocks)+    <#> parameter peekBlocksFuzzy "Blocks" "blocks" "document contents"+    <#> optionalParameter peekMeta "Meta" "meta" "document metadata"+    =#> functionResult pushPandoc "Pandoc" "new Pandoc document" +  , defun "Citation"+    ### (\cid mode mprefix msuffix mnote_num mhash ->+          cid `seq` mode `seq` mprefix `seq` msuffix `seq`+          mnote_num `seq` mhash `seq` return $! Citation+            { citationId = cid+            , citationMode = mode+            , citationPrefix = fromMaybe mempty mprefix+            , citationSuffix = fromMaybe mempty msuffix+            , citationNoteNum = fromMaybe 0 mnote_num+            , citationHash = fromMaybe 0 mhash+            })+    <#> parameter peekText "string" "cid" "citation ID (e.g. bibtex key)"+    <#> parameter peekRead "citation mode" "mode" "citation rendering mode"+    <#> optionalParameter peekInlinesFuzzy "prefix" "Inlines" ""+    <#> optionalParameter peekInlinesFuzzy "suffix" "Inlines" ""+    <#> optionalParameter peekIntegral "note_num" "integer" "note number"+    <#> optionalParameter peekIntegral "hash" "integer" "hash number"+    =#> functionResult pushCitation "Citation" "new citation object"+    #? "Creates a single citation."++  , mkAttr+  , mkAttributeList+  , mkListAttributes+  , mkSimpleTable+  ]++stringConstants :: [Field e]+stringConstants =+  let constrs :: forall a. Data a => Proxy a -> [String]+      constrs _ = map showConstr . dataTypeConstrs . dataTypeOf @a $ undefined+      nullaryConstructors = mconcat+        [ constrs (Proxy @ListNumberStyle)+        , constrs (Proxy @ListNumberDelim)+        , constrs (Proxy @QuoteType)+        , constrs (Proxy @MathType)+        , constrs (Proxy @Alignment)+        , constrs (Proxy @CitationMode)+        ]+      toField s = Field+        { fieldName = T.pack s+        , fieldDescription = T.pack s+        , fieldPushValue = pushString s+        }+  in map toField nullaryConstructors+ walkElement :: (Walkable (SingletonsList Inline) a,                 Walkable (SingletonsList Block) a,                 Walkable (List Inline) a,                 Walkable (List Block) a)-            => Peeker PandocError a -> Pusher PandocError a-            -> LuaE PandocError NumResults-walkElement peek' push' = do-  x <- forcePeek $ peek' (nthBottom 1)-  f <- peek (nthBottom 2)-  let walk' =  walkInlines f-           >=> walkInlineLists f-           >=> walkBlocks f-           >=> walkBlockLists f-  walk' x >>= push'-  return (NumResults 1)+            => a -> LuaFilter -> LuaE PandocError a+walkElement x f = walkInlines f x+              >>= walkInlineLists f+              >>= walkBlocks f+              >>= walkBlockLists f -read :: T.Text -> Optional T.Text -> PandocLua NumResults-read content formatSpecOrNil = liftPandocLua $ do-  let formatSpec = fromMaybe "markdown" (Lua.fromOptional formatSpecOrNil)-  res <- Lua.liftIO . runIO $-           getReader formatSpec >>= \(rdr,es) ->-             case rdr of-               TextReader r ->-                 r def{ readerExtensions = es } content-               _ -> throwError $ PandocSomeError-                      "Only textual formats are supported"-  case res of-    Right pd -> (1 :: NumResults) <$ Lua.push pd -- success, push Pandoc-    Left  (PandocUnknownReaderError f) -> Lua.raiseError $-       "Unknown reader: " <> f-    Left  (PandocUnsupportedExtensionError e f) -> Lua.raiseError $-       "Extension " <> e <> " not supported for " <> f-    Left  e      -> Lua.raiseError $ show e+functions :: [DocumentedFunction PandocError]+functions =+  [ defun "pipe"+    ### (\command args input -> do+            (ec, output) <- Lua.liftIO $ pipeProcess Nothing command args input+                            `catch` (throwM . PandocIOError "pipe")+            case ec of+              ExitSuccess -> 1 <$ Lua.pushLazyByteString output+              ExitFailure n -> do+                pushPipeError (PipeError (T.pack command) n output)+                Lua.error)+    <#> parameter peekString "string" "command" "path to executable"+    <#> parameter (peekList peekString) "{string,...}" "args"+          "list of arguments"+    <#> parameter peekLazyByteString "string" "input"+          "input passed to process via stdin"+    =?> "output string, or error triple" --- | Pipes input through a command.-pipe :: String           -- ^ path to executable-     -> [String]         -- ^ list of arguments-     -> BL.ByteString    -- ^ input passed to process via stdin-     -> PandocLua NumResults-pipe command args input = liftPandocLua $ do-  (ec, output) <- Lua.liftIO $ pipeProcess Nothing command args input-    `catch` (throwM . PandocIOError "pipe")-  case ec of-    ExitSuccess -> 1 <$ Lua.push output-    ExitFailure n -> do-      pushPipeError (PipeError (T.pack command) n output)-      Lua.error+  , defun "read"+    ### (\content mformatspec -> do+            let formatSpec = fromMaybe "markdown" mformatspec+            res <- Lua.liftIO . runIO $ getReader formatSpec >>= \case+              (TextReader r, es) -> r def{ readerExtensions = es } content+              _ -> throwError $ PandocSomeError+                   "Only textual formats are supported"+            case res of+              Right pd -> return pd -- success, got a Pandoc document+              Left  (PandocUnknownReaderError f) ->+                Lua.failLua . T.unpack $ "Unknown reader: " <> f+              Left  (PandocUnsupportedExtensionError e f) ->+                Lua.failLua . T.unpack $+                "Extension " <> e <> " not supported for " <> f+              Left e ->+                throwM e)+    <#> parameter peekText "string" "content" "text to parse"+    <#> optionalParameter peekText "string" "formatspec" "format and extensions"+    =#> functionResult pushPandoc "Pandoc" "result document" +  , sha1++  , defun "walk_block"+    ### walkElement+    <#> parameter peekBlockFuzzy "Block" "block" "element to traverse"+    <#> parameter peekLuaFilter "LuaFilter" "filter" "filter functions"+    =#> functionResult pushBlock "Block" "modified Block"++  , defun "walk_inline"+    ### walkElement+    <#> parameter peekInlineFuzzy "Inline" "inline" "element to traverse"+    <#> parameter peekLuaFilter "LuaFilter" "filter" "filter functions"+    =#> functionResult pushInline "Inline" "modified Inline"+  ]+ data PipeError = PipeError   { pipeErrorCommand :: T.Text   , pipeErrorCode :: Int@@ -256,12 +481,3 @@           , if output == mempty then BSL.pack "<no output>" else output           ]         return (NumResults 1)--mkPandoc :: PandocLua NumResults-mkPandoc = liftPandocLua $ do-  doc <- forcePeek $ do-    blks <- peekBlocks (nthBottom 1)-    mMeta <- optional $ peekMeta (nthBottom 2)-    pure $ Pandoc (fromMaybe nullMeta mMeta) blks-  pushPandoc doc-  return 1
src/Text/Pandoc/Lua/Module/System.hs view
@@ -11,34 +11,28 @@ Pandoc's system Lua module. -} module Text.Pandoc.Lua.Module.System-  ( pushModule+  ( documentedModule   ) where -import HsLua hiding (pushModule)+import HsLua import HsLua.Module.System   (arch, env, getwd, os, with_env, with_tmpdir, with_wd)-import Text.Pandoc.Error (PandocError)-import Text.Pandoc.Lua.ErrorConversion () -import qualified HsLua as Lua- -- | Push the pandoc.system module on the Lua stack.-pushModule :: LuaE PandocError NumResults-pushModule = do-  Lua.pushModule $ Module-    { moduleName = "system"-    , moduleDescription = "system functions"-    , moduleFields =-        [ arch-        , os-        ]-    , moduleFunctions =-        [ setName "environment" env-        , setName "get_working_directory" getwd-        , setName "with_environment" with_env-        , setName "with_temporary_directory" with_tmpdir-        , setName "with_working_directory" with_wd-        ]-    , moduleOperations = []-    }-  return 1+documentedModule :: LuaError e => Module e+documentedModule = Module+  { moduleName = "pandoc.system"+  , moduleDescription = "system functions"+  , moduleFields =+      [ arch+      , os+      ]+  , moduleFunctions =+      [ setName "environment" env+      , setName "get_working_directory" getwd+      , setName "with_environment" with_env+      , setName "with_temporary_directory" with_tmpdir+      , setName "with_working_directory" with_wd+      ]+  , moduleOperations = []+  }
src/Text/Pandoc/Lua/Module/Types.hs view
@@ -10,40 +10,52 @@ Pandoc data type constructors. -} module Text.Pandoc.Lua.Module.Types-  ( pushModule+  ( documentedModule   ) where -import HsLua (LuaE, NumResults, Peeker, Pusher)+import HsLua ( LuaE, NumResults, Peeker, Pusher, Module (..), Field (..)+             , defun, functionResult, parameter, (###), (<#>), (=#>))+import HsLua.Module.Version (peekVersionFuzzy, pushVersion) import Text.Pandoc.Error (PandocError) import Text.Pandoc.Lua.ErrorConversion () import Text.Pandoc.Lua.Marshaling.AST-import Text.Pandoc.Lua.Util (addFunction)  import qualified HsLua as Lua-import qualified HsLua.Module.Version as Version  -- | Push the pandoc.types module on the Lua stack.-pushModule :: LuaE PandocError NumResults-pushModule = do-  Lua.newtable-  Lua.pushName "Version" *> Lua.pushModule Version.documentedModule-    *> Lua.rawset (Lua.nth 3)-  pushCloneTable-  Lua.setfield (Lua.nth 2) "clone"-  return 1--pushCloneTable :: LuaE PandocError NumResults-pushCloneTable = do-  Lua.newtable-  addFunction "Attr"      $ cloneWith peekAttr pushAttr-  addFunction "Block"     $ cloneWith peekBlock pushBlock-  addFunction "Citation"  $ cloneWith peekCitation Lua.push-  addFunction "Inline"    $ cloneWith peekInline pushInline-  addFunction "Meta"      $ cloneWith peekMeta Lua.push-  addFunction "MetaValue" $ cloneWith peekMetaValue pushMetaValue-  addFunction "ListAttributes" $ cloneWith peekListAttributes pushListAttributes-  addFunction "Pandoc"    $ cloneWith peekPandoc pushPandoc-  return 1+documentedModule :: Module PandocError+documentedModule = Module+  { moduleName = "pandoc.types"+  , moduleDescription =+      "Constructors for types that are not part of the pandoc AST."+  , moduleFields =+    [ Field+      { fieldName = "clone"+      , fieldDescription = "DEPRECATED! Helper functions for element cloning."+      , fieldPushValue = do+          Lua.newtable+          addFunction "Meta" $ cloneWith peekMeta pushMeta+          addFunction "MetaValue" $ cloneWith peekMetaValue pushMetaValue+      }+    ]+  , moduleFunctions =+      [ defun "Version"+        ### return+        <#> parameter peekVersionFuzzy "string|integer|{integer,...}|Version"+              "version_specifier"+              (mconcat [ "either a version string like `'2.7.3'`, "+                       , "a single integer like `2`, "+                       , "list of integers like `{2,7,3}`, "+                       , "or a Version object"+                       ])+        =#> functionResult pushVersion "Version" "A new Version object."+      ]+  , moduleOperations = []+  }+ where addFunction name fn = do+         Lua.pushName name+         Lua.pushHaskellFunction fn+         Lua.rawset (Lua.nth 3)  cloneWith :: Peeker PandocError a           -> Pusher PandocError a
src/Text/Pandoc/Lua/Module/Utils.hs view
@@ -13,7 +13,8 @@ Utility module for Lua, exposing internal helper functions. -} module Text.Pandoc.Lua.Module.Utils-  ( pushModule+  ( documentedModule+  , sha1   ) where  import Control.Applicative ((<|>))@@ -21,7 +22,7 @@ import Data.Data (showConstr, toConstr) import Data.Default (def) import Data.Version (Version)-import HsLua as Lua hiding (pushModule)+import HsLua as Lua import HsLua.Class.Peekable (PeekError) import HsLua.Module.Version (peekVersionFuzzy, pushVersion) import Text.Pandoc.Definition@@ -29,7 +30,8 @@ import Text.Pandoc.Lua.Marshaling () import Text.Pandoc.Lua.Marshaling.AST   ( peekBlock, peekInline, peekPandoc, pushBlock, pushInline, pushPandoc-  , peekAttr, peekListAttributes, peekMeta, peekMetaValue)+  , peekAttr, peekMeta, peekMetaValue)+import Text.Pandoc.Lua.Marshaling.ListAttributes (peekListAttributes) import Text.Pandoc.Lua.Marshaling.List (pushPandocList) import Text.Pandoc.Lua.Marshaling.SimpleTable   ( SimpleTable (..), peekSimpleTable, pushSimpleTable )@@ -38,7 +40,6 @@ import qualified Data.Digest.Pure.SHA as SHA import qualified Data.ByteString.Lazy as BSL import qualified Data.Text as T-import qualified HsLua.Packaging as Lua import qualified Text.Pandoc.Builder as B import qualified Text.Pandoc.Filter.JSON as JSONFilter import qualified Text.Pandoc.Shared as Shared@@ -46,8 +47,8 @@ import qualified Text.Pandoc.Writers.Shared as Shared  -- | Push the "pandoc.utils" module to the Lua stack.-pandocUtilsModule :: Module PandocError-pandocUtilsModule = Module+documentedModule :: Module PandocError+documentedModule = Module   { moduleName = "pandoc.utils"   , moduleDescription = "pandoc utility functions"   , moduleFields = []@@ -91,12 +92,7 @@       , "Returns nil instead of a string if the conversion failed."       ] -    , defun "sha1"-      ### liftPure (SHA.showDigest . SHA.sha1)-      <#> parameter (fmap BSL.fromStrict . peekByteString) "string"-            "input" ""-      =#> functionResult pushString "string" "hexadecimal hash value"-      #? "Compute the hash of the given string value."+    , sha1      , defun "Version"       ### liftPure (id @Version)@@ -145,8 +141,13 @@     ]   } -pushModule :: LuaE PandocError NumResults-pushModule = 1 <$ Lua.pushModule pandocUtilsModule+-- | Documented Lua function to compute the hash of a string.+sha1 :: DocumentedFunction e+sha1 = defun "sha1"+  ### liftPure (SHA.showDigest . SHA.sha1)+  <#> parameter (fmap BSL.fromStrict . peekByteString) "string" "input" ""+  =#> functionResult pushString "string" "hexadecimal hash value"+  #? "Compute the hash of the given string value."   -- | Convert pandoc structure to a string with formatting removed.@@ -184,10 +185,10 @@   [ (fmap PandocElement . peekPandoc)   , (fmap InlineElement . peekInline)   , (fmap BlockElement . peekBlock)+  , (fmap MetaValueElement . peekMetaValue)   , (fmap AttrElement . peekAttr)   , (fmap ListAttributesElement . peekListAttributes)   , (fmap MetaElement . peekMeta)-  , (fmap MetaValueElement . peekMetaValue)   ]  -- | Converts an old/simple table into a normal table block element.
src/Text/Pandoc/Lua/Packages.hs view
@@ -16,7 +16,6 @@   ) where  import Control.Monad (forM_)-import HsLua (NumResults) import Text.Pandoc.Error (PandocError) import Text.Pandoc.Lua.PandocLua (PandocLua, liftPandocLua, loadDefaultModule) @@ -43,24 +42,27 @@     Lua.rawseti (-2) (i + 1)  -- | Load a pandoc module.-pandocPackageSearcher :: String -> PandocLua NumResults+pandocPackageSearcher :: String -> PandocLua Lua.NumResults pandocPackageSearcher pkgName =   case pkgName of     "pandoc"          -> pushWrappedHsFun $ Lua.toHaskellFunction @PandocError Pandoc.pushModule-    "pandoc.mediabag" -> pushWrappedHsFun $ Lua.toHaskellFunction @PandocError MediaBag.pushModule-    "pandoc.path"     -> pushWrappedHsFun-      (Lua.NumResults 1 <$ Lua.pushModule @PandocError Path.documentedModule)-    "pandoc.system"   -> pushWrappedHsFun $ Lua.toHaskellFunction System.pushModule-    "pandoc.types"    -> pushWrappedHsFun $ Lua.toHaskellFunction @PandocError Types.pushModule-    "pandoc.utils"    -> pushWrappedHsFun $ Lua.toHaskellFunction @PandocError Utils.pushModule-    "text"            -> pushWrappedHsFun-      (Lua.NumResults 1 <$ Lua.pushModule @PandocError Text.documentedModule)-    "pandoc.List"     -> pushWrappedHsFun $ Lua.toHaskellFunction @PandocError (loadDefaultModule pkgName)+    "pandoc.mediabag" -> pushModuleLoader MediaBag.documentedModule+    "pandoc.path"     -> pushModuleLoader Path.documentedModule+    "pandoc.system"   -> pushModuleLoader System.documentedModule+    "pandoc.types"    -> pushModuleLoader Types.documentedModule+    "pandoc.utils"    -> pushModuleLoader Utils.documentedModule+    "text"            -> pushModuleLoader Text.documentedModule+    "pandoc.List"     -> pushWrappedHsFun . Lua.toHaskellFunction @PandocError $+                         loadDefaultModule pkgName     _                 -> reportPandocSearcherFailure  where+  pushModuleLoader mdl = liftPandocLua $ do+    Lua.pushHaskellFunction $+      Lua.NumResults 1 <$ Lua.pushModule @PandocError mdl+    return (Lua.NumResults 1)   pushWrappedHsFun f = liftPandocLua $ do     Lua.pushHaskellFunction f     return 1   reportPandocSearcherFailure = liftPandocLua $ do     Lua.push ("\n\t" <> pkgName <> "is not one of pandoc's default packages")-    return (1 :: NumResults)+    return (Lua.NumResults 1)
src/Text/Pandoc/Lua/PandocLua.hs view
@@ -22,7 +22,6 @@   ( PandocLua (..)   , runPandocLua   , liftPandocLua-  , addFunction   , loadDefaultModule   ) where @@ -75,13 +74,6 @@  instance Pushable a => Exposable PandocError (PandocLua a) where   partialApply _narg x = 1 <$ (unPandocLua x >>= Lua.push)---- | Add a function to the table at the top of the stack, using the given name.-addFunction :: Exposable PandocError a => Name -> a -> PandocLua ()-addFunction name fn = liftPandocLua $ do-  Lua.pushName name-  Lua.pushHaskellFunction $ toHaskellFunction fn-  Lua.rawset (-3)  -- | Load a pure Lua module included with pandoc. Leaves the result on -- the stack and returns @NumResults 1@.
src/Text/Pandoc/Lua/Util.hs view
@@ -18,8 +18,6 @@ module Text.Pandoc.Lua.Util   ( getTag   , addField-  , addFunction-  , pushViaConstructor   , callWithTraceback   , dofileWithTraceback   , pushViaConstr'@@ -35,41 +33,6 @@   Lua.push key   Lua.push value   Lua.rawset (Lua.nth 3)---- | Add a function to the table at the top of the stack, using the--- given name.-addFunction :: Exposable e a => String -> a -> LuaE e ()-addFunction name fn = do-  Lua.push name-  Lua.pushHaskellFunction $ toHaskellFunction fn-  Lua.rawset (-3)---- | Helper class for pushing a single value to the stack via a lua--- function. See @pushViaCall@.-class LuaError e => PushViaCall e a where-  pushViaCall' :: LuaError e => Name -> LuaE e () -> NumArgs -> a--instance LuaError e => PushViaCall e (LuaE e ()) where-  pushViaCall' fn pushArgs num = do-    Lua.pushName @e fn-    Lua.rawget Lua.registryindex-    pushArgs-    Lua.call num 1--instance (LuaError e, Pushable a, PushViaCall e b) =>-         PushViaCall e (a -> b) where-  pushViaCall' fn pushArgs num x =-    pushViaCall' @e fn (pushArgs *> Lua.push x) (num + 1)---- | Push an value to the stack via a lua function. The lua function is called--- with all arguments that are passed to this function and is expected to return--- a single value.-pushViaCall :: forall e a. LuaError e => PushViaCall e a => Name -> a-pushViaCall fn = pushViaCall' @e fn (return ()) 0---- | Call a pandoc element constructor within Lua, passing all given arguments.-pushViaConstructor :: forall e a. LuaError e => PushViaCall e a => Name -> a-pushViaConstructor pandocFn = pushViaCall @e ("pandoc." <> pandocFn)  -- | Get the tag of a value. This is an optimized and specialized version of -- @Lua.getfield idx "tag"@. It only checks for the field on the table at index
src/Text/Pandoc/Options.hs view
@@ -34,10 +34,10 @@                            , defaultKaTeXURL                            ) where import Control.Applicative ((<|>))-import Data.Char (toLower) import Data.Maybe (fromMaybe) import Data.Data (Data) import Data.Default+import Data.Char (toLower) import Data.Text (Text) import qualified Data.Set as Set import Data.Typeable (Typeable)@@ -46,10 +46,9 @@ import Text.DocTemplates (Context(..), Template) import Text.Pandoc.Extensions import Text.Pandoc.Highlighting (Style, pygments)-import Text.Pandoc.Shared (camelCaseStrToHyphenated)-import Data.Aeson.TH (deriveJSON, defaultOptions, Options(..),-                      SumEncoding(..))-import Data.YAML+import Text.Pandoc.UTF8 (toStringLazy)+import Data.Aeson.TH (deriveJSON)+import Data.Aeson  class HasSyntaxExtensions a where   getExtensions :: a -> Extensions@@ -106,9 +105,9 @@                     | KaTeX Text                -- url of KaTeX files                     deriving (Show, Read, Eq, Data, Typeable, Generic) -instance FromYAML HTMLMathMethod where-   parseYAML node =-     (withMap "HTMLMathMethod" $ \m -> do+instance FromJSON HTMLMathMethod where+   parseJSON node =+     (withObject "HTMLMathMethod" $ \m -> do         method <- m .: "method"         mburl <- m .:? "url"         case method :: Text of@@ -121,43 +120,68 @@           "katex" -> return $ KaTeX $                          fromMaybe defaultKaTeXURL mburl           _ -> fail $ "Unknown HTML math method " ++ show method) node-       <|> (withStr "HTMLMathMethod" $ \method ->-             case method of-               "plain" -> return PlainMath-               "webtex" -> return $ WebTeX ""-               "gladtex" -> return GladTeX-               "mathml" -> return MathML-               "mathjax" -> return $ MathJax defaultMathJaxURL-               "katex" -> return $ KaTeX defaultKaTeXURL-               _  -> fail $ "Unknown HTML math method " ++ show method) node+       <|> (case node of+               String "plain" -> return PlainMath+               String "webtex" -> return $ WebTeX ""+               String "gladtex" -> return GladTeX+               String "mathml" -> return MathML+               String "mathjax" -> return $ MathJax defaultMathJaxURL+               String "katex" -> return $ KaTeX defaultKaTeXURL+               _ -> fail $ "Unknown HTML math method " <>+                             toStringLazy (encode node)) +instance ToJSON HTMLMathMethod where+  toJSON PlainMath = String "plain"+  toJSON (WebTeX "") = String "webtex"+  toJSON (WebTeX url) = object ["method" .= String "webtex",+                                "url" .= String url]+  toJSON GladTeX = String "gladtex"+  toJSON MathML = String "mathml"+  toJSON (MathJax "") = String "mathjax"+  toJSON (MathJax url) = object ["method" .= String "mathjax",+                                 "url" .= String url]+  toJSON (KaTeX "") = String "katex"+  toJSON (KaTeX url) = object ["method" .= String "katex",+                               "url" .= String url]+ data CiteMethod = Citeproc                        -- use citeproc to render them                   | Natbib                        -- output natbib cite commands                   | Biblatex                      -- output biblatex cite commands                 deriving (Show, Read, Eq, Data, Typeable, Generic) -instance FromYAML CiteMethod where-  parseYAML = withStr "Citeproc" $ \t ->-    case t of-      "citeproc" -> return Citeproc-      "natbib"   -> return Natbib-      "biblatex" -> return Biblatex-      _          -> fail $ "Unknown citation method " ++ show t+instance FromJSON CiteMethod where+  parseJSON v =+    case v of+      String "citeproc" -> return Citeproc+      String "natbib"   -> return Natbib+      String "biblatex" -> return Biblatex+      _                 -> fail $ "Unknown citation method: " <>+                                    toStringLazy (encode v) +instance ToJSON CiteMethod where+  toJSON Citeproc = String "citeproc"+  toJSON Natbib = String "natbib"+  toJSON Biblatex = String "biblatex"+ -- | Methods for obfuscating email addresses in HTML. data ObfuscationMethod = NoObfuscation                        | ReferenceObfuscation                        | JavascriptObfuscation                        deriving (Show, Read, Eq, Data, Typeable, Generic) -instance FromYAML ObfuscationMethod where-  parseYAML = withStr "Citeproc" $ \t ->-    case t of-      "none"       -> return NoObfuscation-      "references" -> return ReferenceObfuscation-      "javascript" -> return JavascriptObfuscation-      _            -> fail $ "Unknown obfuscation method " ++ show t+instance FromJSON ObfuscationMethod where+  parseJSON v =+    case v of+      String "none"       -> return NoObfuscation+      String "references" -> return ReferenceObfuscation+      String "javascript" -> return JavascriptObfuscation+      _ -> fail $ "Unknown obfuscation method " ++ toStringLazy (encode v) +instance ToJSON ObfuscationMethod where+   toJSON NoObfuscation = String "none"+   toJSON ReferenceObfuscation = String "references"+   toJSON JavascriptObfuscation = String "javascript"+ -- | Varieties of HTML slide shows. data HTMLSlideVariant = S5Slides                       | SlidySlides@@ -173,28 +197,44 @@                   | AllChanges                   deriving (Show, Read, Eq, Data, Typeable, Generic) -instance FromYAML TrackChanges where-  parseYAML = withStr "TrackChanges" $ \t ->-    case t of-      "accept"     -> return AcceptChanges-      "reject"     -> return RejectChanges-      "all"        -> return AllChanges-      _            -> fail $ "Unknown track changes method " ++ show t+-- update in doc/filters.md if this changes:+instance FromJSON TrackChanges where+  parseJSON v =+    case v of+      String "accept"     -> return AcceptChanges+      String "reject"     -> return RejectChanges+      String "all"        -> return AllChanges+      String "accept-changes" -> return AcceptChanges+      String "reject-changes" -> return RejectChanges+      String "all-changes"    -> return AllChanges+      _  -> fail $ "Unknown track changes method " <> toStringLazy (encode v) +instance ToJSON TrackChanges where+  toJSON AcceptChanges = String "accept-changes"+  toJSON RejectChanges = String "reject-changes"+  toJSON AllChanges = String "all-changes"+ -- | Options for wrapping text in the output. data WrapOption = WrapAuto        -- ^ Automatically wrap to width                 | WrapNone        -- ^ No non-semantic newlines                 | WrapPreserve    -- ^ Preserve wrapping of input source                 deriving (Show, Read, Eq, Data, Typeable, Generic) -instance FromYAML WrapOption where-  parseYAML = withStr "WrapOption" $ \t ->-    case t of-      "auto"     -> return WrapAuto-      "none"     -> return WrapNone-      "preserve" -> return WrapPreserve-      _          -> fail $ "Unknown wrap method " ++ show t+instance FromJSON WrapOption where+  parseJSON v =+    case v of+      String "auto"      -> return WrapAuto+      String "wrap-auto" -> return WrapAuto+      String "none"      -> return WrapNone+      String "wrap-none" -> return WrapNone+      String "preserve"  -> return WrapPreserve+      String "wrap-preserve" -> return WrapPreserve+      _ -> fail $ "Unknown wrap method " <> toStringLazy (encode v) +instance ToJSON WrapOption where+  toJSON WrapAuto = "wrap-auto"+  toJSON WrapNone = "wrap-none"+  toJSON WrapPreserve = "wrap-preserve"  -- | Options defining the type of top-level headers. data TopLevelDivision = TopLevelPart      -- ^ Top-level headers become parts@@ -204,15 +244,24 @@                                           --   heuristics                       deriving (Show, Read, Eq, Data, Typeable, Generic) -instance FromYAML TopLevelDivision where-  parseYAML = withStr "TopLevelDivision" $ \t ->-    case t of-      "part"     -> return TopLevelPart-      "chapter"  -> return TopLevelChapter-      "section"  -> return TopLevelSection-      "default"  -> return TopLevelDefault-      _          -> fail $ "Unknown top level division " ++ show t+instance FromJSON TopLevelDivision where+  parseJSON v =+      case v of+        String "part"              -> return TopLevelPart+        String "top-level-part"    -> return TopLevelPart+        String "chapter"           -> return TopLevelChapter+        String "top-level-chapter" -> return TopLevelChapter+        String "section"           -> return TopLevelSection+        String "top-level-section" -> return TopLevelSection+        String "default"           -> return TopLevelDefault+        String "top-level-default" -> return TopLevelDefault+        _ -> fail $ "Unknown top level division " <> toStringLazy (encode v) +instance ToJSON TopLevelDivision where+  toJSON TopLevelPart = "top-level-part"+  toJSON TopLevelChapter = "top-level-chapter"+  toJSON TopLevelSection = "top-level-section"+  toJSON TopLevelDefault = "top-level-default"  -- | Locations for footnotes and references in markdown output data ReferenceLocation = EndOfBlock    -- ^ End of block@@ -220,14 +269,21 @@                        | EndOfDocument -- ^ at end of document                        deriving (Show, Read, Eq, Data, Typeable, Generic) -instance FromYAML ReferenceLocation where-  parseYAML = withStr "ReferenceLocation" $ \t ->-    case t of-      "block"    -> return EndOfBlock-      "section"  -> return EndOfSection-      "document" -> return EndOfDocument-      _          -> fail $ "Unknown reference location " ++ show t+instance FromJSON ReferenceLocation where+  parseJSON v =+    case v of+      String "block"           -> return EndOfBlock+      String "end-of-block"    -> return EndOfBlock+      String "section"         -> return EndOfSection+      String "end-of-section"  -> return EndOfSection+      String "document"        -> return EndOfDocument+      String "end-of-document" -> return EndOfDocument+      _ -> fail $ "Unknown reference location " <> toStringLazy (encode v) +instance ToJSON ReferenceLocation where+   toJSON EndOfBlock = "end-of-block"+   toJSON EndOfSection = "end-of-section"+   toJSON EndOfDocument = "end-of-document"  -- | Options for writers data WriterOptions = WriterOptions@@ -316,42 +372,9 @@ defaultKaTeXURL = "https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.11.1/"  -- Update documentation in doc/filters.md if this is changed.-$(deriveJSON defaultOptions{ constructorTagModifier =-                               camelCaseStrToHyphenated-                           } ''TrackChanges)--$(deriveJSON defaultOptions{ constructorTagModifier =-                               camelCaseStrToHyphenated-                           } ''WrapOption)--$(deriveJSON defaultOptions{ constructorTagModifier =-                               camelCaseStrToHyphenated . drop 8-                           } ''TopLevelDivision)--$(deriveJSON defaultOptions{ constructorTagModifier =-                               camelCaseStrToHyphenated-                           } ''ReferenceLocation)---- Update documentation in doc/filters.md if this is changed.-$(deriveJSON defaultOptions ''ReaderOptions)--$(deriveJSON defaultOptions{-   constructorTagModifier = map toLower,-   sumEncoding = TaggedObject{-                    tagFieldName = "method",-                    contentsFieldName = "url" }-                           } ''HTMLMathMethod)--$(deriveJSON defaultOptions{ constructorTagModifier =-                               camelCaseStrToHyphenated-                           } ''CiteMethod)--$(deriveJSON defaultOptions{ constructorTagModifier =-                            \case-                                    "NoObfuscation"         -> "none"-                                    "ReferenceObfuscation"  -> "references"-                                    "JavascriptObfuscation" -> "javascript"-                                    _                       -> "none"-                           } ''ObfuscationMethod)+$(deriveJSON defaultOptions{ fieldLabelModifier =+                               camelTo2 '-' . drop 6 }+                            ''ReaderOptions) -$(deriveJSON defaultOptions ''HTMLSlideVariant)+$(deriveJSON defaultOptions{ constructorTagModifier = map toLower }+  ''HTMLSlideVariant)
src/Text/Pandoc/Readers/Markdown.hs view
@@ -28,7 +28,7 @@ import qualified Data.Set as Set import Data.Text (Text) import qualified Data.Text as T-import qualified Data.ByteString.Lazy as BL+import qualified Data.ByteString as BS import System.FilePath (addExtension, takeExtension, takeDirectory) import qualified System.FilePath.Windows as Windows import qualified System.FilePath.Posix as Posix@@ -72,14 +72,12 @@ yamlToMeta :: PandocMonad m            => ReaderOptions            -> Maybe FilePath-           -> BL.ByteString+           -> BS.ByteString            -> m Meta yamlToMeta opts mbfp bstr = do   let parser = do         oldPos <- getPosition-        case mbfp of-          Nothing -> return ()-          Just fp -> setPosition $ initialPos fp+        setPosition $ initialPos (fromMaybe "" mbfp)         meta <- yamlBsToMeta (fmap B.toMetaValue <$> parseBlocks) bstr         setPosition oldPos         return $ runF meta defaultParserState@@ -95,7 +93,7 @@            => (Text -> Bool)            -> ReaderOptions            -> Maybe FilePath-           -> BL.ByteString+           -> BS.ByteString            -> m [MetaValue] yamlToRefs idpred opts mbfp bstr = do   let parser = do
src/Text/Pandoc/Readers/Metadata.hs view
@@ -17,102 +17,61 @@   yamlMetaBlock,   yamlMap ) where -import Control.Monad+ import Control.Monad.Except (throwError)-import qualified Data.ByteString.Lazy as BL+import qualified Data.ByteString as B import qualified Data.Map as M-import Data.Maybe import Data.Text (Text) import qualified Data.Text as T-import qualified Data.YAML as YAML-import qualified Data.YAML.Event as YE+import qualified Data.Yaml as Yaml+import Data.Aeson (Value(..), Object, Result(..), fromJSON, (.:?), withObject)+import Data.Aeson.Types (parse)+import Text.Pandoc.Shared (tshow) import Text.Pandoc.Class.PandocMonad (PandocMonad (..))-import Text.Pandoc.Definition+import Text.Pandoc.Definition hiding (Null) import Text.Pandoc.Error-import Text.Pandoc.Parsing hiding (tableWith)-import Text.Pandoc.Shared-import qualified Data.Text.Lazy as TL+import Text.Pandoc.Parsing hiding (tableWith, parse)++ import qualified Text.Pandoc.UTF8 as UTF8  yamlBsToMeta :: (PandocMonad m, HasLastStrPosition st)              => ParserT Sources st m (Future st MetaValue)-             -> BL.ByteString+             -> B.ByteString              -> ParserT Sources st m (Future st Meta) yamlBsToMeta pMetaValue bstr = do-  case YAML.decodeNode' YAML.failsafeSchemaResolver False False bstr of-       Right (YAML.Doc (YAML.Mapping _ _ o):_)-                -> fmap Meta <$> yamlMap pMetaValue o-       Right [] -> return . return $ mempty-       Right [YAML.Doc (YAML.Scalar _ YAML.SNull)]-                -> return . return $ mempty-       -- the following is what we get from a comment:-       Right [YAML.Doc (YAML.Scalar _ (YAML.SUnknown _ ""))]-                -> return . return $ mempty+  case Yaml.decodeAllEither' bstr of+       Right (Object o:_) -> fmap Meta <$> yamlMap pMetaValue o+       Right [Null] -> return . return $ mempty        Right _  -> Prelude.fail "expected YAML object"-       Left (yamlpos, err')-                -> do pos <- getPosition-                      setPosition $ incSourceLine-                            (setSourceColumn pos (YE.posColumn yamlpos))-                            (YE.posLine yamlpos - 1)-                      Prelude.fail err'--fakePos :: YAML.Pos-fakePos = YAML.Pos (-1) (-1) 1 0--lookupYAML :: Text-           -> YAML.Node YE.Pos-           -> Maybe (YAML.Node YE.Pos)-lookupYAML t (YAML.Mapping _ _ m) =-  M.lookup (YAML.Scalar fakePos (YAML.SUnknown YE.untagged t)) m-    `mplus`-    M.lookup (YAML.Scalar fakePos (YAML.SStr t)) m-lookupYAML _ _ = Nothing+       Left err' -> do+         throwError $ PandocParseError+                    $ T.pack $ Yaml.prettyPrintParseException err'  -- Returns filtered list of references. yamlBsToRefs :: (PandocMonad m, HasLastStrPosition st)              => ParserT Sources st m (Future st MetaValue)              -> (Text -> Bool) -- ^ Filter for id-             -> BL.ByteString+             -> B.ByteString              -> ParserT Sources st m (Future st [MetaValue]) yamlBsToRefs pMetaValue idpred bstr =-  case YAML.decodeNode' YAML.failsafeSchemaResolver False False bstr of-       Right (YAML.Doc o@YAML.Mapping{}:_)-                -> case lookupYAML "references" o of-                     Just (YAML.Sequence _ _ ns) -> do-                       let g n = case lookupYAML "id" n of-                                    Just n' ->-                                      case nodeToKey n' of-                                        Nothing -> False-                                        Just t -> idpred t ||-                                          case lookupYAML "other-ids" n of-                                            Just (YAML.Sequence _ _ ns') ->-                                              let ts' = mapMaybe nodeToKey ns'-                                               in any idpred ts'-                                            _ -> False-                                    Nothing   -> False-                       sequence <$>-                         mapM (yamlToMetaValue pMetaValue) (filter g ns)-                     Just _ ->-                       Prelude.fail "expecting sequence in 'references' field"-                     Nothing ->-                       Prelude.fail "expecting 'references' field"--       Right [] -> return . return $ mempty-       Right [YAML.Doc (YAML.Scalar _ YAML.SNull)]-                -> return . return $ mempty-       Right _  -> Prelude.fail "expecting YAML object"-       Left (yamlpos, err')-                -> do pos <- getPosition-                      setPosition $ incSourceLine-                            (setSourceColumn pos (YE.posColumn yamlpos))-                            (YE.posLine yamlpos - 1)-                      Prelude.fail err'---nodeToKey :: YAML.Node YE.Pos -> Maybe Text-nodeToKey (YAML.Scalar _ (YAML.SStr t))       = Just t-nodeToKey (YAML.Scalar _ (YAML.SUnknown _ t)) = Just t-nodeToKey _                                   = Nothing+  case Yaml.decodeEither' bstr of+       Right (Object m) -> do+         let isSelected (String t) = idpred t+             isSelected _ = False+         let hasSelectedId (Object o) =+               case parse (withObject "ref" (.:? "id")) (Object o) of+                 Success (Just id') -> isSelected id'+                 _ -> False+             hasSelectedId _ = False+         case parse (withObject "metadata" (.:? "references")) (Object m) of+           Success (Just refs) -> sequence <$>+                 mapM (yamlToMetaValue pMetaValue) (filter hasSelectedId refs)+           _ -> return $ return []+       Right _ -> return . return $ []+       Left err' -> do+         throwError $ PandocParseError+                    $ T.pack $ Yaml.prettyPrintParseException err'  normalizeMetaValue :: (PandocMonad m, HasLastStrPosition st)                    => ParserT Sources st m (Future st MetaValue)@@ -133,47 +92,36 @@         isSpaceChar '\t' = True         isSpaceChar _    = False -checkBoolean :: Text -> Maybe Bool-checkBoolean t-  | t == T.pack "true" || t == T.pack "True" || t == T.pack "TRUE" = Just True-  | t == T.pack "false" || t == T.pack "False" || t == T.pack "FALSE" = Just False-  | otherwise = Nothing- yamlToMetaValue :: (PandocMonad m, HasLastStrPosition st)                 => ParserT Sources st m (Future st MetaValue)-                -> YAML.Node YE.Pos+                -> Value                 -> ParserT Sources st m (Future st MetaValue)-yamlToMetaValue pMetaValue (YAML.Scalar _ x) =-  case x of-       YAML.SStr t       -> normalizeMetaValue pMetaValue t-       YAML.SBool b      -> return $ return $ MetaBool b-       YAML.SFloat d     -> return $ return $ MetaString $ tshow d-       YAML.SInt i       -> return $ return $ MetaString $ tshow i-       YAML.SUnknown _ t ->-         case checkBoolean t of-           Just b        -> return $ return $ MetaBool b-           Nothing       -> normalizeMetaValue pMetaValue t-       YAML.SNull        -> return $ return $ MetaString ""--yamlToMetaValue pMetaValue (YAML.Sequence _ _ xs) =-  fmap MetaList . sequence-  <$> mapM (yamlToMetaValue pMetaValue) xs-yamlToMetaValue pMetaValue (YAML.Mapping _ _ o) =-  fmap MetaMap <$> yamlMap pMetaValue o-yamlToMetaValue _ _ = return $ return $ MetaString ""+yamlToMetaValue pMetaValue v =+  case v of+       String t -> normalizeMetaValue pMetaValue t+       Bool b -> return $ return $ MetaBool b+       Number d -> normalizeMetaValue pMetaValue $+         case fromJSON v of+           Success (x :: Int) -> tshow x+           _ -> tshow d+       Null -> return $ return $ MetaString ""+       Array{} -> do+         case fromJSON v of+           Error err' -> throwError $ PandocParseError $ T.pack err'+           Success xs -> fmap MetaList . sequence <$>+                          mapM (yamlToMetaValue pMetaValue) xs+       Object o -> fmap MetaMap <$> yamlMap pMetaValue o  yamlMap :: (PandocMonad m, HasLastStrPosition st)         => ParserT Sources st m (Future st MetaValue)-        -> M.Map (YAML.Node YE.Pos) (YAML.Node YE.Pos)+        -> Object         -> ParserT Sources st m (Future st (M.Map Text MetaValue)) yamlMap pMetaValue o = do-    kvs <- forM (M.toList o) $ \(key, v) -> do-             k <- maybe (throwError $ PandocParseError-                            "Non-string key in YAML mapping")-                        return $ nodeToKey key-             return (k, v)-    let kvs' = filter (not . ignorable . fst) kvs-    fmap M.fromList . sequence <$> mapM toMeta kvs'+    case fromJSON (Object o) of+      Error err' -> throwError $ PandocParseError $ T.pack err'+      Success (m' :: M.Map Text Value) -> do+        let kvs = filter (not . ignorable . fst) $ M.toList m'+        fmap M.fromList . sequence <$> mapM toMeta kvs   where     ignorable t = "_" `T.isSuffixOf` t     toMeta (k, v) = do@@ -194,7 +142,7 @@   -- by including --- and ..., we allow yaml blocks with just comments:   let rawYaml = T.unlines ("---" : (rawYamlLines ++ ["..."]))   optional blanklines-  yamlBsToMeta parser $ UTF8.fromTextLazy $ TL.fromStrict rawYaml+  yamlBsToMeta parser $ UTF8.fromText rawYaml  stopLine :: Monad m => ParserT Sources st m () stopLine = try $ (string "---" <|> string "...") >> blankline >> return ()
src/Text/Pandoc/Translations.hs view
@@ -33,10 +33,11 @@ import qualified Data.Aeson.Types as Aeson import qualified Data.Map as M import qualified Data.Text as T-import qualified Data.YAML as YAML+import qualified Data.Yaml as Yaml import GHC.Generics (Generic) import Text.Pandoc.Shared (safeRead) import qualified Text.Pandoc.UTF8 as UTF8+import Data.Yaml (prettyPrintParseException)  data Term =     Abstract@@ -73,14 +74,6 @@                                                  show t   parseJSON invalid = Aeson.typeMismatch "Term" invalid -instance YAML.FromYAML Term where-  parseYAML (YAML.Scalar _ (YAML.SStr t)) =-                         case safeRead t of-                               Just t' -> pure t'-                               Nothing -> Prelude.fail $ "Invalid Term name " ++-                                                 show t-  parseYAML invalid = YAML.typeMismatch "Term" invalid- instance FromJSON Translations where   parseJSON o@(Object{}) = do     xs <- parseJSON o >>= mapM addItem . M.toList@@ -94,27 +87,12 @@                         inv        -> Aeson.typeMismatch "String" inv   parseJSON invalid = Aeson.typeMismatch "Translations" invalid -instance YAML.FromYAML Translations where-  parseYAML = YAML.withMap "Translations" $-    \tr -> Translations .M.fromList <$> mapM addItem (M.toList tr)-   where addItem (n@(YAML.Scalar _ (YAML.SStr k)), v) =-            case safeRead k of-                 Nothing -> YAML.typeMismatch "Term" n-                 Just t  ->-                   case v of-                        (YAML.Scalar _ (YAML.SStr s)) ->-                          return (t, T.strip s)-                        n' -> YAML.typeMismatch "String" n'-         addItem (n, _) = YAML.typeMismatch "String" n- lookupTerm :: Term -> Translations -> Maybe T.Text lookupTerm t (Translations tm) = M.lookup t tm  readTranslations :: T.Text -> Either T.Text Translations readTranslations s =-  case YAML.decodeStrict $ UTF8.fromText s of-       Left (pos,err') -> Left $ T.pack $ err' ++-           " (line " ++ show (YAML.posLine pos) ++ " column " ++-           show (YAML.posColumn pos) ++ ")"+  case Yaml.decodeAllEither' $ UTF8.fromText s of+       Left err' -> Left $ T.pack $ prettyPrintParseException err'        Right (t:_)     -> Right t        Right []        -> Left "empty YAML document"
src/Text/Pandoc/Writers/Docx.hs view
@@ -880,8 +880,7 @@                                            ("<w:fldSimple w:instr=\"SEQ Figure"                                            <> " \\* ARABIC \"><w:r><w:t>"                                            <> tshow fignum-                                           <> "</w:t></w:r></w:fldSimple>"),-                                           Str ":", Space] : alt+                                           <> "</w:t></w:r></w:fldSimple>")] : Str ": " : alt                               else alt   return $     Elem (mknode "w:p" [] (map Elem paraProps ++ contents))
src/Text/Pandoc/Writers/Docx/Table.hs view
@@ -98,8 +98,8 @@ addLabel :: Text -> Text -> Int -> [Block] -> [Block] addLabel tableid tablename tablenum bs =   case bs of-    (Para ils : rest)  -> Para (label : Space : ils) : rest-    (Plain ils : rest) -> Plain (label : Space : ils) : rest+    (Para ils : rest)  -> Para (label : Str ": " : ils) : rest+    (Plain ils : rest) -> Plain (label : Str ": " : ils) : rest     _ -> Para [label] : bs  where   label = Span (tableid,[],[])@@ -108,8 +108,7 @@                ("<w:fldSimple w:instr=\"SEQ Table"                <> " \\* ARABIC \"><w:r><w:t>"                <> tshow tablenum-               <> "</w:t></w:r></w:fldSimple>"),-             Str ":"]+               <> "</w:t></w:r></w:fldSimple>")]  -- | Parts of a table data RowType = HeadRow | BodyRow | FootRow
src/Text/Pandoc/Writers/Markdown.hs view
@@ -140,10 +140,20 @@   | otherwise =       if hasNewlines x          then hang 0 ("|" <> cr) x-         else if isNothing $ foldM needsDoubleQuotes True x-           then "\"" <> fmap escapeInDoubleQuotes x <> "\""-           else x+         else case x of+                Text _ t | isSpecialString t ->+                         "\"" <> fmap escapeInDoubleQuotes x <> "\""+                _ | isNothing (foldM needsDoubleQuotes True x) ->+                         "\"" <> fmap escapeInDoubleQuotes x <> "\""+                  | otherwise -> x     where+      isSpecialString t = Set.member t specialStrings+      specialStrings = Set.fromList+       ["y", "Y", "yes", "Yes", "YES", "n", "N",+        "no", "No", "NO", "true", "True", "TRUE",+        "false", "False", "FALSE", "on", "On", "ON",+        "off", "Off", "OFF", "null", "Null",+        "NULL", "~", "*"]       needsDoubleQuotes isFirst t         = if T.any isBadAnywhere t ||              (isFirst && T.any isYamlPunct (T.take 1 t))
stack.yaml view
@@ -7,8 +7,8 @@ packages: - '.' extra-deps:-- skylighting-core-0.12-- skylighting-0.12+- skylighting-core-0.12.1+- skylighting-0.12.1 - doctemplates-0.10 - emojis-0.1.2 - doclayout-0.3.1.1
test/command/4819.md view
@@ -49,9 +49,7 @@ ... ^D Pandoc-  Meta-    { unMeta = fromList [ ( "foo" , MetaInlines [ Str "no" ] ) ]-    }+  Meta { unMeta = fromList [ ( "foo" , MetaBool False ) ] }   [] ``` 
test/command/6741.md view
@@ -35,13 +35,13 @@   type: article-journal - author:   - family: Suzuki-    given: Y+    given: Y.   - family: Minami-    given: T+    given: T.   - family: Laeng-    given: B+    given: B.   - family: Nakauchi-    given: S+    given: S.   container-title: Acta Psychologica   DOI: 10.1016/j.actpsy.2019.102882   id: suzuki2019
test/command/pandoc-citeproc-312.md view
@@ -6,7 +6,7 @@ references: - author:   - literal: NN-  id: Y+  id: 'Y'   issued:   - year: 1950   title: 'Date: Year'
test/command/pandoc-citeproc-327.md view
@@ -45,7 +45,7 @@ ::: {#ref-LiLiaoDongWanHaiYuDiQiDongWuCiJiShengChanLiYanJiuJiShengJingGuaYiXingPingJie2017 .csl-entry} [\[1\] ]{.csl-left-margin}[李轶平, 于旭光, 孙明, 等. [辽东湾海域底栖动物次级生产力研究及生境适宜性评价](http://kns.cnki.net/kns/detail/detail.aspx?QueryID=4&CurRec=4&recid=&FileName=CHAN201706006&DbName=CJFDLAST2018&DbCode=CJFQ&yx=Y&pr=&URLID=21.1110.S.20171129.1725.006)\[J\].-水产科学, 2017(06): 728--734.]{.csl-right-inline}+水产科学, 2017(6): 728--734.]{.csl-right-inline} ::: ::: ```
test/command/yaml-metadata-blocks.md view
@@ -51,11 +51,11 @@                    , ( "float" , MetaInlines [ Str "2.5" ] )                    , ( "int" , MetaInlines [ Str "8" ] )                    , ( "more" , MetaBool False )-                   , ( "nothing" , MetaInlines [ Str "null" ] )+                   , ( "nothing" , MetaString "" )                    , ( "scientific" , MetaInlines [ Str "3.7e-5" ] )                    ])             )-          , ( "nothing" , MetaInlines [ Str "null" ] )+          , ( "nothing" , MetaString "" )           , ( "scientific" , MetaInlines [ Str "3.7e-5" ] )           ]     }
test/docx/golden/image.docx view

binary file changed (26816 → 26861 bytes)

test/docx/image_writer_test.native view
@@ -1,8 +1,10 @@ [Para [Str "No",Space,Str "width",Space,Str "given:"]-,Para [Image ("",[],[]) [Str "testimg"] ("lalune.jpg","fig:")]+,Para [Image ("fig:testimg",[],[]) [Str "testimg"] ("lalune.jpg","fig:")] ,Para [Str "With",Space,Str "height",Space,Str "10cm:"]-,Para [Image ("",[],[("height","10cm")]) [Str "2testimg"] ("lalune.jpg","fig:")]+,Para [Image ("fig:2testimg",[],[("height","10cm")]) [Str "2testimg"] ("lalune.jpg","fig:")] ,Para [Str "With",Space,Str "width",Space,Str "6cm:"] ,Para [Image ("",[],[("width","6cm")]) [Str "3testimg"] ("lalune.jpg","fig:")] ,Header 1 ("with-height-3in-and-width-6in",[],[]) [Str "With",Space,Str "height",Space,Str "3in",Space,Str "and",Space,Str "width",Space,Str "6in:"]-,Para [Image ("",[],[("width","6in"),("height","3in")]) [Str "4testimg"] ("lalune.jpg","fig:")]]+,Para [Image ("",[],[("width","6in"),("height","3in")]) [Str "4testimg"] ("lalune.jpg","fig:")]+,Para [RawInline (Format "openxml") "<w:fldSimple w:instr=\"REF ref_fig:testimg\" />"]+,Para [RawInline (Format "openxml") "<w:fldSimple w:instr=\"REF ref_fig:2testimg\" />"]]
test/epub/epub2_cover.epub view

binary file changed (17937 → 11794 bytes)

test/epub/epub2_no_cover.epub view

binary file changed (9730 → 3584 bytes)

test/epub/epub2_picture.epub view

binary file changed (17939 → 11742 bytes)

test/epub/features.epub view

binary file changed (66371 → 8970 bytes)

test/epub/formatting.epub view

binary file changed (13460 → 14022 bytes)

test/epub/img.epub view

binary file changed (61768 → 20478 bytes)

test/epub/img_no_cover.epub view

binary file changed (50594 → 10602 bytes)

test/epub/wasteland.epub view

binary file changed (26051 → 25840 bytes)

test/lua/module/pandoc.lua view
@@ -40,6 +40,13 @@         end       )     },+    group 'Properties' {+      test('has t and tag property', function ()+        local attr = pandoc.Attr('')+        assert.are_equal(attr.t, 'Attr')+        assert.are_equal(attr.tag, 'Attr')+      end)+    },     group 'AttributeList' {       test('allows access via fields', function ()         local attributes = pandoc.Attr('', {}, {{'a', '1'}, {'b', '2'}}).attributes@@ -141,7 +148,198 @@       end)     }   },+  group "Inline elements" {+    test('Link has property `content`', function ()+      local link = pandoc.Link('example', 'https://example.org')+      assert.are_same(link.content, {pandoc.Str 'example'}) +      link.content = 'commercial'+      link.target = 'https://example.com'+      assert.are_equal(link, pandoc.Link('commercial', 'https://example.com'))+    end)+  },+  group "Block elements" {+    group "BulletList" {+      test('access items via property `content`', function ()+        local para = pandoc.Para 'one'+        local blist = pandoc.BulletList{{para}}+        assert.are_same({{para}}, blist.content)+      end),+      test('property `content` uses fuzzy marshalling', function ()+        local old = pandoc.Plain 'old'+        local new = pandoc.Plain 'new'+        local blist = pandoc.BulletList{{old}}+        blist.content = {{new}}+        assert.are_same({{new}}, blist:clone().content)+        blist.content = new+        assert.are_same({{new}}, blist:clone().content)+      end),+    },+    group "OrderedList" {+      test('access items via property `content`', function ()+        local para = pandoc.Plain 'one'+        local olist = pandoc.OrderedList{{para}}+        assert.are_same({{para}}, olist.content)+      end),+      test('forgiving constructor', function ()+        local plain = pandoc.Plain 'old'+        local olist = pandoc.OrderedList({plain}, {3, 'Example', 'Period'})+        local listAttribs = pandoc.ListAttributes(3, 'Example', 'Period')+        assert.are_same(olist.listAttributes, listAttribs)+      end),+      test('has list attribute aliases', function ()+        local olist = pandoc.OrderedList({}, {4, 'Decimal', 'OneParen'})+        assert.are_equal(olist.start, 4)+        assert.are_equal(olist.style, 'Decimal')+        assert.are_equal(olist.delimiter, 'OneParen')+      end)+    },+    group 'DefinitionList' {+      test('access items via property `content`', function ()+        local deflist = pandoc.DefinitionList{+          {'apple', {{pandoc.Plain 'fruit'}, {pandoc.Plain 'company'}}},+          {pandoc.Str 'coffee', 'Best when hot.'}+        }+        assert.are_equal(#deflist.content, 2)+        assert.are_same(deflist.content[1][1], {pandoc.Str 'apple'})+        assert.are_same(deflist.content[1][2][2],+                         {pandoc.Plain{pandoc.Str 'company'}})+        assert.are_same(deflist.content[2][2],+                         {{pandoc.Plain{pandoc.Str 'Best when hot.'}}})+      end),+      test('modify items via property `content`', function ()+        local deflist = pandoc.DefinitionList{+          {'apple', {{{'fruit'}}, {{'company'}}}}+        }+        deflist.content[1][1] = pandoc.Str 'orange'+        deflist.content[1][2][1] = {pandoc.Plain 'tasty fruit'}+        local newlist = pandoc.DefinitionList{+          { {pandoc.Str 'orange'},+            {{pandoc.Plain 'tasty fruit'}, {pandoc.Plain 'company'}}+          }+        }+        assert.are_equal(deflist, newlist)+      end),+    },+    group 'Para' {+      test('access inline via property `content`', function ()+        local para = pandoc.Para{'Moin, ', pandoc.Space(), 'Sylt!'}+        assert.are_same(+          para.content,+          {pandoc.Str 'Moin, ', pandoc.Space(), pandoc.Str 'Sylt!'}+        )+      end),+      test('modifying `content` changes the element', function ()+        local para = pandoc.Para{'Moin, ', pandoc.Space(), pandoc.Str 'Sylt!'}++        para.content[3] = 'Hamburg!'+        assert.are_same(+          para:clone().content,+          {pandoc.Str 'Moin, ', pandoc.Space(), pandoc.Str 'Hamburg!'}+        )++        para.content = 'Huh'+        assert.are_same(+          para:clone().content,+          {pandoc.Str 'Huh'}+        )+        end),+    },+    group 'LineBlock' {+      test('access lines via property `content`', function ()+        local spc = pandoc.Space()+        local lineblock = pandoc.LineBlock{+          {'200', spc, 'Main', spc, 'St.'},+          {'Berkeley', spc, 'CA', spc, '94718'}+        }+        assert.are_equal(#lineblock.content, 2) -- has two lines+        assert.are_same(lineblock.content[2][1], pandoc.Str 'Berkeley')+      end),+      test('modifying `content` alter the element', function ()+        local spc = pandoc.Space()+        local lineblock = pandoc.LineBlock{+          {'200', spc, 'Main', spc, 'St.'},+          {'Berkeley', spc, 'CA', spc, '94718'}+        }+        lineblock.content[1][1] = '404'+        assert.are_same(+          lineblock:clone().content[1],+          {pandoc.Str '404', spc, pandoc.Str 'Main', spc, pandoc.Str 'St.'}+        )++        lineblock.content = {{'line1'}, {'line2'}}+        assert.are_same(+          lineblock:clone(),+          pandoc.LineBlock{+            {pandoc.Str 'line1'},+            {pandoc.Str 'line2'}+          }+        )+      end)+    },+  },+  group 'Other types' {+    group 'SimpleTable' {+      test('can access properties', function ()+        local spc = pandoc.Space()+        local caption = {pandoc.Str 'Languages', spc, pandoc.Str 'overview.'}+        local aligns = {pandoc.AlignDefault, pandoc.AlignDefault}+        local widths = {0, 0} -- let pandoc determine col widths+        local headers = {{pandoc.Plain({pandoc.Str "Language"})},+          {pandoc.Plain({pandoc.Str "Typing"})}}+        local rows = {+          {{pandoc.Plain "Haskell"}, {pandoc.Plain "static"}},+          {{pandoc.Plain "Lua"}, {pandoc.Plain "Dynamic"}},+        }+        local simple_table = pandoc.SimpleTable(+          caption,+          aligns,+          widths,+          headers,+          rows+        )+        assert.are_same(simple_table.caption, caption)+        assert.are_same(simple_table.aligns, aligns)+        assert.are_same(simple_table.widths, widths)+        assert.are_same(simple_table.headers, headers)+        assert.are_same(simple_table.rows, rows)+      end),+      test('can modify properties', function ()+        local new_table = pandoc.SimpleTable(+          {'Languages'},+          {pandoc.AlignDefault, pandoc.AlignDefault},+          {0.5, 0.5},+          {{pandoc.Plain({pandoc.Str "Language"})},+           {pandoc.Plain({pandoc.Str "Typing"})}},+          {+            {{pandoc.Plain "Haskell"}, {pandoc.Plain "static"}},+            {{pandoc.Plain "Lua"}, {pandoc.Plain "Dynamic"}},+          }+        )++        new_table.caption = {pandoc.Str 'Good', pandoc.Space(),+                             pandoc.Str 'languages'}+        new_table.aligns[1] = pandoc.AlignLeft+        new_table.widths = {0, 0}+        new_table.headers[2] = {pandoc.Plain{pandoc.Str 'compiled/interpreted'}}+        new_table.rows[1][2] = {pandoc.Plain{pandoc.Str 'both'}}+        new_table.rows[2][2] = {pandoc.Plain{pandoc.Str 'interpreted'}}++        local expected_table = pandoc.SimpleTable(+          {pandoc.Str 'Good', pandoc.Space(), pandoc.Str 'languages'},+          {pandoc.AlignLeft, pandoc.AlignDefault},+          {0, 0},+          {{pandoc.Plain 'Language'}, {pandoc.Plain 'compiled/interpreted'}},+          {+            {{pandoc.Plain 'Haskell'}, {pandoc.Plain 'both'}},+            {{pandoc.Plain 'Lua'}, {pandoc.Plain 'interpreted'}}+          }+        )+        assert.are_same(expected_table, new_table)+      end)+    }+  },+   group 'clone' {     test('clones Attr', function ()       local attr = pandoc.Attr('test', {'my-class'}, {foo = 'bar'})@@ -176,6 +374,8 @@       local cloned = cite:clone()       cite.id = 'newton'       assert.are_same(cloned.id, 'leibniz')+      assert.are_same(cite.id, 'newton')+      assert.are_same(cite.mode, cloned.mode)     end),   }, @@ -217,6 +417,12 @@           }       })       assert.are_same(expected, pandoc.read(valid_markdown))+    end),+    test('unsupported extension', function ()+      assert.error_matches(+        function () pandoc.read('foo', 'gfm+empty_paragraphs') end,+        'Extension empty_paragraphs not supported for gfm'+      )     end),     test('failing read', function ()       assert.error_matches(
trypandoc/trypandoc.hs view
@@ -52,12 +52,12 @@   let result = case runPure $ reader (tabFilter 4 text) >>= writer of                     Right s   -> s                     Left  err -> error (show err)-  let output = encode $ object [ T.pack "html" .= result-                               , T.pack "name" .=+  let output = encode $ object [ "html" .= result+                               , "name" .=                                   if fromFormat == "markdown_strict"                                      then T.pack "pandoc (strict)"                                      else T.pack "pandoc"-                               , T.pack "version" .= pandocVersion]+                               , "version" .= pandocVersion]   respond $ responseLBS status200 [(hContentType,"text/json; charset=UTF-8")] output  checkLength :: Text -> IO Text